Compare commits

...

148 Commits
v0.1.0 ... main

Author SHA1 Message Date
Pranav Jerry d45ac72442 Merge pull request 'Updated installation instructions for debian' (#29) from update-debian-installation-instructions into main
Reviewed-on: #29
2022-09-13 04:52:02 +00:00
Pranav Jerry 3354584045
updated installation instructions for debian
dasbus is now in debian repos. We no longer need to install it with pip
2022-09-13 10:12:04 +05:30
Pranav Jerry 0c6bdea4a8
updated CHANGELOG.md
I'm renaming the project to pybatmesh. Added instructions to update via
the command-line on the CHANGELOG
2022-08-03 11:08:41 +05:30
Pranav Jerry 9123224de0 Merge pull request 'Rename to pybatmesh' (#27) from rename-to-pybatmesh into main
Reviewed-on: pranav/naxalnet#27
2022-08-03 05:23:03 +00:00
Pranav Jerry 396fe9af7e
updated version and minor changes
Removed some more traces of the previous name.
Removed an unused import and updated CHANGELOG.md
2022-08-03 10:39:26 +05:30
Pranav Jerry 72dda12d7b
renaming to pybatmesh
pybatmesh better describes the project and does not attract the
attention of caged investigation agencies, like it probably would have
before. I probably left traces of the original name somewhere, so this
commit will likely be followed by other commits to erase all traces of
the previous name
2022-07-23 15:58:32 +05:30
Pranav Jerry 38d0aa8ab5
not maintained anymore
If anyone is interested to takeover naxalnet, see #8
2022-02-04 12:51:07 +05:30
Pranav Jerry fad2591b9f
new version -- 0.5.2 2021-12-10 20:16:34 +05:30
Pranav Jerry 05b91e7721 Merge pull request 'Fix for issue #25' (#26) from fix-issue-25 into master
Reviewed-on: pranav/naxalnet#26
2021-12-02 14:13:31 +00:00
Pranav Jerry 4d4e5e15d7
Merge branch 'master' into fix-issue-25
Things should be working fine now
2021-12-02 19:40:49 +05:30
Pranav Jerry 6bca6149b7
ready to merge 2021-12-02 19:29:19 +05:30
Pranav Jerry 710da18af9
moved naxalnet.service to the main directory 2021-12-01 21:34:40 +05:30
Pranav Jerry 888fdf3856
removed all print() calls from network.py
Updated CHANGELOG.md. We (another word for 'me') can push after moving
naxalnet.service out of service/. I am told the unit file is having a
rather dull time coping with per lonely life.
2021-12-01 21:27:27 +05:30
Pranav Jerry fc1f3d4216
another fix for #25
Or, to be more precise, a fix for the fix preceding the current fix for
issue #25 that just didn't fix things right. If your head spins, see the
previous commit, or call an ambulance (that is, if you are privileged
enough to access a phone and know your local helpline number)
2021-11-29 14:47:59 +05:30
Pranav Jerry 5e58df0b71
temporary fix for #25
Uses multithreading.Process instead of GLib.timeout_add()

The moment I finished writing this part, I found out the only problem
with my previous commit was that I had setup the timeout _after_ calling
the blocking function wait_for_change instead of before it.

Although this version (with Process) works, I'm reverting to the
previous version and swapping the two lines (which I had tested and
found to work)

And in case you have read upto the previous line you should also know I
fixed some code in the README

TL;DR: I have proven once again I am an idiot
2021-11-29 14:36:59 +05:30
Pranav Jerry d7a84d8ccc
replaced GObject with GLib in network.py
See the previous commit. And the one preceding that. And the one before
that. Keep going until /dev/brain0 gets symlinked to /dev/urandom
2021-11-16 22:00:00 +05:30
Pranav Jerry 183ce16eca
added timeout
This doesn't work yet
2021-11-14 19:57:35 +05:30
Pranav Jerry caeb042612
implemented NetworkLoop call in scripts.py
See any_interface_is_routable()
2021-11-14 19:46:04 +05:30
Pranav Jerry f657146eb3 Revert "added class to wait until routable"
This reverts commit fbf518e14c.
2021-11-14 19:39:51 +05:30
Pranav Jerry cd44357496
updated version
I accidentally pushed the previous commit to master instead of this
branch. This should revert things
2021-11-14 19:32:34 +05:30
Pranav Jerry fbf518e14c
added class to wait until routable
I haven't tested this properly yet
2021-11-14 19:00:10 +05:30
Pranav Jerry 28de9570b5
updated minimum debian version in README.md
I have added a comment on #20 about this
2021-11-08 21:20:24 +05:30
Pranav Jerry 009f6364cd
add xmpp channel to README.md and HACKING.md 2021-10-31 20:18:56 +05:30
Pranav Jerry a09ababd06
removed telegram group
We could use something else instead
2021-10-30 21:57:41 +05:30
Pranav Jerry 9749cf0c00
added telegram group and something else in README
Added Briar to the list in internet shutdown
2021-10-30 21:54:43 +05:30
Pranav Jerry 542347eac7 Updated use cases in README.md 2021-10-30 13:06:13 +00:00
Pranav Jerry a5ba99ca2a
Version 0.5.1
Fixed issue #21
2021-10-22 13:28:16 +05:30
Pranav Jerry 0d5d3c5cc6 Merge pull request 'fix for issue #21' (#22) from geoclue-fix into master
Reviewed-on: pranav/naxalnet#22
2021-10-22 07:53:45 +00:00
Pranav Jerry 26a907d907
updated readme, changelog
prepare to merge to master
2021-10-22 13:20:09 +05:30
Pranav Jerry 704fe646f8
renamed systemd-networkd/ to network/
Nothing big. And naxalnet needs a new maintainer or I will keep screwing
up things.
2021-10-22 13:09:15 +05:30
Pranav Jerry aa079c7c29
reverted the changes
Instead, removed the wpa_supplicant "conflicts" line from naxalnet.service
2021-10-22 13:05:37 +05:30
Pranav Jerry 295fde3f0b
added override service for wpa_supplicant
This probably isn't working like we want
2021-10-22 12:54:52 +05:30
Pranav Jerry 270db3cf90
added hack to fix #21 2021-10-22 12:06:17 +05:30
Pranav Jerry 6fbebc51bb
almost fixed things 2021-10-22 11:58:41 +05:30
Pranav Jerry 1f8be50dd6
moved systemd service to a dir
This is to add another service file alongside naxalnet.service
2021-10-22 11:11:11 +05:30
Pranav Jerry c4933378ff
quick fix for #21
Added a couple of lines in the README until #21 is closed.
2021-10-22 11:02:53 +05:30
Pranav Jerry 0a85c465ee
added features section in README.md
And added some more info on adding bug reports.
See issue #20.
2021-10-15 16:05:06 +05:30
Pranav Jerry 5dd90d349e
prepare for version 0.5.0
Now that this version is being released, I have no ambitions left on
this program and I would happily accept a new maintainer to take over
this project (Let's see if anyone ever reads this message)
2021-10-10 20:43:34 +05:30
Pranav Jerry a6f5b07310 Merge pull request 'Set gateway mode automatically' (#18) from gateway into master
Reviewed-on: pranav/naxalnet#18
2021-10-09 09:57:29 +00:00
Pranav Jerry de63113098
ready to merge
Updated __version__ to 0.4.0a6
2021-10-09 15:20:57 +05:30
Pranav Jerry e56ff40495
improved documentation 2021-10-08 22:28:01 +05:30
Pranav Jerry 3b3644e107
updated install guide for Fedora in README.md
systemd-resolved is used by default, so there is no need to install it
in rawhide.
2021-10-06 19:27:32 +05:30
Pranav Jerry 65e1906753
added Makefile rule to build rpm
And updated README with the details. There is probably something missing
in the Fedora installation section
2021-10-05 15:04:19 +05:30
Pranav Jerry 6acd7084f2
made README better
Added info on how to check requirements
2021-10-05 12:06:50 +05:30
Pranav Jerry 61a96ea3b3
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.
2021-10-02 14:13:53 +05:30
Pranav Jerry a7304a986b
turn off all wifi devices at exit
This makes things easier to maintain, or so I hope.

Added more comments in files in systemd-networkd, made CHANGELOG.md
better, and updated the README.
2021-09-29 15:14:13 +05:30
Pranav Jerry 32e9559e6e
fixed bug in main()
For some days I've been testing this program without realising that
gateway_mode was set to off every time. Remove dependencies from install
in Makefile, which we don't need anyway, since it builds twice when
installing from the AUR PKGBUILD.
2021-09-29 08:37:59 +05:30
Pranav Jerry a061852a59
commented out a line causing trouble
And added a  bit more logging
2021-09-28 15:58:31 +05:30
Pranav Jerry 5bde1faeba
temporary hack to fix #19
Probably s/temporary/permanent/ if someone doesn't take over this
"project" soon.
2021-09-28 12:37:11 +05:30
Pranav Jerry 87612fac2c
delete interface during cleanup
Read the previous commit for some unhelpful remarks.
2021-09-27 22:48:13 +05:30
Pranav Jerry 2e4c3a70a4
cleanup before exit
This was previously done by the systemd service. But since we allowed
changing the name of bat0 and bridge0, we can't expect systemd to still
do that job. Commented out some lines in the systemd service and made it
send SIGINT instead of the default SIGTERM to kill naxalnet. I
accidentally used to increment a2, a3, a4, ... in the __version__
instead of dev1, dev2, &c. a few commits back. Removed some print()
lines lurking somewhere in the code. The cleanup is still not completed.
We still have to delete the interfaces bridge0 and bat0, or whatever
name the user gives it. Just out of boredom, I added some description to
some network configuration, though so I doubt if anyone will understand
it more because of that.
2021-09-27 22:30:07 +05:30
Pranav Jerry d0389e5638
set gateway mode automatically
Added arg and config option to manually set gw_mode.
When gateway_mode is auto, a temporary config will be added, and after a
ten sec delay, naxalnet will check if systemd-networkd shows a
'routable' connection. If the connection is routable, gw_mode will be
set to server; or client otherwise.
2021-09-27 12:43:09 +05:30
Pranav Jerry 8ba8d6af6c
cleaned up code 2021-09-27 11:43:50 +05:30
Pranav Jerry 761618aff4
added new args and config options
This will allow changing name of batman and bridge interface.
But deleting them after stopping naxalnet will not work at the moment.
2021-09-27 11:27:44 +05:30
Pranav Jerry 798cd3e988
fixed bug in previous commit
Added function to get glob as sorted list. This fixes the errors
reported by systemd-networkd
2021-09-27 11:03:27 +05:30
Pranav Jerry a81449b898
changed how network config is done
We now use NetworkD() to configure systemd-networkd.
Path.glob doesn't return things in alphabetical order, which is needed
to configure networkd without any error. Need a fix for that.
2021-09-27 10:00:59 +05:30
Pranav Jerry ab3252683a
added func for parsing and writing networkd config 2021-09-26 13:57:40 +05:30
Pranav Jerry 8f905ed970
prepared *.net{work,dev} files to work with str.format() 2021-09-26 13:31:36 +05:30
Pranav Jerry 25ac54dfad
removed arguments added in previous commit
Too much configs and args make debugging harder. The class networkd will
be used to add config files to the networkd runtime dir after formatting
the file with str.format().
2021-09-26 13:25:35 +05:30
Pranav Jerry 25a5bdee30
added network.py and some other changes
This will be used to control systemd-networkd via d-bus and runtime
configs and make things easier in implementing B.A.T.M.A.N. gateway support
2021-09-25 15:04:29 +05:30
Pranav Jerry 9171b942db
added temporary network config file
This will be used to check if the machine has internet access.
2021-09-24 12:42:13 +05:30
Pranav Jerry ea283a3247
Duplicate mesh.07-bridge.network history in check.01-eth.network history. 2021-09-24 12:38:46 +05:30
Pranav Jerry 8137b5067b
made error messages more readable
Not a big commit, so pushed directly to master
2021-09-21 22:43:41 +05:30
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
Pranav Jerry feb362b149
Version 0.3.0
Let's assume I haven't forgotten anything.
2021-08-19 12:51:18 +05:30
Pranav Jerry 1a6dbc4bcb
Merge branch 'args-and-config'
See CHANGELOG.md for details
2021-08-19 12:49:18 +05:30
Pranav Jerry 9f8a5b3d0d
updated CHANGELOG and version
Ready for merge
2021-08-19 12:48:02 +05:30
Pranav Jerry fdbbca686d
removed license from package description
Fixed MANIFEST.in and changed data_files in setup.cfg
2021-08-19 12:36:40 +05:30
Pranav Jerry be8de69b73
updated README and Makefile
Added uninstall as dependency for purge in Makefile.
Changed pkexec and pkcon to sudo and apt and dnf
2021-08-19 12:03:20 +05:30
Pranav Jerry 7e0fe5ef4c
many changes -- see full commit message
The config file is now installed as /etc/naxalnet/naxalnet.conf.example
by default.
make uninstall now does not ask for confirmation. Added rule purge in
Makefile.
Updated the README.
Changed order of stop commands in service file.
Updated setup.cfg and docstrings.
2021-08-18 17:33:46 +05:30
Pranav Jerry 274f08cded
added install instructions for fedora and ubuntu
May not work, I have not tested it.
2021-08-18 15:34:07 +05:30
Pranav Jerry d1ec77dc69
clean up runtime files when stopped
This only applies to the systemd service
2021-08-17 09:49:16 +05:30
Pranav Jerry cf54edf9b9
updated README
Changed order of services to stop in section Stopping the service. This
is because while stopping naxalnet, the ExecStopPost line says to delete
two interfaces. But just before it is run, networkd is stopped. Running
the command will again start networkd, which is not what we need.
2021-08-16 21:32:57 +05:30
Pranav Jerry e99b3222e1
simplified systemd-networkd reload in naxalnet.service 2021-08-16 21:29:27 +05:30
Pranav Jerry d18160c46c
disabled buffering in python
Buffering makes the systemd journal not show the logs at the right time.
And changed the systemd service file so that the new batman and bridge
interfaces are deleted when naxalnet.service is stopped. Also simplified
the Stopping section in the README because of this change.
2021-08-16 18:56:17 +05:30
Pranav Jerry 397269823d
almost ready for merge
* Improved CHANGELOG, README, HACKING
* Added naxalnet.conf containing default values. This will be installed
along with the package.
2021-08-15 15:02:28 +05:30
Pranav Jerry d7a9edc1e8
many changes -- read full commit
* Improved docstrings, README
* Added argument --version and its implementation
* Added "uninstall" rule to Makefile and added it in the README
* Updated CHANGELOG
* Cleaned up code

I've probably forgot something so we can't merge to master yet.
And we still have to add installation instructions for ubuntu and fedora
2021-08-14 22:00:07 +05:30
Pranav Jerry fe146b7a0d
added implementation of --print-wifi
And added it to the README.
Cleaned up the docstring in naxalnet/__main__.py
2021-08-13 12:30:30 +05:30
Pranav Jerry b50d0e3656
made README and HACKING.md more readable 2021-08-13 11:32:42 +05:30
Pranav Jerry 550529e3d0
updated CHANGELOG
I forgot to update it in the previous commit
2021-08-13 10:48:58 +05:30
Pranav Jerry dfd521f9b9
added new args and support for conf files
Tidied up code, added more documentation, and the version now confirms
to some PEP standard. Because of the way configuration and arguments are
implemented, ALL the keys in configuration files should have an argument
that can change its value.

Verbose option was commented out, since it is not implemented. An
argument --print-wifi, which should print out WiFi ssid and password is
not implemented at the moment. Also, the README should be updated to
show the new changes. By the way I just remembered I didn't update the
CHANGELOG; I'll do it in the next commit. 😁
2021-08-13 10:35:13 +05:30
Pranav Jerry 90464f0304
made how it works section more legible in README.md 2021-08-10 13:20:27 +05:30
Pranav Jerry e24ff03e0c
Updated how it works section in README.md 2021-08-09 21:46:10 +05:30
Pranav Jerry 2f97bab5cf
changed README.md
Changed the section on internet shutdowns.
Let's see if anyone actually reads the README in source form.
2021-08-09 20:06:57 +05:30
Pranav Jerry a798ac8051
improved README.md
And added a new argument (not implemented) in scripts.py
2021-08-09 12:54:41 +05:30
Pranav Jerry fb4b11b9fd
added link to internetshutdowns.in in README.md 2021-08-08 22:20:05 +05:30
Pranav Jerry ebc7e39d76
added CHANGELOG.md
Contributors should update this file everytime they create a commit
2021-08-05 14:45:24 +05:30
Pranav Jerry 2e4149d943
moved device setup into a single function
By the way, --verbose is not implemented yet. We will need to wait until
systemd journal or some other form of logging is implemented.
2021-08-05 12:11:31 +05:30
Pranav Jerry df73f94018
Added alt text to some links in README.md
And removed a sentence in manual installation section
2021-08-02 18:26:14 +05:30
Pranav Jerry 3d63ddd2d2
Fixed typo in README.md
Forgot a space after comma
2021-08-02 18:13:32 +05:30
Pranav Jerry 5db3d1dc09
added new section in HACKING.md 2021-08-02 16:05:24 +05:30
Pranav Jerry f55fc74ad4
added PYTHON variable in Makefile
This should be used if the python executable is not python3 in your
distro.

I would like to express my displeasure to the Government of India for
not including me in the list of targets for Pegasus, even though I'm
convinced I am a threat to the sovereignty and integrity of the nation
2021-08-01 16:58:48 +05:30
Pranav Jerry 16dff8bb49
added support for arguments
Try naxalnet --help to see help
2021-07-30 17:56:33 +05:30
Pranav Jerry 946d20a72c
Fixed typo and improved README (again) 2021-07-29 22:44:01 +05:30
Pranav Jerry 7b7ce8044b
improved README
Let's see if anyone reads the comments :)
Changed python to python3 in Makefile
2021-07-29 22:36:53 +05:30
Pranav Jerry f6a5a8556b
fixed version number in __init__.py 2021-07-26 16:47:36 +05:30
Pranav Jerry 5068250ad6
added link to HACKING.md in README.md 2021-07-26 16:08:36 +05:30
Pranav Jerry 19137faab3
reduced 5s delay in the systemd service to 2s 2021-07-26 15:58:50 +05:30
Pranav Jerry b3710633cc
Merge branch 'fix-rfkill'
Added rfkill support, among other things.
See pull request #10 for more info.
2021-07-26 15:47:38 +05:30
Pranav Jerry 86042b9852
uncommented IPNS address 2021-07-26 12:48:45 +05:30
Pranav Jerry 1500f486ef
added clean in Makefile 2021-07-26 12:44:24 +05:30
Pranav Jerry 9c6081ea87
added rfkill support
Updated HACKING.md and added license disclaimer to all python files.
And tidied up scripts.py
2021-07-25 14:06:17 +05:30
Pranav Jerry c8e98b2c4f
Merge branch 'python-module'
The pypackage version is ready for use by non-nerds
2021-07-23 21:43:00 +05:30
Pranav Jerry adb8c62407
Removed alpha stage disclaimer
naxalnet doesn't seem to fit into the alpha stage anymore, although it
is probably unstable according to debian standards
2021-07-23 21:39:46 +05:30
Pranav Jerry e0d2602552
Updated README.md
Removed IPFS git link and updated .gitignore
And fixed a tiny mistake in uninstalling section in README.md
2021-07-23 21:35:11 +05:30
Pranav Jerry c2fba89816
Made python package!
Finally, the python package is ready to use!
2021-07-21 15:36:11 +05:30
Pranav Jerry b2f30bad62
added AP support in naxalnet.py and iwd.py 2021-07-21 14:36:23 +05:30
Pranav Jerry af5fc0e285
Added ipns git clone url
Probably wont work properly
2021-07-19 19:02:25 +05:30
Pranav Jerry f0689016ce
ad-hoc part done
Check out naxalnet/naxalnet.py
2021-07-19 14:11:43 +05:30
Pranav Jerry b9592696f2
Fixed another typo in HACKING.md 2021-07-18 20:05:39 +05:30
Pranav Jerry 809c09afe0
Added class Adapter in iwd.py
Initial implementation. No useful public methods yet
2021-07-18 14:24:27 +05:30
Pranav Jerry 3c22fa63f4
Fixed typo in HACKING.md 2021-07-18 14:11:36 +05:30
Pranav Jerry 91be0b0189
Added main.py
This file at the moment contains debugging code.
Changed HACKING.md
2021-07-18 14:07:16 +05:30
Pranav Jerry b1d970a0f6
fixed bug in iwd.py
And fixed a typo in README.md
2021-07-17 13:34:06 +05:30
Pranav Jerry 7b7c3f0b2e
added license to iwd.py 2021-07-12 20:20:50 +05:30
Pranav Jerry 8bf05ba334
added new functions 2021-07-12 20:17:33 +05:30
Pranav Jerry 0e7a69be53
Updated HACKING.md and naxalnet/iwd.py
Added Device.reload() to reload the proxy every time the device mode is
changed. Added Device.set_mode() and partial implementation of
Device.start_adhoc_open().

Added link to meaning of hack in HACKING.md
2021-07-07 14:08:05 +05:30
Pranav Jerry d4e6b929d2
added HACKING.md 2021-07-02 09:30:28 +05:30
Pranav Jerry e4fd0ff04d
basic implementaion of class Device and IWD
When work is finished, we can use them to start adhoc or ap
2021-07-01 12:18:44 +05:30
Pranav Jerry f4a490210d added prototype functions in naxalnet/iwd.py
They won't work yet but when they do we can use the classes in iwd.py
instead of using dasbus directly. Also added a Name to Match in
systemd-networkd/06-eth.network
2021-06-30 21:50:39 +05:30
Pranav Jerry ba2425f008
initial implementation of iwd api
iwd.py is used to communicate with iwd via d-bus
2021-06-27 14:25:36 +05:30
Pranav Jerry 8bdeddf08e
Renamed naxalnet into naxalnet/naxalnet.py 2021-06-27 13:59:42 +05:30
Pranav Jerry d57c92588f
Added AUR package
Now there are two AUR packages - naxalnet and naxalnet-git
2021-06-24 17:04:31 +05:30
Pranav Jerry 47f2324604
Improved README.md
Added how to stop the systemd service and improved the similar projects section.
2021-06-23 13:48:05 +05:30
Pranav Jerry af98a57b0e
Updated README.md
Added shell code to clone git repo. Not everyone knows how to clone a
repo and cd into it 😁
2021-06-19 15:53:16 +05:30
31 changed files with 1970 additions and 305 deletions

145
.gitignore vendored Normal file
View File

@ -0,0 +1,145 @@
# 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]
*$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

77
CHANGELOG.md Normal file
View File

@ -0,0 +1,77 @@
# Changelog
## [v0.5.3][] - 2022-08-03
- Renamed to pybatmesh, to be more clear what the program does
- code cleanup
To update via the repo, do the following:
```sh
git remote set-url origin git@git.disroot.org:pranav/pybatmesh.git
# or
git remote set-url origin https://git.disroot.org/pranav/pybatmesh.git
# remove naxlnet and install pybatmesh
git pull && git checkout 38d0aa8ab5dd60f2febffda335df6df1ea143ab3 && make clean && sudo make purge && git checkout main && make && sudo make install
```
## [v0.5.2][] - 2021-12-10
- Optimised auto gateway mode selection (#25)
## [v0.5.1][] - 2021-10-22
- Fixed stopping at boot when GNOME starts location service (#21)
- Changes in directory structure
## [v0.5.0][] - 2021-10-10
- Better error messages
- Sets gateway mode automatically (to choose the best available
connection). **This might cause problems with nodes running previous
version of naxalnet** (#15)
- Cleanup before exit
- Closed #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 (#14)
- **Logging**: logs to systemd journal when run from systemd, stderr
otherwise (#13)
- New dependency `python-systemd`
- Fixed dependency order in systemd service
- Added `--verbose` argument
## [v0.3.0][] - 2021-08-19
- Support for arguments (#11)
- Configuration file support with fallback values (#11)
- Made messages more readable
- Improved documentation in docstrings
- Changed default name of mesh network. **This will make naxalnet
incompatible with nodes running previous versions.**
- New versioning scheme that conforms to PEP 440
## [v0.2.0][] - 2021-07-26
- rfkill support (#9)
- rewrite into python module (#5)
## [v0.1.0][] - 2021-06-19
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.
- Closed #1 and #3
[unreleased]: https://git.disroot.org/pranav/pybatmesh/compare/v0.5.3...HEAD
[v0.5.3]: https://git.disroot.org/pranav/pybatmesh/compare/v0.5.2...v0.5.3
[v0.5.2]: https://git.disroot.org/pranav/pybatmesh/compare/v0.5.1...v0.5.2
[v0.5.1]: https://git.disroot.org/pranav/pybatmesh/compare/v0.5.0...v0.5.1
[v0.5.0]: https://git.disroot.org/pranav/pybatmesh/compare/v0.4.0...v0.5.0
[v0.4.0]: https://git.disroot.org/pranav/pybatmesh/compare/v0.3.0...v0.4.0
[v0.3.0]: https://git.disroot.org/pranav/pybatmesh/compare/v0.2.0...v0.3.0
[v0.2.0]: https://git.disroot.org/pranav/pybatmesh/compare/v0.1.0...v0.2.0
[v0.1.0]: https://git.disroot.org/pranav/pybatmesh/releases/tag/v0.1.0

33
HACKING.md Normal file
View File

@ -0,0 +1,33 @@
# Hacking
Everyone can [hack][] pybatmesh. 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/pybatmesh/issues>
While reporting a bug, you can add the debug messages to provide more
data. Run `journalctl -fu pybatmesh` on a terminal emulator (this could
take some time on some machines). Now on another one, type `sudo systemctl start pybatmesh.service` or whatever caused the error. Now copy the error
messages and paste it in the issue body along with the description.
## Improving documentation
The README and HACKING.md needs to be more beginner friendly. See #20.
## Contribute code
To push to this repo, you need your username to be in the contributors
list. Add your username to issue #8 to add you as a contributor. Before
each commit, update the CHANGELOG.md and `__version__` in
`pybatmesh/__init__.py`
## Packaging
Currently this program is only packaged for Arch Linux. pybatmesh 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 a
message to issue #6.
[hack]: https://catb.org/jargon/html/H/hack.html

View File

@ -1,16 +1,37 @@
PREFIX := /usr
# 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.
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
PYTHON := python3
PIP := pip3
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
# This can be changed when creating a package for your POSIX distribution
DESTDIR:= /
all: build
# Build only when pybatmesh/__init__.py changes. We assume here that anyone
# creating a new commit will first update the __version__ in
# pybatmesh/__init__.py
build: pybatmesh/__init__.py
$(PYTHON) setup.py build
install:
$(PYTHON) setup.py install --root="$(DESTDIR)" --optimize=1 --skip-build
uninstall:
$(PIP) uninstall -y pybatmesh
rm -rf /usr/share/pybatmesh /usr/lib/systemd/system/pybatmesh.service
@echo "make uninstall will not remove anything in /etc/pybatmesh" && \
echo "Do 'sudo make purge' to remove it."
rpm:
$(PYTHON) setup.py bdist_rpm --requires python3-dasbus,python3-systemd,iwd,systemd-networkd
# 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/pybatmesh
clean:
rm -rf build *.egg-info **/__pycache__ dist

375
README.md
View File

@ -1,168 +1,343 @@
# naxalnet
# pybatmesh
**naxalnet** is an experiment to create a wireless mesh network for
communicating with each other during an internet shutdown, using
existing software and tech as much as possible. Currently
you can only communicate with other peers running naxalnet or
using the same network as naxalnet. 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.
**pybatmesh** 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)
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,
West Bengal.
**WARNING**: This program uses an **unencrypted** network. This means you do
not get any more privacy or security than with an open WiFi network.
<!-- UNCOMMENT WHEN NECESSARY
## Features
**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.
Using the name Naxal does not imply any form of connection
with anyone the government of India collectively calles Urban
Naxals (human rights activists, lawyers, poets, writers, journalists
or anyone else advocating for their rights).
-->
- Select best network when multiple nodes have internet access (gateway
mode)
- Detect insertion and removal of wifi adapters and reconfigure them
- Readable logs
- Supports rfkill
## Requirements
- systemd{,-networkd} v248 or more (for [batman support][batman-systemd])
- Linux kernel with batman-adv module (if `modinfo batman-adv` shows
no error then you already have it)
- iwd (for starting ad-hoc network)
- python3
- [python-dasbus][]
- wifi adapter with ad-hoc support
- two or more computers with wifi adapter, called nodes
- systemd-resolved (optional, for DNS)
- [systemd-networkd v248 or greater][batman-systemd]
- Linux kernel with [batman-adv v2021.0][batman-systemd] or greater
- [iwd][] for controlling the WiFi adapter
- python (tested on 3.9 and 3.10)
- python setuptools, for building and installing pybatmesh
- [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)
- python3-pip (for installing dasbus on Debian-based distributions)
## Installing
This program is available in the AUR for Arch users. Users of other
distributions will have to build manually.
### Arch Linux
Install [naxalnet-git][] from the AUR with your favourite helper:
Install [pybatmesh][aur] (or [pybatmesh-git][aur-devel] for the
development version) from the AUR with your favourite helper:
```sh
yay -S naxalnet-git
yay -S pybatmesh
```
Optionally, [setup systemd-resolved][arch-resolved] for DNS if any
of the nodes have internet access.
Optionally, [setup systemd-resolved][arch-resolved] for DNS. [Start
pybatmesh][startnx] when you need it.
### Debian or Ubuntu
pybatmesh is not packaged for Debian or Ubuntu, so you will have to build
and install it manually. Currently, only Debian bookworm (testing) and
Ubuntu 21.10 comes with the required version of systemd. Therefore,
pybatmesh requires **Debian testing** or **Ubuntu 21.10 or greater** to
work.
Install the requirements from the repositories:
```sh
# batctl is optional
sudo apt install python3-pip python3-systemd python3-dasbus iwd batctl
```
Now follow the instructions in the
[manual installation section][install-manual]
### Fedora
pybatmesh is not packaged for Fedora, so it should be installed manually.
pybatmesh requires at least systemd v248, which is only available on
**Fedora 34 and above**. python-setuptools support building rpms, which
are the preferred way of installing software in Fedora. Follow the steps
to install pybatmesh on Fedora:
```sh
# Install the build requirements
sudo dnf install python3-setuptools make git
# Clone the repo
git clone https://git.disroot.org/pranav/pybatmesh.git
cd pybatmesh
# Create an installable rpm from the source code
make rpm
# Now install it. This will also install the requirements
sudo dnf install dist/pybatmesh-$(python3 -m setup --version)-1.noarch.rpm
```
### Manually
Clone the repo and cd into it.
Verify that the [requirements][] are of required versions.
Run `sudo make install` to install naxalnet. This will install naxalnet in
`/usr/bin/naxalnet`.
```sh
# Should be greater than or equal to 2021.0
batctl -v
After installing, reload systemd so that you can enable `naxalnet.service`
without rebooting:
# 248 or greater
systemctl --version
# Atleast 4.4
uname -r
# >= 3.6
python3 --version
# Check for IBSS (ad-hoc) support in your WiFi firmware or driver
iw phy | grep -q join_ibss && echo "IBSS is supported" || echo "IBSS not supported"
```
Clone the pybatmesh repo and cd into it.
```sh
git clone https://git.disroot.org/pranav/pybatmesh.git
cd pybatmesh
```
Now, build and install pybatmesh:
```sh
make
sudo make install
```
After installing, reload systemd so that it detects the new
service files:
```sh
sudo systemctl daemon-reload
```
## How to use
You need more than one computer running for the connection to work.
### Communicate between peers
Connect a wifi adapter to all the computers you intend to run
naxalnet.
Start the naxalnet service on all of them:
To upgrade, clean the build files, update the repo and reinstall:
```sh
sudo systemctl start naxalnet.service
make clean
git pull
make
sudo make uninstall
sudo make install
```
To test if it works, run `ip addr` to find out your address.
Note the `inet` or `inet6` address of `bridge0`. Ping the address
from another computer (example: `ping 169.254.62.90`) to find out
if it is online. Press Ctrl-C to stop.
This will keep the configuration files.
## How to use
You need more than one machine running pybatmesh for the connection to work.
### Start pybatmesh
Though pybatmesh can run from the command line, it was designed to be
run as a systemd service.
To start pybatmesh, do the command on all the nodes:
```sh
sudo systemctl start pybatmesh.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. Press Ctrl+C to stop `batctl`.
### Getting internet access
Connect an ethernet to any of the peers and start naxalnet.
Now all the peers should be able to connect after renewing
their DHCP connection (`sudo networkctl renew bridge0`).
Connect an ethernet cable from a router to any of the nodes. Now restart
pybatmesh on the node to set `gateway_mode` to `server`. Other nodes will
take a minute or more to renew DHCP. You can optionally do this manually
if you don't want the delay. To do this, type
`sudo networkctl renew bridge0` on all nodes.
### Tethering via WiFi AP
Connect two wifi adapters on a device and start naxalnet.
Now an ap will be created on one of the devices with
SSID `NaxalNet` and password `naxalnet256`.
If you had set up internet access on one of the peers, internet
If there are two adapters in a peer, pybatmesh will start a
WiFi ap (also called WiFi hotspot) on one of them.
Connect two WiFi adapters on a node.
Now an AP will be started on one of the adapters.
Type `pybatmesh --print-wifi` to get the WiFi SSID and password.
If you had set up internet access on one of the nodes, internet
can be accessed from the AP.
### Running at boot
Starting the service will stop `NetworkManager.service` and
`wpa_supplicant.service` if it is running. If you start either of these
services after naxalnet is started, systemd will stop naxalnet.
To run naxalnet at boot, enable the service:
To run pybatmesh at boot, enable the service on all the nodes:
```sh
sudo systemctl enable naxalnet.service
sudo systemctl enable pybatmesh.service
```
Now naxalnet will configure a batman interface on every boot.
Disable the service to stop running at boot:
Now pybatmesh will start a mesh on every boot.
If you have NetworkManager enabled, which is the default in Ubuntu and
Fedora, it should be disabled:
```sh
sudo systemctl disable naxalnet.service
sudo systemctl disable NetworkManager.service
```
To stop running at boot, you should disable `pybatmesh.service`:
```sh
sudo systemctl disable pybatmesh.service
```
If you had disabled `NetworkManager` before, enable it:
```sh
sudo systemctl enable NetworkManager.service
```
### Stopping the service
```sh
sudo systemctl stop pybatmesh iwd systemd-networkd systemd-resolved
```
If your distribution uses NetworkManager, starting `pybatmesh.service`
will have stopped it. Start NetworkManager again:
```sh
sudo systemctl start NetworkManager.service
```
### Configuration
pybatmesh comes with a sample configuration file
`/etc/pybatmesh/pybatmesh.conf.example`. To change how the program
behaves, copy it to /etc/pybatmesh/pybatmesh.conf and edit it:
```sh
sudo cp /etc/pybatmesh/pybatmesh.conf{.example,}
# Now edit the file with your favourite editor as root
gedit admin:/etc/pybatmesh/pybatmesh.conf
```
Also, you can change its behaviour every time you run it using
arguments:
```sh
pybatmesh --help
```
## Contributing or reporting bugs
See [HACKING.md](HACKING.md)
## How it works
The program naxalnet copies predefined systemd-networkd configuration
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
services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb]
and others which can work without internet access.
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.
pybatmesh uses two modes - `ad-hoc` and `ap`, for connecting to the
mesh. pybatmesh uses iwd to start an `ad-hoc` network and configures
systemd-networkd to setup a BATMAN Advanced network.
If there are two WiFi adapters connected to the machine,
pybatmesh 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 and the documentation in the code to learn the details.
See the directory [network](network) to see how
systemd-networkd configures the network.
## Use cases
### Online class
pybatmesh can be used to share connections to join online classes. You need
at least one device with internet access if you are not using a program
like [Jami][] (see below).
### Internet shutdown
You can communicate with neighbouring devices running pybatmesh, using
services like [IPFS][], [Jami][], [Briar][] [Secure Scuttlebutt][ssb] or
similar software 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 pybatmesh][enable-pybatmesh] and use the
installed software to communicate with anyone within range.
## Uninstalling
Currently there is now way to uninstall naxalnet than manually removing
the files:
If you installed pybatmesh manually, use make uninstall to remove
pybatmesh and its data files. This requires python pip to be installed.
```sh
sudo rm -rf /usr/{bin,share}/naxalnet \
/usr/lib/systemd/system/naxalnet.service
# Uninstall the program, keeping the config files
sudo make uninstall
# Or, to uninstall and remove config files
sudo make purge
```
## Similar projects
- [LibreMesh][libremesh]: framework for OpenWrt-based
firmwares
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 pybatmesh 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 pybatmesh, 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 pybatmesh.
- [LibreMesh][]: framework for OpenWrt-based firmwares
- [disaster.radio][]: solar-powered communications network
## License
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.
pybatmesh is [free/libre/swatantra][free-sw] and open source 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,
eitherversion 3 of the License, or (at your option) any later version.
See [LICENSE](LICENSE) for the complete version of the
license.
This project is in alpha stage. Documentation is incomplete.
See [LICENSE](LICENSE) for the complete version of the license.
[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
[arch-resolved]: https://wiki.archlinux.org/title/Systemd-resolved#DNS
[batman-systemd]: https://www.open-mesh.org/news/101
[internet shutdown]: https://internetshutdowns.in
[ipfs]: https://ipfs.io "InterPlanetary File System"
[jami]: https://jami.net "Peer to peer video calls"
[ssb]: https://scuttlebutt.nz "Secure Scuttlebutt"
[briar]: https://briarproject.org/
[dasbus]: https://github.com/rhinstaller/dasbus "A python D-Bus library"
[aur]: https://aur.archlinux.org/packages/pybatmesh
[aur-devel]: https://aur.archlinux.org/packages/pybatmesh-git
[arch-resolved]: https://wiki.archlinux.org/title/Systemd-resolved#DNS "systemd-resolved on ArchWiki"
[batman-systemd]: https://www.open-mesh.org/news/101 "systemd v248 brings support for batman advanced"
[libremesh]: https://libremesh.org
[disaster.radio]: https://disaster.radio/
[disaster.radio]: https://disaster.radio
[startnx]: #start-pybatmesh
[iwd]: https://iwd.wiki.kernel.org "WiFi daemon"
[free-sw]: https://gnu.org/philosophy/free-sw.html "What is free software?"
[enable-pybatmesh]: #running-at-boot
[requirements]: #requirements
[install-manual]: #manually
[python-systemd]: https://github.com/systemd/python-systemd

134
naxalnet
View File

@ -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")

View File

@ -1,27 +0,0 @@
[Unit]
Description=Naxalnet
Requires=systemd-networkd.service
Requires=iwd.service
Wants=systemd-resolved.service
Before=systemd-networkd.service
After=iwd.service
# Stops NetworkManager and wpa_supplicant if already running
Conflicts=NetworkManager.service
Conflicts=wpa_supplicant.service
After=NetworkManager.service
After=wpa_supplicant.service
[Service]
Type=oneshot
RemainAfterExit=yes
Restart=on-failure
RestartSec=5sec
# IWD takes some time to find devices.
# Without the sleep 5, naxalnet could not detect the second
# device while testing.
ExecStartPre=/usr/bin/sleep 5
ExecStart=/usr/bin/naxalnet
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,13 @@
# Create the BATMAN interface
# See mesh.04-batman.network for configuration details
[NetDev]
Name={batdev}
Description=BATMAN interface
Kind=batadv
# See man:systemd.netdev(5) § [BATMANADVANCED] SECTION OPTIONS
[BatmanAdvanced]
# This helps choose the best network when many nodes have a DHCP
# server. See the B.A.T.M.A.N. documentation at
# https://www.open-mesh.org/projects/batman-adv/wiki/Gateways
GatewayMode={gateway_mode}

View File

@ -1,8 +1,8 @@
# Create a bridge interface
# The batman interface be will later linked to this bridge.
# See 07-bridge.network to see how this bridge is configured
# See mesh.07-bridge.network to see how this bridge is configured
[NetDev]
Name=bridge0
Name={bridgedev}
Description=Bridge
Kind=bridge

View File

@ -10,7 +10,7 @@ MTUBytes=1560
[Network]
Description=ad-hoc network connecting to other nodes
BatmanAdvanced=bat0
BatmanAdvanced={batdev}
# This interface should not have any IP addresses assigned.
# IP will be given later to the bridge
DHCP=no

View File

@ -1,11 +1,11 @@
[Match]
Name=bat0
Name={batdev}
[Network]
Description=The BATMAN interface
Bridge=bridge0
Description=Configuration for the BATMAN interface
Bridge={bridgedev}
# like in 03-wireless-ad-hoc.network, this interface
# like in mesh.03-wireless-ad-hoc.network, this interface
# also shouldn't have IP address the address will
# be assigned to the bridge
DHCP=no

View File

@ -1,15 +1,17 @@
# 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 pybatmesh.service
# This file won't do anything if an ap interface is not found.
[Match]
WLANInterfaceType=ap
[Network]
Description=Wireless AP
Description=Configuration for Wireless AP
# link the interface to the bridge
Bridge=bridge0
Bridge={bridgedev}
# Like in the ad-hoc network and bat0, this interface
# should not have any ip address assigned to it.

View File

@ -0,0 +1,9 @@
# This file bridges any ethernet device found
# to the bridge made in mesh.02-bridge.netdev
[Match]
Name=en*
Name=eth*
[Network]
Description=Connect ethernet to the bridge
Bridge={bridgedev}

View File

@ -3,13 +3,15 @@
# communicate with others devices
[Match]
Name=bridge0
Name={bridgedev}
[Network]
# use DHCP to assign an IP
Description=bridge to link non-batman machines
# Use DHCP to assign an IP
DHCP=yes
# if DHCP fails, assign a random address
# If DHCP fails, assign a random address. This is probably the default,
# but we are specifying it anyway.
LinkLocalAddressing=yes
# LLMNR and MulticastDNS are used for hostname discovery

View File

@ -0,0 +1,10 @@
# This is used to check if any ethernet or USB ethernet ports
# is connected to a router or some other device with a DHCP server.
# After checking, this file is no longer needed.
[Match]
Name=eth*
Name=en*
[Network]
Description=Check for ethernet connection
DHCP=yes

35
pybatmesh.conf.example Normal file
View File

@ -0,0 +1,35 @@
# This configuration file is part of pybatmesh.
# To configure this program, rename this file
# to pybatmesh.conf and edit it.
# The values given here are defaults.
[networkd]
# systemd-networkd configuration files bundled with pybatmesh.
# THese will be copied to runtimedir at runtime.
confdir = /usr/share/pybatmesh/networkd
# systemd-networkd runtime configuration directory.
# See man:systemd.network(5)
runtimedir = /run/systemd/network
[device]
# These are better left this way
# Changing this won't do you any good, unless you have
# other network configs that would mess things up.
batman=bat0
bridge=bridge0
[gateway]
# This helps users choose the best network when multiple machines
# offer an internet connection, or to be more precise, a DHCP server
# Allowed values: auto, server, client or off
mode=auto
[adhoc]
# All your nodes should have the same name
name = pybatmesh
[ap]
# An AP is started if your machine has more than one WiFi adapter.
ssid = BatWiFi
# Note the spelling. It's passwd, not password.
passwd = pybatmesh256

30
pybatmesh.service Normal file
View File

@ -0,0 +1,30 @@
# The pybatmesh systemd service
# See man:systemd.service(5) and man:systemd.unit(5)
# before editing this file.
[Unit]
Description=Setup mesh networks
Requires=systemd-networkd.service
Requires=iwd.service
Wants=systemd-resolved.service
After=iwd.service
After=systemd-networkd.service
After=systemd-resolved.service
# Stops NetworkManager if already running
Conflicts=NetworkManager.service
# This stops NetworkManager when pybatmesh is enabled
After=NetworkManager.service
[Service]
Type=notify
NotifyAccess=all
Restart=on-failure
RestartSec=2sec
ExecStart=pybatmesh --systemd
KillSignal=SIGINT
# pybatmesh already logs to systemd journal so we don't need
# stdout and stderr.
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target

45
pybatmesh/__init__.py Normal file
View File

@ -0,0 +1,45 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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/>.
"""
pybatmesh
========
Create mesh networks with batman-adv, systemd-networkd and iwd.
See README.md and the docstrings for documentation. You can read
documentaion in the python interpretor using something like the example
given below.
>>> help("pybatmesh")
>>> help("pybatmesh.config")
"""
# GUIDE FOR CHANGING __version__
#
# All commits in master should have the version as
# {last published version tag}.a{1,2,3,...}
# example: 0.2.0a3 should mean 3 commits after tag v0.2.0
#
# All commits in other branches should
# have {version in master}.dev{1,2,...}
# example: 0.2.0a3.dev1 should mean 1 commit in the new
# branch after the commit in master.
#
# In case you forgot to change the version, skip the number
# and put the next number in the next commit.
__version__ = "0.5.3"

30
pybatmesh/__main__.py Normal file
View File

@ -0,0 +1,30 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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/>.
"""
__main__.py
-----------
If called as python -m pybatmesh, this file makes pybatmesh run like
it was called from the commandline. Try:
python -m pybatmesh --help
"""
from pybatmesh.scripts import main
if __name__ == "__main__":
main()

194
pybatmesh/config.py Normal file
View File

@ -0,0 +1,194 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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
---------
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 pybatmesh 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/pybatmesh/pybatmesh.conf and then from
/usr/share/pybatmesh/pybatmesh.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/pybatmesh
- Then, it looks for the files pybatmesh.conf and pybatmesh.conf.d/*.conf
from the directory /etc/pybatmesh, 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
from configparser import ConfigParser
from argparse import ArgumentParser, Namespace
from pybatmesh.default import CONFIG, CONFIG_FILES, CONFIG_DIRS
def get_config_files():
"""
Read list of configuration files and return a list
of files that exists as pathlib.Path objects
"""
config_files = []
for directory in CONFIG_DIRS:
path = Path(directory)
if path.exists():
for i in CONFIG_FILES:
glob = path.glob(i)
config_files.extend(glob)
return config_files
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
def parse_args() -> Namespace:
"""
Parse all arguments and return ArgumentParser.parse_args(),
with values in config files as fallback. Ideally, only this
function should be used by pybatmesh to get arguments and
configuration.
"""
config = parse_config()
parser = ArgumentParser(
description="setup batman-adv networks with systemd and iwd"
)
parser.add_argument(
"--ap-ssid",
"-n",
type=str,
help="SSID of the WiFi AP",
default=config["ap"]["ssid"],
)
parser.add_argument(
"--ap-passwd",
"-p",
"--ap-password",
type=str,
help="password of the WiFi AP",
default=config["ap"]["passwd"],
)
parser.add_argument(
"--adhoc-name",
"-a",
type=str,
default=config["adhoc"]["name"],
help="name of adhoc network",
)
parser.add_argument(
"--print-wifi",
action="store_true",
default=False,
help="prints the ssid and password of the WiFi network and exit",
)
parser.add_argument(
"--networkd-config-dir",
type=str,
default=config["networkd"]["confdir"],
help="the directory where systemd-networkd configuration files are stored",
)
parser.add_argument(
"--networkd-runtime-dir",
type=str,
default=config["networkd"]["runtimedir"],
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(
"--batman-device",
default=config["device"]["batman"],
help="name of interface used by batman-adv",
)
parser.add_argument(
"--bridge-device",
default=config["device"]["bridge"],
help="name of bridge interface",
)
parser.add_argument(
"--gateway-mode",
default=config["gateway"]["mode"],
help="auto, server, client, or off",
)
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"
)
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()

71
pybatmesh/daemon.py Normal file
View File

@ -0,0 +1,71 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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 used to perform some work when a new wifi adapter
is plugged in, or it is removed.
"""
from dasbus.loop import EventLoop
from pybatmesh.iwd import IWD, IWD_DEVICE_INTERFACE
from pybatmesh.log import logger
class Daemon:
"""implements the daemon part"""
def __init__(self):
self.loop = EventLoop()
self.iwd = IWD()
self.callback = None
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", 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()

50
pybatmesh/default.py Normal file
View File

@ -0,0 +1,50 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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
----------
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 pybatmesh is called from the commandline.
See config.py for more info.
"""
CONFIG = {
"networkd": {
"confdir": "/usr/share/pybatmesh/networkd",
"runtimedir": "/run/systemd/network",
},
"device": {"batman": "bat0", "bridge": "bridge0"},
"adhoc": {"name": "pybatmesh"},
"ap": {"ssid": "BatWiFi", "passwd": "pybatmesh256"},
"gateway": {"mode": "auto"},
}
# glob
CONFIG_FILES = ["pybatmesh.conf", "pybatmesh.conf.d/*.conf"]
CONFIG_DIRS = ["/usr/share/pybatmesh", "/usr/local/share/pybatmesh", "/etc/pybatmesh"]
MESH_GLOB = "mesh.*"
TMP_NET_GLOB = "tmp.*"
ISSUE_URL = "https://git.disroot.org/pranav/pybatmesh/issues"
REPORT_BUG_INFO = "If you think this is a bug, report it to " + ISSUE_URL
# Changing this constant will alter not just the behaviour of pybatmesh,
# but affect the meaning of Life, the Universe and Everthing
ANSWER = 42

325
pybatmesh/iwd.py Normal file
View File

@ -0,0 +1,325 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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/>.
"""
iwd.py
------
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:
- 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 pybatmesh 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. pybatmesh 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.
- 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.
- node: a machine that runs pybatmesh and is therefore connected to the
mesh.
"""
from dasbus.connection import SystemMessageBus
from pybatmesh.log import logger
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 submodule
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:
# 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"""
adapter_paths = self.get_all_adapter_paths()
for i in adapter_paths:
proxy = self._bus.get_proxy(IWD_BUS, i)
if proxy.Name == name:
# 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"""
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 all 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):
self._iwd = IWD()
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
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):
"""
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
# name of adapter ('phy0' for example)
self.adapter = self._iwd.get_name_from_path(adapter_path)
def is_adhoc_started(self) -> bool:
"""
Returns True if an adhoc network is started on this device.
Returns False if the network is in staring stage, 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 False
return False
def is_ap_started(self) -> bool:
"""
Same as is_adhoc_started(), but for ap
"""
if self.is_powered_on() and self.get_mode() == "ap":
return self._proxy.Started
return False
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
logger.debug("Set mode on %s to %s", self.name, 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
"""
# 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()
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()
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
"""
# 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()
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()
class Adapter:
"""represents an adapter as a python object"""
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
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
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
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:
"""
Returns True if the adapter supports the mode.
mode can be "ad-hoc", "ap" or "station"
"""
return mode in self.supported_modes

55
pybatmesh/log.py Normal file
View File

@ -0,0 +1,55 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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 other than pybatmesh.config, which is needed to set the
loglevel and to add the systemd journal handler
"""
import logging
from systemd.journal import JournalHandler
from pybatmesh.config import args
def get_logger():
"""
Initialise the logger and return it.
This function is meant to be used only by pybatmesh.log.
If you want to import the logger, use:
from pybatmesh.log import logger
"""
log = logging.getLogger("pybatmesh")
# --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()

187
pybatmesh/network.py Normal file
View File

@ -0,0 +1,187 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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/>.
"""
network.py
----------
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
from dasbus.loop import EventLoop, GLib
NETWORKD_BUS = "org.freedesktop.network1"
NETWORKD_PATH = "/org/freedesktop/network1"
class NetworkD:
"""
Control systemd-networkd using configuration files. Since these
were made for use by pybatmesh only, the class is not suitable for
importing outside pybatmesh.
"""
def __init__(self, runtime_dir="/run/systemd/network", bus=SystemMessageBus()):
print("NetworkD init")
self._bus = bus
self.proxy_reload()
self.variables = {}
self.runtime_path = Path(runtime_dir)
# Create the runtime directory if it doesn't exist
self.runtime_path.mkdir(parents=True, exist_ok=True)
def set_vars(self, **variables):
"""set the variables to replace with str.format"""
self.variables = variables
def proxy_reload(self) -> None:
"""reload the proxy"""
self.proxy = self._bus.get_proxy(NETWORKD_BUS, NETWORKD_PATH)
def reload(self) -> None:
"""
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:
"""add config file to runtime directory and reload networkd"""
source = Path(name)
destination = self.runtime_path / source.name
# Substitute variables in the config
text = source.read_text(encoding="utf-8").format(**self.variables)
# now write it to a runtime config of the same name
destination.write_text(text, encoding="utf-8")
self.reload()
def is_routable(self) -> bool:
"""returns true if any interface is routable"""
return self.proxy.AddressState == "routable"
def delete_interface(self, name: str) -> None:
"""delete the given interface"""
# If anyone knows a better way of doing this, create
# an issue and get things done
subprocess.run(["networkctl", "delete", name], check=True)
# This is probably not required. This is mainly to shut up
# pylint's messages
self.reload()
def disable_config(self, name: str) -> None:
"""
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()
def remove_config(self, name: str) -> None:
"""
remove the file called 'name' from the runtime dir and reload
"""
path = self.runtime_path / name
path.unlink()
self.reload()
def remove_all_configs(self) -> None:
"""
Remove all configs in runtime_path. This will remove all files
in runtime_path without checking who put them there.
"""
for i in self.runtime_path.iterdir():
self.remove_config(i.name)
class NetworkLoop(NetworkD):
"""Used to wait until a condition is met
Available methods:
NetworkLoop.wait_until_routable(timeout=0):
return true when the network is routable, or false when timed out
"""
def __init__(self, *args, **kwargs):
# first, initialise the parent object
super().__init__(*args, **kwargs)
self.waitfor = None
self.wait_function = None
self.loop = EventLoop()
def start_loop(self):
"""start the dasbus loop"""
self.proxy.PropertiesChanged.connect(self.on_properties_changed)
self.loop.run()
def wait_until_routable(self, timeout=0):
"""
Wait until timeout in milliseconds and returns True when any
network interface is shown routable by networkd. Does not wait
for timeout if timeout==0
"""
self.setup_timeout(timeout)
self.wait_for_change("AddressState", self.on_addressstate_change)
return self.is_routable()
def wait_for_change(self, name, function):
"""
Wait until the given property is changed and stop. If setup_timeout()
is called before calling this function, the loop stops after the timeout
or after the property is changed, whichever occurs first.
"""
self.waitfor = name
self.wait_function = function
self.start_loop()
def on_addressstate_change(self):
"""quit the loop if the network is routable"""
if self.is_routable():
self.loop.quit()
def on_properties_changed(self, bus_interface, data, blah):
"""called by dasbus everytime the configured property is changed"""
if self.waitfor in data:
return self.wait_function()
# Just to shut up pylint
return None
def setup_timeout(self, timeout):
"""setup a timeout"""
if timeout != 0:
GLib.timeout_add(timeout, self.on_timeout)
def on_timeout(self):
"""called by dasbus when a timeout occurs"""
self.loop.quit()

271
pybatmesh/scripts.py Normal file
View File

@ -0,0 +1,271 @@
# This file is part of pybatmesh.
# Copyright (C) 2021 The pybatmesh 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/>.
"""
scripts.py
----------
The functions in this file is used for reading configs, args
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 pybatmesh, this is the right place to start.
When run from the commandline, the function main() is called.
"""
import sys
from pathlib import Path
from dasbus.error import DBusError
from systemd.daemon import notify
from pybatmesh import __version__
from pybatmesh.default import REPORT_BUG_INFO, MESH_GLOB, TMP_NET_GLOB
from pybatmesh.log import logger
from pybatmesh.iwd import Adapter, Device, IWD
from pybatmesh.config import args
from pybatmesh.daemon import Daemon
from pybatmesh.network import NetworkD, NetworkLoop
def get_sorted_glob(directory: str, glob: str) -> list:
"""return sorted list of filenames matching glob"""
path = Path(directory)
glob_list = path.glob(glob)
sorted_list = []
for i in glob_list:
# g is a list of PosixPath objects.
# So we add their absolute path as str.
sorted_list.append(str(i))
# sorted_list is not sorted, so we sort them here
sorted_list.sort()
return sorted_list
def any_interface_is_routable():
"""returns true if any of the interfaces is routable"""
networkd = NetworkLoop(runtime_dir=args.networkd_runtime_dir)
# First, add the temporary configs to networkd.
for i in get_sorted_glob(args.networkd_config_dir, TMP_NET_GLOB):
logger.debug("Adding temporary config %s", i)
networkd.add_config(i)
# timeout = 10 seconds
routable = networkd.wait_until_routable(10 * 1000)
networkd.remove_all_configs()
return routable
def setup_mesh(gateway_mode: str = "off"):
"""
configure networkd to setup the mesh
gateway_mode can be client, server, or off
"""
try:
notify("STATUS=Configuring the network...")
logger.info("Copying network config files")
networkd = NetworkD(runtime_dir=args.networkd_runtime_dir)
networkd.set_vars(
batdev=args.batman_device,
bridgedev=args.bridge_device,
gateway_mode=gateway_mode,
)
# 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. Make sure you are root."
)
logger.error(REPORT_BUG_INFO)
sys.exit(3)
except:
logger.exception("An unknown error occured while copying files")
logger.error(REPORT_BUG_INFO)
sys.exit(3)
def setup_devices():
"""
Setup wifi interfaces using iwd
This function should be called every time an interface
is connected or removed.
"""
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)
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)
# Turn on adapter if it is off
# See issue #9
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 pybatmesh --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")
logger.error(REPORT_BUG_INFO)
sys.exit(4)
except:
logger.exception("An unknown error occured while setting up the mesh")
logger.error(REPORT_BUG_INFO)
sys.exit(4)
def cleanup():
"""
Remove all network config, poweroff used wireless devices and
exit with 0.
"""
networkd = NetworkD(runtime_dir=args.networkd_runtime_dir)
logger.info("Exiting gracefully")
networkd.remove_all_configs()
for i in IWD().get_devices():
logger.debug("Turning off %s", i)
device = Device(i)
# device.set_mode("station")
device.power_off()
logger.debug("Deleting interface %s", args.batman_device)
networkd.delete_interface(args.batman_device)
logger.debug("Deleting interface %s", args.bridge_device)
networkd.delete_interface(args.bridge_device)
def print_wifi():
"""
Prints the name and password of the adhoc, and ap
from the arguments
"""
print("Mesh name:", args.adhoc_name)
print("SSID:", args.ap_ssid)
print("Password:", args.ap_passwd)
def print_version():
"""Just does what the name suggests"""
print(__version__)
def main():
"""
This is where the magic happens!
This function is run every time you
execute pybatmesh from the commandline
"""
if args.print_wifi:
print_wifi()
sys.exit(0)
elif args.version:
print_version()
sys.exit(0)
# Notify systemd that pybatmesh is ready.
# 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. It defaults to "auto" in pybatmesh.
# https://www.open-mesh.org/projects/batman-adv/wiki/Gateways
if args.gateway_mode == "auto":
logger.info("Checking for internet connection")
notify("STATUS=Checking for internet")
# If any interface is routable, set gateway mode to server
if any_interface_is_routable():
logger.info("Network is routable. Setting gw_mode to server")
gateway_mode = "server"
else:
logger.info("Network is not routable. Setting gw_mode to client")
gateway_mode = "client"
logger.info("gateway_mode set to %s", gateway_mode)
elif args.gateway_mode in ["server", "client", "off"]:
gateway_mode = args.gateway_mode
else:
logger.error("gateway-mode has an illegal value")
sys.exit(5)
try:
setup_devices()
setup_mesh(gateway_mode=gateway_mode)
# Start the daemon so that setup_devices() is called every
# time a device is connected or removed.
daemon = Daemon()
daemon.add_callback(setup_devices)
notify("STATUS=Waiting for changes")
daemon.start()
# systemd uses SIGINT to kill this program
except KeyboardInterrupt:
cleanup()

4
pyproject.toml Normal file
View File

@ -0,0 +1,4 @@
[build-system]
# I don't know what this means, I just copied it from some setuptools tutorial
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

52
setup.cfg Normal file
View File

@ -0,0 +1,52 @@
# This file is loosely based on the setup.cfg used in django.
# pybatmesh is not meant to be distributed through PyPi. This program uses
# a systemd service, and some other files whose path is hardcoded into the
# module.
[metadata]
name = pybatmesh
version = attr: pybatmesh.__version__
description = create mesh networks with batman-adv and systemd
long_description = file: README.md
url = https://git.disroot.org/pranav/pybatmesh
author = Pranav Jerry
author_email = libreinator@disroot.org
license = GPLv3
license_files = LICENSE
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
# pathlib, configparser and argparse are already
# in the standard library
configparser
pathlib
argparse
systemd
[options.entry_points]
console_scripts =
pybatmesh = pybatmesh.scripts:main
[options.data_files]
lib/systemd/system =
pybatmesh.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 in the Makefile.
/etc/pybatmesh =
pybatmesh.conf.example
share/pybatmesh/networkd =
network/mesh.01-batman.netdev
network/mesh.02-bridge.netdev
network/mesh.03-wireless-ad-hoc.network
network/mesh.04-batman.network
network/mesh.05-wireless-ap.network
network/mesh.06-eth.network
network/mesh.07-bridge.network
network/tmp.01-eth.network

7
setup.py Executable file
View File

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

View File

@ -1,10 +0,0 @@
# Create the BATMAN interface
# See 04-batman.network for configuration details
[NetDev]
Name=bat0
Description=BATMAN interface
Kind=batadv
# Use default settings. Uncomment to change
# see man:systemd.netdev(5) § [BATMANADVANCED] SECTION OPTIONS
#[BatmanAdvanced]

View File

@ -1,7 +0,0 @@
# This file bridges any ethernet device found
# to the bridge made in 02-bridge.netdev
[Match]
Name=en*
[Network]
Bridge=bridge0