Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a43d6bfc6e
4
LICENSE
4
LICENSE
@ -1,5 +1,5 @@
|
|||||||
The code of Project Gluon may be distributed under the following terms, unless
|
The code of Project Gluon may be distributed under the following terms, unless
|
||||||
noted otherwise in indiviual files or subtrees.
|
noted otherwise in individual files or subtrees.
|
||||||
|
|
||||||
Copyright (c) 2013, Project Gluon
|
Copyright (c) 2013, Project Gluon
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
@ -25,7 +25,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
OpenWRT is licensed under the terms of the GNU General Public License Version 2,
|
OpenWrt is licensed under the terms of the GNU General Public License Version 2,
|
||||||
which can be found under openwrt/LICENSE after the openwrt submodule has been
|
which can be found under openwrt/LICENSE after the openwrt submodule has been
|
||||||
obtained. This applies to the following submodules:
|
obtained. This applies to the following submodules:
|
||||||
* openwrt
|
* openwrt
|
||||||
|
23
Makefile
23
Makefile
@ -177,6 +177,9 @@ GLUON_$(1)_MODEL_$(2)_ALIASES += $(3)
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
||||||
|
export SHA512SUM := $(GLUONDIR)/scripts/sha512sum.sh
|
||||||
|
|
||||||
|
|
||||||
prereq: FORCE
|
prereq: FORCE
|
||||||
+$(NO_TRACE_MAKE) prereq
|
+$(NO_TRACE_MAKE) prereq
|
||||||
|
|
||||||
@ -209,7 +212,12 @@ gluon-tools: FORCE
|
|||||||
+$(GLUONMAKE_EARLY) package/lua/host/install package/usign/host/install
|
+$(GLUONMAKE_EARLY) package/lua/host/install package/usign/host/install
|
||||||
|
|
||||||
|
|
||||||
early_prepared_stamp := $(GLUON_BUILDDIR)/prepared
|
|
||||||
|
early_prepared_stamp := $(GLUON_BUILDDIR)/prepared_$(shell \
|
||||||
|
( \
|
||||||
|
$(SHA512SUM) $(GLUONDIR)/modules; \
|
||||||
|
[ ! -r $(GLUON_SITEDIR)/modules ] || $(SHA512SUM) $(GLUON_SITEDIR)/modules \
|
||||||
|
) | $(SHA512SUM) )
|
||||||
|
|
||||||
prepare-early: FORCE
|
prepare-early: FORCE
|
||||||
for dir in build_dir dl staging_dir; do \
|
for dir in build_dir dl staging_dir; do \
|
||||||
@ -223,11 +231,12 @@ prepare-early: FORCE
|
|||||||
touch $(early_prepared_stamp)
|
touch $(early_prepared_stamp)
|
||||||
|
|
||||||
$(early_prepared_stamp):
|
$(early_prepared_stamp):
|
||||||
|
rm -f $(GLUON_BUILDDIR)/prepared_*
|
||||||
+$(GLUONMAKE_EARLY) prepare-early
|
+$(GLUONMAKE_EARLY) prepare-early
|
||||||
|
|
||||||
$(GLUON_OPKG_KEY): $(early_prepared_stamp) FORCE
|
$(GLUON_OPKG_KEY): $(early_prepared_stamp) FORCE
|
||||||
[ -s $(GLUON_OPKG_KEY) -a -s $(GLUON_OPKG_KEY).pub ] || \
|
[ -s $(GLUON_OPKG_KEY) -a -s $(GLUON_OPKG_KEY).pub ] || \
|
||||||
mkdir -p $$(dirname $(GLUON_OPKG_KEY)) && $(STAGING_DIR_HOST)/bin/usign -G -s $(GLUON_OPKG_KEY) -p $(GLUON_OPKG_KEY).pub -c "Gluon opkg key"
|
( mkdir -p $$(dirname $(GLUON_OPKG_KEY)) && $(STAGING_DIR_HOST)/bin/usign -G -s $(GLUON_OPKG_KEY) -p $(GLUON_OPKG_KEY).pub -c "Gluon opkg key" )
|
||||||
|
|
||||||
$(GLUON_OPKG_KEY).pub: $(GLUON_OPKG_KEY)
|
$(GLUON_OPKG_KEY).pub: $(GLUON_OPKG_KEY)
|
||||||
|
|
||||||
@ -253,8 +262,9 @@ MODULE_PREFIX = gluon-$(GLUON_SITE_CODE)-$(PREPARED_RELEASE)
|
|||||||
include $(INCLUDE_DIR)/target.mk
|
include $(INCLUDE_DIR)/target.mk
|
||||||
|
|
||||||
build-key: FORCE
|
build-key: FORCE
|
||||||
ln -sf $(GLUON_OPKG_KEY) $(BUILD_KEY)
|
rm -f $(BUILD_KEY) $(BUILD_KEY).pub
|
||||||
ln -sf $(GLUON_OPKG_KEY).pub $(BUILD_KEY).pub
|
cp $(GLUON_OPKG_KEY) $(BUILD_KEY)
|
||||||
|
cp $(GLUON_OPKG_KEY).pub $(BUILD_KEY).pub
|
||||||
|
|
||||||
config: FORCE
|
config: FORCE
|
||||||
+$(NO_TRACE_MAKE) scripts/config/conf OPENWRT_BUILD= QUIET=0
|
+$(NO_TRACE_MAKE) scripts/config/conf OPENWRT_BUILD= QUIET=0
|
||||||
@ -304,9 +314,6 @@ clean: FORCE
|
|||||||
rm -f $(gluon_prepared_stamp)
|
rm -f $(gluon_prepared_stamp)
|
||||||
|
|
||||||
|
|
||||||
export SHA512SUM := $(GLUONDIR)/scripts/sha512sum.sh
|
|
||||||
|
|
||||||
|
|
||||||
download: FORCE
|
download: FORCE
|
||||||
+$(SUBMAKE) tools/download
|
+$(SUBMAKE) tools/download
|
||||||
+$(SUBMAKE) toolchain/download
|
+$(SUBMAKE) toolchain/download
|
||||||
@ -331,7 +338,7 @@ prepare-image: FORCE
|
|||||||
+$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image image_prepare KDIR="$(BOARD_KDIR)"
|
+$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image image_prepare KDIR="$(BOARD_KDIR)"
|
||||||
|
|
||||||
prepare: FORCE
|
prepare: FORCE
|
||||||
@$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua \
|
@$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/scripts/site_config.lua \
|
||||||
|| (echo 'Your site configuration did not pass validation.'; false)
|
|| (echo 'Your site configuration did not pass validation.'; false)
|
||||||
|
|
||||||
mkdir -p $(GLUON_IMAGEDIR) $(BOARD_BUILDDIR)
|
mkdir -p $(GLUON_IMAGEDIR) $(BOARD_BUILDDIR)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Documentation (incomplete at this time, contribute if you can!) may be found at
|
Documentation (incomplete at this time, contribute if you can!) may be found at
|
||||||
http://gluon.readthedocs.org/
|
http://gluon.readthedocs.org/.
|
||||||
|
|
||||||
If you're new to Gluon and ready to get your feet wet, have a look at the
|
If you're new to Gluon and ready to get your feet wet, have a look at the
|
||||||
[Getting Started Guide](http://gluon.readthedocs.org/en/latest/user/getting_started.html).
|
[Getting Started Guide](http://gluon.readthedocs.org/en/latest/user/getting_started.html).
|
||||||
@ -8,15 +8,15 @@ If you're new to Gluon and ready to get your feet wet, have a look at the
|
|||||||
|
|
||||||
## Issues & Feature requests
|
## Issues & Feature requests
|
||||||
|
|
||||||
Before opening an issue make sure to read check whether any existing issues
|
Before opening an issue, make sure to check whether any existing issues
|
||||||
(open or closed) match. If you're suggesting a new feature, drop by on IRC or
|
(open or closed) match. If you're suggesting a new feature, drop by on IRC or
|
||||||
our mailinglist to discuss it first.
|
our mailinglist to discuss it first.
|
||||||
|
|
||||||
## Use a release!
|
## Use a release!
|
||||||
|
|
||||||
Please refrain from using the master branch for anything else but development purposes!
|
Please refrain from using the `master` branch for anything else but development purposes!
|
||||||
Use the most recent release instead. You can list all relaseses by running `git branch -a`
|
Use the most recent release instead. You can list all relaseses by running `git branch -a`
|
||||||
and switch to one by running `git checkout v2015.1 && make update`.
|
and switch to one by running `git checkout v2016.1 && make update`.
|
||||||
|
|
||||||
If you're using the autoupdater, do not autoupdate nodes with anything but releases.
|
If you're using the autoupdater, do not autoupdate nodes with anything but releases.
|
||||||
If you upgrade using random master commits the nodes *will break* eventually.
|
If you upgrade using random master commits the nodes *will break* eventually.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ $# -eq 0 -o "-h" = "$1" -o "-help" = "$1" -o "--help" = "$1" ]; then
|
set -e
|
||||||
|
|
||||||
|
if [ $# -ne 2 -o "-h" = "$1" -o "--help" = "$1" -o ! -r "$1" -o ! -r "$2" ]; then
|
||||||
cat <<EOHELP
|
cat <<EOHELP
|
||||||
Usage: $0 <secret> <manifest>
|
Usage: $0 <secret> <manifest>
|
||||||
|
|
||||||
@ -25,16 +27,18 @@ manifest="$2"
|
|||||||
upper="$(mktemp)"
|
upper="$(mktemp)"
|
||||||
lower="$(mktemp)"
|
lower="$(mktemp)"
|
||||||
|
|
||||||
awk "BEGIN { sep=0 }
|
trap 'rm -f "$upper" "$lower"' EXIT
|
||||||
/^---\$/ { sep=1; next }
|
|
||||||
{ if(sep==0) print > \"$upper\";
|
awk 'BEGIN { sep=0 }
|
||||||
else print > \"$lower\"}" \
|
/^---$/ { sep=1; next }
|
||||||
|
{ if(sep==0) print > "'"$upper"'";
|
||||||
|
else print > "'"$lower"'"}' \
|
||||||
"$manifest"
|
"$manifest"
|
||||||
|
|
||||||
ecdsasign "$upper" < "$SECRET" >> "$lower"
|
ecdsasign "$upper" < "$SECRET" >> "$lower"
|
||||||
|
|
||||||
cat "$upper" > "$manifest"
|
(
|
||||||
echo --- >> "$manifest"
|
cat "$upper"
|
||||||
cat "$lower" >> "$manifest"
|
echo ---
|
||||||
|
cat "$lower"
|
||||||
rm -f "$upper" "$lower"
|
) > "$manifest"
|
||||||
|
@ -54,9 +54,9 @@ copyright = '2015, Project Gluon'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '2015.1+'
|
version = '2016.1+'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '2015.1+'
|
release = '2016.1+'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
@ -15,8 +15,8 @@ ecdsautils) can by found in the `contrib` directory. When creating the manifest,
|
|||||||
be set on the command line, or it can be taken from the ``site.mk``.
|
be set on the command line, or it can be taken from the ``site.mk``.
|
||||||
|
|
||||||
The priority defines the maximum number of days that may pass between releasing an update and installation
|
The priority defines the maximum number of days that may pass between releasing an update and installation
|
||||||
of the images. The update probability with start at 0 after the release time mentioned in the manifest
|
of the images. The update probability will start at 0 after the release time mentioned in the manifest
|
||||||
and then slowly rise to 1 after the number of days given by the priority has passed.
|
and then slowly rise to 1 up to the point when the number of days given by the priority has passed.
|
||||||
|
|
||||||
The priority may be an integer or a decimal fraction.
|
The priority may be an integer or a decimal fraction.
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ The server must be available via IPv6.
|
|||||||
Command Line
|
Command Line
|
||||||
------------
|
------------
|
||||||
|
|
||||||
These commands can be used on a node.
|
These commands can be used on a node:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Announcing Node Information
|
Node monitoring
|
||||||
===========================
|
===============
|
||||||
|
|
||||||
Gluon is capable of announcing information about each node to the mesh
|
Gluon is capable of announcing information about each node to the mesh
|
||||||
and to neighbouring nodes. This allows nodes to learn each others hostname,
|
and to neighbouring nodes. This allows nodes to learn each others hostname,
|
||||||
@ -8,7 +8,7 @@ IP addresses, location, software versions and various other information.
|
|||||||
Format of collected data
|
Format of collected data
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Information to be announced is currently split into two categories:
|
Information to be announced is currently split into three categories:
|
||||||
|
|
||||||
nodeinfo
|
nodeinfo
|
||||||
In this category (mostly) static information is collected. If
|
In this category (mostly) static information is collected. If
|
||||||
@ -19,15 +19,19 @@ Information to be announced is currently split into two categories:
|
|||||||
This category holds fast changing data, like traffic counters, uptime,
|
This category holds fast changing data, like traffic counters, uptime,
|
||||||
system load or the selected gateway.
|
system load or the selected gateway.
|
||||||
|
|
||||||
Both categories will have a ``node_id`` key by default. It should be used to
|
neighbours
|
||||||
match data from *statistics* to *nodeinfo*.
|
`neighbours` contains information about all neighbouring nodes of all
|
||||||
|
interfaces. This data can be used to determine the network topology.
|
||||||
|
|
||||||
|
All categories will have a ``node_id`` key. It should be used to
|
||||||
|
relate data of different catagories.
|
||||||
|
|
||||||
Accessing Node Information
|
Accessing Node Information
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
There are two packages responsible for distribution of the information. For
|
There are two packages responsible for distribution of the information. For
|
||||||
one, information is distributed across the mesh using alfred_. Information
|
one, information is distributed across the mesh using alfred_. Information
|
||||||
between neighbouring nodes is exchanged using `gluon-announced`.
|
between neighbouring nodes is exchanged using `gluon-respondd`.
|
||||||
|
|
||||||
.. _alfred: http://www.open-mesh.org/projects/alfred
|
.. _alfred: http://www.open-mesh.org/projects/alfred
|
||||||
|
|
||||||
@ -43,8 +47,13 @@ installed. Please note that at least one alfred daemon is required to run as
|
|||||||
|
|
||||||
.. _alfred-json: https://github.com/tcatm/alfred-json
|
.. _alfred-json: https://github.com/tcatm/alfred-json
|
||||||
|
|
||||||
`nodeinfo` is distributed as alfred datatype `158`, while `statistics` uses
|
The following datatypes are used:
|
||||||
`159`. Both are compressed using GZip (alfred-json can handle the decompression).
|
|
||||||
|
* `nodeinfo`: 158
|
||||||
|
* `statistics`: 159
|
||||||
|
* `neighbours`: 160
|
||||||
|
|
||||||
|
All data is compressed using GZip (alfred-json can handle the decompression).
|
||||||
|
|
||||||
In order to retrieve statistics data you could run:
|
In order to retrieve statistics data you could run:
|
||||||
|
|
||||||
@ -90,18 +99,26 @@ You can find more information about alfred in its README_.
|
|||||||
|
|
||||||
.. _README: http://www.open-mesh.org/projects/alfred/repository/revisions/master/entry/README
|
.. _README: http://www.open-mesh.org/projects/alfred/repository/revisions/master/entry/README
|
||||||
|
|
||||||
gluon-announced
|
gluon-respondd
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
`gluon-announced` allows querying neighbouring nodes for their `nodeinfo`.
|
`gluon-respondd` allows querying neighbouring nodes for their information.
|
||||||
It is a daemon listening on the multicast address ``ff02::2:1001`` on
|
It is a daemon listening on the multicast address ``ff02::2:1001`` on
|
||||||
UDP port 1001 on the bare mesh interfaces.
|
UDP port 1001 on both the bare mesh interfaces and `br-client`. Unicast
|
||||||
|
requests are supported as well.
|
||||||
|
|
||||||
|
The supported requests are:
|
||||||
|
|
||||||
|
* ``nodeinfo``, ``statistics``, ``neighbours``: Returns the data of single category uncompressed.
|
||||||
|
* ``GET nodeinfo``, ...: Returns the data of one or multiple categories (separated by spaces)
|
||||||
|
compressed using the `deflate` algorithm (without a gzip header). The data may
|
||||||
|
be decompressed using zlib and many zlib bindings using -15 as the window size parameter.
|
||||||
|
|
||||||
gluon-neighbour-info
|
gluon-neighbour-info
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A programm called `gluon-neighbour-info` has been developed to retrieve
|
The programm `gluon-neighbour-info` can be used to retrieve
|
||||||
information from neighbours.
|
information from other nodes.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -109,55 +126,13 @@ information from neighbours.
|
|||||||
-p 1001 -d ff02:0:0:0:0:0:2:1001 \
|
-p 1001 -d ff02:0:0:0:0:0:2:1001 \
|
||||||
-r nodeinfo
|
-r nodeinfo
|
||||||
|
|
||||||
On optional timeout may be specified, e.g. `-t 5` (default: 3 seconds).
|
An optional timeout may be specified, e.g. `-t 5` (default: 3 seconds). See
|
||||||
|
the usage information printed by ``gluon-neighbour-info -h`` for more information
|
||||||
|
about the supported arguments.
|
||||||
|
|
||||||
Adding a fact
|
Adding a data provider
|
||||||
-------------
|
----------------------
|
||||||
|
|
||||||
To add a fact just add a file to either ``/lib/gluon/announce/nodeinfo.d/`` or
|
To add a provider, you need to install a shared object into ``/lib/gluon/respondd``.
|
||||||
``/lib/gluon/announce/statistics.d/``.
|
For more information, refer to the `respondd README <https://github.com/freifunk-gluon/packages/blob/master/net/respondd/README.md>`_
|
||||||
|
and have a look the existing providers.
|
||||||
The file must contain a lua script and its name will become the key for the
|
|
||||||
resulting JSON object. A simple script adding a ``hostname`` field might look
|
|
||||||
like this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
return uci:get_first('system', 'system', 'hostname')
|
|
||||||
|
|
||||||
The directory structure will be converted to a JSON object, i.e. you may
|
|
||||||
create subdirectories. So, if the directories look like this
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
.
|
|
||||||
├── hardware
|
|
||||||
│ └── model
|
|
||||||
├── hostname
|
|
||||||
├── network
|
|
||||||
│ └── mac
|
|
||||||
├── node_id
|
|
||||||
└── software
|
|
||||||
└── firmware
|
|
||||||
|
|
||||||
the resulting JSON would become:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# /lib/gluon/announce/announce.lua nodeinfo
|
|
||||||
{
|
|
||||||
"hardware" : {
|
|
||||||
"model" : "TP-Link TL-MR3420 v1"
|
|
||||||
},
|
|
||||||
"hostname" : "mr3420-test",
|
|
||||||
"network" : {
|
|
||||||
"mac" : "90:f6:52:82:06:02"
|
|
||||||
},
|
|
||||||
"node_id" : "90f652820602",
|
|
||||||
"software" : {
|
|
||||||
"firmware" : {
|
|
||||||
"base" : "gluon-v2014.2-32-ge831099",
|
|
||||||
"release" : "0.4.1+0-exp20140720"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -60,6 +60,6 @@ It may be disabled by running::
|
|||||||
done
|
done
|
||||||
uci commit
|
uci commit
|
||||||
|
|
||||||
Please note that this configuration has changed in Gluon v2015.2. Using
|
Please note that this configuration has changed in Gluon v2016.1. Using
|
||||||
the old commands on v2015.2 will break the corresponding Export Mode
|
the old commands on v2016.1 will break the corresponding Expert Mode
|
||||||
settings.
|
settings.
|
||||||
|
26
docs/features/wlan-configuration.rst
Normal file
26
docs/features/wlan-configuration.rst
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
WLAN configuration
|
||||||
|
==================
|
||||||
|
|
||||||
|
Gluon allows to configure 2.4GHz and 5GHz radios independently. The configuration
|
||||||
|
may include any or all of the three networks "client" (AP mode), "mesh" (802.11s
|
||||||
|
mode) and "ibss" (adhoc mode), which can be used simultaneously (using "mesh" and
|
||||||
|
"ibss" at same time should be avoided though as weaker hardware usually can't handle the additional
|
||||||
|
load). See :doc:`../user/site` for details on the configuration.
|
||||||
|
|
||||||
|
Upgrade behaviour
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
For each of these networks, the site configuration may define a `disabled` flag (by
|
||||||
|
default, all configured networks are enabled). This flag is merely a default setting,
|
||||||
|
on upgrades the existing setting is always retained (as this setting may have been changed
|
||||||
|
by the user). This means that is is not possible to enable or disable an existing network
|
||||||
|
configurations during upgrades.
|
||||||
|
|
||||||
|
For the "mesh" and "ibss" networks, the default setting only has an effect if none
|
||||||
|
of the two has existed before. If a new configuration has been added for "mesh" or "ibss",
|
||||||
|
while the other of the two has already existed before, the enabled/disabled state of the
|
||||||
|
existing configuration will also be set for the new configuration.
|
||||||
|
|
||||||
|
This allows upgrades to change from IBSS to 11s and vice-versa while retaining the
|
||||||
|
"wireless meshing is enabled/disabled" property configured by the user regardless
|
||||||
|
of the used mode.
|
@ -24,9 +24,10 @@ Features
|
|||||||
|
|
||||||
features/configmode
|
features/configmode
|
||||||
features/autoupdater
|
features/autoupdater
|
||||||
|
features/wlan-configuration
|
||||||
features/private-wlan
|
features/private-wlan
|
||||||
features/wired-mesh
|
features/wired-mesh
|
||||||
features/announce
|
features/monitoring
|
||||||
features/authorized-keys
|
features/authorized-keys
|
||||||
features/roles
|
features/roles
|
||||||
|
|
||||||
@ -50,6 +51,8 @@ Packages
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
package/gluon-client-bridge
|
package/gluon-client-bridge
|
||||||
|
package/gluon-ebtables-filter-multicast
|
||||||
|
package/gluon-ebtables-filter-ra-dhcp
|
||||||
|
|
||||||
Releases
|
Releases
|
||||||
--------
|
--------
|
||||||
@ -57,7 +60,7 @@ Releases
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
releases/v2015.2
|
releases/v2016.1
|
||||||
releases/v2015.1.2
|
releases/v2015.1.2
|
||||||
releases/v2015.1.1
|
releases/v2015.1.1
|
||||||
releases/v2015.1
|
releases/v2015.1
|
||||||
@ -79,12 +82,14 @@ ar71xx-generic
|
|||||||
* Buffalo
|
* Buffalo
|
||||||
|
|
||||||
- WZR-HP-AG300H / WZR-600DHP
|
- WZR-HP-AG300H / WZR-600DHP
|
||||||
|
- WZR-HP-G300NH
|
||||||
- WZR-HP-G450H
|
- WZR-HP-G450H
|
||||||
|
|
||||||
* D-Link
|
* D-Link
|
||||||
|
|
||||||
- DIR-825 (B1)
|
- DIR-505 (A1)
|
||||||
- DIR-615 (C1)
|
- DIR-615 (C1)
|
||||||
|
- DIR-825 (B1)
|
||||||
|
|
||||||
* GL-Inet
|
* GL-Inet
|
||||||
|
|
||||||
@ -103,10 +108,10 @@ ar71xx-generic
|
|||||||
|
|
||||||
* TP-Link
|
* TP-Link
|
||||||
|
|
||||||
- CPE210 (v1)
|
- CPE210 (v1.0, v1.1)
|
||||||
- CPE220 (v1)
|
- CPE220 (v1.0, v1.1)
|
||||||
- CPE510 (v1)
|
- CPE510 (v1.0, v1.1)
|
||||||
- CPE520 (v1)
|
- CPE520 (v1.0, v1.1)
|
||||||
- TL-MR3020 (v1)
|
- TL-MR3020 (v1)
|
||||||
- TL-MR3040 (v1, v2)
|
- TL-MR3040 (v1, v2)
|
||||||
- TL-MR3220 (v1, v2)
|
- TL-MR3220 (v1, v2)
|
||||||
@ -117,32 +122,43 @@ ar71xx-generic
|
|||||||
- TL-WA830RE (v1, v2)
|
- TL-WA830RE (v1, v2)
|
||||||
- TL-WA850RE (v1)
|
- TL-WA850RE (v1)
|
||||||
- TL-WA860RE (v1)
|
- TL-WA860RE (v1)
|
||||||
- TL-WA901N/ND (v2, v3)
|
- TL-WA901N/ND (v1, v2, v3)
|
||||||
- TL-WDR3500 (v1)
|
- TL-WDR3500 (v1)
|
||||||
- TL-WDR3600 (v1)
|
- TL-WDR3600 (v1)
|
||||||
- TL-WDR4300 (v1)
|
- TL-WDR4300 (v1)
|
||||||
- TL-WR1043N/ND (v1, v2)
|
|
||||||
- TL-WR703N (v1)
|
- TL-WR703N (v1)
|
||||||
- TL-WR710N (v1)
|
- TL-WR710N (v1, v2)
|
||||||
- TL-WR740N (v1, v3, v4, v5)
|
- TL-WR740N (v1, v3, v4, v5)
|
||||||
- TL-WR741N/ND (v1, v2, v4, v5)
|
- TL-WR741N/ND (v1, v2, v4, v5)
|
||||||
- TL-WR743N/ND (v1, v2)
|
- TL-WR743N/ND (v1, v2)
|
||||||
|
- TL-WR801N/ND (v1, v2)
|
||||||
- TL-WR841N/ND (v3, v5, v7, v8, v9, v10)
|
- TL-WR841N/ND (v3, v5, v7, v8, v9, v10)
|
||||||
- TL-WR842N/ND (v1, v2)
|
- TL-WR842N/ND (v1, v2)
|
||||||
- TL-WR941N/ND (v2, v3, v4, v5)
|
- TL-WR843N/ND (v1)
|
||||||
|
- TL-WR940N (v1, v2, v3)
|
||||||
|
- TL-WR941ND (v2, v3, v4, v5, v6)
|
||||||
|
- TL-WR1043N/ND (v1, v2, v3)
|
||||||
- TL-WR2543N/ND (v1)
|
- TL-WR2543N/ND (v1)
|
||||||
|
|
||||||
* Ubiquiti
|
* Ubiquiti
|
||||||
|
|
||||||
- Bullet M2
|
- Air Gateway
|
||||||
- Nanostation M2
|
- Air Router
|
||||||
|
- Bullet M
|
||||||
|
- Nanostation M
|
||||||
- Nanostation M XW
|
- Nanostation M XW
|
||||||
- Loco M XW
|
- Loco M XW
|
||||||
- Picostation M2
|
- Picostation M
|
||||||
- Rocket M2
|
- Rocket M
|
||||||
- UniFi AP
|
- UniFi AP
|
||||||
- UniFi AP Pro
|
- UniFi AP Pro
|
||||||
- UniFi AP Outdoor
|
- UniFi AP Outdoor
|
||||||
|
- UniFi AP Outdoor+
|
||||||
|
|
||||||
|
* Western Digital
|
||||||
|
|
||||||
|
- My Net N600
|
||||||
|
- My Net N750
|
||||||
|
|
||||||
ar71xx-nand
|
ar71xx-nand
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
@ -173,6 +189,20 @@ x86-kvm_guest
|
|||||||
|
|
||||||
See also: :doc:`user/x86`
|
See also: :doc:`user/x86`
|
||||||
|
|
||||||
|
x86-xen_domu
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
* x86-xen
|
||||||
|
|
||||||
|
See also: :doc:`user/x86`
|
||||||
|
|
||||||
|
x86-64
|
||||||
|
^^^^^^
|
||||||
|
* x86-64-generic
|
||||||
|
* x86-64-virtualbox
|
||||||
|
* x86-64-vmware
|
||||||
|
|
||||||
|
See also: :doc:`user/x86`
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
30
docs/package/gluon-ebtables-filter-multicast.rst
Normal file
30
docs/package/gluon-ebtables-filter-multicast.rst
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
gluon-ebtables-filter-multicast
|
||||||
|
===============================
|
||||||
|
|
||||||
|
The *gluon-ebtables-filter-multicast* package filters out various kinds of
|
||||||
|
non-essential multicast traffic, as this traffic often constitutes a
|
||||||
|
disproportionate burden on the mesh network. Unfortunately, this breaks many useful services
|
||||||
|
(Avahi, Bonjour chat, ...), but this seems unavoidable, as the current Avahi implementation is
|
||||||
|
optimized for small local networks and causes too much traffic in large mesh networks.
|
||||||
|
|
||||||
|
The multicast packets are filtered between the nodes' client bridge (*br-client*) and mesh
|
||||||
|
interface (*bat0*) on output.
|
||||||
|
|
||||||
|
|
||||||
|
The following packet types are considered essential and aren't filtered:
|
||||||
|
|
||||||
|
* ARP (except requests for/replies from 0.0.0.0)
|
||||||
|
* DHCP, DHCPv6
|
||||||
|
* ICMPv6 (except Echo Requests (ping) and Node Information Queries (RFC4620)
|
||||||
|
* IGMP
|
||||||
|
|
||||||
|
In addition, the following packet types are allowed to allow experimentation with
|
||||||
|
layer 3 routing protocols.
|
||||||
|
|
||||||
|
* Babel
|
||||||
|
* OSPF
|
||||||
|
* RIPng
|
||||||
|
|
||||||
|
The following packet types are also allowed:
|
||||||
|
|
||||||
|
* BitTorrent Local Peer Discovery (it seems better to have local peers for BitTorrent than sending everything through the internet)
|
13
docs/package/gluon-ebtables-filter-ra-dhcp.rst
Normal file
13
docs/package/gluon-ebtables-filter-ra-dhcp.rst
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
gluon-ebtables-filter-ra-dhcp
|
||||||
|
=============================
|
||||||
|
|
||||||
|
The *gluon-ebtables-filter-ra-dhcp* package tries to prevent common
|
||||||
|
misconfigurations (i.e. connecting the client interface of a Gluon
|
||||||
|
node to a private network) from causing issues for either of the
|
||||||
|
networks.
|
||||||
|
|
||||||
|
The rules are the following:
|
||||||
|
|
||||||
|
* DHCP requests, DHCPv6 requests and Router Solicitations may only be sent from clients to the mesh, but aren't forwarded
|
||||||
|
from the mesh to clients
|
||||||
|
* DHCP replies, DHCPv6 replies and Router Advertisements from clients aren't forwarded to the mesh
|
@ -1,145 +0,0 @@
|
|||||||
Gluon 2015.2 (in development)
|
|
||||||
=============================
|
|
||||||
|
|
||||||
Added (and removed) hardware support
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
New features
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
Site changes
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
* ``site.conf``
|
|
||||||
|
|
||||||
- New WLAN configuration
|
|
||||||
|
|
||||||
``wifi24`` and ``wifi5`` need to be updated to a new more flexible format.
|
|
||||||
A configuration using the old format
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
channel = 1,
|
|
||||||
htmode = 'HT20'
|
|
||||||
ssid = 'entenhausen.freifunk.net',
|
|
||||||
mesh_ssid = 'xe:xx:xx:xx:xx:xx',
|
|
||||||
mesh_bssid = 'xe:xx:xx:xx:xx:xx',
|
|
||||||
mesh_mcast_rate = 12000,
|
|
||||||
}
|
|
||||||
|
|
||||||
would look like this in the new format::
|
|
||||||
|
|
||||||
{
|
|
||||||
channel = 1,
|
|
||||||
ap = {
|
|
||||||
ssid = 'entenhausen.freifunk.net',
|
|
||||||
},
|
|
||||||
ibss = {
|
|
||||||
ssid = 'xe:xx:xx:xx:xx:xx',
|
|
||||||
bssid = 'xe:xx:xx:xx:xx:xx',
|
|
||||||
mcast_rate = 12000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
The ``htmode`` option has been dropped, the channel width is now always set to 20MHz
|
|
||||||
(see https://github.com/freifunk-gluon/gluon/issues/487 for a discussion of this change).
|
|
||||||
|
|
||||||
In addition to the old IBSS (Adhoc) based meshing, 802.11s-based meshing can be configured
|
|
||||||
using the ``mesh`` section. Example::
|
|
||||||
|
|
||||||
{
|
|
||||||
channel = 1,
|
|
||||||
ap = {
|
|
||||||
ssid = 'entenhausen.freifunk.net',
|
|
||||||
},
|
|
||||||
mesh = {
|
|
||||||
id = 'mesh.entenhausen.freifunk.net', -- can by any string, human-readable or random
|
|
||||||
mcast_rate = 12000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
While using ``ibss`` and ``mesh`` at the same time is possible, is causes high load in
|
|
||||||
very active meshes, so it is advisable to avoid such configurations.
|
|
||||||
|
|
||||||
- Bandwidth limitation defaults
|
|
||||||
|
|
||||||
The old section ``simple_tc.mesh_vpn`` has been moved to ``fastd_mesh_vpn.bandwidth_limit`` and the ``ifname``
|
|
||||||
field isn't used anymore. What looked like this
|
|
||||||
before
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
simple_tc = {
|
|
||||||
mesh_vpn = {
|
|
||||||
ifname = 'mesh-vpn',
|
|
||||||
enabled = false,
|
|
||||||
limit_ingress = 3000,
|
|
||||||
limit_egress = 200,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
needs to be changed to
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
fastd_mesh_vpn = {
|
|
||||||
-- ...
|
|
||||||
|
|
||||||
bandwidth_limit = {
|
|
||||||
enabled = false,
|
|
||||||
ingress = 3000,
|
|
||||||
egress = 200,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
- opkg repository configuration
|
|
||||||
|
|
||||||
The opkg configuration has been changed to be more flexible and allow specifying custom repositories.
|
|
||||||
Example::
|
|
||||||
|
|
||||||
opkg = {
|
|
||||||
openwrt = 'http://opkg.services.ffeh/openwrt/%n/%v/%S/packages',
|
|
||||||
extra = {
|
|
||||||
modules = 'http://opkg.services.ffeh/modules/gluon-%GS-%GR/%S',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
The keys of the ``extra`` table (like ``modules`` in this example) can be chosen arbitrarily.
|
|
||||||
|
|
||||||
Instead of explicitly specifying the whole URL, using patterns is recommended. The following
|
|
||||||
patterns are understood:
|
|
||||||
|
|
||||||
- ``%n`` is replaced by the OpenWrt version codename (e.g. "chaos_calmer")
|
|
||||||
- ``%v`` is replaced by the OpenWrt version number (e.g. "15.05")
|
|
||||||
- ``%S`` is replaced by the target architecture (e.g. "ar71xx/generic")
|
|
||||||
- ``%GS`` is replaced by the Gluon site code (as specified in ``site.conf``)
|
|
||||||
- ``%GV`` is replaced by the Gluon version
|
|
||||||
- ``%GR`` is replaced by the Gluon release (as specified in ``site.mk``)
|
|
||||||
|
|
||||||
|
|
||||||
* ``i18n/``
|
|
||||||
|
|
||||||
- The translations of ``gluon-config-mode:pubkey`` now have to show the fastd
|
|
||||||
public key itself if desired, making the formatting of the key and whether it is shown at
|
|
||||||
all configurable. To retain the old format, add ``<p>`` to the beginning of
|
|
||||||
your translations and append::
|
|
||||||
|
|
||||||
"</p>"
|
|
||||||
"<div class=\"the-key\">"
|
|
||||||
" # <%= hostname %>"
|
|
||||||
" <br/>"
|
|
||||||
"<%= pubkey %>"
|
|
||||||
"</div>"
|
|
||||||
|
|
||||||
Internals
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
Known Issues
|
|
||||||
~~~~~~~~~~~~
|
|
276
docs/releases/v2016.1.rst
Normal file
276
docs/releases/v2016.1.rst
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
Gluon 2016.1
|
||||||
|
============
|
||||||
|
|
||||||
|
Added hardware support
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
ar71xx-generic
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
* Buffalo
|
||||||
|
|
||||||
|
- WZR-HP-G300NH
|
||||||
|
|
||||||
|
* D-Link
|
||||||
|
|
||||||
|
- DIR-505 (A1)
|
||||||
|
|
||||||
|
* TP-Link
|
||||||
|
|
||||||
|
- CPE210/220/510/520 v1.1
|
||||||
|
- TL-WA901N/ND v1
|
||||||
|
- TL-WR710N v2
|
||||||
|
- TL-WR801N/ND v1, v2
|
||||||
|
- TL-WR841N/ND v10
|
||||||
|
- TL-WR843N/ND v1
|
||||||
|
- TL-WR940N v1, v2, v3
|
||||||
|
- TL-WR941ND v6
|
||||||
|
- TL-WR1043N/ND v3
|
||||||
|
|
||||||
|
* Ubiquiti
|
||||||
|
|
||||||
|
- airGateway
|
||||||
|
- airRouter
|
||||||
|
- UniFi AP Outdoor+
|
||||||
|
|
||||||
|
* Western Digital
|
||||||
|
|
||||||
|
- My Net N600
|
||||||
|
- My Net N750
|
||||||
|
|
||||||
|
x86-xen_domu
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
New target containing the necessary drivers for use in Xen.
|
||||||
|
|
||||||
|
x86-64
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
64bit version of `x86-generic`. The generic image can also be used in KVM with VirtIO.
|
||||||
|
|
||||||
|
New features
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Kernel module opkg repository
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
We've not been able to keep ABI compatiblity with the kernel of the official OpenWrt images.
|
||||||
|
Therefore, Gluon now generates an opkg repository with modules itself.
|
||||||
|
|
||||||
|
The repository can be found at `output/modules/` by default, the image output directory has
|
||||||
|
been moved from `images/` to `output/images/`. See the updated :doc:`../user/getting_started` guide
|
||||||
|
for information on the handling of the signing keys for this repository.
|
||||||
|
|
||||||
|
The `opkg_repo` site.conf option has been replaced to allow specifying this and other additional repositories.
|
||||||
|
|
||||||
|
New status page
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The new status page provides a visually pleasing experience, and displays all important information
|
||||||
|
on a node in a clear manner. It also contains a real-time signal strength graph for all neighbouring
|
||||||
|
nodes to aid with the alignment of antennas.
|
||||||
|
|
||||||
|
802.11s mesh support
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Gluon now supports using 802.11s for its mesh links instead of IBSS (Adhoc). This will allow supporting
|
||||||
|
more WLAN hardware in the future (like Ralink/Mediatek, which don't support AP and IBSS mode simultaneously).
|
||||||
|
|
||||||
|
Note that batman-adv is still used on top of 802.11s (and 802.11s forwarding is disabled), the mesh routing protocol
|
||||||
|
provided by 802.11s is not used.
|
||||||
|
|
||||||
|
Multicast filter extension
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The `gluon-ebtables-filter-multicast` package has been extended to filter out multicast
|
||||||
|
ICMP and ICMPv6 Echo Requests (ping) and Node Information Queries (RFC4620). This prevents
|
||||||
|
pings to multicast addresses like ff02::1 to cause traffic peaks
|
||||||
|
(as all nodes and clients would answer such a ping).
|
||||||
|
|
||||||
|
French translation
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
A French translation for the Config Mode/Expert Mode has been added.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
* Update kernel code for the QCA953x
|
||||||
|
|
||||||
|
Might improve stability of the TP-Link TL-WR841N/ND v9.
|
||||||
|
* Fix model detection on some Netgear WNDR3700v2
|
||||||
|
|
||||||
|
The broken devices will identify as "NETGEAR ".
|
||||||
|
This also breaks the autoupdater, making a manual upgrade necessary.
|
||||||
|
* Ensure that `odhcp6c` doesn't spawn multiple instances of ``dhcpv6.script``
|
||||||
|
* Fix support for Buffalo WZR-600DHP
|
||||||
|
|
||||||
|
A flashable factory image is generated now. The sysupgrade image is still shared
|
||||||
|
with the WZR-HP-AG300H.
|
||||||
|
|
||||||
|
Site changes
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
* ``site.conf``
|
||||||
|
|
||||||
|
- New WLAN configuration
|
||||||
|
|
||||||
|
``wifi24`` and ``wifi5`` need to be updated to a new more flexible format.
|
||||||
|
A configuration using the old format
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
{
|
||||||
|
channel = 1,
|
||||||
|
htmode = 'HT20'
|
||||||
|
ssid = 'entenhausen.freifunk.net',
|
||||||
|
mesh_ssid = 'xe:xx:xx:xx:xx:xx',
|
||||||
|
mesh_bssid = 'xe:xx:xx:xx:xx:xx',
|
||||||
|
mesh_mcast_rate = 12000,
|
||||||
|
}
|
||||||
|
|
||||||
|
would look like this in the new format::
|
||||||
|
|
||||||
|
{
|
||||||
|
channel = 1,
|
||||||
|
ap = {
|
||||||
|
ssid = 'entenhausen.freifunk.net',
|
||||||
|
},
|
||||||
|
ibss = {
|
||||||
|
ssid = 'xe:xx:xx:xx:xx:xx',
|
||||||
|
bssid = 'xe:xx:xx:xx:xx:xx',
|
||||||
|
mcast_rate = 12000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``htmode`` option has been dropped, the channel width is now always set to 20MHz
|
||||||
|
(see https://github.com/freifunk-gluon/gluon/issues/487 for a discussion of this change).
|
||||||
|
|
||||||
|
In addition to the old IBSS (Adhoc) based meshing, 802.11s-based meshing can be configured
|
||||||
|
using the ``mesh`` section. Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
channel = 1,
|
||||||
|
ap = {
|
||||||
|
ssid = 'entenhausen.freifunk.net',
|
||||||
|
},
|
||||||
|
mesh = {
|
||||||
|
id = 'mesh.entenhausen.freifunk.net', -- can by any string, human-readable or random
|
||||||
|
mcast_rate = 12000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
While using ``ibss`` and ``mesh`` at the same time is possible, is causes high load in
|
||||||
|
very active meshes, so it is advisable to avoid such configurations.
|
||||||
|
|
||||||
|
- Bandwidth limitation defaults
|
||||||
|
|
||||||
|
The old section ``simple_tc.mesh_vpn`` has been moved to ``fastd_mesh_vpn.bandwidth_limit`` and the ``ifname``
|
||||||
|
field isn't used anymore. What looked like this
|
||||||
|
before
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
simple_tc = {
|
||||||
|
mesh_vpn = {
|
||||||
|
ifname = 'mesh-vpn',
|
||||||
|
enabled = false,
|
||||||
|
limit_ingress = 3000,
|
||||||
|
limit_egress = 200,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
needs to be changed to
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
fastd_mesh_vpn = {
|
||||||
|
-- ...
|
||||||
|
|
||||||
|
bandwidth_limit = {
|
||||||
|
enabled = false,
|
||||||
|
ingress = 3000,
|
||||||
|
egress = 200,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
- opkg repository configuration
|
||||||
|
|
||||||
|
The opkg configuration has been changed to be more flexible and allow specifying custom repositories.
|
||||||
|
Example::
|
||||||
|
|
||||||
|
opkg = {
|
||||||
|
openwrt = 'http://opkg.services.ffeh/openwrt/%n/%v/%S/packages',
|
||||||
|
extra = {
|
||||||
|
modules = 'http://opkg.services.ffeh/modules/gluon-%GS-%GR/%S',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
The keys of the ``extra`` table (like ``modules`` in this example) can be chosen arbitrarily.
|
||||||
|
|
||||||
|
Instead of explicitly specifying the whole URL, using patterns is recommended. The following
|
||||||
|
patterns are understood:
|
||||||
|
|
||||||
|
- ``%n`` is replaced by the OpenWrt version codename (e.g. "chaos_calmer")
|
||||||
|
- ``%v`` is replaced by the OpenWrt version number (e.g. "15.05")
|
||||||
|
- ``%S`` is replaced by the target architecture (e.g. "ar71xx/generic")
|
||||||
|
- ``%GS`` is replaced by the Gluon site code (as specified in ``site.conf``)
|
||||||
|
- ``%GV`` is replaced by the Gluon version
|
||||||
|
- ``%GR`` is replaced by the Gluon release (as specified in ``site.mk``)
|
||||||
|
|
||||||
|
|
||||||
|
* ``site.mk``
|
||||||
|
|
||||||
|
- The packages `gluon-announce` and `gluon-announced` were merged into
|
||||||
|
the package `gluon-respondd`. If you had any of them (probably
|
||||||
|
`gluon-announced`) in your package list, you have to replace them.
|
||||||
|
|
||||||
|
|
||||||
|
* ``i18n/``
|
||||||
|
|
||||||
|
- The translations of ``gluon-config-mode:pubkey`` now have to show the fastd
|
||||||
|
public key themselves if desired, making the formatting of the key and whether it is shown at
|
||||||
|
all configurable. To retain the old format, add ``<p>`` to the beginning of
|
||||||
|
your translations and append::
|
||||||
|
|
||||||
|
"</p>"
|
||||||
|
"<div class=\"the-key\">"
|
||||||
|
" # <%= hostname %>"
|
||||||
|
" <br/>"
|
||||||
|
"<%= pubkey %>"
|
||||||
|
"</div>"
|
||||||
|
|
||||||
|
Internals
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
* OpenWrt has been updated to Chaos Calmer
|
||||||
|
* mac80211 has been backported from OpenWrt trunk r47249 (wireless-testing 2015-07-21)
|
||||||
|
|
||||||
|
This allows us to support the TL-WR940N v3/TL-WR941ND v6, which uses a TP9343 (QCA956x) SoC.
|
||||||
|
* Several packages have been moved from the Gluon repo to the packages repo, removing references to Gluon:
|
||||||
|
|
||||||
|
- gluon-cron -> micrond (the crontabs are now read from ``/usr/lib/micron.d`` instead of ``/lib/gluon/cron``)
|
||||||
|
- gluon-radvd -> uradvd
|
||||||
|
- gluon-simple-tc -> simple-tc (the config file has been renamed as well)
|
||||||
|
|
||||||
|
* Some of the Gluon-specific i18n support code in the build system has been removed, as LuCI now provides
|
||||||
|
similar facilities
|
||||||
|
* The C-based `luci-lib-jsonc` library is now used for JSON encoding/decoding instead of the pure Lua `luci-lib-json`
|
||||||
|
* The site config is now stored as JSON on the node. The Lua interface ``gluon.site_config`` is still available, and a C interface was added as part of the new package `libgluonutil`.
|
||||||
|
* The `respondd` daemon now uses C modules instead of Lua snippets, which greatly enhances response speed and reduces memory usage. The Gluon integration package has
|
||||||
|
been renamed from `gluon-announced` to `gluon-respondd`.
|
||||||
|
|
||||||
|
Known Issues
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 <https://github.com/freifunk-gluon/gluon/issues/94>`_)
|
||||||
|
|
||||||
|
Reducing the TX power in the Expert Mode is recommended.
|
||||||
|
* batman-adv causes stability issues for both alfred and respondd/announced (`#177 <https://github.com/freifunk-gluon/gluon/issues/177>`_)
|
||||||
|
* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 <https://github.com/freifunk-gluon/gluon/issues/496>`_)
|
||||||
|
|
||||||
|
This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed).
|
||||||
|
|
||||||
|
* Inconsistent respondd/announced API (`#522 <https://github.com/freifunk-gluon/gluon/issues/522>`_)
|
||||||
|
|
||||||
|
The current API is inconsistent and will be replaced in the next release. The old API will still be supported for a while.
|
@ -2,8 +2,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"PO-Revision-Date: 2015-03-19 20:28+0100\n"
|
"PO-Revision-Date: 2016-02-04 14:28+0100\n"
|
||||||
"Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n"
|
"Last-Translator: David Lutz <kpanic@hirnduenger.de>\n"
|
||||||
"Language-Team: English\n"
|
"Language-Team: English\n"
|
||||||
"Language: en\n"
|
"Language: en\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -12,15 +12,15 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "gluon-config-mode:welcome"
|
msgid "gluon-config-mode:welcome"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Welcome the the setup wizard of your new Freifunk Duckburg node. "
|
"Welcome to the setup wizard of your new Freifunk Duckburg node. "
|
||||||
"Please fill out the following form and transmit it."
|
"Please fill out the following form and submit it."
|
||||||
|
|
||||||
msgid "gluon-config-mode:pubkey"
|
msgid "gluon-config-mode:pubkey"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>This is your Freifunk node's public key. The node won't be able to "
|
"<p>This is your Freifunk node's public key. The node won't be able to "
|
||||||
"connect to the mesh VPN until the key has been registered on the Freifunk "
|
"connect to the mesh VPN until the key has been registered on the Freifunk "
|
||||||
"Duckburg servers. "
|
"Duckburg servers. "
|
||||||
"To register the key send it together with your node's name (<em><%=hostname%></em>) to "
|
"To register, send the key together with your node's name (<em><%=hostname%></em>) to "
|
||||||
"<a href=\"mailto:keys@entenhausen.freifunk.net\">keys@entenhausen.freifunk.net</a>."
|
"<a href=\"mailto:keys@entenhausen.freifunk.net\">keys@entenhausen.freifunk.net</a>."
|
||||||
"</p>"
|
"</p>"
|
||||||
"<div class=\"the-key\">"
|
"<div class=\"the-key\">"
|
||||||
@ -33,10 +33,10 @@ msgstr ""
|
|||||||
msgid "gluon-config-mode:reboot"
|
msgid "gluon-config-mode:reboot"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>The node is currently rebooting and will try to connect to other "
|
"<p>The node is currently rebooting and will try to connect to other "
|
||||||
"nearby Freifunk nodes after that. "
|
"nearby Freifunk nodes after that. "
|
||||||
"Your can find lots of information on the Freifunk Duckburg community on "
|
"For more information on the Freifunk Duckburg community, have a look at "
|
||||||
"<a href=\"https://entenhausen.freifunk.net/\">our homepage</a>.</p>"
|
"<a href=\"https://entenhausen.freifunk.net/\">our homepage</a>.</p>"
|
||||||
"<p>To get back to this configuration interface, press the reset button for "
|
"<p>To get back to this configuration interface, press the reset button for "
|
||||||
"3 seconds during normal operation. The device will then reboot into config "
|
"3 seconds during normal operation. The device will then reboot into config "
|
||||||
"mode.</p>"
|
"mode.</p>"
|
||||||
"<p>Have fun with your node and exploring the Freifunk network!</p>"
|
"<p>Have fun with your node and exploring of the Freifunk network!</p>"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
-- This is an example site configuration for Gluon v2015.1+
|
-- This is an example site configuration for Gluon v2016.1+
|
||||||
--
|
--
|
||||||
-- Take a look at the documentation located at
|
-- Take a look at the documentation located at
|
||||||
-- http://gluon.readthedocs.org/ for details.
|
-- http://gluon.readthedocs.org/ for details.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
GLUON_SITE_PACKAGES := \
|
GLUON_SITE_PACKAGES := \
|
||||||
gluon-mesh-batman-adv-15 \
|
gluon-mesh-batman-adv-15 \
|
||||||
gluon-alfred \
|
gluon-alfred \
|
||||||
gluon-announced \
|
gluon-respondd \
|
||||||
gluon-autoupdater \
|
gluon-autoupdater \
|
||||||
gluon-config-mode-autoupdater \
|
gluon-config-mode-autoupdater \
|
||||||
gluon-config-mode-contact-info \
|
gluon-config-mode-contact-info \
|
||||||
|
@ -8,7 +8,7 @@ Gluon's releases are managed using `Git tags`_. If you are just getting
|
|||||||
started with Gluon we recommend to use the latest stable release of Gluon.
|
started with Gluon we recommend to use the latest stable release of Gluon.
|
||||||
|
|
||||||
Take a look at the `list of gluon releases`_ and notice the latest release,
|
Take a look at the `list of gluon releases`_ and notice the latest release,
|
||||||
e.g. *v2014.3*. Always get Gluon using git and don't try to download it
|
e.g. *v2016.1*. Always get Gluon using git and don't try to download it
|
||||||
as a Zip archive as the archive will be missing version information.
|
as a Zip archive as the archive will be missing version information.
|
||||||
|
|
||||||
Please keep in mind that there is no "default Gluon" build; a site configuration
|
Please keep in mind that there is no "default Gluon" build; a site configuration
|
||||||
@ -42,7 +42,7 @@ Building the images
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
To build Gluon, first check out the repository. Replace *RELEASE* with the
|
To build Gluon, first check out the repository. Replace *RELEASE* with the
|
||||||
version you'd like to checkout, e.g. *v2015.1*.
|
version you'd like to checkout, e.g. *v2016.1*.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -90,12 +90,21 @@ In case of errors read the messages carefully and try to fix the stated issues (
|
|||||||
``ar71xx-generic`` is the most common target and will generate images for most of the supported hardware.
|
``ar71xx-generic`` is the most common target and will generate images for most of the supported hardware.
|
||||||
To see a complete list of supported targets, call ``make`` without setting ``GLUON_TARGET``.
|
To see a complete list of supported targets, call ``make`` without setting ``GLUON_TARGET``.
|
||||||
|
|
||||||
The built images can be found in the directory `output/images`. Of these, the factory
|
You should reserve about 10GB of disk space for each `GLUON_TARGET`.
|
||||||
|
|
||||||
|
The built images can be found in the directory `output/images`. Of these, the `factory`
|
||||||
images are to be used when flashing from the original firmware a device came with,
|
images are to be used when flashing from the original firmware a device came with,
|
||||||
and sysupgrade is to upgrade from other versions of Gluon or any other OpenWRT-based
|
and `sysupgrade` is to upgrade from other versions of Gluon or any other OpenWrt-based
|
||||||
system.
|
system.
|
||||||
|
|
||||||
You should reserve about 10GB of disk space for each `GLUON_TARGET`.
|
**Note:** The images for some models are identical; to save disk space, symlinks are generated instead
|
||||||
|
of multiple copies of the same image. If your webserver's configuration prohibits following
|
||||||
|
symlinks, you can use the following command to resolve these links while copying the images::
|
||||||
|
|
||||||
|
cp -rL output/images /var/www
|
||||||
|
|
||||||
|
Cleaning the build tree
|
||||||
|
.......................
|
||||||
|
|
||||||
There are two levels of `make clean`::
|
There are two levels of `make clean`::
|
||||||
|
|
||||||
|
@ -95,14 +95,16 @@ wifi24 : optional
|
|||||||
This will only affect new installations.
|
This will only affect new installations.
|
||||||
Upgrades will not changed the disabled state.
|
Upgrades will not changed the disabled state.
|
||||||
|
|
||||||
``ap`` requires a single parameter, a string, named ``ssid`` which sets the interface's ESSID.
|
``ap`` requires a single parameter, a string, named ``ssid`` which sets the
|
||||||
|
interface's ESSID.
|
||||||
|
|
||||||
``mesh`` requires a single parameter, a string, named ``id`` which sets the mesh id.
|
``mesh`` requires a single parameter, a string, named ``id`` which sets the mesh id.
|
||||||
|
|
||||||
``ibss`` requires two parametersr: ``ssid`` (a string) and ``bssid`` (a MAC).
|
``ibss`` requires two parametersr: ``ssid`` (a string) and ``bssid`` (a MAC).
|
||||||
An optional parameter ``vlan`` (integer) is supported.
|
An optional parameter ``vlan`` (integer) is supported.
|
||||||
|
|
||||||
Both ``mesh`` and ``ibss`` accept an optional ``mcast_rate`` (kbit/s) parameter for setting the default multicast datarate.
|
Both ``mesh`` and ``ibss`` accept an optional ``mcast_rate`` (kbit/s) parameter for
|
||||||
|
setting the default multicast datarate.
|
||||||
::
|
::
|
||||||
|
|
||||||
wifi24 = {
|
wifi24 = {
|
||||||
@ -156,10 +158,10 @@ fastd_mesh_vpn
|
|||||||
|
|
||||||
The `enabled` option can be set to true to enable the VPN by default.
|
The `enabled` option can be set to true to enable the VPN by default.
|
||||||
|
|
||||||
If `configurable` is `false` or unset, the method list will be replaced on updates
|
If `configurable` is set to `false` or unset, the method list will be replaced on updates
|
||||||
with the list in the site configuration. Setting `configurable` to `true` will allow the user to
|
with the list from the site configuration. Setting `configurable` to `true` will allow the user to
|
||||||
add the method ``null`` to the front of the method list or remove ``null`` from it,
|
add the method ``null`` to the beginning of the method list or remove ``null`` from it,
|
||||||
and make this change survive updates. Settings configurable is necessary for the
|
and make this change survive updates. Setting `configurable` is necessary for the
|
||||||
package `gluon-luci-mesh-vpn-fastd`, which adds a UI for this configuration.
|
package `gluon-luci-mesh-vpn-fastd`, which adds a UI for this configuration.
|
||||||
|
|
||||||
In any case, the ``null`` method should always be the first method in the list
|
In any case, the ``null`` method should always be the first method in the list
|
||||||
@ -169,19 +171,41 @@ fastd_mesh_vpn
|
|||||||
|
|
||||||
fastd_mesh_vpn = {
|
fastd_mesh_vpn = {
|
||||||
methods = {'salsa2012+umac'},
|
methods = {'salsa2012+umac'},
|
||||||
-- enabled = true,
|
-- enabled = true,
|
||||||
-- configurable = true,
|
-- configurable = true,
|
||||||
mtu = 1280,
|
mtu = 1280,
|
||||||
groups = {
|
groups = {
|
||||||
backbone = {
|
backbone = {
|
||||||
|
-- Limit number of connected peers from this group
|
||||||
limit = 1,
|
limit = 1,
|
||||||
peers = {
|
peers = {
|
||||||
peer1 = {
|
peer1 = {
|
||||||
key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||||
remotes = {'ipv4 "vpn1.entenhausen.freifunk.net" port 10000'},
|
-- Having multiple domains prevents SPOF in freifunk.net
|
||||||
|
remotes = {
|
||||||
|
'ipv4 "vpn1.entenhausen.freifunk.net" port 10000',
|
||||||
|
'ipv4 "vpn1.entenhausener-freifunk.de" port 10000',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
peer2 = {
|
||||||
}
|
key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||||
|
-- You can also omit the ipv4 to allow both connection via ipv4 and ipv6
|
||||||
|
remotes = {'"vpn2.entenhausen.freifunk.net" port 10000'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
-- Optional: nested peer groups
|
||||||
|
-- groups = {
|
||||||
|
-- lowend_backbone = {
|
||||||
|
-- limit = 1,
|
||||||
|
-- peers = ...
|
||||||
|
-- },
|
||||||
|
-- },
|
||||||
|
},
|
||||||
|
-- Optional: additional peer groups, possibly with other limits
|
||||||
|
-- peertopeer = {
|
||||||
|
-- limit = 10,
|
||||||
|
-- peers = { ... },
|
||||||
|
-- },
|
||||||
},
|
},
|
||||||
|
|
||||||
bandwidth_limit = {
|
bandwidth_limit = {
|
||||||
@ -207,14 +231,15 @@ autoupdater : package
|
|||||||
::
|
::
|
||||||
|
|
||||||
autoupdater = {
|
autoupdater = {
|
||||||
branch = 'experimental',
|
branch = 'stable',
|
||||||
branches = {
|
branches = {
|
||||||
stable = {
|
stable = {
|
||||||
name = 'stable',
|
name = 'stable',
|
||||||
mirrors = {
|
mirrors = {
|
||||||
'http://[fdca:ffee:babe:1::fec1]/firmware/stable/sysupgrade/',
|
'http://[fdca:ffee:babe:1::fec1]/firmware/stable/sysupgrade/',
|
||||||
'http://[fdca:ffee:babe:1::fec2]/firmware/stable/sysupgrade/',
|
'http://autoupdate.entenhausen.freifunk.net/firmware/stable/sysupgrade/',
|
||||||
},
|
},
|
||||||
|
-- Number of good signatures required
|
||||||
good_signatures = 2,
|
good_signatures = 2,
|
||||||
pubkeys = {
|
pubkeys = {
|
||||||
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', -- someguy
|
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', -- someguy
|
||||||
@ -225,9 +250,9 @@ autoupdater : package
|
|||||||
}
|
}
|
||||||
|
|
||||||
roles : optional
|
roles : optional
|
||||||
Optional role definitions. With this nodes will announce their role inside the mesh.
|
Optional role definitions. Nodes will announce their role inside the mesh.
|
||||||
In the backend this adds the facility to distinguish between normal, backbone and
|
This will allow in the backend to distinguish between normal, backbone and
|
||||||
service nodes or even gateways (if they advertise the role, also). It is up to
|
service nodes or even gateways (if they advertise that role). It is up to
|
||||||
the community which roles to define. See the section below as an example.
|
the community which roles to define. See the section below as an example.
|
||||||
``default`` takes the default role which is set initially. This value should be
|
``default`` takes the default role which is set initially. This value should be
|
||||||
part of ``list``. If you want node owners to change the role via config mode add
|
part of ``list``. If you want node owners to change the role via config mode add
|
||||||
@ -279,7 +304,7 @@ The ``site.mk`` is a Makefile which should define constants
|
|||||||
involved in the build process of Gluon.
|
involved in the build process of Gluon.
|
||||||
|
|
||||||
GLUON_SITE_PACKAGES
|
GLUON_SITE_PACKAGES
|
||||||
Defines a list of packages which should installed in addition
|
Defines a list of packages which should be installed additionally
|
||||||
to the ``gluon-core`` package.
|
to the ``gluon-core`` package.
|
||||||
|
|
||||||
GLUON_RELEASE
|
GLUON_RELEASE
|
||||||
@ -290,7 +315,7 @@ GLUON_PRIORITY
|
|||||||
for more information).
|
for more information).
|
||||||
|
|
||||||
GLUON_LANGS
|
GLUON_LANGS
|
||||||
List of languages (as two-letter-codes) to include for the web interface. Should always contain
|
List of languages (as two-letter-codes) to be included in the web interface. Should always contain
|
||||||
``en``.
|
``en``.
|
||||||
|
|
||||||
.. _site-config-mode-texts:
|
.. _site-config-mode-texts:
|
||||||
@ -362,6 +387,7 @@ site-repos in the wild
|
|||||||
|
|
||||||
This is a non-exhaustive list of site-repos from various communities:
|
This is a non-exhaustive list of site-repos from various communities:
|
||||||
|
|
||||||
|
* `site-ffa <https://github.com/tecff/site-ffa>`_ (Altdorf, Landshut & Umgebung)
|
||||||
* `site-ffbs <https://github.com/ffbs/site-ffbs>`_ (Braunschweig)
|
* `site-ffbs <https://github.com/ffbs/site-ffbs>`_ (Braunschweig)
|
||||||
* `site-ffhb <https://github.com/FreifunkBremen/gluon-site-ffhb>`_ (Bremen)
|
* `site-ffhb <https://github.com/FreifunkBremen/gluon-site-ffhb>`_ (Bremen)
|
||||||
* `site-ffda <https://github.com/freifunk-darmstadt/site-ffda>`_ (Darmstadt)
|
* `site-ffda <https://github.com/freifunk-darmstadt/site-ffda>`_ (Darmstadt)
|
||||||
@ -374,7 +400,7 @@ This is a non-exhaustive list of site-repos from various communities:
|
|||||||
* `site-ffmyk <https://github.com/FreifunkMYK/site-ffmyk>`_ (Mayen-Koblenz)
|
* `site-ffmyk <https://github.com/FreifunkMYK/site-ffmyk>`_ (Mayen-Koblenz)
|
||||||
* `site-ffm <https://github.com/freifunkMUC/site-ffm>`_ (München)
|
* `site-ffm <https://github.com/freifunkMUC/site-ffm>`_ (München)
|
||||||
* `site-ffms <https://github.com/FreiFunkMuenster/site-ffms>`_ (Münsterland)
|
* `site-ffms <https://github.com/FreiFunkMuenster/site-ffms>`_ (Münsterland)
|
||||||
* `site-ffnw <https://git.freifunk-ol.de/root/siteconf.git>`_ (Nordwest)
|
* `site-ffnw <https://git.nordwest.freifunk.net/ffnw/siteconf/tree/master>`_ (Nordwest)
|
||||||
* `site-ffpb <https://git.c3pb.de/freifunk-pb/site-ffpb>`_ (Paderborn)
|
* `site-ffpb <https://git.c3pb.de/freifunk-pb/site-ffpb>`_ (Paderborn)
|
||||||
* `site-ffka <https://github.com/ffka/site-ffka>`_ (Karlsruhe)
|
* `site-ffka <https://github.com/ffka/site-ffka>`_ (Karlsruhe)
|
||||||
* `site-ffrl <https://github.com/ffrl/sites-ffrl>`_ (Rheinland)
|
* `site-ffrl <https://github.com/ffrl/sites-ffrl>`_ (Rheinland)
|
||||||
|
@ -2,12 +2,12 @@ x86 support
|
|||||||
===========
|
===========
|
||||||
|
|
||||||
Gluon can run on normal x86 systems, for example virtual machines
|
Gluon can run on normal x86 systems, for example virtual machines
|
||||||
and VPN boxes. There is no WLAN support on x86 though.
|
and VPN boxes. By default, there is no WLAN support on x86 though.
|
||||||
|
|
||||||
Targets
|
Targets
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
There are two targets for x86 images:
|
The following targets for x86 images exist:
|
||||||
|
|
||||||
`x86-generic`
|
`x86-generic`
|
||||||
Generic x86 support with many different ethernet drivers; should run on
|
Generic x86 support with many different ethernet drivers; should run on
|
||||||
@ -27,3 +27,10 @@ There are two targets for x86 images:
|
|||||||
|
|
||||||
`x86-kvm`
|
`x86-kvm`
|
||||||
The `x86-kvm` image uses VirtIO as its harddisk and network driver.
|
The `x86-kvm` image uses VirtIO as its harddisk and network driver.
|
||||||
|
|
||||||
|
`x86-xen_domu`
|
||||||
|
The `x86-xen_domu` target contains the necessary drivers for use in Xen.
|
||||||
|
|
||||||
|
`x86-64`
|
||||||
|
64bit version of `x86-generic`. Also has VirtIO support, so there's no need for an
|
||||||
|
`x86-64-kvm` target.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
CONFIG_IMAGEOPT=y
|
CONFIG_IMAGEOPT=y
|
||||||
# CONFIG_PER_FEED_REPO is not set
|
# CONFIG_PER_FEED_REPO is not set
|
||||||
|
# CONFIG_TARGET_ROOTFS_INITRAMFS is not set
|
||||||
CONFIG_DEVEL=y
|
CONFIG_DEVEL=y
|
||||||
CONFIG_ALL_KMODS=y
|
CONFIG_ALL_KMODS=y
|
||||||
|
|
||||||
@ -17,6 +18,5 @@ CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_TIMEOUT=y
|
|||||||
|
|
||||||
CONFIG_ATH_USER_REGD=y
|
CONFIG_ATH_USER_REGD=y
|
||||||
CONFIG_PACKAGE_ATH_DEBUG=y
|
CONFIG_PACKAGE_ATH_DEBUG=y
|
||||||
CONFIG_ATH10K_CT_COMMUNITY_FW=y
|
|
||||||
|
|
||||||
CONFIG_LUCI_SRCDIET=y
|
CONFIG_LUCI_SRCDIET=y
|
||||||
|
10
modules
10
modules
@ -1,18 +1,18 @@
|
|||||||
GLUON_FEEDS='openwrt gluon routing luci'
|
GLUON_FEEDS='openwrt gluon routing luci'
|
||||||
|
|
||||||
OPENWRT_REPO=git://git.openwrt.org/15.05/openwrt.git
|
OPENWRT_REPO=git://git.openwrt.org/15.05/openwrt.git
|
||||||
OPENWRT_COMMIT=363508bcabd8e9205f5fffc8ff282439e61d618f
|
OPENWRT_COMMIT=c698aa66043a151ac76d19849be9ee24dfd78b72
|
||||||
|
|
||||||
PACKAGES_OPENWRT_REPO=git://github.com/openwrt/packages.git
|
PACKAGES_OPENWRT_REPO=git://github.com/openwrt/packages.git
|
||||||
PACKAGES_OPENWRT_COMMIT=f8a70fc188673d0ae8739b0a3095f7f61335fc10
|
PACKAGES_OPENWRT_COMMIT=9622fe984bba3a4547f48bc507ebaba7637eb2b0
|
||||||
PACKAGES_OPENWRT_BRANCH=for-15.05
|
PACKAGES_OPENWRT_BRANCH=for-15.05
|
||||||
|
|
||||||
PACKAGES_GLUON_REPO=git://github.com/freifunk-gluon/packages.git
|
PACKAGES_GLUON_REPO=git://github.com/freifunk-gluon/packages.git
|
||||||
PACKAGES_GLUON_COMMIT=b4f04f51d53b151a45f0618eef6d89d32f52dae7
|
PACKAGES_GLUON_COMMIT=06f2a62b97a25ddd1b9919d084c626d42cef5489
|
||||||
|
|
||||||
PACKAGES_ROUTING_REPO=git://github.com/openwrt-routing/packages.git
|
PACKAGES_ROUTING_REPO=git://github.com/openwrt-routing/packages.git
|
||||||
PACKAGES_ROUTING_COMMIT=ae65d4fe027592652376f8dbd3ff2ef37f5a84bc
|
PACKAGES_ROUTING_COMMIT=2a8338559de5c4b077cde7a83f43f4700a17d5cc
|
||||||
|
|
||||||
PACKAGES_LUCI_REPO=git://github.com/openwrt/luci.git
|
PACKAGES_LUCI_REPO=git://github.com/openwrt/luci.git
|
||||||
PACKAGES_LUCI_COMMIT=8832d534e96d3a934bd02711884371fc78a0d506
|
PACKAGES_LUCI_COMMIT=cdcdfd2594634804ab09dc8105e46116edce0cd6
|
||||||
PACKAGES_LUCI_BRANCH=for-15.05
|
PACKAGES_LUCI_BRANCH=for-15.05
|
||||||
|
@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/package.mk
|
|||||||
define Package/gluon-alfred
|
define Package/gluon-alfred
|
||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
DEPENDS:=+gluon-core +gluon-announced +gluon-neighbour-info +micrond +alfred
|
DEPENDS:=+gluon-core +gluon-respondd +gluon-neighbour-info +micrond +alfred
|
||||||
TITLE:=Configure alfred
|
TITLE:=Configure alfred
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
6
package/gluon-alfred/files/usr/lib/autoupdater/abort.d/60gluon-alfred
Executable file
6
package/gluon-alfred/files/usr/lib/autoupdater/abort.d/60gluon-alfred
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
start_enabled alfred
|
6
package/gluon-alfred/files/usr/lib/autoupdater/download.d/40gluon-alfred
Executable file
6
package/gluon-alfred/files/usr/lib/autoupdater/download.d/40gluon-alfred
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
stop alfred
|
@ -1,32 +0,0 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
|
||||||
|
|
||||||
PKG_NAME:=gluon-announce
|
|
||||||
PKG_VERSION:=1
|
|
||||||
PKG_RELEASE:=1
|
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
|
||||||
|
|
||||||
define Package/gluon-announce
|
|
||||||
SECTION:=gluon
|
|
||||||
CATEGORY:=Gluon
|
|
||||||
DEPENDS:=+gluon-core +luci-lib-jsonc +lua-ethtool-stats
|
|
||||||
TITLE:=Lua scripts announcing various information
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Prepare
|
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/gluon-announce/install
|
|
||||||
$(CP) ./files/* $(1)/
|
|
||||||
endef
|
|
||||||
|
|
||||||
$(eval $(call BuildPackage,gluon-announce))
|
|
@ -1 +0,0 @@
|
|||||||
return require('gluon.util').node_id()
|
|
@ -1 +0,0 @@
|
|||||||
return require('platform_info').get_model()
|
|
@ -1,14 +0,0 @@
|
|||||||
local n = 0
|
|
||||||
|
|
||||||
local cpus = util.readline(io.open('/sys/devices/system/cpu/online'))
|
|
||||||
|
|
||||||
for entry in cpus:gmatch('([^,]+)') do
|
|
||||||
local x, y = entry:match('(%d+)-(%d+)')
|
|
||||||
if x then
|
|
||||||
n = n + tonumber(y) - tonumber(x) + 1
|
|
||||||
else
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return n
|
|
@ -1 +0,0 @@
|
|||||||
return uci:get_first('system', 'system', 'hostname')
|
|
@ -1 +0,0 @@
|
|||||||
return require('gluon.sysconfig').primary_mac
|
|
@ -1 +0,0 @@
|
|||||||
return require('gluon.util').node_id()
|
|
@ -1,4 +0,0 @@
|
|||||||
return {
|
|
||||||
base = 'gluon-' .. util.readline(io.open('/lib/gluon/gluon-version')),
|
|
||||||
release = util.readline(io.open('/lib/gluon/release')),
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
return require('gluon.site_config').site_code
|
|
@ -1 +0,0 @@
|
|||||||
return tonumber(util.readline(io.open('/proc/uptime')):match('^[^ ]+ ([^ ]+)'))
|
|
@ -1 +0,0 @@
|
|||||||
return tonumber(util.readline(io.open('/proc/loadavg')):match('^([^ ]+) '))
|
|
@ -1,13 +0,0 @@
|
|||||||
local data = io.open('/proc/meminfo'):read('*a')
|
|
||||||
|
|
||||||
local fields = {}
|
|
||||||
for k, v in data:gmatch('([^\n:]+):%s*(%d+) kB') do
|
|
||||||
fields[k] = tonumber(v)
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
total = fields.MemTotal,
|
|
||||||
free = fields.MemFree,
|
|
||||||
buffers = fields.Buffers,
|
|
||||||
cached = fields.Cached,
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
return require('gluon.util').node_id()
|
|
@ -1,3 +0,0 @@
|
|||||||
local running, total = util.readline(io.open('/proc/loadavg')):match('^[^ ]+ [^ ]+ [^ ]+ (%d+)/(%d+)')
|
|
||||||
|
|
||||||
return { running = tonumber(running), total = tonumber(total) }
|
|
@ -1,4 +0,0 @@
|
|||||||
local fs = require "nixio.fs"
|
|
||||||
|
|
||||||
local st = fs.statvfs("/")
|
|
||||||
return 1 - st.bfree / st.blocks
|
|
@ -1 +0,0 @@
|
|||||||
return tonumber(util.readline(io.open('/proc/uptime')):match('^([^ ]+) '))
|
|
@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/lua
|
|
||||||
|
|
||||||
module('gluon.announce', package.seeall)
|
|
||||||
|
|
||||||
fs = require 'nixio.fs'
|
|
||||||
uci = require('luci.model.uci').cursor()
|
|
||||||
util = require 'gluon.util'
|
|
||||||
|
|
||||||
local function collect_entry(entry)
|
|
||||||
if fs.stat(entry, 'type') == 'dir' then
|
|
||||||
return collect_dir(entry)
|
|
||||||
else
|
|
||||||
return loadfile(entry)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function collect_dir(dir)
|
|
||||||
local fns = {}
|
|
||||||
|
|
||||||
for entry in fs.dir(dir) do
|
|
||||||
if entry:sub(1, 1) ~= '.' then
|
|
||||||
collectgarbage()
|
|
||||||
local fn, err = collect_entry(dir .. '/' .. entry)
|
|
||||||
|
|
||||||
if fn then
|
|
||||||
fns[entry] = fn
|
|
||||||
else
|
|
||||||
io.stderr:write(err, '\n')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return function ()
|
|
||||||
local ret = { [{}] = true }
|
|
||||||
|
|
||||||
for k, v in pairs(fns) do
|
|
||||||
collectgarbage()
|
|
||||||
local ok, val = pcall(setfenv(v, _M))
|
|
||||||
|
|
||||||
if ok then
|
|
||||||
ret[k] = val
|
|
||||||
else
|
|
||||||
io.stderr:write(val, '\n')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
collectgarbage()
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,32 +0,0 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
|
||||||
|
|
||||||
PKG_NAME:=gluon-announced
|
|
||||||
PKG_VERSION:=2
|
|
||||||
PKG_RELEASE:=1
|
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
|
||||||
|
|
||||||
define Package/gluon-announced
|
|
||||||
SECTION:=gluon
|
|
||||||
CATEGORY:=Gluon
|
|
||||||
TITLE:=Provides node information to the network
|
|
||||||
DEPENDS:=+gluon-announce +respondd +lua-deflate
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Prepare
|
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/gluon-announced/install
|
|
||||||
$(CP) ./files/* $(1)/
|
|
||||||
endef
|
|
||||||
|
|
||||||
$(eval $(call BuildPackage,gluon-announced))
|
|
@ -1,45 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
. /usr/share/libubox/jshn.sh
|
|
||||||
. /lib/functions/service.sh
|
|
||||||
|
|
||||||
DEVLIST=/var/run/gluon-announced.devs
|
|
||||||
DAEMON=/usr/bin/respondd
|
|
||||||
|
|
||||||
ifname_to_dev () {
|
|
||||||
json_load "$(ubus call network.interface.$1 status)"
|
|
||||||
json_get_var dev device
|
|
||||||
|
|
||||||
echo "$dev"
|
|
||||||
}
|
|
||||||
|
|
||||||
restart_announced () {
|
|
||||||
SERVICE_USE_PID=1
|
|
||||||
SERVICE_WRITE_PID=1
|
|
||||||
SERVICE_DAEMONIZE=1
|
|
||||||
|
|
||||||
DEVS=$(cat $DEVLIST | while read dev iface; do echo -n " -i $dev"; done)
|
|
||||||
|
|
||||||
service_stop $DAEMON
|
|
||||||
service_start $DAEMON -g ff02::2:1001 -p 1001 -c 'return require("gluon.announced").handle_request' $DEVS
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$ACTION" in
|
|
||||||
ifdown)
|
|
||||||
sed -i "/$INTERFACE/d" $DEVLIST
|
|
||||||
;;
|
|
||||||
ifup)
|
|
||||||
DEVICE="$(ifname_to_dev "$INTERFACE")"
|
|
||||||
MESH="$(cat "/sys/class/net/$DEVICE/batman_adv/mesh_iface" 2>/dev/null)"
|
|
||||||
|
|
||||||
[ "$MESH" = "bat0" -o "$INTERFACE" = "client" ] || exit 0
|
|
||||||
|
|
||||||
DEVS=$(cat $DEVLIST; echo $DEVICE $INTERFACE)
|
|
||||||
|
|
||||||
echo "$DEVS" | sort -u > $DEVLIST
|
|
||||||
|
|
||||||
restart_announced
|
|
||||||
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/lua
|
|
||||||
|
|
||||||
local uci = require('luci.model.uci').cursor()
|
|
||||||
|
|
||||||
-- Allow announced port on WAN to allow resolving neighbours over mesh-on-wan
|
|
||||||
uci:section('firewall', 'rule', 'wan_announced',
|
|
||||||
{
|
|
||||||
name = 'wan_announced',
|
|
||||||
src = 'wan',
|
|
||||||
src_ip = 'fe80::/64',
|
|
||||||
dest_port = '1001',
|
|
||||||
proto = 'udp',
|
|
||||||
target = 'ACCEPT',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
uci:save('firewall')
|
|
||||||
uci:commit('firewall')
|
|
@ -1,50 +0,0 @@
|
|||||||
local announce = require 'gluon.announce'
|
|
||||||
local deflate = require 'deflate'
|
|
||||||
local json = require 'luci.jsonc'
|
|
||||||
local nixio = require 'nixio'
|
|
||||||
local fs = require 'nixio.fs'
|
|
||||||
|
|
||||||
local memoize = {}
|
|
||||||
|
|
||||||
nixio.chdir('/lib/gluon/announce/')
|
|
||||||
|
|
||||||
for dir in fs.glob('*.d') do
|
|
||||||
local name = dir:sub(1, -3)
|
|
||||||
memoize[name] = announce.collect_dir(dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function collect(type)
|
|
||||||
return memoize[type] and memoize[type]()
|
|
||||||
end
|
|
||||||
|
|
||||||
module('gluon.announced', package.seeall)
|
|
||||||
|
|
||||||
function handle_request(query)
|
|
||||||
collectgarbage()
|
|
||||||
|
|
||||||
local m = query:match('^GET ([a-z ]+)$')
|
|
||||||
local ret
|
|
||||||
if m then
|
|
||||||
local data = {}
|
|
||||||
|
|
||||||
for q in m:gmatch('([a-z]+)') do
|
|
||||||
local ok, val = pcall(collect, q)
|
|
||||||
if ok then
|
|
||||||
data[q] = val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(data) then
|
|
||||||
ret = deflate.compress(json.stringify(data))
|
|
||||||
end
|
|
||||||
elseif query:match('^[a-z]+$') then
|
|
||||||
local ok, data = pcall(collect, query)
|
|
||||||
if ok then
|
|
||||||
ret = json.stringify(data)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
collectgarbage()
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
@ -5,29 +5,28 @@ PKG_VERSION:=4
|
|||||||
PKG_RELEASE:=$(GLUON_BRANCH)
|
PKG_RELEASE:=$(GLUON_BRANCH)
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
PKG_BUILD_DEPENDS := respondd
|
||||||
|
|
||||||
include $(GLUONDIR)/include/package.mk
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
define Package/gluon-autoupdater
|
define Package/gluon-autoupdater
|
||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
DEPENDS:=+gluon-core +micrond +autoupdater
|
DEPENDS:=+gluon-core +libgluonutil +micrond +autoupdater
|
||||||
TITLE:=Automatically update firmware
|
TITLE:=Automatically update firmware
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
endef
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-autoupdater/install
|
define Package/gluon-autoupdater/install
|
||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/autoupdater.so
|
||||||
|
|
||||||
if [ '$(GLUON_BRANCH)' ]; then \
|
if [ '$(GLUON_BRANCH)' ]; then \
|
||||||
$(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \
|
$(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \
|
||||||
echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \
|
echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
local autoupdater = uci:get_all('autoupdater', 'settings')
|
|
||||||
if autoupdater then
|
|
||||||
return {
|
|
||||||
branch = autoupdater['branch'],
|
|
||||||
enabled = uci:get_bool('autoupdater', 'settings', 'enabled'),
|
|
||||||
}
|
|
||||||
end
|
|
16
package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh
Normal file
16
package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Library to be sourced by download.d/abort.d scripts
|
||||||
|
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if [ -x /etc/init.d/$1 ]; then
|
||||||
|
echo "Stopping $1..."
|
||||||
|
/etc/init.d/$1 stop
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start_enabled() {
|
||||||
|
if [ -x /etc/init.d/$1 ] && /etc/init.d/$1 enabled; then
|
||||||
|
echo "Starting $1..."
|
||||||
|
/etc/init.d/$1 start
|
||||||
|
fi
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
start_enabled cron
|
||||||
|
start_enabled haveged
|
||||||
|
start_enabled micrond
|
||||||
|
start_enabled sysntpd
|
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
stop cron
|
||||||
|
stop haveged
|
||||||
|
stop micrond
|
||||||
|
stop sysntpd
|
6
package/gluon-autoupdater/src/Makefile
Normal file
6
package/gluon-autoupdater/src/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
all: respondd.so
|
||||||
|
|
||||||
|
CFLAGS += -Wall
|
||||||
|
|
||||||
|
respondd.so: respondd.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci
|
79
package/gluon-autoupdater/src/respondd.c
Normal file
79
package/gluon-autoupdater/src/respondd.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <respondd.h>
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <libgluonutil.h>
|
||||||
|
|
||||||
|
#include <uci.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * get_autoupdater(void) {
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
|
||||||
|
struct uci_package *p;
|
||||||
|
if (uci_load(ctx, "autoupdater", &p))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
struct uci_section *s = uci_lookup_section(ctx, p, "settings");
|
||||||
|
if (!s)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_add(ret, "branch", gluonutil_wrap_string(uci_lookup_option_string(ctx, s, "branch")));
|
||||||
|
|
||||||
|
const char *enabled = uci_lookup_option_string(ctx, s, "enabled");
|
||||||
|
json_object_object_add(ret, "enabled", json_object_new_boolean(enabled && !strcmp(enabled, "1")));
|
||||||
|
|
||||||
|
uci_free_context(ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
uci_free_context(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_nodeinfo(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *software = json_object_new_object();
|
||||||
|
json_object_object_add(software, "autoupdater", get_autoupdater());
|
||||||
|
json_object_object_add(ret, "software", software);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct respondd_provider_info respondd_providers[] = {
|
||||||
|
{"nodeinfo", respondd_provider_nodeinfo},
|
||||||
|
{}
|
||||||
|
};
|
@ -12,7 +12,7 @@ define Package/gluon-core
|
|||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
TITLE:=Base files of Gluon
|
TITLE:=Base files of Gluon
|
||||||
DEPENDS:=+gluon-site +lua-platform-info +luci-base +odhcp6c +firewall
|
DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +luci-base +luci-lib-jsonc +odhcp6c +firewall
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,20 +1,26 @@
|
|||||||
local config = os.getenv('GLUON_SITE_CONFIG') or '/lib/gluon/site.conf'
|
local function get_site_config()
|
||||||
|
local config = '/lib/gluon/site.json'
|
||||||
|
|
||||||
local function loader()
|
local json = require 'luci.jsonc'
|
||||||
coroutine.yield('return ')
|
local ltn12 = require 'luci.ltn12'
|
||||||
coroutine.yield(io.open(config):read('*a'))
|
|
||||||
|
local file = assert(io.open(config))
|
||||||
|
|
||||||
|
local decoder = json.new()
|
||||||
|
ltn12.pump.all(ltn12.source.file(io.open(config)), decoder:sink())
|
||||||
|
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
return assert(decoder:get())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- setfenv doesn't work with Lua 5.2 anymore, but we're using 5.1
|
|
||||||
local site_config = setfenv(assert(load(coroutine.wrap(loader), 'site.conf')), {})()
|
|
||||||
|
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
module 'gluon.site_config'
|
module 'gluon.site_config'
|
||||||
|
|
||||||
setmetatable(_M,
|
setmetatable(_M,
|
||||||
{
|
{
|
||||||
__index = site_config,
|
__index = get_site_config(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
rule 'MULTICAST_OUT -p IPv4 --ip-protocol icmp -j RETURN'
|
|
@ -1,2 +1,5 @@
|
|||||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol 0 -j RETURN' -- hop-by-hop
|
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type echo-request -j DROP'
|
||||||
|
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 139 -j DROP'
|
||||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j RETURN'
|
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j RETURN'
|
||||||
|
|
||||||
|
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol 0 -j RETURN' -- hop-by-hop
|
||||||
|
@ -44,7 +44,7 @@ if fs.access("/etc/config/dropbear") then
|
|||||||
|
|
||||||
function keys.write(self, section, value)
|
function keys.write(self, section, value)
|
||||||
if value then
|
if value then
|
||||||
fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"))
|
fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"):trim() .. "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ f.template = "admin/expertmode"
|
|||||||
|
|
||||||
s = f:section(SimpleSection, nil, translate(
|
s = f:section(SimpleSection, nil, translate(
|
||||||
'Your node can additionally extend your private network by bridging the WAN interface '
|
'Your node can additionally extend your private network by bridging the WAN interface '
|
||||||
.. 'with a seperate WLAN. This feature is completely independent of the mesh functionality. '
|
.. 'with a separate WLAN. This feature is completely independent of the mesh functionality. '
|
||||||
.. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled '
|
.. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled '
|
||||||
.. 'at the same time.'
|
.. 'at the same time.'
|
||||||
))
|
))
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"PO-Revision-Date: 2015-08-19 23:30+0100\n"
|
"PO-Revision-Date: 2015-08-19 23:30+0100\n"
|
||||||
"Last-Translator:Tobias Bernot <tqbs@airmail.cc>\n"
|
"Last-Translator:Tobias Bernot <tqbs@airmail.cc>\n"
|
||||||
"Language-Team: French\n"
|
"Language-Team: French\n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
@ -25,6 +25,7 @@ msgid ""
|
|||||||
"the mesh functionality. Please note that the private WLAN and meshing on the "
|
"the mesh functionality. Please note that the private WLAN and meshing on the "
|
||||||
"WAN interface should not be enabled at the same time."
|
"WAN interface should not be enabled at the same time."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Votre nœud peut étendre votre réseau privé en interfaçant le WAN avec un WLAN séparé. "
|
"Votre nœud peut étendre votre réseau privé en interfaçant le WAN avec un "
|
||||||
"Cette fonction est complètement indépendante de les fonctions de MESH. "
|
"WLAN séparé. Cette fonction est complètement indépendante de les fonctions "
|
||||||
"Il ne faut pas activer la fonction de MESH et de WLAN privé en même temps."
|
"de MESH. Il ne faut pas activer la fonction de MESH et de WLAN privé en même "
|
||||||
|
"temps."
|
||||||
|
@ -1 +0,0 @@
|
|||||||
return 14
|
|
@ -0,0 +1 @@
|
|||||||
|
14
|
@ -1 +0,0 @@
|
|||||||
return 15
|
|
@ -0,0 +1 @@
|
|||||||
|
15
|
@ -4,6 +4,7 @@ PKG_NAME:=gluon-mesh-batman-adv-core
|
|||||||
PKG_VERSION:=1
|
PKG_VERSION:=1
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
PKG_BUILD_DEPENDS := respondd
|
||||||
|
|
||||||
include $(GLUONDIR)/include/package.mk
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
@ -11,21 +12,19 @@ define Package/gluon-mesh-batman-adv-core
|
|||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
TITLE:=Support for batman-adv meshing (core)
|
TITLE:=Support for batman-adv meshing (core)
|
||||||
DEPENDS:=+gluon-core +gluon-client-bridge +firewall +libiwinfo-lua
|
DEPENDS:=+gluon-core +libgluonutil +gluon-client-bridge +firewall +libiwinfo
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
endef
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-mesh-batman-adv-core/install
|
define Package/gluon-mesh-batman-adv-core/install
|
||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/mesh-batman-adv-core.so
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-mesh-batman-adv-core/postinst
|
define Package/gluon-mesh-batman-adv-core/postinst
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
local ifname_address_cache = {}
|
|
||||||
|
|
||||||
function ifname2address(ifname)
|
|
||||||
local ifaddress
|
|
||||||
if ifname_address_cache[ifname] ~= nil then
|
|
||||||
ifaddress = ifname_address_cache[ifname]
|
|
||||||
else
|
|
||||||
ifaddress = util.readline(io.open("/sys/class/net/" .. ifname .. "/address"))
|
|
||||||
ifname_address_cache[ifname] = ifaddress
|
|
||||||
end
|
|
||||||
|
|
||||||
return ifaddress
|
|
||||||
end
|
|
||||||
|
|
||||||
function batadv()
|
|
||||||
local interfaces = {}
|
|
||||||
local list = io.lines("/sys/kernel/debug/batman_adv/bat0/originators")
|
|
||||||
for line in list do
|
|
||||||
local mac1, lastseen, tq, mac2, ifname =
|
|
||||||
line:match("^([0-9a-f:]+) +(%d+%.%d+)s +%( *(%d+)%) +([0-9a-f:]+) +%[ *(.-)%]")
|
|
||||||
|
|
||||||
if mac1 ~= nil and mac1 == mac2 then
|
|
||||||
ifaddress = ifname2address(ifname)
|
|
||||||
if interfaces[ifaddress] == nil then
|
|
||||||
interfaces[ifaddress] = { neighbours = { [{}] = true } }
|
|
||||||
end
|
|
||||||
|
|
||||||
interfaces[ifaddress].neighbours[mac1] = { tq = tonumber(tq)
|
|
||||||
, lastseen = tonumber(lastseen)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(interfaces) then
|
|
||||||
return interfaces
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return batadv()
|
|
@ -1,40 +0,0 @@
|
|||||||
local batman_adv = require 'gluon.batman_adv'
|
|
||||||
local iwinfo = require 'iwinfo'
|
|
||||||
|
|
||||||
function neighbours(iface)
|
|
||||||
local stations = {}
|
|
||||||
for k, v in pairs(iface.iw.assoclist(iface.ifname)) do
|
|
||||||
stations[k:lower()] = { signal = v.signal
|
|
||||||
, noise = v.noise
|
|
||||||
, inactive = v.inactive
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(stations) then
|
|
||||||
return stations
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function interfaces()
|
|
||||||
local interfaces = {}
|
|
||||||
for ifname in batman_adv.interfaces('bat0') do
|
|
||||||
pcall(function()
|
|
||||||
local address = util.readline(io.open('/sys/class/net/' .. ifname .. '/address'))
|
|
||||||
local wifitype = iwinfo.type(ifname)
|
|
||||||
if wifitype ~= nil then
|
|
||||||
interfaces[address] = { ifname = ifname, iw = iwinfo[wifitype] }
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
return interfaces
|
|
||||||
end
|
|
||||||
|
|
||||||
local wifi = {}
|
|
||||||
for address, iface in pairs(interfaces()) do
|
|
||||||
wifi[address] = { [{}] = true, neighbours = neighbours(iface) }
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(wifi) then
|
|
||||||
return wifi
|
|
||||||
end
|
|
@ -1,15 +0,0 @@
|
|||||||
local ip = require 'luci.ip'
|
|
||||||
local bit = require 'nixio'.bit
|
|
||||||
|
|
||||||
local addresses = {}
|
|
||||||
|
|
||||||
for line in io.lines('/proc/net/if_inet6') do
|
|
||||||
local matches = { line:match('^' .. string.rep('(%x%x%x%x)', 8) .. string.rep(' %x%x', 3) .. ' (%x%x)%s+([^%s]+)$') }
|
|
||||||
-- exclude wrong interfaces and deprecated as well as tentative addresses
|
|
||||||
-- (see /include/uapi/linux/if_addr.h in linux source for flags)
|
|
||||||
if matches[10] == 'br-client' and bit.band(tonumber(matches[9], 16), 0x60) == 0 then
|
|
||||||
table.insert(addresses, ip.IPv6(string.format('%s:%s:%s:%s:%s:%s:%s:%s', unpack(matches))):string():lower())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return addresses
|
|
@ -1,56 +0,0 @@
|
|||||||
local batman_adv = require 'gluon.batman_adv'
|
|
||||||
|
|
||||||
local wireless = {}
|
|
||||||
local tunnel = {}
|
|
||||||
local other = {}
|
|
||||||
|
|
||||||
local function get_address(t, ifname)
|
|
||||||
pcall(
|
|
||||||
function()
|
|
||||||
table.insert(t, util.readline(io.open('/sys/class/net/' .. ifname .. '/address')))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function file_exists(filename)
|
|
||||||
local f = io.open(filename)
|
|
||||||
if f == nil then
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
f:close()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function is_wireless(ifname)
|
|
||||||
return file_exists('/sys/class/net/' .. ifname .. '/wireless')
|
|
||||||
end
|
|
||||||
|
|
||||||
local function is_tuntap(ifname)
|
|
||||||
return file_exists('/sys/class/net/' .. ifname .. '/tun_flags')
|
|
||||||
end
|
|
||||||
|
|
||||||
local function nil_table(t)
|
|
||||||
if next(t) ~= nil then
|
|
||||||
return t
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for ifname in batman_adv.interfaces('bat0') do
|
|
||||||
if is_wireless(ifname) then
|
|
||||||
get_address(wireless, ifname)
|
|
||||||
elseif is_tuntap(ifname) then
|
|
||||||
get_address(tunnel, ifname)
|
|
||||||
else
|
|
||||||
get_address(other, ifname)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
wireless = nil_table(wireless),
|
|
||||||
tunnel = nil_table(tunnel),
|
|
||||||
other = nil_table(other),
|
|
||||||
[{}] = true
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
local batman_adv = require 'gluon.batman_adv'
|
|
||||||
|
|
||||||
local interfaces = {}
|
|
||||||
|
|
||||||
for ifname in batman_adv.interfaces('bat0') do
|
|
||||||
pcall(
|
|
||||||
function()
|
|
||||||
table.insert(interfaces, util.readline(io.open('/sys/class/net/' .. ifname .. '/address')))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
return interfaces
|
|
@ -1 +0,0 @@
|
|||||||
return util.readline(io.open('/sys/module/batman_adv/version'))
|
|
@ -1,55 +0,0 @@
|
|||||||
local iwinfo = require 'iwinfo'
|
|
||||||
|
|
||||||
local counts = { total = 0
|
|
||||||
, wifi = 0
|
|
||||||
, wifi24 = 0
|
|
||||||
, wifi5 = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
local list = io.lines("/sys/kernel/debug/batman_adv/bat0/transtable_local")
|
|
||||||
local clients = {}
|
|
||||||
for line in list do
|
|
||||||
local mac, _, flags, lastseen = line:match("^ %* ([0-9a-f:]+) *(.- )%[(.-)%] +(%d+%.%d+)")
|
|
||||||
if mac then
|
|
||||||
if not flags:match('P') then
|
|
||||||
counts.total = counts.total + 1
|
|
||||||
clients[mac:lower()] = true
|
|
||||||
|
|
||||||
if flags:match('W') then
|
|
||||||
counts.wifi = counts.wifi +1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function count_iface_stations(iface)
|
|
||||||
local wifitype = iwinfo.type(iface)
|
|
||||||
if wifitype == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local freq = iwinfo[wifitype].frequency(iface)
|
|
||||||
local key
|
|
||||||
if freq >= 2400 and freq < 2500 then
|
|
||||||
key = "wifi24"
|
|
||||||
elseif freq >= 5000 and freq < 6000 then
|
|
||||||
key = "wifi5"
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(iwinfo[wifitype].assoclist(iface)) do
|
|
||||||
if clients[k:lower()] then
|
|
||||||
counts[key] = counts[key] + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ifaces = {}
|
|
||||||
uci:foreach("wireless", "wifi-iface", function(s)
|
|
||||||
if s.network == "client" and s.mode == "ap" then
|
|
||||||
count_iface_stations(s.ifname)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
return counts
|
|
@ -1,12 +0,0 @@
|
|||||||
local gateway = ''
|
|
||||||
|
|
||||||
for line in io.lines('/sys/kernel/debug/batman_adv/bat0/gateways') do
|
|
||||||
if line:sub(1, 3) == '=> ' then
|
|
||||||
gateway = line:sub(4, 20)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if gateway ~= '' then
|
|
||||||
return gateway
|
|
||||||
end
|
|
@ -1,14 +0,0 @@
|
|||||||
local ethtool = require 'ethtool_stats'
|
|
||||||
|
|
||||||
local fields = ethtool.interface_stats('bat0')
|
|
||||||
|
|
||||||
local traffic = {}
|
|
||||||
for _, class in ipairs({'rx', 'tx', 'forward', 'mgmt_rx', 'mgmt_tx'}) do
|
|
||||||
traffic[class] = {
|
|
||||||
bytes = fields[class .. '_bytes'],
|
|
||||||
packets = fields[class],
|
|
||||||
}
|
|
||||||
end
|
|
||||||
traffic['tx']['dropped'] = fields['tx_dropped']
|
|
||||||
|
|
||||||
return traffic
|
|
@ -10,6 +10,7 @@ if not c:get('network', 'mesh_wan') then
|
|||||||
{ ifname = 'br-wan'
|
{ ifname = 'br-wan'
|
||||||
, proto = 'batadv'
|
, proto = 'batadv'
|
||||||
, mesh = 'bat0'
|
, mesh = 'bat0'
|
||||||
|
, mesh_no_rebroadcast = '1'
|
||||||
, auto = site.mesh_on_wan and 1 or 0
|
, auto = site.mesh_on_wan and 1 or 0
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -27,6 +27,7 @@ if sysconfig.lan_ifname and not uci:get('network', 'mesh_lan') then
|
|||||||
{ ifname = sysconfig.lan_ifname
|
{ ifname = sysconfig.lan_ifname
|
||||||
, proto = 'batadv'
|
, proto = 'batadv'
|
||||||
, mesh = 'bat0'
|
, mesh = 'bat0'
|
||||||
|
, mesh_no_rebroadcast = '1'
|
||||||
, macaddr = util.generate_mac(1, 1)
|
, macaddr = util.generate_mac(1, 1)
|
||||||
, auto = enable and 1 or 0
|
, auto = enable and 1 or 0
|
||||||
})
|
})
|
||||||
@ -34,4 +35,3 @@ if sysconfig.lan_ifname and not uci:get('network', 'mesh_lan') then
|
|||||||
uci:save('network')
|
uci:save('network')
|
||||||
uci:commit('network')
|
uci:commit('network')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
6
package/gluon-mesh-batman-adv-core/src/Makefile
Normal file
6
package/gluon-mesh-batman-adv-core/src/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
all: respondd.so
|
||||||
|
|
||||||
|
CFLAGS += -Wall
|
||||||
|
|
||||||
|
respondd.so: respondd.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -liwinfo -luci
|
604
package/gluon-mesh-batman-adv-core/src/respondd.c
Normal file
604
package/gluon-mesh-batman-adv-core/src/respondd.c
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <respondd.h>
|
||||||
|
|
||||||
|
#include <iwinfo.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <libgluonutil.h>
|
||||||
|
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_addr.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define _STRINGIFY(s) #s
|
||||||
|
#define STRINGIFY(s) _STRINGIFY(s)
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * get_addresses(void) {
|
||||||
|
FILE *f = fopen("/proc/net/if_inet6", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_array();
|
||||||
|
|
||||||
|
while (getline(&line, &len, f) >= 0) {
|
||||||
|
/* IF_NAMESIZE would be enough, but adding 1 here is simpler than subtracting 1 in the format string */
|
||||||
|
char ifname[IF_NAMESIZE+1];
|
||||||
|
unsigned int flags;
|
||||||
|
struct in6_addr addr;
|
||||||
|
char buf[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (sscanf(line,
|
||||||
|
"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8
|
||||||
|
"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8
|
||||||
|
" %*2x %*2x %*2x %2x %"STRINGIFY(IF_NAMESIZE)"s",
|
||||||
|
&addr.s6_addr[0], &addr.s6_addr[1], &addr.s6_addr[2], &addr.s6_addr[3],
|
||||||
|
&addr.s6_addr[4], &addr.s6_addr[5], &addr.s6_addr[6], &addr.s6_addr[7],
|
||||||
|
&addr.s6_addr[8], &addr.s6_addr[9], &addr.s6_addr[10], &addr.s6_addr[11],
|
||||||
|
&addr.s6_addr[12], &addr.s6_addr[13], &addr.s6_addr[14], &addr.s6_addr[15],
|
||||||
|
&flags, ifname) != 18)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(ifname, "br-client"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (flags & (IFA_F_TENTATIVE|IFA_F_DEPRECATED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
|
||||||
|
|
||||||
|
json_object_array_add(ret, json_object_new_string(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_if_not_empty(struct json_object *obj, const char *key, struct json_object *val) {
|
||||||
|
if (json_object_array_length(val))
|
||||||
|
json_object_object_add(obj, key, val);
|
||||||
|
else
|
||||||
|
json_object_put(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool interface_file_exists(const char *ifname, const char *name) {
|
||||||
|
const char *format = "/sys/class/net/%s/%s";
|
||||||
|
char path[strlen(format) + strlen(ifname) + strlen(name)];
|
||||||
|
snprintf(path, sizeof(path), format, ifname, name);
|
||||||
|
|
||||||
|
return !access(path, F_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mesh_add_subif(const char *ifname, struct json_object *wireless,
|
||||||
|
struct json_object *tunnel, struct json_object *other) {
|
||||||
|
struct json_object *address = gluonutil_wrap_and_free_string(gluonutil_get_interface_address(ifname));
|
||||||
|
|
||||||
|
if (interface_file_exists(ifname, "wireless"))
|
||||||
|
json_object_array_add(wireless, address);
|
||||||
|
else if (interface_file_exists(ifname, "tun_flags"))
|
||||||
|
json_object_array_add(tunnel, address);
|
||||||
|
else
|
||||||
|
json_object_array_add(other, address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_mesh_subifs(const char *ifname) {
|
||||||
|
struct json_object *wireless = json_object_new_array();
|
||||||
|
struct json_object *tunnel = json_object_new_array();
|
||||||
|
struct json_object *other = json_object_new_array();
|
||||||
|
|
||||||
|
const char *format = "/sys/class/net/%s/lower_*";
|
||||||
|
char pattern[strlen(format) + strlen(ifname) - 1];
|
||||||
|
snprintf(pattern, sizeof(pattern), format, ifname);
|
||||||
|
|
||||||
|
size_t pattern_len = strlen(pattern);
|
||||||
|
|
||||||
|
glob_t lower;
|
||||||
|
if (!glob(pattern, GLOB_NOSORT, NULL, &lower)) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < lower.gl_pathc; i++) {
|
||||||
|
mesh_add_subif(lower.gl_pathv[i] + pattern_len - 1,
|
||||||
|
wireless, tunnel, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&lower);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
add_if_not_empty(ret, "wireless", wireless);
|
||||||
|
add_if_not_empty(ret, "tunnel", tunnel);
|
||||||
|
add_if_not_empty(ret, "other", other);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_mesh(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
struct json_object *bat0_interfaces = json_object_new_object();
|
||||||
|
json_object_object_add(bat0_interfaces, "interfaces", get_mesh_subifs("bat0"));
|
||||||
|
json_object_object_add(ret, "bat0", bat0_interfaces);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_batman_adv_compat(void) {
|
||||||
|
FILE *f = fopen("/lib/gluon/mesh-batman-adv-core/compat", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *ret = NULL;
|
||||||
|
|
||||||
|
int compat;
|
||||||
|
if (fscanf(f, "%i", &compat) == 1)
|
||||||
|
ret = json_object_new_int(compat);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_nodeinfo(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *network = json_object_new_object();
|
||||||
|
json_object_object_add(network, "addresses", get_addresses());
|
||||||
|
json_object_object_add(network, "mesh", get_mesh());
|
||||||
|
json_object_object_add(ret, "network", network);
|
||||||
|
|
||||||
|
struct json_object *software = json_object_new_object();
|
||||||
|
struct json_object *software_batman_adv = json_object_new_object();
|
||||||
|
json_object_object_add(software_batman_adv, "version", gluonutil_wrap_and_free_string(gluonutil_read_line("/sys/module/batman_adv/version")));
|
||||||
|
json_object_object_add(software_batman_adv, "compat", get_batman_adv_compat());
|
||||||
|
json_object_object_add(software, "batman-adv", software_batman_adv);
|
||||||
|
json_object_object_add(ret, "software", software);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_gateway(struct json_object *obj) {
|
||||||
|
FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/gateways", "r");
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (getline(&line, &len, f) >= 0) {
|
||||||
|
char addr[18];
|
||||||
|
|
||||||
|
if (sscanf(line, "=> %17[0-9a-fA-F:]", addr) != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
json_object_object_add(obj, "gateway", json_object_new_string(addr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool ethtool_ioctl(int fd, struct ifreq *ifr, void *data) {
|
||||||
|
ifr->ifr_data = data;
|
||||||
|
|
||||||
|
return (ioctl(fd, SIOCETHTOOL, ifr) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ethtool_get_stats_length(int fd, struct ifreq *ifr) {
|
||||||
|
const size_t sset_info_len = sizeof(struct ethtool_sset_info) + sizeof(uint32_t);
|
||||||
|
struct ethtool_sset_info *sset_info = alloca(sset_info_len);
|
||||||
|
memset(sset_info, 0, sset_info_len);
|
||||||
|
|
||||||
|
sset_info->cmd = ETHTOOL_GSSET_INFO;
|
||||||
|
sset_info->sset_mask = 1ull << ETH_SS_STATS;
|
||||||
|
|
||||||
|
if (!ethtool_ioctl(fd, ifr, sset_info))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sset_info->sset_mask ? sset_info->data[0] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ethtool_gstrings * ethtool_get_stats_strings(int fd, struct ifreq *ifr) {
|
||||||
|
uint32_t n_stats = ethtool_get_stats_length(fd, ifr);
|
||||||
|
|
||||||
|
if (!n_stats)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct ethtool_gstrings *strings = calloc(1, sizeof(*strings) + n_stats * ETH_GSTRING_LEN);
|
||||||
|
|
||||||
|
strings->cmd = ETHTOOL_GSTRINGS;
|
||||||
|
strings->string_set = ETH_SS_STATS;
|
||||||
|
strings->len = n_stats;
|
||||||
|
|
||||||
|
if (!ethtool_ioctl(fd, ifr, strings)) {
|
||||||
|
free(strings);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * get_traffic(void) {
|
||||||
|
struct ethtool_gstrings *strings = NULL;
|
||||||
|
struct ethtool_stats *stats = NULL;
|
||||||
|
|
||||||
|
struct ifreq ifr = {};
|
||||||
|
strncpy(ifr.ifr_name, "bat0", IF_NAMESIZE);
|
||||||
|
|
||||||
|
struct json_object *ret = NULL;
|
||||||
|
|
||||||
|
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
strings = ethtool_get_stats_strings(fd, &ifr);
|
||||||
|
if (!strings)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
stats = calloc(1, sizeof(struct ethtool_stats) + strings->len * sizeof(uint64_t));
|
||||||
|
stats->cmd = ETHTOOL_GSTATS;
|
||||||
|
stats->n_stats = strings->len;
|
||||||
|
|
||||||
|
if (!ethtool_ioctl(fd, &ifr, stats))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
struct json_object *rx = json_object_new_object();
|
||||||
|
struct json_object *tx = json_object_new_object();
|
||||||
|
struct json_object *forward = json_object_new_object();
|
||||||
|
struct json_object *mgmt_rx = json_object_new_object();
|
||||||
|
struct json_object *mgmt_tx = json_object_new_object();
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < strings->len; i++) {
|
||||||
|
if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "rx", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(rx, "packets", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "rx_bytes", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(rx, "bytes", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "tx", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(tx, "packets", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "tx_dropped", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(tx, "dropped", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "tx_bytes", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(tx, "bytes", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "forward", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(forward, "packets", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "forward_bytes", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(forward, "bytes", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "mgmt_rx", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(mgmt_rx, "packets", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "mgmt_rx_bytes", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(mgmt_rx, "bytes", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "mgmt_tx", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(mgmt_tx, "packets", json_object_new_int64(stats->data[i]));
|
||||||
|
else if (!strncmp((const char*)&strings->data[i * ETH_GSTRING_LEN], "mgmt_tx_bytes", ETH_GSTRING_LEN))
|
||||||
|
json_object_object_add(mgmt_tx, "bytes", json_object_new_int64(stats->data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = json_object_new_object();
|
||||||
|
json_object_object_add(ret, "rx", rx);
|
||||||
|
json_object_object_add(ret, "tx", tx);
|
||||||
|
json_object_object_add(ret, "forward", forward);
|
||||||
|
json_object_object_add(ret, "mgmt_rx", mgmt_rx);
|
||||||
|
json_object_object_add(ret, "mgmt_tx", mgmt_tx);
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(stats);
|
||||||
|
free(strings);
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void count_iface_stations(size_t *wifi24, size_t *wifi5, const char *ifname) {
|
||||||
|
const struct iwinfo_ops *iw = iwinfo_backend(ifname);
|
||||||
|
if (!iw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int freq;
|
||||||
|
if (iw->frequency(ifname, &freq) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t *wifi;
|
||||||
|
if (freq >= 2400 && freq < 2500)
|
||||||
|
wifi = wifi24;
|
||||||
|
else if (freq >= 5000 && freq < 6000)
|
||||||
|
wifi = wifi5;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char buf[IWINFO_BUFSIZE];
|
||||||
|
if (iw->assoclist(ifname, buf, &len) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct iwinfo_assoclist_entry *entry;
|
||||||
|
for (entry = (struct iwinfo_assoclist_entry *)buf; (char*)(entry+1) <= buf + len; entry++)
|
||||||
|
(*wifi)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void count_stations(size_t *wifi24, size_t *wifi5) {
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
struct uci_package *p;
|
||||||
|
if (uci_load(ctx, "wireless", &p))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
|
||||||
|
struct uci_element *e;
|
||||||
|
uci_foreach_element(&p->sections, e) {
|
||||||
|
struct uci_section *s = uci_to_section(e);
|
||||||
|
if (strcmp(s->type, "wifi-iface"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *network = uci_lookup_option_string(ctx, s, "network");
|
||||||
|
if (!network || strcmp(network, "client"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *mode = uci_lookup_option_string(ctx, s, "mode");
|
||||||
|
if (!mode || strcmp(mode, "ap"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *ifname = uci_lookup_option_string(ctx, s, "ifname");
|
||||||
|
if (!ifname)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
count_iface_stations(wifi24, wifi5, ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
uci_free_context(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_clients(void) {
|
||||||
|
size_t total = 0, wifi = 0, wifi24 = 0, wifi5 = 0;
|
||||||
|
|
||||||
|
FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/transtable_local", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (getline(&line, &len, f) >= 0) {
|
||||||
|
char flags[16];
|
||||||
|
|
||||||
|
if (sscanf(line, " * %*[^[] [%15[^]]]", flags) != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strchr(flags, 'P'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
total++;
|
||||||
|
|
||||||
|
if (strchr(flags, 'W'))
|
||||||
|
wifi++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
count_stations(&wifi24, &wifi5);
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
json_object_object_add(ret, "total", json_object_new_int(total));
|
||||||
|
json_object_object_add(ret, "wifi", json_object_new_int(wifi));
|
||||||
|
json_object_object_add(ret, "wifi24", json_object_new_int(wifi24));
|
||||||
|
json_object_object_add(ret, "wifi5", json_object_new_int(wifi5));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_statistics(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_add(ret, "clients", get_clients());
|
||||||
|
json_object_object_add(ret, "traffic", get_traffic());
|
||||||
|
|
||||||
|
add_gateway(ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * ifnames2addrs(struct json_object *interfaces) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_foreach(interfaces, ifname, interface) {
|
||||||
|
char *ifaddr = gluonutil_get_interface_address(ifname);
|
||||||
|
if (!ifaddr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct json_object *obj = json_object_new_object();
|
||||||
|
json_object_object_add(obj, "neighbours", json_object_get(interface));
|
||||||
|
json_object_object_add(ret, ifaddr, obj);
|
||||||
|
|
||||||
|
free(ifaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_put(interfaces);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_batadv(void) {
|
||||||
|
FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/originators", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
struct json_object *interfaces = json_object_new_object();
|
||||||
|
|
||||||
|
while (getline(&line, &len, f) >= 0) {
|
||||||
|
char mac1[18], mac2[18];
|
||||||
|
/* IF_NAMESIZE would be enough, but adding 1 here is simpler than subtracting 1 in the format string */
|
||||||
|
char ifname[IF_NAMESIZE+1];
|
||||||
|
double lastseen;
|
||||||
|
int tq;
|
||||||
|
|
||||||
|
if (sscanf(line,
|
||||||
|
"%17[0-9a-fA-F:] %lfs ( %i ) %17[0-9a-fA-F:] [ %"STRINGIFY(IF_NAMESIZE)"[^]] ]",
|
||||||
|
mac1, &lastseen, &tq, mac2, ifname) != 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(mac1, mac2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct json_object *interface;
|
||||||
|
if (!json_object_object_get_ex(interfaces, ifname, &interface)) {
|
||||||
|
interface = json_object_new_object();
|
||||||
|
json_object_object_add(interfaces, ifname, interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *obj = json_object_new_object();
|
||||||
|
json_object_object_add(obj, "tq", json_object_new_int(tq));
|
||||||
|
json_object_object_add(obj, "lastseen", json_object_new_double(lastseen));
|
||||||
|
json_object_object_add(interface, mac1, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
return ifnames2addrs(interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_wifi_neighbours(const char *ifname) {
|
||||||
|
const struct iwinfo_ops *iw = iwinfo_backend(ifname);
|
||||||
|
if (!iw)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char buf[IWINFO_BUFSIZE];
|
||||||
|
if (iw->assoclist(ifname, buf, &len) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *neighbours = json_object_new_object();
|
||||||
|
|
||||||
|
struct iwinfo_assoclist_entry *entry;
|
||||||
|
for (entry = (struct iwinfo_assoclist_entry *)buf; (char*)(entry+1) <= buf + len; entry++) {
|
||||||
|
struct json_object *obj = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_add(obj, "signal", json_object_new_int(entry->signal));
|
||||||
|
json_object_object_add(obj, "noise", json_object_new_int(entry->noise));
|
||||||
|
json_object_object_add(obj, "inactive", json_object_new_int(entry->inactive));
|
||||||
|
|
||||||
|
char mac[18];
|
||||||
|
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
entry->mac[0], entry->mac[1], entry->mac[2],
|
||||||
|
entry->mac[3], entry->mac[4], entry->mac[5]);
|
||||||
|
|
||||||
|
json_object_object_add(neighbours, mac, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
if (json_object_object_length(neighbours))
|
||||||
|
json_object_object_add(ret, "neighbours", neighbours);
|
||||||
|
else
|
||||||
|
json_object_put(neighbours);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_wifi(void) {
|
||||||
|
const char *mesh = "bat0";
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
const char *format = "/sys/class/net/%s/lower_*";
|
||||||
|
char pattern[strlen(format) + strlen(mesh)];
|
||||||
|
snprintf(pattern, sizeof(pattern), format, mesh);
|
||||||
|
|
||||||
|
size_t pattern_len = strlen(pattern);
|
||||||
|
|
||||||
|
glob_t lower;
|
||||||
|
if (!glob(pattern, GLOB_NOSORT, NULL, &lower)) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < lower.gl_pathc; i++) {
|
||||||
|
const char *ifname = lower.gl_pathv[i] + pattern_len - 1;
|
||||||
|
char *ifaddr = gluonutil_get_interface_address(ifname);
|
||||||
|
if (!ifaddr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct json_object *neighbours = get_wifi_neighbours(ifname);
|
||||||
|
if (neighbours)
|
||||||
|
json_object_object_add(ret, ifaddr, neighbours);
|
||||||
|
|
||||||
|
free(ifaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&lower);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_neighbours(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *batadv = get_batadv();
|
||||||
|
if (batadv)
|
||||||
|
json_object_object_add(ret, "batadv", batadv);
|
||||||
|
|
||||||
|
struct json_object *wifi = get_wifi();
|
||||||
|
if (wifi)
|
||||||
|
json_object_object_add(ret, "wifi", wifi);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct respondd_provider_info respondd_providers[] = {
|
||||||
|
{"nodeinfo", respondd_provider_nodeinfo},
|
||||||
|
{"statistics", respondd_provider_statistics},
|
||||||
|
{"neighbours", respondd_provider_neighbours},
|
||||||
|
{}
|
||||||
|
};
|
@ -4,6 +4,7 @@ PKG_NAME:=gluon-mesh-vpn-fastd
|
|||||||
PKG_VERSION:=3
|
PKG_VERSION:=3
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
PKG_BUILD_DEPENDS := respondd
|
||||||
|
|
||||||
include $(GLUONDIR)/include/package.mk
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
@ -11,25 +12,19 @@ define Package/gluon-mesh-vpn-fastd
|
|||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
TITLE:=Support for connecting batman-adv meshes via fastd
|
TITLE:=Support for connecting batman-adv meshes via fastd
|
||||||
DEPENDS:=+gluon-core gluon-mesh-batman-adv +gluon-wan-dnsmasq +fastd +iptables-mod-extra +simple-tc
|
DEPENDS:=+gluon-core +libgluonutil gluon-mesh-batman-adv +gluon-wan-dnsmasq +fastd +iptables-mod-extra +simple-tc
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/gluon-mesh-vpn-fastd/description
|
|
||||||
Gluon community wifi mesh firmware framework: fastd support
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
endef
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-mesh-vpn-fastd/install
|
define Package/gluon-mesh-vpn-fastd/install
|
||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/mesh-vpn-fastd.so
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-mesh-vpn-fastd/postinst
|
define Package/gluon-mesh-vpn-fastd/postinst
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
local ret = {
|
|
||||||
enabled = uci:get('fastd', 'mesh_vpn', 'enabled') ~= 0,
|
|
||||||
version = util.readline(io.popen('exec fastd -v')):match('^[^%s]+%s+(.+)'),
|
|
||||||
}
|
|
||||||
return ret
|
|
@ -1,70 +0,0 @@
|
|||||||
local json = require 'luci.jsonc'
|
|
||||||
local ltn12 = require 'luci.ltn12'
|
|
||||||
local nixio = require 'nixio'
|
|
||||||
local site = require 'gluon.site_config'
|
|
||||||
|
|
||||||
local fastd_sock = nixio.socket('unix', 'stream')
|
|
||||||
local socket_path = uci:get('fastd', 'mesh_vpn', 'status_socket')
|
|
||||||
|
|
||||||
if not fastd_sock:connect(socket_path) then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local decoder = json.new()
|
|
||||||
ltn12.pump.all(ltn12.source.file(fastd_sock), decoder:sink())
|
|
||||||
|
|
||||||
local status = decoder:get()
|
|
||||||
|
|
||||||
|
|
||||||
local peer_groups
|
|
||||||
|
|
||||||
local function peer_connection(config)
|
|
||||||
local peer = status.peers[config.key]
|
|
||||||
if peer then
|
|
||||||
if peer.connection then
|
|
||||||
return {
|
|
||||||
established = peer.connection.established/1000
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return function()end -- nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function peer_group(config)
|
|
||||||
local ret = {}
|
|
||||||
|
|
||||||
if config.peers then
|
|
||||||
local peers = {}
|
|
||||||
|
|
||||||
for peername, peerconfig in pairs(config.peers) do
|
|
||||||
peers[peername] = peer_connection(peerconfig)
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(peers) then
|
|
||||||
ret.peers = peers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ret.groups = peer_groups(config.groups)
|
|
||||||
|
|
||||||
if next(ret) then
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function peer_groups(groups)
|
|
||||||
if groups then
|
|
||||||
local ret = {}
|
|
||||||
|
|
||||||
for name, group in pairs(groups) do
|
|
||||||
ret[name] = peer_group(group)
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(ret) then
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return peer_group(site.fastd_mesh_vpn)
|
|
6
package/gluon-mesh-vpn-fastd/src/Makefile
Normal file
6
package/gluon-mesh-vpn-fastd/src/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
all: respondd.so
|
||||||
|
|
||||||
|
CFLAGS += -Wall
|
||||||
|
|
||||||
|
respondd.so: respondd.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci
|
305
package/gluon-mesh-vpn-fastd/src/respondd.c
Normal file
305
package/gluon-mesh-vpn-fastd/src/respondd.c
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <respondd.h>
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <libgluonutil.h>
|
||||||
|
#include <uci.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
|
||||||
|
static struct json_object * get_peer_groups(struct json_object *groups, struct json_object *peers);
|
||||||
|
|
||||||
|
static struct json_object * get_fastd_version(void) {
|
||||||
|
FILE *f = popen("exec fastd -v", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
ssize_t r = getline(&line, &len, f);
|
||||||
|
|
||||||
|
pclose(f);
|
||||||
|
|
||||||
|
if (r >= 0) {
|
||||||
|
len = strlen(line); /* The len given by getline is the buffer size, not the string length */
|
||||||
|
|
||||||
|
if (len && line[len-1] == '\n')
|
||||||
|
line[len-1] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free(line);
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *version = line;
|
||||||
|
if (strncmp(version, "fastd ", 6) == 0)
|
||||||
|
version += 6;
|
||||||
|
|
||||||
|
struct json_object *ret = gluonutil_wrap_string(version);
|
||||||
|
free(line);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_fastd(void) {
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
|
||||||
|
struct uci_package *p;
|
||||||
|
if (uci_load(ctx, "fastd", &p))
|
||||||
|
goto disabled;
|
||||||
|
|
||||||
|
struct uci_section *s = uci_lookup_section(ctx, p, "mesh_vpn");
|
||||||
|
if (!s)
|
||||||
|
goto disabled;
|
||||||
|
|
||||||
|
const char *enabled_str = uci_lookup_option_string(ctx, s, "enabled");
|
||||||
|
if (!enabled_str || !strcmp(enabled_str, "1"))
|
||||||
|
enabled = true;
|
||||||
|
|
||||||
|
disabled:
|
||||||
|
|
||||||
|
uci_free_context(ctx);
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
json_object_object_add(ret, "version", get_fastd_version());
|
||||||
|
json_object_object_add(ret, "enabled", json_object_new_boolean(enabled));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_nodeinfo(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *software = json_object_new_object();
|
||||||
|
json_object_object_add(software, "fastd", get_fastd());
|
||||||
|
json_object_object_add(ret, "software", software);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char * get_status_socket(struct uci_context *ctx, struct uci_section *s) {
|
||||||
|
return uci_lookup_option_string(ctx, s, "status_socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * read_status(struct uci_context *ctx, struct uci_section *s) {
|
||||||
|
const char *path = get_status_socket(ctx, s);
|
||||||
|
|
||||||
|
size_t addrlen = strlen(path);
|
||||||
|
|
||||||
|
/* Allocate enough space for arbitrary-length paths */
|
||||||
|
char addrbuf[offsetof(struct sockaddr_un, sun_path) + addrlen + 1];
|
||||||
|
memset(addrbuf, 0, sizeof(addrbuf));
|
||||||
|
|
||||||
|
struct sockaddr_un *addr = (struct sockaddr_un *)addrbuf;
|
||||||
|
addr->sun_family = AF_UNIX;
|
||||||
|
memcpy(addr->sun_path, path, addrlen+1);
|
||||||
|
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (connect(fd, (struct sockaddr*)addr, sizeof(addrbuf)) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *ret = NULL;
|
||||||
|
struct json_tokener *tok = json_tokener_new();
|
||||||
|
|
||||||
|
do {
|
||||||
|
char buf[1024];
|
||||||
|
size_t len = read(fd, buf, sizeof(buf));
|
||||||
|
if (len <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = json_tokener_parse_ex(tok, buf, len);
|
||||||
|
} while (!ret && json_tokener_get_error(tok) == json_tokener_continue);
|
||||||
|
|
||||||
|
json_tokener_free(tok);
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_status(void) {
|
||||||
|
struct json_object *ret = NULL;
|
||||||
|
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
|
||||||
|
struct uci_package *p;
|
||||||
|
if (!uci_load(ctx, "fastd", &p)) {
|
||||||
|
struct uci_section *s = uci_lookup_section(ctx, p, "mesh_vpn");
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
ret = read_status(ctx, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
uci_free_context(ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_peer_connection(struct json_object **ret, struct json_object *config, struct json_object *peers) {
|
||||||
|
struct json_object *key_object;
|
||||||
|
if (!json_object_object_get_ex(config, "key", &key_object))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *key = json_object_get_string(key_object);
|
||||||
|
if (!key)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct json_object *peer, *connection, *established;
|
||||||
|
if (!json_object_object_get_ex(peers, key, &peer) ||
|
||||||
|
!json_object_object_get_ex(peer, "connection", &connection))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(connection, "established", &established)) {
|
||||||
|
int64_t established_time = json_object_get_int64(established);
|
||||||
|
|
||||||
|
*ret = json_object_new_object();
|
||||||
|
json_object_object_add(*ret, "established", json_object_new_double(established_time/1000.0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ret = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_peer_group(struct json_object *config, struct json_object *peers) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *config_peers;
|
||||||
|
if (json_object_object_get_ex(config, "peers", &config_peers) &&
|
||||||
|
json_object_is_type(config_peers, json_type_object)) {
|
||||||
|
struct json_object *ret_peers = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_foreach(config_peers, peername, peerconfig) {
|
||||||
|
struct json_object *obj;
|
||||||
|
if (get_peer_connection(&obj, peerconfig, peers))
|
||||||
|
json_object_object_add(ret_peers, peername, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_object_object_length(ret_peers))
|
||||||
|
json_object_object_add(ret, "peers", ret_peers);
|
||||||
|
else
|
||||||
|
json_object_put(ret_peers);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *config_groups;
|
||||||
|
if (json_object_object_get_ex(config, "groups", &config_groups)) {
|
||||||
|
struct json_object *obj = get_peer_groups(config_groups, peers);
|
||||||
|
if (obj)
|
||||||
|
json_object_object_add(ret, "groups", obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!json_object_object_length(ret)) {
|
||||||
|
json_object_put(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_peer_groups(struct json_object *groups, struct json_object *peers) {
|
||||||
|
if (!json_object_is_type(groups, json_type_object))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
json_object_object_foreach(groups, name, group) {
|
||||||
|
struct json_object *g = get_peer_group(group, peers);
|
||||||
|
if (g)
|
||||||
|
json_object_object_add(ret, name, g);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_length(ret)) {
|
||||||
|
json_object_put(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_mesh_vpn(void) {
|
||||||
|
struct json_object *ret = NULL;
|
||||||
|
struct json_object *status = NULL;
|
||||||
|
struct json_object *site = NULL;
|
||||||
|
|
||||||
|
status = get_status();
|
||||||
|
if (!status)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
struct json_object *peers;
|
||||||
|
if (!json_object_object_get_ex(status, "peers", &peers))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
site = gluonutil_load_site_config();
|
||||||
|
if (!site)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
struct json_object *fastd_mesh_vpn;
|
||||||
|
if (!json_object_object_get_ex(site, "fastd_mesh_vpn", &fastd_mesh_vpn))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
ret = get_peer_group(fastd_mesh_vpn, peers);
|
||||||
|
|
||||||
|
end:
|
||||||
|
json_object_put(site);
|
||||||
|
json_object_put(status);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_statistics(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *mesh_vpn = get_mesh_vpn();
|
||||||
|
if (mesh_vpn)
|
||||||
|
json_object_object_add(ret, "mesh_vpn", mesh_vpn);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct respondd_provider_info respondd_providers[] = {
|
||||||
|
{"nodeinfo", respondd_provider_nodeinfo},
|
||||||
|
{"statistics", respondd_provider_statistics},
|
||||||
|
{}
|
||||||
|
};
|
@ -32,6 +32,8 @@ define Build/Compile
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-neighbour-info/install
|
define Package/gluon-neighbour-info/install
|
||||||
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/usr/bin
|
$(INSTALL_DIR) $(1)/usr/bin
|
||||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-neighbour-info $(1)/usr/bin/
|
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-neighbour-info $(1)/usr/bin/
|
||||||
endef
|
endef
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/lua
|
||||||
|
|
||||||
|
local uci = require('luci.model.uci').cursor()
|
||||||
|
|
||||||
|
-- Allow incoming respondd replies to queries on WAN
|
||||||
|
-- If the query was via multicast, the response isn't matched by --state RELATED
|
||||||
|
uci:section('firewall', 'rule', 'wan_respondd_reply',
|
||||||
|
{
|
||||||
|
name = 'wan_respondd_reply',
|
||||||
|
src = 'wan',
|
||||||
|
src_ip = 'fe80::/64',
|
||||||
|
src_port = '1001',
|
||||||
|
dest_port = '32768:61000', -- see /proc/sys/net/ipv4/ip_local_port_range
|
||||||
|
proto = 'udp',
|
||||||
|
target = 'ACCEPT',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
uci:save('firewall')
|
||||||
|
uci:commit('firewall')
|
@ -58,7 +58,7 @@ void getclock(struct timeval *tv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Assumes a and b are normalized */
|
/* Assumes a and b are normalized */
|
||||||
void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) {
|
void tv_subtract (struct timeval *r, const struct timeval *a, const struct timeval *b) {
|
||||||
r->tv_usec = a->tv_usec - b->tv_usec;
|
r->tv_usec = a->tv_usec - b->tv_usec;
|
||||||
r->tv_sec = a->tv_sec - b->tv_sec;
|
r->tv_sec = a->tv_sec - b->tv_sec;
|
||||||
|
|
||||||
@ -68,18 +68,17 @@ void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, struct timeval *timeout, struct timeval *offset) {
|
ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) {
|
||||||
struct timeval now, delta;
|
struct timeval now, timeout_left;
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout));
|
|
||||||
ret = recv(socket, buffer, length, flags);
|
|
||||||
|
|
||||||
getclock(&now);
|
getclock(&now);
|
||||||
tv_subtract(&delta, &now, offset);
|
tv_subtract(&timeout_left, timeout, &now);
|
||||||
tv_subtract(timeout, timeout, &delta);
|
|
||||||
|
|
||||||
return ret;
|
if (timeout_left.tv_sec < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left));
|
||||||
|
return recv(socket, buffer, length, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) {
|
int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) {
|
||||||
@ -94,14 +93,18 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeval tv_timeout, tv_offset;
|
struct timeval tv_timeout;
|
||||||
tv_timeout.tv_sec = (int) timeout;
|
getclock(&tv_timeout);
|
||||||
tv_timeout.tv_usec = ((int) (timeout * 1000000)) % 1000000;
|
|
||||||
|
|
||||||
getclock(&tv_offset);
|
tv_timeout.tv_sec += (int) timeout;
|
||||||
|
tv_timeout.tv_usec += ((int) (timeout * 1000000)) % 1000000;
|
||||||
|
if (tv_timeout.tv_usec >= 1000000) {
|
||||||
|
tv_timeout.tv_usec -= 1000000;
|
||||||
|
tv_timeout.tv_sec += 1;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout, &tv_offset);
|
ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
@ -133,7 +136,6 @@ int main(int argc, char **argv) {
|
|||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in6 client_addr = {};
|
struct sockaddr_in6 client_addr = {};
|
||||||
char *request_string = NULL;
|
char *request_string = NULL;
|
||||||
struct in6_addr mgroup_addr;
|
|
||||||
|
|
||||||
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
@ -147,9 +149,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
|
|
||||||
int port_set = 0;
|
int max_count = 0;
|
||||||
int destination_set = 0;
|
|
||||||
unsigned int max_count = 0;
|
|
||||||
double timeout = 3.0;
|
double timeout = 3.0;
|
||||||
char *sse = NULL;
|
char *sse = NULL;
|
||||||
bool loop = false;
|
bool loop = false;
|
||||||
@ -179,6 +179,10 @@ int main(int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
timeout = atof(optarg);
|
timeout = atof(optarg);
|
||||||
|
if (timeout < 0) {
|
||||||
|
perror("Negative timeout not supported");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
sse = optarg;
|
sse = optarg;
|
||||||
@ -206,8 +210,10 @@ int main(int argc, char **argv) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sse)
|
if (sse) {
|
||||||
fputs("Content-Type: text/event-stream\n\n", stdout);
|
fputs("Content-Type: text/event-stream\n\n", stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = request(sock, &client_addr, request_string, sse, timeout, max_count);
|
ret = request(sock, &client_addr, request_string, sse, timeout, max_count);
|
||||||
|
@ -5,6 +5,7 @@ PKG_VERSION:=1
|
|||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
PKG_BUILD_DEPENDS := respondd
|
||||||
|
|
||||||
include $(GLUONDIR)/include/package.mk
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
@ -12,25 +13,19 @@ define Package/gluon-node-info
|
|||||||
SECTION:=gluon
|
SECTION:=gluon
|
||||||
CATEGORY:=Gluon
|
CATEGORY:=Gluon
|
||||||
TITLE:=Add /etc/config/gluon-node-info to uci
|
TITLE:=Add /etc/config/gluon-node-info to uci
|
||||||
DEPENDS:=+gluon-core
|
DEPENDS:=+gluon-core +libgluonutil
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/gluon-node-info/description
|
|
||||||
This packages creates /etc/config/gluon-node-info.
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
endef
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
|
||||||
define Build/Configure
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Build/Compile
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-node-info/install
|
define Package/gluon-node-info/install
|
||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/node-info.so
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-node-info/postinst
|
define Package/gluon-node-info/postinst
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
if uci:get_first('gluon-node-info', 'location', 'share_location', false) then
|
|
||||||
return {
|
|
||||||
latitude = tonumber(uci:get_first('gluon-node-info', 'location', 'latitude')),
|
|
||||||
longitude = tonumber(uci:get_first('gluon-node-info', 'location', 'longitude')),
|
|
||||||
altitude = tonumber(uci:get_first('gluon-node-info', 'location', 'altitude')),
|
|
||||||
}
|
|
||||||
end
|
|
@ -1,4 +0,0 @@
|
|||||||
local contact = uci:get_first('gluon-node-info', 'owner', 'contact', '')
|
|
||||||
if contact ~= '' then
|
|
||||||
return { contact = contact }
|
|
||||||
end
|
|
@ -1,4 +0,0 @@
|
|||||||
local role = uci:get_first('gluon-node-info', 'system', 'role', '')
|
|
||||||
if role ~= '' then
|
|
||||||
return role
|
|
||||||
end
|
|
6
package/gluon-node-info/src/Makefile
Normal file
6
package/gluon-node-info/src/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
all: respondd.so
|
||||||
|
|
||||||
|
CFLAGS += -Wall
|
||||||
|
|
||||||
|
respondd.so: respondd.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci
|
144
package/gluon-node-info/src/respondd.c
Normal file
144
package/gluon-node-info/src/respondd.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <respondd.h>
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <libgluonutil.h>
|
||||||
|
|
||||||
|
#include <uci.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
static struct uci_section * get_first_section(struct uci_package *p, const char *type) {
|
||||||
|
struct uci_element *e;
|
||||||
|
uci_foreach_element(&p->sections, e) {
|
||||||
|
struct uci_section *s = uci_to_section(e);
|
||||||
|
if (!strcmp(s->type, type))
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * get_first_option(struct uci_context *ctx, struct uci_package *p, const char *type, const char *option) {
|
||||||
|
struct uci_section *s = get_first_section(p, type);
|
||||||
|
if (s)
|
||||||
|
return uci_lookup_option_string(ctx, s, option);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_number(struct uci_context *ctx, struct uci_section *s, const char *name) {
|
||||||
|
const char *val = uci_lookup_option_string(ctx, s, name);
|
||||||
|
if (!val || !*val)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
double d = strtod(val, &end);
|
||||||
|
if (*end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return json_object_new_double(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_location(struct uci_context *ctx, struct uci_package *p) {
|
||||||
|
struct uci_section *s = get_first_section(p, "location");
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const char *share = uci_lookup_option_string(ctx, s, "share_location");
|
||||||
|
if (!share || strcmp(share, "1"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *latitude = get_number(ctx, s, "latitude");
|
||||||
|
if (latitude)
|
||||||
|
json_object_object_add(ret, "latitude", latitude);
|
||||||
|
|
||||||
|
struct json_object *longitude = get_number(ctx, s, "longitude");
|
||||||
|
if (longitude)
|
||||||
|
json_object_object_add(ret, "longitude", longitude);
|
||||||
|
|
||||||
|
struct json_object *altitude = get_number(ctx, s, "altitude");
|
||||||
|
if (altitude)
|
||||||
|
json_object_object_add(ret, "altitude", altitude);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_owner(struct uci_context *ctx, struct uci_package *p) {
|
||||||
|
const char *contact = get_first_option(ctx, p, "owner", "contact");
|
||||||
|
if (!contact || !*contact)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
json_object_object_add(ret, "contact", gluonutil_wrap_string(contact));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * get_system(struct uci_context *ctx, struct uci_package *p) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
const char *role = get_first_option(ctx, p, "system", "role");
|
||||||
|
if (role && *role)
|
||||||
|
json_object_object_add(ret, "role", gluonutil_wrap_string(role));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object * respondd_provider_nodeinfo(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
|
||||||
|
struct uci_package *p;
|
||||||
|
if (!uci_load(ctx, "gluon-node-info", &p)) {
|
||||||
|
struct json_object *location = get_location(ctx, p);
|
||||||
|
if (location)
|
||||||
|
json_object_object_add(ret, "location", location);
|
||||||
|
|
||||||
|
struct json_object *owner = get_owner(ctx, p);
|
||||||
|
if (owner)
|
||||||
|
json_object_object_add(ret, "owner", owner);
|
||||||
|
|
||||||
|
json_object_object_add(ret, "system", get_system(ctx, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
uci_free_context(ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct respondd_provider_info respondd_providers[] = {
|
||||||
|
{"nodeinfo", respondd_provider_nodeinfo},
|
||||||
|
{}
|
||||||
|
};
|
6
package/gluon-radvd/files/usr/lib/autoupdater/abort.d/80gluon-radvd
Executable file
6
package/gluon-radvd/files/usr/lib/autoupdater/abort.d/80gluon-radvd
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
start_enabled gluon-radvd
|
6
package/gluon-radvd/files/usr/lib/autoupdater/download.d/20gluon-radvd
Executable file
6
package/gluon-radvd/files/usr/lib/autoupdater/download.d/20gluon-radvd
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/gluon/autoupdater/lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
stop gluon-radvd
|
29
package/gluon-respondd/Makefile
Normal file
29
package/gluon-respondd/Makefile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=gluon-respondd
|
||||||
|
PKG_VERSION:=1
|
||||||
|
|
||||||
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/gluon-respondd
|
||||||
|
SECTION:=gluon
|
||||||
|
CATEGORY:=Gluon
|
||||||
|
TITLE:=Provides node information to the network
|
||||||
|
DEPENDS:=+gluon-core +libplatforminfo +libgluonutil +respondd
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Prepare
|
||||||
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/gluon-respondd/install
|
||||||
|
$(CP) ./files/* $(1)/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/respondd.so
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,gluon-respondd))
|
@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /usr/share/libubox/jshn.sh
|
||||||
|
. /lib/functions/service.sh
|
||||||
|
|
||||||
|
DEVLIST=/var/run/gluon-respondd.devs
|
||||||
|
|
||||||
|
ifname_to_dev () {
|
||||||
|
json_load "$(ubus call network.interface.$1 status)"
|
||||||
|
json_get_var dev device
|
||||||
|
|
||||||
|
echo "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$ACTION" in
|
||||||
|
ifdown)
|
||||||
|
sed "/ $INTERFACE$/d" $DEVLIST > $DEVLIST.new
|
||||||
|
mv $DEVLIST.new $DEVLIST
|
||||||
|
;;
|
||||||
|
ifup)
|
||||||
|
DEVICE="$(ifname_to_dev "$INTERFACE")"
|
||||||
|
MESH="$(cat "/sys/class/net/$DEVICE/batman_adv/mesh_iface" 2>/dev/null)"
|
||||||
|
|
||||||
|
[ "$MESH" = "bat0" -o "$INTERFACE" = "client" ] || exit 0
|
||||||
|
|
||||||
|
DEVS=$(cat $DEVLIST 2>/dev/null; echo $DEVICE $INTERFACE)
|
||||||
|
|
||||||
|
echo "$DEVS" | sort -u > $DEVLIST.new
|
||||||
|
mv $DEVLIST.new $DEVLIST
|
||||||
|
|
||||||
|
/etc/init.d/gluon-respondd restart_if_running &
|
||||||
|
|
||||||
|
;;
|
||||||
|
esac
|
45
package/gluon-respondd/files/etc/init.d/gluon-respondd
Executable file
45
package/gluon-respondd/files/etc/init.d/gluon-respondd
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
EXTRA_COMMANDS='restart_if_running'
|
||||||
|
|
||||||
|
START=50
|
||||||
|
|
||||||
|
SERVICE_WRITE_PID=1
|
||||||
|
SERVICE_DAEMONIZE=1
|
||||||
|
|
||||||
|
DEVLIST=/var/run/gluon-respondd.devs
|
||||||
|
DAEMON=/usr/bin/respondd
|
||||||
|
LOCK=/var/run/gluon-respondd.lock
|
||||||
|
|
||||||
|
|
||||||
|
do_start() {
|
||||||
|
DEVS=$(cat $DEVLIST 2>/dev/null | while read dev iface; do echo -n " -i $dev"; done)
|
||||||
|
service_start $DAEMON -g ff02::2:1001 -p 1001 -d /lib/gluon/respondd $DEVS
|
||||||
|
}
|
||||||
|
|
||||||
|
do_stop() {
|
||||||
|
service_stop $DAEMON
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
lock $LOCK
|
||||||
|
do_start
|
||||||
|
lock -u $LOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
lock $LOCK
|
||||||
|
do_stop
|
||||||
|
lock -u $LOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
restart_if_running() {
|
||||||
|
lock $LOCK
|
||||||
|
|
||||||
|
if service_check $DAEMON; then
|
||||||
|
do_stop
|
||||||
|
do_start
|
||||||
|
fi
|
||||||
|
|
||||||
|
lock -u $LOCK
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
10000
|
@ -0,0 +1 @@
|
|||||||
|
300000
|
@ -0,0 +1 @@
|
|||||||
|
5000
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user