Merge branch 'master' of https://github.com/freifunk-gluon/gluon
(and removed trailing whitespace)
This commit is contained in:
commit
90ba3608ec
7
Makefile
7
Makefile
@ -103,6 +103,13 @@ endef
|
||||
list-targets: FORCE
|
||||
@$(foreach target,$(GLUON_TARGETS),echo '$(target)';)
|
||||
|
||||
lint: lint-lua lint-sh
|
||||
|
||||
lint-lua: FORCE
|
||||
@scripts/lint-lua.sh
|
||||
|
||||
lint-sh: FORCE
|
||||
@scripts/lint-sh.sh
|
||||
|
||||
GLUON_DEFAULT_PACKAGES := hostapd-mini
|
||||
|
||||
|
@ -21,7 +21,7 @@ the future development of Gluon.
|
||||
|
||||
Please refrain from using the `master` branch for anything else but development purposes!
|
||||
Use the most recent release instead. You can list all releases by running `git tag`
|
||||
and switch to one by running `git checkout v2019.1 && make update`.
|
||||
and switch to one by running `git checkout v2020.1 && make update`.
|
||||
|
||||
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.
|
||||
|
@ -17,6 +17,7 @@ RUN apt update && apt install -y --no-install-recommends \
|
||||
time \
|
||||
ecdsautils \
|
||||
lua-check \
|
||||
shellcheck \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd -d /gluon gluon
|
||||
|
75
contrib/ci/Jenkinsfile
vendored
75
contrib/ci/Jenkinsfile
vendored
@ -1,27 +1,52 @@
|
||||
pipeline {
|
||||
agent { label 'gluon-docker' }
|
||||
environment {
|
||||
GLUON_SITEDIR = "contrib/ci/minimal-site"
|
||||
GLUON_TARGET = "x86-64"
|
||||
BUILD_LOG = "1"
|
||||
}
|
||||
stages {
|
||||
stage('lint') {
|
||||
steps {
|
||||
sh 'luacheck package scripts targets'
|
||||
}
|
||||
}
|
||||
stage('docs') {
|
||||
steps {
|
||||
sh 'make -C docs html'
|
||||
}
|
||||
}
|
||||
stage('build') {
|
||||
steps {
|
||||
sh 'make update'
|
||||
sh 'test -d /dl_cache && ln -s /dl_cache openwrt/dl || true'
|
||||
sh 'make -j$(nproc) V=s'
|
||||
}
|
||||
}
|
||||
}
|
||||
agent none
|
||||
environment {
|
||||
GLUON_SITEDIR = "contrib/ci/minimal-site"
|
||||
GLUON_TARGET = "x86-64"
|
||||
BUILD_LOG = "1"
|
||||
}
|
||||
stages {
|
||||
stage('lint') {
|
||||
parallel {
|
||||
stage('lint-lua') {
|
||||
agent { label 'gluon-docker' }
|
||||
steps {
|
||||
sh 'make lint-lua'
|
||||
}
|
||||
}
|
||||
stage('lint-sh') {
|
||||
agent { label 'gluon-docker-v1' }
|
||||
steps {
|
||||
sh 'make lint-sh'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('docs') {
|
||||
agent { label 'gluon-docker' }
|
||||
steps {
|
||||
sh 'make -C docs html'
|
||||
}
|
||||
}
|
||||
stage('build') {
|
||||
agent { label 'gluon-docker' }
|
||||
steps {
|
||||
sh 'make update'
|
||||
sh 'test -d /dl_cache && ln -s /dl_cache openwrt/dl || true'
|
||||
sh 'make -j$(nproc) V=s'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
api-history:
|
||||
|
||||
Every time the build dependencies of gluon change, the version
|
||||
every container has to be rebuilt. Therefore, we use Jenkins
|
||||
labels which intoduce a version number which is documented here.
|
||||
As soon, as you properly rebuilt your docker container, you
|
||||
can notify lemoer, that you have updated your node.
|
||||
|
||||
- gluon-docker-v1: add shellcheck binary to the build environment
|
||||
*/
|
||||
|
@ -26,7 +26,7 @@ docker run --detach --restart always \
|
||||
- Your node should appear [here](https://build.ffh.zone/label/gluon-docker/).
|
||||
- When clicking on it, Jenkins should state "Agent is connected." like here:
|
||||

|
||||
5. **Your docker container needs to be rebuilt, when the build dependencies of gluon change. So please be aware of that and update your docker container in that case.**
|
||||
5. **Your docker container needs to be rebuilt, when the build dependencies of gluon change. As soon as build dependencies have changed, the build dependency api level has to be raised.** After you rebuilt your docker container, notifiy @lemoer, so he can bump the versioning number.
|
||||
|
||||
## Backoff
|
||||
- If @lemoer is not reachable, please be patient at first if possible. Otherwise contact info@hannover.freifunk.net or join the channel `#freifunkh` on hackint.
|
||||
|
@ -5,8 +5,7 @@
|
||||
# * Works only if directory names and package names are the same (true for all Gluon packages)
|
||||
# * Doesn't show dependencies through virtual packages correctly
|
||||
|
||||
|
||||
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
# Script to list all upgrade scripts in a clear manner
|
||||
# Limitations:
|
||||
# * Does only show scripts of packages whose `files'/`luasrc' directories represent the whole image filesystem (which are all Gluon packages)
|
||||
@ -27,7 +28,7 @@ fi
|
||||
|
||||
pushd "$(dirname "$0")/.." >/dev/null
|
||||
|
||||
find ./package packages -name Makefile | while read makefile; do
|
||||
find ./package packages -name Makefile | while read -r makefile; do
|
||||
dir="$(dirname "$makefile")"
|
||||
|
||||
pushd "$dir" >/dev/null
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# -ne 2 -o "-h" = "$1" -o "--help" = "$1" -o ! -r "$1" -o ! -r "$2" ]; then
|
||||
if [ $# -ne 2 ] || [ "-h" = "$1" ] || [ "--help" = "$1" ] || [ ! -r "$1" ] || [ ! -r "$2" ]; then
|
||||
cat <<EOHELP
|
||||
Usage: $0 <secret> <manifest>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -eq 0 -o "-h" = "$1" -o "-help" = "$1" -o "--help" = "$1" ]; then
|
||||
if [ $# -eq 0 ] || [ "-h" = "$1" ] || [ "-help" = "$1" ] || [ "--help" = "$1" ]; then
|
||||
cat <<EOHELP
|
||||
Usage: $0 <public> <signed manifest>
|
||||
|
||||
@ -27,7 +27,7 @@ awk "BEGIN { sep=0 }
|
||||
else print > \"$lower\"}" \
|
||||
"$manifest"
|
||||
|
||||
while read line
|
||||
while read -r line
|
||||
do
|
||||
if ecdsaverify -s "$line" -p "$public" "$upper"; then
|
||||
ret=0
|
||||
|
@ -20,11 +20,11 @@
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Gluon'
|
||||
copyright = '2015-2019, Project Gluon'
|
||||
copyright = '2015-2020, Project Gluon'
|
||||
author = 'Project Gluon'
|
||||
|
||||
# The short X.Y version
|
||||
version = '2019.1+'
|
||||
version = '2020.1+'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = version
|
||||
|
||||
|
@ -5,7 +5,7 @@ for new hardware to Gluon.
|
||||
|
||||
Hardware requirements
|
||||
---------------------
|
||||
Having an ath9k (or ath10k) based WLAN adapter is highly recommended,
|
||||
Having an ath9k, ath10k or mt76 based WLAN adapter is highly recommended,
|
||||
although other chipsets may also work. VAP (multiple SSID) support
|
||||
is a requirement.
|
||||
|
||||
|
@ -11,6 +11,11 @@ There are two cases in which the WAN port is used:
|
||||
After the VPN connection has been established, the node should be able to reach
|
||||
the mesh's DNS servers and use these for all other name resolution.
|
||||
|
||||
If the device does not feature a WAN port, the LAN port is configured as WAN port.
|
||||
In case such a device has multiple LAN ports, all these can be used as WAN.
|
||||
Devices, which feature a "hybrid" port (labled as WAN/LAN), this port is used as WAN.
|
||||
|
||||
This behavior can be reversed using the ``single_as_lan`` site.conf option.
|
||||
|
||||
Routing tables
|
||||
~~~~~~~~~~~~~~
|
||||
|
@ -74,7 +74,11 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre
|
||||
:caption: Releases
|
||||
:maxdepth: 1
|
||||
|
||||
releases/v2020.1
|
||||
releases/v2019.1.2
|
||||
releases/v2019.1.1
|
||||
releases/v2019.1
|
||||
releases/v2018.2.4
|
||||
releases/v2018.2.3
|
||||
releases/v2018.2.2
|
||||
releases/v2018.2.1
|
||||
|
@ -13,29 +13,32 @@ Selected router
|
||||
The router selection mechanism is independent from the batman-adv gateway mode.
|
||||
In contrast, the device originating the router advertisement could be any router
|
||||
or client connected to the mesh, as radv-filterd captures all router
|
||||
advertisements originating from it. All nodes announcing router advertisement
|
||||
advertisements originating from it. All nodes announcing router advertisement
|
||||
**with** a default lifetime greater than 0 are being considered as candidates.
|
||||
|
||||
In case a router is not a batman-adv originator itself, its TQ is defined by
|
||||
the originator it is connected to. This lookup uses the batman-adv global
|
||||
translation table.
|
||||
|
||||
Initially the router is the selected by choosing the candidate with the
|
||||
strongest TQ. When another candidate can provide a better TQ metric it is not
|
||||
picked up as the selected router until it will outperform the currently
|
||||
selected router by X metric units. The hysteresis threshold is configurable
|
||||
and prevents excessive flapping of the gateway.
|
||||
Initially the router is selected by choosing the candidate with the strongest
|
||||
TQ. When another candidate can provide a better TQ metric, that outperforms the
|
||||
currently selected router by X metric units, it will be picked as the new
|
||||
selected router. The hysteresis threshold is configurable and prevents excessive
|
||||
flapping of the gateway.
|
||||
|
||||
"Local" routers
|
||||
---------------
|
||||
Local routers
|
||||
-------------
|
||||
|
||||
The package has functionality to select "local" routers, i.e. those connected
|
||||
via cable or WLAN instead of via the mesh (technically: appearing in the
|
||||
``transtable_local``), a fake TQ of 512 so that they are always preferred.
|
||||
However, if used together with the :doc:`gluon-ebtables-filter-ra-dhcp`
|
||||
package, these router advertisements are filtered anyway and reach neither the
|
||||
node nor any other client. You currently have to disable the package or insert
|
||||
custom ebtables rules in order to use local routers.
|
||||
Local routers (i.e. local internet gateways connected to some nodes) that are
|
||||
connected to the client interface via cable or WLAN instead of via the mesh
|
||||
(technically: appearing in the transtable_local) are taken into account with a
|
||||
fake TQ of 512, so that they are always preferred.
|
||||
|
||||
Be aware of problems if you plan to use local routers together with the
|
||||
:doc:`gluon-ebtables-filter-ra-dhcp` package. These router advertisements are
|
||||
filtered anyway and reach neither the node nor any other client. Therefore the
|
||||
use of local routers is not possible as long as the package
|
||||
``gluon-radv-filterd`` is used.
|
||||
|
||||
respondd module
|
||||
---------------
|
||||
|
53
docs/releases/v2018.2.4.rst
Normal file
53
docs/releases/v2018.2.4.rst
Normal file
@ -0,0 +1,53 @@
|
||||
Gluon 2018.2.4
|
||||
==============
|
||||
|
||||
End of life
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
This will be the final release of the v2018.2.x series. Updating to the v2019.1.x release series is the recommended course of action, which should be fairly easy.
|
||||
|
||||
Bugfixes
|
||||
~~~~~~~~
|
||||
|
||||
* Fixes device alias for Ubiquiti UniFi AC LR. (`#1834 <https://github.com/freifunk-gluon/gluon/issues/1834>`_)
|
||||
Autoupdates on this model were impossible before, since we were missing the proper device alias.
|
||||
|
||||
* Add correct ath10k firmware package for OCEDO Koala. (`#1838 <https://github.com/freifunk-gluon/gluon/pull/1838>`_)
|
||||
|
||||
* Fixes various batman-adv bugs with backports from 2019.4 and 2019.5 by updating the openwrt-routing packages feed
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* Linux kernel has been updated to either
|
||||
|
||||
- 4.9.207 (ar71xx, brcm2708, mpc85xx) or
|
||||
- 4.14.160 (ipq40xx, ipq806x, mvebu, ramips, sunxi, x86).
|
||||
|
||||
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 Advanced Settings is recommended.
|
||||
|
||||
* 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 promiscuous mode is disallowed).
|
||||
|
||||
* Inconsistent respondd API
|
||||
(`#522 <https://github.com/freifunk-gluon/gluon/issues/522>`_)
|
||||
|
||||
The current API is inconsistent and will be replaced eventually. The old API
|
||||
will still be supported for a while.
|
||||
|
||||
* Frequent reboots due to out-of-memory or high load due to memory pressure on
|
||||
weak hardware especially in larger meshes
|
||||
(`#1243 <https://github.com/freifunk-gluon/gluon/issues/1243>`_)
|
||||
|
||||
Optimizations in Gluon 2018.1 have significantly improved memory usage.
|
||||
There are still known bugs leading to unreasonably high load that we hope to
|
||||
solve in future releases.
|
62
docs/releases/v2019.1.1.rst
Normal file
62
docs/releases/v2019.1.1.rst
Normal file
@ -0,0 +1,62 @@
|
||||
Gluon 2019.1.1
|
||||
##############
|
||||
|
||||
Bugfixes
|
||||
********
|
||||
|
||||
* Fixes device alias for Ubiquiti UniFi AC LR. (`#1834 <https://github.com/freifunk-gluon/gluon/issues/1834>`_)
|
||||
Autoupdates on this model were impossible before, since we were missing the proper device alias.
|
||||
|
||||
* Add correct ath10k firmware package for OCEDO Koala. (`#1838 <https://github.com/freifunk-gluon/gluon/pull/1838>`_)
|
||||
|
||||
* Fixes various batman-adv bugs with backports from 2019.4 and 2019.5 by updating the openwrt-routing packages feed.
|
||||
|
||||
* Fixes node role list. (`#1851 <https://github.com/freifunk-gluon/gluon/issues/1851>`_)
|
||||
With Gluon v2019.1 it became impossible to change the role of a node via the config mode.
|
||||
|
||||
Other Changes
|
||||
*************
|
||||
|
||||
* Linux kernel has been updated to either
|
||||
|
||||
- 4.9.207 (ar71xx, brcm2708, mpc85xx) or
|
||||
- 4.14.160 (ipq40xx, ipq806x, mvebu, ramips, sunxi, x86).
|
||||
|
||||
Known issues
|
||||
************
|
||||
|
||||
* Out of memory situations with high client count on ath9k.
|
||||
(`#1768 <https://github.com/freifunk-gluon/gluon/issues/1768>`_)
|
||||
|
||||
* The integration of the BATMAN_V routing algorithm is incomplete.
|
||||
|
||||
- | Mesh neighbors don't appear on the status page. (`#1726 <https://github.com/freifunk-gluon/gluon/issues/1726>`_)
|
||||
| Many tools have the BATMAN_IV metric hardcoded, these need to be updated to account for the new throughput
|
||||
| metric.
|
||||
|
||||
- | Throughput values are not correctly acquired for different interface types.
|
||||
| (`#1728 <https://github.com/freifunk-gluon/gluon/issues/1728>`_)
|
||||
| This affects virtual interface types like bridges and VXLAN.
|
||||
|
||||
* 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 Advanced Settings is recommended.
|
||||
|
||||
* 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 promiscuous mode is
|
||||
disallowed).
|
||||
|
||||
* Inconsistent respondd API (`#522 <https://github.com/freifunk-gluon/gluon/issues/522>`_)
|
||||
|
||||
The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while.
|
||||
|
||||
* Frequent reboots due to out-of-memory or high load due to memory pressure on weak hardware especially in larger
|
||||
meshes (`#1243 <https://github.com/freifunk-gluon/gluon/issues/1243>`_)
|
||||
|
||||
Optimizations in Gluon 2018.1 have significantly improved memory usage.
|
||||
There are still known bugs leading to unreasonably high load that we hope to
|
||||
solve in future releases.
|
||||
|
58
docs/releases/v2019.1.2.rst
Normal file
58
docs/releases/v2019.1.2.rst
Normal file
@ -0,0 +1,58 @@
|
||||
Gluon 2019.1.2
|
||||
##############
|
||||
|
||||
Bugfixes
|
||||
********
|
||||
|
||||
* Fixes a buffer-overflow vulnerability in libubox, a core component of OpenWrt
|
||||
(CVE-2020-7248)
|
||||
|
||||
* Fixes a vulnerability in the OpenWrt package manager (opkg). By using this vulnerability,
|
||||
an attacker could bypass the integrity check of the package artifacts. (CVE-2020-7982)
|
||||
|
||||
Other Changes
|
||||
*************
|
||||
|
||||
* Linux kernel has been updated to either
|
||||
|
||||
- 4.9.211 (ar71xx, brcm2708, mpc85xx) or
|
||||
- 4.14.167 (ipq40xx, ipq806x, mvebu, ramips, sunxi, x86).
|
||||
|
||||
Known issues
|
||||
************
|
||||
|
||||
* Out of memory situations with high client count on ath9k.
|
||||
(`#1768 <https://github.com/freifunk-gluon/gluon/issues/1768>`_)
|
||||
|
||||
* The integration of the BATMAN_V routing algorithm is incomplete.
|
||||
|
||||
- | Mesh neighbors don't appear on the status page. (`#1726 <https://github.com/freifunk-gluon/gluon/issues/1726>`_)
|
||||
| Many tools have the BATMAN_IV metric hardcoded, these need to be updated to account for the new throughput
|
||||
| metric.
|
||||
|
||||
- | Throughput values are not correctly acquired for different interface types.
|
||||
| (`#1728 <https://github.com/freifunk-gluon/gluon/issues/1728>`_)
|
||||
| This affects virtual interface types like bridges and VXLAN.
|
||||
|
||||
* 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 Advanced Settings is recommended.
|
||||
|
||||
* 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 promiscuous mode is
|
||||
disallowed).
|
||||
|
||||
* Inconsistent respondd API (`#522 <https://github.com/freifunk-gluon/gluon/issues/522>`_)
|
||||
|
||||
The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while.
|
||||
|
||||
* Frequent reboots due to out-of-memory or high load due to memory pressure on weak hardware especially in larger
|
||||
meshes (`#1243 <https://github.com/freifunk-gluon/gluon/issues/1243>`_)
|
||||
|
||||
Optimizations in Gluon 2018.1 have significantly improved memory usage.
|
||||
There are still known bugs leading to unreasonably high load that we hope to
|
||||
solve in future releases.
|
||||
|
@ -15,6 +15,7 @@ possible.
|
||||
With Gluon v2019.1, nodes will not answer respondd queries on ``[ff02::2:1001]:1001`` anymore. Respondd
|
||||
querier setups still using this address must be updated to the new address ``[ff05::2:1001]:1001``
|
||||
(supported since Gluon v2017.1). This change was required due to cross-domain leakage of respondd data.
|
||||
If you are using hopglass-server to query respondd data, you need to update it to at least commit f0e2c0a5.
|
||||
|
||||
If you are upgrading from a version prior to v2018.1, please note that the flash layout on some
|
||||
devices (TP-Link CPE/WBS 210/510) was changed. To avoid upgrade failures, make sure to upgrade
|
||||
|
191
docs/releases/v2020.1.rst
Normal file
191
docs/releases/v2020.1.rst
Normal file
@ -0,0 +1,191 @@
|
||||
Gluon 2020.1
|
||||
============
|
||||
|
||||
This is the first release of Gluon in 2020, based on OpenWrt 19.07. It
|
||||
introduces the ath79 target, which will replace ar71xx in the short
|
||||
term.
|
||||
|
||||
Added hardware support
|
||||
----------------------
|
||||
|
||||
ath79-generic
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- devolo WiFi pro 1200e
|
||||
- devolo WiFi pro 1200i
|
||||
- devolo WiFi pro 1750c
|
||||
- devolo WiFi pro 1750e
|
||||
- devolo WiFi pro 1750i
|
||||
- devolo WiFi pro 1750x
|
||||
- GL.iNet GL-AR300M-Lite
|
||||
- OCEDO Raccoon
|
||||
- TP-Link Archer C6 v2
|
||||
|
||||
ipq40xx-generic
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Aruba AP-303
|
||||
- Aruba Instant On AP11
|
||||
- AVM FRITZ!Repeater 1200
|
||||
|
||||
ipq806x-generic
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Netgear R7800
|
||||
|
||||
lantiq-xway
|
||||
~~~~~~~~~~~
|
||||
|
||||
- AVM FRITZ!Box 7312
|
||||
- AVM FRITZ!Box 7320
|
||||
- AVM FRITZ!Box 7330
|
||||
- AVM FRITZ!Box 7330 SL
|
||||
|
||||
lantiq-xrx200
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- AVM FRITZ!Box 7360 (v1, v2)
|
||||
- AVM FRITZ!Box 7360 SL
|
||||
- AVM FRITZ!Box 7362 SL
|
||||
- AVM FRITZ!Box 7412
|
||||
|
||||
mpc85xx-p1020
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- Enterasys WS-AP3710i
|
||||
- OCEDO Panda
|
||||
|
||||
ramips-mt7620
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- TP-Link Archer C2 (v1)
|
||||
- TP-Link Archer C20 (v1)
|
||||
- TP-Link Archer C20i
|
||||
- TP-Link Archer C50 (v1)
|
||||
- Xiaomi MiWifi Mini
|
||||
|
||||
ramips-mt7621
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- Netgear EX6150 (v1)
|
||||
- Netgear R6220
|
||||
|
||||
ramips-mt76x8
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- GL.iNet VIXMINI
|
||||
- TP-Link TL-MR3020 (v3)
|
||||
- TP-Link TL-WA801ND (v5)
|
||||
- TP-Link TL-WR902AC (v3)
|
||||
|
||||
Removed hardware support
|
||||
------------------------
|
||||
|
||||
- ALFA Network Hornet-UB [#kernelpartition_too_small]_
|
||||
- ALFA Network Tube2H [#kernelpartition_too_small]_
|
||||
- ALFA Network N2 [#kernelpartition_too_small]_
|
||||
- ALFA Network N5 [#kernelpartition_too_small]_
|
||||
|
||||
.. [#kernelpartition_too_small]
|
||||
The kernel partition on this device is too small to build a working image.
|
||||
|
||||
Major changes
|
||||
-------------
|
||||
|
||||
OpenWrt 19.07
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Gluon v2020.1 is the first release to use OpenWrt 19.07. All targets
|
||||
therefore use Linux 4.14.166.
|
||||
|
||||
batman-adv compat v14 removal
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Support for the long deprecated compat 14 version of batman-adv has been
|
||||
dropped. Communities still using this version should migrate to batman-adv
|
||||
using the scheduled domain switch.
|
||||
|
||||
IBSS wireless mesh removal
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Support for the IBSS wireless protocol has been dropped. Communities
|
||||
still using IBSS are suggested to migrate to 802.11s using the scheduled
|
||||
domain switch.
|
||||
|
||||
Performance enhancements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We install zram-swap by default on ``ar71xx`` devices with 8MB of flash
|
||||
and 32MB of RAM.
|
||||
|
||||
Renamed targets
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- The ``ipq40xx`` target was renamed to ``ipq40xx-generic``.
|
||||
- The ``ipq806x`` target was renamed to ``ipq806x-generic``.
|
||||
|
||||
Status Page
|
||||
~~~~~~~~~~~
|
||||
|
||||
- Gateway nexthop information has been added to the statuspage when batman-adv
|
||||
is used. This includes its MAC address and prettyname as well as the interface
|
||||
name towards the selected gateway.
|
||||
- The site name has been added to the statuspage. If the node is in a multidomain
|
||||
setup it will also show the domain name.
|
||||
|
||||
DECT button to enter config mode
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many AVM devices don't feature a separate RESET/WPS button, therefore
|
||||
starting this release we support entering the config mode via DECT buttons.
|
||||
|
||||
X86 partition size
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The x86 partition size has been reduced to fit on disks with a capacity of 128 MB.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
Autoupdater aliases
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We have added several new aliases for autoupdater compatibility on
|
||||
the following devices:
|
||||
|
||||
- Ubiquiti UniFi AC LR
|
||||
- Raspberry Pi
|
||||
|
||||
Site changes
|
||||
------------
|
||||
|
||||
site.mk
|
||||
~~~~~~~
|
||||
|
||||
- The ``GLUON_WLAN_MESH`` variable can be dropped, as 802.11s is
|
||||
the only supported wireless transport from now on.
|
||||
|
||||
Internals
|
||||
---------
|
||||
|
||||
Linting Targets
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Support for linter make targets was added.
|
||||
|
||||
- ``make lint``
|
||||
- ``make lint-sh`` to only check shell scripts
|
||||
- ``make lint-lua`` to only check lua scripts
|
||||
|
||||
These require the shellcheck and luacheck tools. The docker image has
|
||||
been updated accordingly.
|
||||
|
||||
Continuous integration
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We have implemented continuous integration testing using Jenkins and thereby
|
||||
ensure that all lua and shell scripts are linted, that the documentation
|
||||
still builds and warnings are highlighted, and that Gluon still
|
||||
compiles, by testing a build on the ``x86_64`` target. We expect this to
|
||||
significantly improve the feedback cycle and quality of contributions.
|
||||
|
@ -1,4 +1,4 @@
|
||||
-- This is an example site configuration for Gluon v2019.1
|
||||
-- This is an example site configuration for Gluon v2020.1
|
||||
--
|
||||
-- Take a look at the documentation located at
|
||||
-- https://gluon.readthedocs.io/ for details.
|
||||
|
@ -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.
|
||||
|
||||
Take a look at the `list of gluon releases`_ and notice the latest release,
|
||||
e.g. *v2019.1*. Always get Gluon using git and don't try to download it
|
||||
e.g. *v2020.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.
|
||||
|
||||
Please keep in mind that there is no "default Gluon" build; a site configuration
|
||||
@ -44,7 +44,7 @@ Building the images
|
||||
-------------------
|
||||
|
||||
To build Gluon, first check out the repository. Replace *RELEASE* with the
|
||||
version you'd like to checkout, e.g. *v2019.1*.
|
||||
version you'd like to checkout, e.g. *v2020.1*.
|
||||
|
||||
::
|
||||
|
||||
@ -120,7 +120,7 @@ There are two levels of `make clean`::
|
||||
|
||||
make clean GLUON_TARGET=ar71xx-generic
|
||||
|
||||
will ensure all packages are rebuilt for a single target. This normally not
|
||||
will ensure all packages are rebuilt for a single target. This is usually not
|
||||
necessary, but may fix certain kinds of build failures.
|
||||
|
||||
::
|
||||
|
@ -37,13 +37,13 @@ ar71xx-generic
|
||||
- DIR-505 (A1, A2)
|
||||
- DIR-825 (B1)
|
||||
|
||||
* GL Innovations
|
||||
* GL.iNet
|
||||
|
||||
- 6408A
|
||||
- 6416A
|
||||
- GL-AR150
|
||||
- GL-AR300M
|
||||
- GL-AR750
|
||||
- GL-iNet 6408A (v1)
|
||||
- GL-iNet 6416A (v1)
|
||||
|
||||
* Linksys
|
||||
|
||||
@ -82,7 +82,7 @@ ar71xx-generic
|
||||
- CPE220 (v1.1)
|
||||
- CPE510 (v1.0, v1.1)
|
||||
- CPE520 (v1.1)
|
||||
- RE450
|
||||
- RE450 (v1)
|
||||
- TL-WDR3500 (v1)
|
||||
- TL-WDR3600 (v1)
|
||||
- TL-WDR4300 (v1)
|
||||
@ -183,6 +183,23 @@ ar71xx-tiny [#deprecated]_
|
||||
ath79-generic
|
||||
--------------
|
||||
|
||||
* devolo
|
||||
|
||||
- WiFi pro 1200e [#lan_as_wan]_
|
||||
- WiFi pro 1200i
|
||||
- WiFi pro 1750c
|
||||
- WiFi pro 1750e [#lan_as_wan]_
|
||||
- WiFi pro 1750i
|
||||
- WiFi pro 1750x
|
||||
|
||||
* GL.iNet
|
||||
|
||||
- GL-AR300M-Lite
|
||||
|
||||
* OCEDO
|
||||
|
||||
- Raccoon
|
||||
|
||||
* TP-Link
|
||||
|
||||
- Archer C6 (v2)
|
||||
@ -212,8 +229,8 @@ ipq40xx-generic
|
||||
|
||||
* NETGEAR
|
||||
|
||||
- EX6100v2
|
||||
- EX6150v2
|
||||
- EX6100 (v2)
|
||||
- EX6150 (v2)
|
||||
|
||||
* OpenMesh
|
||||
|
||||
@ -237,6 +254,9 @@ lantiq-xrx200
|
||||
|
||||
* AVM
|
||||
|
||||
- FRITZ!Box 7360 (v1, v2) [#avmflash]_ [#lan_as_wan]_
|
||||
- FRITZ!Box 7360 SL [#avmflash]_ [#lan_as_wan]_
|
||||
- FRITZ!Box 7362 SL [#eva_ramboot]_ [#lan_as_wan]_
|
||||
- FRITZ!Box 7412 [#eva_ramboot]_
|
||||
|
||||
lantiq-xway
|
||||
@ -245,6 +265,9 @@ lantiq-xway
|
||||
* AVM
|
||||
|
||||
- FRITZ!Box 7312 [#avmflash]_
|
||||
- FRITZ!Box 7320 [#avmflash]_ [#lan_as_wan]_
|
||||
- FRITZ!Box 7330 [#avmflash]_ [#lan_as_wan]_
|
||||
- FRITZ!Box 7330 SL [#avmflash]_ [#lan_as_wan]_
|
||||
|
||||
mpc85xx-generic
|
||||
---------------
|
||||
@ -260,6 +283,10 @@ mpc85xx-p1020
|
||||
|
||||
- HiveAP 330
|
||||
|
||||
* Enterasys
|
||||
|
||||
- WS-AP3710i
|
||||
|
||||
* OCEDO
|
||||
|
||||
- Panda
|
||||
@ -267,7 +294,7 @@ mpc85xx-p1020
|
||||
ramips-mt7620
|
||||
-------------
|
||||
|
||||
* GL Innovations
|
||||
* GL.iNet
|
||||
|
||||
- GL-MT300A
|
||||
- GL-MT300N
|
||||
@ -277,6 +304,17 @@ ramips-mt7620
|
||||
|
||||
- WT3020AD/F/H
|
||||
|
||||
* TP-Link
|
||||
|
||||
- Archer C2 v1
|
||||
- Archer C20 (v1)
|
||||
- Archer C20i
|
||||
- Archer C50 v1
|
||||
|
||||
* Xiaomi
|
||||
|
||||
- MiWiFi Mini
|
||||
|
||||
ramips-mt7621
|
||||
-------------
|
||||
|
||||
@ -290,6 +328,7 @@ ramips-mt7621
|
||||
|
||||
* NETGEAR
|
||||
|
||||
- EX6150 (v1)
|
||||
- R6220
|
||||
|
||||
* Ubiquiti
|
||||
@ -316,10 +355,13 @@ ramips-mt76x8
|
||||
|
||||
* TP-Link
|
||||
|
||||
- TL-MR3420 v5
|
||||
- TL-WR841N v13
|
||||
- Archer C50 v3
|
||||
- Archer C50 v4
|
||||
- TL-MR3020 v3
|
||||
- TL-MR3420 v5
|
||||
- TL-WA801ND v5
|
||||
- TL-WR841N v13
|
||||
- TL-WR902AC v3
|
||||
|
||||
* VoCore
|
||||
|
||||
@ -382,4 +424,7 @@ Footnotes
|
||||
|
||||
.. [#eva_ramboot]
|
||||
For instructions on how to flash AVM NAND devices, see the respective
|
||||
commit which added support in OpenWrt.
|
||||
commit which added support in OpenWrt.
|
||||
|
||||
.. [#lan_as_wan]
|
||||
All LAN ports on this device are used as WAN.
|
||||
|
14
modules
14
modules
@ -1,20 +1,16 @@
|
||||
GLUON_FEEDS='packages routing luci gluon'
|
||||
GLUON_FEEDS='packages routing gluon'
|
||||
|
||||
OPENWRT_REPO=https://git.openwrt.org/openwrt/openwrt.git
|
||||
OPENWRT_BRANCH=openwrt-19.07
|
||||
OPENWRT_COMMIT=a8b293598f181f358ba8ac988ef75a97064792e0
|
||||
OPENWRT_COMMIT=17137076732b18442202e75c7edf10bccbc5f2a2
|
||||
|
||||
PACKAGES_PACKAGES_REPO=https://github.com/openwrt/packages.git
|
||||
PACKAGES_PACKAGES_BRANCH=openwrt-19.07
|
||||
PACKAGES_PACKAGES_COMMIT=702c655874db358706b7858445b06dba09c90cd6
|
||||
PACKAGES_PACKAGES_COMMIT=99efce0cd27adfcc53384fba93f37e5ee2e517de
|
||||
|
||||
PACKAGES_ROUTING_REPO=https://github.com/openwrt-routing/packages.git
|
||||
PACKAGES_ROUTING_BRANCH=openwrt-19.07
|
||||
PACKAGES_ROUTING_COMMIT=8d5ee29f088e9dfaa49dc74573edb1919f14dbf4
|
||||
|
||||
PACKAGES_LUCI_REPO=https://github.com/openwrt/luci.git
|
||||
PACKAGES_LUCI_BRANCH=openwrt-19.07
|
||||
PACKAGES_LUCI_COMMIT=7542d02cd23208ca2ed89ea5341d323ca3dc4e58
|
||||
PACKAGES_ROUTING_COMMIT=efa6e5445adda9c6545f551808829ec927cbade8
|
||||
|
||||
PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git
|
||||
PACKAGES_GLUON_COMMIT=de7b228cae72e87f2dfb3eed5b0354bd7cec4ca7
|
||||
PACKAGES_GLUON_COMMIT=12e41d0ff07ec54bbd67a31ab50d12ca04f2238c
|
||||
|
@ -14,6 +14,7 @@ xor2() {
|
||||
echo -n "${1:1:1}" | tr '0123456789abcdef' '23016745ab89efcd'
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
interface_linklocal() {
|
||||
local macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')"
|
||||
local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS"
|
||||
|
@ -50,6 +50,8 @@ elseif platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c58-v1',
|
||||
table.insert(try_files, 1, '/sys/class/net/eth1/address')
|
||||
elseif platform.match('ar71xx', 'nand', {'hiveap-121'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth0/address')
|
||||
elseif platform.match('ath79', 'generic', {'ocedo,raccoon'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth0/address')
|
||||
elseif platform.match('ipq40xx', 'generic', {'avm,fritzbox-4040',
|
||||
'openmesh,a42', 'openmesh,a62'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth0/address')
|
||||
@ -59,7 +61,7 @@ elseif platform.match('mpc85xx', 'p1020', {'aerohive,hiveap-330'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth0/address')
|
||||
elseif platform.match('mpc85xx', 'p1020', {'ocedo,panda'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth1/address')
|
||||
elseif platform.match('ramips', 'mt7620', {'miwifi-mini'}) then
|
||||
elseif platform.match('ramips', 'mt7620', {'miwifi-mini', 'tplink,c2-v1', 'c20-v1', 'c20i', 'c50'}) then
|
||||
table.insert(try_files, 1, '/sys/class/net/eth0/address')
|
||||
elseif platform.match('ramips', 'mt7621', {'dir-860l-b1'}) then
|
||||
table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress')
|
||||
|
@ -44,6 +44,9 @@ function M.is_outdoor_device()
|
||||
elseif M.match('ar71xx', 'generic', {'unifiac-pro'}) and
|
||||
M.get_model() == 'Ubiquiti UniFi-AC-MESH-PRO' then
|
||||
return true
|
||||
|
||||
elseif M.match('ath79', 'generic', {'devolo,dvl1750x'}) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
|
@ -10,7 +10,7 @@ include ../gluon.mk
|
||||
|
||||
define Package/gluon-mesh-babel
|
||||
TITLE:=Babel mesh
|
||||
DEPENDS:=+gluon-core +babeld +mmfd +libiwinfo +libgluonutil +firewall +libjson-c +libnl-tiny +libubus +libubox +libblobmsg-json +libbabelhelper +luabitop +gluon-l3roamd
|
||||
DEPENDS:=+gluon-core +babeld +gluon-mmfd +libiwinfo +libgluonutil +firewall +libjson-c +libnl-tiny +libubus +libubox +libblobmsg-json +libbabelhelper +luabitop
|
||||
PROVIDES:=gluon-mesh-provider
|
||||
endef
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local site = require 'gluon.site'
|
||||
local uci = require('simple-uci').cursor()
|
||||
local nodeip = uci:get('network', 'loopback', 'ip6addr'):match('^[^/]+')
|
||||
local babelconf='/etc/gluon-babeld.conf'
|
||||
|
||||
local file = io.open(babelconf, "w")
|
||||
@ -15,7 +17,7 @@ file:write("redistribute ip " .. site.prefix6() .. " eq 128 allow\n")
|
||||
file:write("redistribute ip " .. site.node_client_prefix6() .. " eq 128 allow\n")
|
||||
file:write("redistribute ip " .. site.node_prefix6() .. " eq 128 allow\n")
|
||||
file:write("redistribute ip 2000::/3 allow\n")
|
||||
|
||||
file:write("redistribute local if br-wan deny\n")
|
||||
file:write("redistribute local ip 0.0.0.0/0 deny\n")
|
||||
file:write("install pref-src " .. nodeip .."\n")
|
||||
file:close()
|
||||
|
@ -25,7 +25,7 @@ LDFLAGS_JSONC = $(shell pkg-config --libs json-c)
|
||||
|
||||
|
||||
respondd.so: respondd.c handle_neighbour.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared $(LDFLAGS_JSONC) -o $@ $^ -lgluonutil -lblobmsg_json -lubox -lubus -liwinfo -luci
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared $(LDFLAGS_JSONC) -o $@ $^ -lgluonutil -lblobmsg_json -lubox -lubus -luci
|
||||
|
||||
neighbours-babel: neighbours-babel.c handle_neighbour.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_JSONC) $(LDFLAGS) $(LDLIBS) $(LDFLAGS_JSONC) -o $@ $^
|
||||
|
@ -26,17 +26,15 @@
|
||||
|
||||
#include <respondd.h>
|
||||
|
||||
#include <iwinfo.h>
|
||||
#include <json-c/json.h>
|
||||
#include <libgluonutil.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include <glob.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
@ -49,33 +47,18 @@
|
||||
#include <sys/un.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/sockios.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include "errno.h"
|
||||
#include <errno.h>
|
||||
#include <libbabelhelper/babelhelper.h>
|
||||
|
||||
#include <libubox/blobmsg_json.h>
|
||||
#include "libubus.h"
|
||||
|
||||
#define _STRINGIFY(s) #s
|
||||
#define STRINGIFY(s) _STRINGIFY(s)
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_INACTIVITY 60000
|
||||
#include <libubus.h>
|
||||
|
||||
#define SOCKET_INPUT_BUFFER_SIZE 255
|
||||
#define BABEL_PORT 33123
|
||||
#define VPN_INTERFACE "mesh-vpn"
|
||||
#define l3rdctl "/var/run/l3roamd.sock"
|
||||
|
||||
#define IFNAMELEN 32
|
||||
#define PROTOLEN 32
|
||||
|
||||
#define UBUS_TIMEOUT 30
|
||||
#define UBUS_SOCKET "/var/run/ubus.sock"
|
||||
#define UBUS_TIMEOUT 30000
|
||||
|
||||
static struct babelhelper_ctx bhelper_ctx = {};
|
||||
|
||||
@ -241,7 +224,7 @@ static struct json_object * get_babel_neighbours(void) {
|
||||
if (!neighbours)
|
||||
return NULL;
|
||||
|
||||
babelhelper_readbabeldata(&bhelper_ctx, (void*)neighbours, handle_neighbour);
|
||||
babelhelper_readbabeldata(&bhelper_ctx, "dump", (void*)neighbours, handle_neighbour);
|
||||
|
||||
return(neighbours);
|
||||
}
|
||||
@ -258,9 +241,9 @@ static void blobmsg_handle_element(struct blob_attr *attr, bool head, char **ifn
|
||||
|
||||
switch (blob_id(attr)) {
|
||||
case BLOBMSG_TYPE_STRING:
|
||||
if (!strncmp(blobmsg_name(attr),"device", 6)) {
|
||||
if (!strncmp(blobmsg_name(attr), "device", 6)) {
|
||||
free(*ifname);
|
||||
*ifname = strndup(data, IFNAMELEN);
|
||||
*ifname = strndup(data, IF_NAMESIZE);
|
||||
} else if (!strncmp(blobmsg_name(attr), "proto", 5)) {
|
||||
free(*proto);
|
||||
*proto = strndup(data, PROTOLEN);
|
||||
@ -330,7 +313,7 @@ static struct json_object * get_mesh_ifs() {
|
||||
|
||||
unsigned int id=8;
|
||||
|
||||
ubus_ctx = ubus_connect(UBUS_SOCKET);
|
||||
ubus_ctx = ubus_connect(NULL);
|
||||
if (!ubus_ctx) {
|
||||
fprintf(stderr,"could not connect to ubus, not providing mesh-data\n");
|
||||
goto end;
|
||||
@ -338,7 +321,7 @@ static struct json_object * get_mesh_ifs() {
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
ubus_lookup_id(ubus_ctx, "network.interface", &id);
|
||||
int uret = ubus_invoke(ubus_ctx, id, "dump", b.head, receive_call_result_data, &ret, UBUS_TIMEOUT * 1000);
|
||||
int uret = ubus_invoke(ubus_ctx, id, "dump", b.head, receive_call_result_data, &ret, UBUS_TIMEOUT);
|
||||
|
||||
if (uret > 0)
|
||||
fprintf(stderr, "ubus command failed: %s\n", ubus_strerror(uret));
|
||||
@ -386,34 +369,40 @@ static struct json_object * respondd_provider_nodeinfo(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t getnumber(const char *ifname, const char *stat) {
|
||||
static struct json_object * read_number(const char *ifname, const char *stat) {
|
||||
const char *format = "/sys/class/net/%s/statistics/%s";
|
||||
|
||||
struct json_object *ret = NULL;
|
||||
int64_t i;
|
||||
|
||||
char path[strlen(format) + strlen(ifname) + strlen(stat) + 1];
|
||||
snprintf(path, sizeof(path), format, ifname, stat);
|
||||
if (! access(path, F_OK)) {
|
||||
char *line=gluonutil_read_line(path);
|
||||
long long i = atoll(line);
|
||||
free(line);
|
||||
return(i);
|
||||
}
|
||||
return 0;
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
if (fscanf(f, "%"SCNd64, &i) == 1)
|
||||
ret = json_object_new_int64(i);
|
||||
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * get_traffic(void) {
|
||||
char ifname[16];
|
||||
|
||||
strncpy(ifname, "br-client", 16);
|
||||
const char *ifname = "br-client";
|
||||
|
||||
struct json_object *ret = NULL;
|
||||
struct json_object *rx = json_object_new_object();
|
||||
struct json_object *tx = json_object_new_object();
|
||||
|
||||
json_object_object_add(rx, "packets", json_object_new_int64(getnumber(ifname, "rx_packets")));
|
||||
json_object_object_add(rx, "bytes", json_object_new_int64(getnumber(ifname, "rx_bytes")));
|
||||
json_object_object_add(rx, "dropped", json_object_new_int64(getnumber(ifname, "rx_dropped")));
|
||||
json_object_object_add(tx, "packets", json_object_new_int64(getnumber(ifname, "tx_packets")));
|
||||
json_object_object_add(tx, "dropped", json_object_new_int64(getnumber(ifname, "tx_dropped")));
|
||||
json_object_object_add(tx, "bytes", json_object_new_int64(getnumber(ifname, "tx_bytes")));
|
||||
json_object_object_add(rx, "packets", read_number(ifname, "rx_packets"));
|
||||
json_object_object_add(rx, "bytes", read_number(ifname, "rx_bytes"));
|
||||
json_object_object_add(rx, "dropped", read_number(ifname, "rx_dropped"));
|
||||
json_object_object_add(tx, "packets", read_number(ifname, "tx_packets"));
|
||||
json_object_object_add(tx, "dropped", read_number(ifname, "tx_dropped"));
|
||||
json_object_object_add(tx, "bytes", read_number(ifname, "tx_bytes"));
|
||||
|
||||
ret = json_object_new_object();
|
||||
json_object_object_add(ret, "rx", rx);
|
||||
@ -422,72 +411,6 @@ static struct json_object * get_traffic(void) {
|
||||
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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
(*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 bool handle_route_addgw_nexthop(char **data, void *arg) {
|
||||
struct json_object *obj = (struct json_object*) arg;
|
||||
if (data[PREFIX] && data[FROM] && data[VIA] && data[IF]) {
|
||||
@ -569,21 +492,12 @@ end:
|
||||
}
|
||||
|
||||
static struct json_object * get_clients(void) {
|
||||
size_t wifi24 = 0, wifi5 = 0;
|
||||
|
||||
count_stations(&wifi24, &wifi5);
|
||||
|
||||
int total = ask_l3roamd_for_client_count();
|
||||
|
||||
size_t wifi = wifi24 + wifi5;
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
int total = ask_l3roamd_for_client_count();
|
||||
if (total >= 0)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -593,94 +507,11 @@ static struct json_object * respondd_provider_statistics(void) {
|
||||
json_object_object_add(ret, "clients", get_clients());
|
||||
json_object_object_add(ret, "traffic", get_traffic());
|
||||
|
||||
babelhelper_readbabeldata(&bhelper_ctx, (void*)ret, handle_route_addgw_nexthop );
|
||||
babelhelper_readbabeldata(&bhelper_ctx, "dump", (void*)ret, handle_route_addgw_nexthop );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
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) {
|
||||
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
struct uci_package *p;
|
||||
if (uci_load(ctx, "network", &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, "interface"))
|
||||
continue;
|
||||
|
||||
const char *proto = uci_lookup_option_string(ctx, s, "proto");
|
||||
if (!proto || strcmp(proto, "gluon_mesh"))
|
||||
continue;
|
||||
|
||||
const char *ifname = uci_lookup_option_string(ctx, s, "ifname");
|
||||
if (!ifname)
|
||||
continue;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
end:
|
||||
uci_free_context(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * respondd_provider_neighbours(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
@ -689,10 +520,6 @@ static struct json_object * respondd_provider_neighbours(void) {
|
||||
json_object_object_add(ret, "babel", babel);
|
||||
|
||||
|
||||
struct json_object *wifi = get_wifi();
|
||||
if (wifi)
|
||||
json_object_object_add(ret, "wifi", wifi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
lock /var/lock/gluon_bat0.lock
|
||||
(echo 'none' > "/sys/class/net/$IFNAME/batman_adv/mesh_iface") 2>/dev/null
|
||||
batctl interface del "$IFNAME" 2>/dev/null
|
||||
lock -u /var/lock/gluon_bat0.lock
|
||||
|
@ -22,20 +22,9 @@ proto_gluon_bat0_renew() {
|
||||
|
||||
lock /var/lock/gluon_bat0.lock
|
||||
|
||||
local ifdump="$(ubus call network.interface dump)"
|
||||
|
||||
echo "$ifdump" | jsonfilter \
|
||||
-e "@.interface[@.proto='gluon_mesh' && @.up=true]['device','data']" \
|
||||
| while read dev; do
|
||||
read data
|
||||
|
||||
echo bat0 > "/sys/class/net/$dev/batman_adv/mesh_iface"
|
||||
|
||||
! [ "$(echo "$data" | jsonfilter -e "@.transitive")" = 'true' ]
|
||||
transitive=$?
|
||||
|
||||
(echo "$transitive" > "/sys/class/net/$dev/batman_adv/no_rebroadcast") 2>/dev/null
|
||||
done
|
||||
ubus call network.interface dump | jsonfilter \
|
||||
-e "@.interface[@.proto='gluon_mesh' && @.up=true].device" \
|
||||
| xargs -r -n 1 batctl interface add
|
||||
|
||||
lock -u /var/lock/gluon_bat0.lock
|
||||
}
|
||||
|
@ -31,5 +31,8 @@ endif
|
||||
CFLAGS += $(LIBBATADV_CFLAGS)
|
||||
LDLIBS += $(LIBBATADV_LDLIBS)
|
||||
|
||||
respondd.so: respondd.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -liwinfo -luci
|
||||
|
||||
SOURCES = respondd.c respondd-nodeinfo.c respondd-statistics.c respondd-neighbours.c
|
||||
|
||||
respondd.so: $(SOURCES) respondd-common.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -fvisibility=hidden -D_GNU_SOURCE -o $@ $(SOURCES) $(LDLIBS) -lgluonutil
|
||||
|
30
package/gluon-mesh-batman-adv/src/respondd-common.h
Normal file
30
package/gluon-mesh-batman-adv/src/respondd-common.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct json_object * respondd_provider_nodeinfo(void);
|
||||
struct json_object * respondd_provider_statistics(void);
|
||||
struct json_object * respondd_provider_neighbours(void);
|
176
package/gluon-mesh-batman-adv/src/respondd-neighbours.c
Normal file
176
package/gluon-mesh-batman-adv/src/respondd-neighbours.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <batadv-genl.h>
|
||||
#include <libgluonutil.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
struct neigh_netlink_opts {
|
||||
struct json_object *interfaces;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
|
||||
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 const enum batadv_nl_attrs parse_orig_list_mandatory[] = {
|
||||
BATADV_ATTR_ORIG_ADDRESS,
|
||||
BATADV_ATTR_NEIGH_ADDRESS,
|
||||
BATADV_ATTR_TQ,
|
||||
BATADV_ATTR_HARD_IFINDEX,
|
||||
BATADV_ATTR_LAST_SEEN_MSECS,
|
||||
};
|
||||
|
||||
static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
uint8_t *orig;
|
||||
uint8_t *dest;
|
||||
uint8_t tq;
|
||||
uint32_t hardif;
|
||||
uint32_t lastseen;
|
||||
char ifname_buf[IF_NAMESIZE], *ifname;
|
||||
struct neigh_netlink_opts *opts;
|
||||
char mac1[18];
|
||||
|
||||
opts = batadv_container_of(query_opts, struct neigh_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory,
|
||||
BATADV_ARRAY_SIZE(parse_orig_list_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
|
||||
dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
|
||||
tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
|
||||
hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]);
|
||||
lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
|
||||
|
||||
if (memcmp(orig, dest, 6) != 0)
|
||||
return NL_OK;
|
||||
|
||||
ifname = if_indextoname(hardif, ifname_buf);
|
||||
if (!ifname)
|
||||
return NL_OK;
|
||||
|
||||
sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
|
||||
|
||||
struct json_object *obj = json_object_new_object();
|
||||
if (!obj)
|
||||
return NL_OK;
|
||||
|
||||
struct json_object *interface;
|
||||
if (!json_object_object_get_ex(opts->interfaces, ifname, &interface)) {
|
||||
interface = json_object_new_object();
|
||||
json_object_object_add(opts->interfaces, ifname, interface);
|
||||
}
|
||||
|
||||
json_object_object_add(obj, "tq", json_object_new_int(tq));
|
||||
json_object_object_add(obj, "lastseen", json_object_new_double(lastseen / 1000.));
|
||||
json_object_object_add(obj, "best", json_object_new_boolean(!!attrs[BATADV_ATTR_FLAG_BEST]));
|
||||
json_object_object_add(interface, mac1, obj);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object * get_batadv(void) {
|
||||
struct neigh_netlink_opts opts = {
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
opts.interfaces = json_object_new_object();
|
||||
if (!opts.interfaces)
|
||||
return NULL;
|
||||
|
||||
ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS,
|
||||
parse_orig_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
if (ret < 0) {
|
||||
json_object_put(opts.interfaces);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ifnames2addrs(opts.interfaces);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
219
package/gluon-mesh-batman-adv/src/respondd-nodeinfo.c
Normal file
219
package/gluon-mesh-batman-adv/src/respondd-nodeinfo.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <libgluonutil.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
#include <glob.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
|
||||
struct ip_address_information {
|
||||
unsigned int ifindex;
|
||||
struct json_object *addresses;
|
||||
};
|
||||
|
||||
static int get_addresses_cb(struct nl_msg *msg, void *arg) {
|
||||
struct ip_address_information *info = (struct ip_address_information*) arg;
|
||||
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct ifaddrmsg *msg_content = NLMSG_DATA(nlh);
|
||||
int remaining = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||
struct rtattr *hdr;
|
||||
|
||||
for (hdr = IFA_RTA(msg_content); RTA_OK(hdr, remaining); hdr = RTA_NEXT(hdr, remaining)) {
|
||||
char addr_str_buf[INET6_ADDRSTRLEN];
|
||||
|
||||
/* We are only interested in IP-addresses of br-client */
|
||||
if (hdr->rta_type != IFA_ADDRESS ||
|
||||
msg_content->ifa_index != info->ifindex ||
|
||||
msg_content->ifa_flags & (IFA_F_TENTATIVE|IFA_F_DEPRECATED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET6, (struct in6_addr *) RTA_DATA(hdr), addr_str_buf, INET6_ADDRSTRLEN)) {
|
||||
json_object_array_add(info->addresses, json_object_new_string(addr_str_buf));
|
||||
}
|
||||
}
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object *get_addresses(void) {
|
||||
struct ip_address_information info = {
|
||||
.ifindex = if_nametoindex("br-client"),
|
||||
.addresses = json_object_new_array(),
|
||||
};
|
||||
int err;
|
||||
|
||||
/* Open socket */
|
||||
struct nl_sock *socket = nl_socket_alloc();
|
||||
if (!socket) {
|
||||
return info.addresses;
|
||||
}
|
||||
|
||||
err = nl_connect(socket, NETLINK_ROUTE);
|
||||
if (err < 0) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Send message */
|
||||
struct ifaddrmsg rt_hdr = { .ifa_family = AF_INET6, };
|
||||
err = nl_send_simple(socket, RTM_GETADDR, NLM_F_REQUEST | NLM_F_ROOT, &rt_hdr, sizeof(struct ifaddrmsg));
|
||||
if (err < 0) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Retrieve answer. Message is handled by get_addresses_cb */
|
||||
nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, get_addresses_cb, &info);
|
||||
nl_recvmsgs_default(socket);
|
||||
|
||||
out_free:
|
||||
nl_socket_free(socket);
|
||||
return info.addresses;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
char lowername[IFNAMSIZ];
|
||||
strncpy(lowername, ifname, sizeof(lowername)-1);
|
||||
lowername[sizeof(lowername)-1] = 0;
|
||||
|
||||
const char *format = "/sys/class/net/%s/lower_*";
|
||||
char pattern[strlen(format) + IFNAMSIZ];
|
||||
|
||||
/* In case of VLAN and bridge interfaces, we want the lower interface
|
||||
* to determine the interface type (but not for the interface address) */
|
||||
while (true) {
|
||||
snprintf(pattern, sizeof(pattern), format, lowername);
|
||||
size_t pattern_len = strlen(pattern);
|
||||
|
||||
glob_t lower;
|
||||
if (glob(pattern, GLOB_NOSORT, NULL, &lower))
|
||||
break;
|
||||
|
||||
strncpy(lowername, lower.gl_pathv[0] + pattern_len - 1, sizeof(lowername)-1);
|
||||
|
||||
globfree(&lower);
|
||||
}
|
||||
|
||||
if (interface_file_exists(lowername, "wireless"))
|
||||
json_object_array_add(wireless, address);
|
||||
else if (interface_file_exists(lowername, "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;
|
||||
}
|
||||
|
||||
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", json_object_new_int(15));
|
||||
json_object_object_add(software, "batman-adv", software_batman_adv);
|
||||
json_object_object_add(ret, "software", software);
|
||||
|
||||
return ret;
|
||||
}
|
322
package/gluon-mesh-batman-adv/src/respondd-statistics.c
Normal file
322
package/gluon-mesh-batman-adv/src/respondd-statistics.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <batadv-genl.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sockios.h>
|
||||
|
||||
|
||||
#define MAX_INACTIVITY 60000
|
||||
|
||||
|
||||
struct clients_netlink_opts {
|
||||
size_t clients;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
struct gw_netlink_opts {
|
||||
struct json_object *obj;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
|
||||
static const enum batadv_nl_attrs gateways_mandatory[] = {
|
||||
BATADV_ATTR_ORIG_ADDRESS,
|
||||
BATADV_ATTR_ROUTER,
|
||||
};
|
||||
|
||||
static int parse_gw_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
uint8_t *orig;
|
||||
uint8_t *router;
|
||||
struct gw_netlink_opts *opts;
|
||||
char addr[18];
|
||||
|
||||
opts = batadv_container_of(query_opts, struct gw_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_GATEWAYS)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, gateways_mandatory,
|
||||
BATADV_ARRAY_SIZE(gateways_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
if (!attrs[BATADV_ATTR_FLAG_BEST])
|
||||
return NL_OK;
|
||||
|
||||
orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
|
||||
router = nla_data(attrs[BATADV_ATTR_ROUTER]);
|
||||
|
||||
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
|
||||
|
||||
json_object_object_add(opts->obj, "gateway", json_object_new_string(addr));
|
||||
|
||||
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
router[0], router[1], router[2], router[3], router[4], router[5]);
|
||||
|
||||
json_object_object_add(opts->obj, "gateway_nexthop", json_object_new_string(addr));
|
||||
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
static void add_gateway(struct json_object *obj) {
|
||||
struct gw_netlink_opts opts = {
|
||||
.obj = obj,
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
|
||||
batadv_genl_query("bat0", BATADV_CMD_GET_GATEWAYS,
|
||||
parse_gw_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
}
|
||||
|
||||
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) {
|
||||
struct {
|
||||
struct ethtool_sset_info info;
|
||||
uint32_t buf;
|
||||
} sset = {};
|
||||
|
||||
sset.info.cmd = ETHTOOL_GSSET_INFO;
|
||||
sset.info.sset_mask = (uint64_t)1 << 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 const enum batadv_nl_attrs clients_mandatory[] = {
|
||||
BATADV_ATTR_TT_FLAGS,
|
||||
/* Entries without the BATADV_TT_CLIENT_NOPURGE flag do not have a
|
||||
* BATADV_ATTR_LAST_SEEN_MSECS attribute. We can still make this attr
|
||||
* mandatory here, as entries without BATADV_TT_CLIENT_NOPURGE are
|
||||
* ignored anyways.
|
||||
*/
|
||||
BATADV_ATTR_LAST_SEEN_MSECS,
|
||||
};
|
||||
|
||||
static int parse_clients_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
struct clients_netlink_opts *opts;
|
||||
uint32_t flags, lastseen;
|
||||
|
||||
opts = batadv_container_of(query_opts, struct clients_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, clients_mandatory,
|
||||
BATADV_ARRAY_SIZE(clients_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);
|
||||
|
||||
if (flags & (BATADV_TT_CLIENT_NOPURGE))
|
||||
return NL_OK;
|
||||
|
||||
lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
|
||||
if (lastseen > MAX_INACTIVITY)
|
||||
return NL_OK;
|
||||
|
||||
opts->clients++;
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object * get_clients(void) {
|
||||
struct clients_netlink_opts opts = {
|
||||
.clients = 0,
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
|
||||
batadv_genl_query("bat0", BATADV_CMD_GET_TRANSTABLE_LOCAL,
|
||||
parse_clients_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "total", json_object_new_int(opts.clients));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2016-2019, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -23,780 +23,12 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "respondd-common.h"
|
||||
|
||||
#include <respondd.h>
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <iwinfo.h>
|
||||
#include <json-c/json.h>
|
||||
#include <libgluonutil.h>
|
||||
#include <uci.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 <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/sockios.h>
|
||||
|
||||
#include <batadv-genl.h>
|
||||
|
||||
|
||||
#define _STRINGIFY(s) #s
|
||||
#define STRINGIFY(s) _STRINGIFY(s)
|
||||
|
||||
#define MAX_INACTIVITY 60000
|
||||
|
||||
|
||||
struct neigh_netlink_opts {
|
||||
struct json_object *interfaces;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
struct gw_netlink_opts {
|
||||
struct json_object *obj;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
struct clients_netlink_opts {
|
||||
size_t non_wifi;
|
||||
struct batadv_nlquery_opts query_opts;
|
||||
};
|
||||
|
||||
struct ip_address_information {
|
||||
unsigned int ifindex;
|
||||
struct json_object *addresses;
|
||||
};
|
||||
|
||||
static int get_addresses_cb(struct nl_msg *msg, void *arg) {
|
||||
struct ip_address_information *info = (struct ip_address_information*) arg;
|
||||
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct ifaddrmsg *msg_content = NLMSG_DATA(nlh);
|
||||
int remaining = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||
struct rtattr *hdr;
|
||||
|
||||
for (hdr = IFA_RTA(msg_content); RTA_OK(hdr, remaining); hdr = RTA_NEXT(hdr, remaining)) {
|
||||
char addr_str_buf[INET6_ADDRSTRLEN];
|
||||
|
||||
/* We are only interested in IP-addresses of br-client */
|
||||
if (hdr->rta_type != IFA_ADDRESS ||
|
||||
msg_content->ifa_index != info->ifindex ||
|
||||
msg_content->ifa_flags & (IFA_F_TENTATIVE|IFA_F_DEPRECATED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET6, (struct in6_addr *) RTA_DATA(hdr), addr_str_buf, INET6_ADDRSTRLEN)) {
|
||||
json_object_array_add(info->addresses, json_object_new_string(addr_str_buf));
|
||||
}
|
||||
}
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object *get_addresses(void) {
|
||||
struct ip_address_information info = {
|
||||
.ifindex = if_nametoindex("br-client"),
|
||||
.addresses = json_object_new_array(),
|
||||
};
|
||||
int err;
|
||||
|
||||
/* Open socket */
|
||||
struct nl_sock *socket = nl_socket_alloc();
|
||||
if (!socket) {
|
||||
return info.addresses;
|
||||
}
|
||||
|
||||
err = nl_connect(socket, NETLINK_ROUTE);
|
||||
if (err < 0) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Send message */
|
||||
struct ifaddrmsg rt_hdr = { .ifa_family = AF_INET6, };
|
||||
err = nl_send_simple(socket, RTM_GETADDR, NLM_F_REQUEST | NLM_F_ROOT, &rt_hdr, sizeof(struct ifaddrmsg));
|
||||
if (err < 0) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Retrieve answer. Message is handled by get_addresses_cb */
|
||||
nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, get_addresses_cb, &info);
|
||||
nl_recvmsgs_default(socket);
|
||||
|
||||
out_free:
|
||||
nl_socket_free(socket);
|
||||
return info.addresses;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
char lowername[IFNAMSIZ];
|
||||
strncpy(lowername, ifname, sizeof(lowername)-1);
|
||||
lowername[sizeof(lowername)-1] = 0;
|
||||
|
||||
const char *format = "/sys/class/net/%s/lower_*";
|
||||
char pattern[strlen(format) + IFNAMSIZ];
|
||||
|
||||
/* In case of VLAN and bridge interfaces, we want the lower interface
|
||||
* to determine the interface type (but not for the interface address) */
|
||||
while (true) {
|
||||
snprintf(pattern, sizeof(pattern), format, lowername);
|
||||
size_t pattern_len = strlen(pattern);
|
||||
|
||||
glob_t lower;
|
||||
if (glob(pattern, GLOB_NOSORT, NULL, &lower))
|
||||
break;
|
||||
|
||||
strncpy(lowername, lower.gl_pathv[0] + pattern_len - 1, sizeof(lowername)-1);
|
||||
|
||||
globfree(&lower);
|
||||
}
|
||||
|
||||
if (interface_file_exists(lowername, "wireless"))
|
||||
json_object_array_add(wireless, address);
|
||||
else if (interface_file_exists(lowername, "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 * 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", json_object_new_int(15));
|
||||
json_object_object_add(software, "batman-adv", software_batman_adv);
|
||||
json_object_object_add(ret, "software", software);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const enum batadv_nl_attrs gateways_mandatory[] = {
|
||||
BATADV_ATTR_ORIG_ADDRESS,
|
||||
BATADV_ATTR_ROUTER,
|
||||
};
|
||||
|
||||
static int parse_gw_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
uint8_t *orig;
|
||||
uint8_t *router;
|
||||
struct gw_netlink_opts *opts;
|
||||
char addr[18];
|
||||
|
||||
opts = batadv_container_of(query_opts, struct gw_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_GATEWAYS)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, gateways_mandatory,
|
||||
BATADV_ARRAY_SIZE(gateways_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
if (!attrs[BATADV_ATTR_FLAG_BEST])
|
||||
return NL_OK;
|
||||
|
||||
orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
|
||||
router = nla_data(attrs[BATADV_ATTR_ROUTER]);
|
||||
|
||||
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
|
||||
|
||||
json_object_object_add(opts->obj, "gateway", json_object_new_string(addr));
|
||||
|
||||
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
router[0], router[1], router[2], router[3], router[4], router[5]);
|
||||
|
||||
json_object_object_add(opts->obj, "gateway_nexthop", json_object_new_string(addr));
|
||||
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
static void add_gateway(struct json_object *obj) {
|
||||
struct gw_netlink_opts opts = {
|
||||
.obj = obj,
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
|
||||
batadv_genl_query("bat0", BATADV_CMD_GET_GATEWAYS,
|
||||
parse_gw_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
(*wifi)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void count_stations(size_t *wifi24, size_t *wifi5) {
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return;
|
||||
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 const enum batadv_nl_attrs clients_mandatory[] = {
|
||||
BATADV_ATTR_TT_FLAGS,
|
||||
/* Entries without the BATADV_TT_CLIENT_NOPURGE flag do not have a
|
||||
* BATADV_ATTR_LAST_SEEN_MSECS attribute. We can still make this attr
|
||||
* mandatory here, as entries without BATADV_TT_CLIENT_NOPURGE are
|
||||
* ignored anyways.
|
||||
*/
|
||||
BATADV_ATTR_LAST_SEEN_MSECS,
|
||||
};
|
||||
|
||||
static int parse_clients_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
struct clients_netlink_opts *opts;
|
||||
uint32_t flags, lastseen;
|
||||
|
||||
opts = batadv_container_of(query_opts, struct clients_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, clients_mandatory,
|
||||
BATADV_ARRAY_SIZE(clients_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);
|
||||
|
||||
if (flags & (BATADV_TT_CLIENT_NOPURGE | BATADV_TT_CLIENT_WIFI))
|
||||
return NL_OK;
|
||||
|
||||
lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
|
||||
if (lastseen > MAX_INACTIVITY)
|
||||
return NL_OK;
|
||||
|
||||
opts->non_wifi++;
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object * get_clients(void) {
|
||||
size_t wifi24 = 0, wifi5 = 0;
|
||||
size_t total;
|
||||
size_t wifi;
|
||||
struct clients_netlink_opts opts = {
|
||||
.non_wifi = 0,
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
|
||||
batadv_genl_query("bat0", BATADV_CMD_GET_TRANSTABLE_LOCAL,
|
||||
parse_clients_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
|
||||
count_stations(&wifi24, &wifi5);
|
||||
wifi = wifi24 + wifi5;
|
||||
total = wifi + opts.non_wifi;
|
||||
|
||||
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 const enum batadv_nl_attrs parse_orig_list_mandatory[] = {
|
||||
BATADV_ATTR_ORIG_ADDRESS,
|
||||
BATADV_ATTR_NEIGH_ADDRESS,
|
||||
BATADV_ATTR_TQ,
|
||||
BATADV_ATTR_HARD_IFINDEX,
|
||||
BATADV_ATTR_LAST_SEEN_MSECS,
|
||||
};
|
||||
|
||||
static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *attrs[BATADV_ATTR_MAX+1];
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
struct batadv_nlquery_opts *query_opts = arg;
|
||||
struct genlmsghdr *ghdr;
|
||||
uint8_t *orig;
|
||||
uint8_t *dest;
|
||||
uint8_t tq;
|
||||
uint32_t hardif;
|
||||
uint32_t lastseen;
|
||||
char ifname_buf[IF_NAMESIZE], *ifname;
|
||||
struct neigh_netlink_opts *opts;
|
||||
char mac1[18];
|
||||
|
||||
opts = batadv_container_of(query_opts, struct neigh_netlink_opts,
|
||||
query_opts);
|
||||
|
||||
if (!genlmsg_valid_hdr(nlh, 0))
|
||||
return NL_OK;
|
||||
|
||||
ghdr = nlmsg_data(nlh);
|
||||
|
||||
if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
|
||||
return NL_OK;
|
||||
|
||||
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
|
||||
genlmsg_len(ghdr), batadv_genl_policy))
|
||||
return NL_OK;
|
||||
|
||||
if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory,
|
||||
BATADV_ARRAY_SIZE(parse_orig_list_mandatory)))
|
||||
return NL_OK;
|
||||
|
||||
orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
|
||||
dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
|
||||
tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
|
||||
hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]);
|
||||
lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
|
||||
|
||||
if (memcmp(orig, dest, 6) != 0)
|
||||
return NL_OK;
|
||||
|
||||
ifname = if_indextoname(hardif, ifname_buf);
|
||||
if (!ifname)
|
||||
return NL_OK;
|
||||
|
||||
sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
|
||||
|
||||
struct json_object *obj = json_object_new_object();
|
||||
if (!obj)
|
||||
return NL_OK;
|
||||
|
||||
struct json_object *interface;
|
||||
if (!json_object_object_get_ex(opts->interfaces, ifname, &interface)) {
|
||||
interface = json_object_new_object();
|
||||
json_object_object_add(opts->interfaces, ifname, interface);
|
||||
}
|
||||
|
||||
json_object_object_add(obj, "tq", json_object_new_int(tq));
|
||||
json_object_object_add(obj, "lastseen", json_object_new_double(lastseen / 1000.));
|
||||
json_object_object_add(obj, "best", json_object_new_boolean(attrs[BATADV_ATTR_FLAG_BEST]));
|
||||
json_object_object_add(interface, mac1, obj);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
static struct json_object * get_batadv(void) {
|
||||
struct neigh_netlink_opts opts = {
|
||||
.query_opts = {
|
||||
.err = 0,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
opts.interfaces = json_object_new_object();
|
||||
if (!opts.interfaces)
|
||||
return NULL;
|
||||
|
||||
ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS,
|
||||
parse_orig_list_netlink_cb, NLM_F_DUMP,
|
||||
&opts.query_opts);
|
||||
if (ret < 0) {
|
||||
json_object_put(opts.interfaces);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ifnames2addrs(opts.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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((visibility ("default")))
|
||||
const struct respondd_provider_info respondd_providers[] = {
|
||||
{"nodeinfo", respondd_provider_nodeinfo},
|
||||
{"statistics", respondd_provider_statistics},
|
||||
|
@ -37,8 +37,8 @@
|
||||
|
||||
void usage() {
|
||||
puts("Usage: gluon-neighbour-info [-h] [-s] [-l] [-c <count>] [-t <sec>] -d <dest> -p <port> -i <if0> -r <request>");
|
||||
puts(" -p <int> UDP port");
|
||||
puts(" -d <ip6> destination address (unicast ip6 or multicast group, e.g. ff02:0:0:0:0:0:2:1001)");
|
||||
puts(" -p <int> UDP port (default: 1001)");
|
||||
puts(" -d <ip6> destination address (unicast ip6 or multicast group, e.g. ff02:0:0:0:0:0:2:1001, default: ::1)");
|
||||
puts(" -i <string> interface, e.g. eth0 ");
|
||||
puts(" -r <string> request, e.g. nodeinfo");
|
||||
puts(" -t <sec> timeout in seconds (default: 3)");
|
||||
@ -144,6 +144,8 @@ int main(int argc, char **argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
client_addr.sin6_addr = in6addr_loopback;
|
||||
client_addr.sin6_port = htons(1001);
|
||||
client_addr.sin6_family = AF_INET6;
|
||||
|
||||
opterr = 0;
|
||||
|
@ -2,5 +2,7 @@ all: respondd.so
|
||||
|
||||
CFLAGS += -Wall
|
||||
|
||||
respondd.so: respondd.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -lplatforminfo -luci
|
||||
SOURCES = respondd.c respondd-nodeinfo.c respondd-statistics.c respondd-neighbours.c
|
||||
|
||||
respondd.so: $(SOURCES) respondd-common.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -fvisibility=hidden -D_GNU_SOURCE -o $@ $(SOURCES) $(LDLIBS) -lgluonutil -lplatforminfo -luci -liwinfo
|
||||
|
32
package/gluon-respondd/src/respondd-common.h
Normal file
32
package/gluon-respondd/src/respondd-common.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MAX_INACTIVITY 60000
|
||||
|
||||
struct json_object * respondd_provider_nodeinfo(void);
|
||||
struct json_object * respondd_provider_statistics(void);
|
||||
struct json_object * respondd_provider_neighbours(void);
|
130
package/gluon-respondd/src/respondd-neighbours.c
Normal file
130
package/gluon-respondd/src/respondd-neighbours.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <libgluonutil.h>
|
||||
|
||||
#include <iwinfo.h>
|
||||
#include <json-c/json.h>
|
||||
|
||||
|
||||
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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
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) {
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
struct uci_package *p;
|
||||
if (uci_load(ctx, "network", &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, "interface"))
|
||||
continue;
|
||||
|
||||
const char *proto = uci_lookup_option_string(ctx, s, "proto");
|
||||
if (!proto || strcmp(proto, "gluon_mesh"))
|
||||
continue;
|
||||
|
||||
const char *ifname = uci_lookup_option_string(ctx, s, "ifname");
|
||||
if (!ifname)
|
||||
continue;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
end:
|
||||
uci_free_context(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct json_object * respondd_provider_neighbours(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
|
||||
struct json_object *wifi = get_wifi();
|
||||
if (wifi)
|
||||
json_object_object_add(ret, "wifi", wifi);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
132
package/gluon-respondd/src/respondd-nodeinfo.c
Normal file
132
package/gluon-respondd/src/respondd-nodeinfo.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <libgluonutil.h>
|
||||
#include <libplatforminfo.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static struct json_object * gluon_version(void) {
|
||||
char *version = gluonutil_read_line("/lib/gluon/gluon-version");
|
||||
if (!version)
|
||||
return NULL;
|
||||
|
||||
char full_version[6 + strlen(version) + 1];
|
||||
snprintf(full_version, sizeof(full_version), "gluon-%s", version);
|
||||
|
||||
free(version);
|
||||
|
||||
|
||||
return json_object_new_string(full_version);
|
||||
}
|
||||
|
||||
static struct json_object * get_site_code(void) {
|
||||
struct json_object *site = gluonutil_load_site_config();
|
||||
if (!site)
|
||||
return NULL;
|
||||
|
||||
struct json_object *ret = NULL;
|
||||
json_object_object_get_ex(site, "site_code", &ret);
|
||||
if (ret)
|
||||
json_object_get(ret);
|
||||
|
||||
json_object_put(site);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * get_domain_code(void) {
|
||||
return gluonutil_wrap_and_free_string(gluonutil_get_domain());
|
||||
}
|
||||
|
||||
static struct json_object * get_hostname(void) {
|
||||
struct json_object *ret = NULL;
|
||||
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||
|
||||
char section[] = "system.@system[0]";
|
||||
struct uci_ptr ptr;
|
||||
if (uci_lookup_ptr(ctx, &ptr, section, true))
|
||||
goto error;
|
||||
|
||||
struct uci_section *s = ptr.s;
|
||||
|
||||
const char *hostname = uci_lookup_option_string(ctx, s, "pretty_hostname");
|
||||
|
||||
if (!hostname)
|
||||
hostname = uci_lookup_option_string(ctx, s, "hostname");
|
||||
|
||||
ret = gluonutil_wrap_string(hostname);
|
||||
|
||||
error:
|
||||
uci_free_context(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct json_object * respondd_provider_nodeinfo(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
json_object_object_add(ret, "hostname", get_hostname());
|
||||
|
||||
struct json_object *hardware = json_object_new_object();
|
||||
|
||||
const char *model = platforminfo_get_model();
|
||||
if (model)
|
||||
json_object_object_add(hardware, "model", json_object_new_string(model));
|
||||
|
||||
json_object_object_add(hardware, "nproc", json_object_new_int(sysconf(_SC_NPROCESSORS_ONLN)));
|
||||
json_object_object_add(ret, "hardware", hardware);
|
||||
|
||||
struct json_object *network = json_object_new_object();
|
||||
json_object_object_add(network, "mac", gluonutil_wrap_and_free_string(gluonutil_get_sysconfig("primary_mac")));
|
||||
json_object_object_add(ret, "network", network);
|
||||
|
||||
struct json_object *software = json_object_new_object();
|
||||
struct json_object *software_firmware = json_object_new_object();
|
||||
json_object_object_add(software_firmware, "base", gluon_version());
|
||||
json_object_object_add(software_firmware, "release", gluonutil_wrap_and_free_string(gluonutil_read_line("/lib/gluon/release")));
|
||||
json_object_object_add(software, "firmware", software_firmware);
|
||||
json_object_object_add(ret, "software", software);
|
||||
|
||||
struct json_object *system = json_object_new_object();
|
||||
json_object_object_add(system, "site_code", get_site_code());
|
||||
if (gluonutil_has_domains())
|
||||
json_object_object_add(system, "domain_code", get_domain_code());
|
||||
json_object_object_add(ret, "system", system);
|
||||
|
||||
return ret;
|
||||
}
|
309
package/gluon-respondd/src/respondd-statistics.c
Normal file
309
package/gluon-respondd/src/respondd-statistics.c
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
Copyright (c) 2016-2019, 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-common.h"
|
||||
|
||||
#include <libgluonutil.h>
|
||||
|
||||
#include <iwinfo.h>
|
||||
#include <json-c/json.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
|
||||
static void add_uptime(struct json_object *obj) {
|
||||
FILE *f = fopen("/proc/uptime", "r");
|
||||
struct json_object* jso;
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
double uptime, idletime;
|
||||
if (fscanf(f, "%lf %lf", &uptime, &idletime) == 2) {
|
||||
jso = json_object_new_double(uptime);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "uptime", jso);
|
||||
jso = json_object_new_double(idletime);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "idletime", jso);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void add_loadavg(struct json_object *obj) {
|
||||
FILE *f = fopen("/proc/loadavg", "r");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
double loadavg;
|
||||
unsigned proc_running, proc_total;
|
||||
if (fscanf(f, "%lf %*f %*f %u/%u", &loadavg, &proc_running, &proc_total) == 3) {
|
||||
struct json_object *jso = json_object_new_double(loadavg);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "loadavg", jso);
|
||||
|
||||
struct json_object *processes = json_object_new_object();
|
||||
json_object_object_add(processes, "running", json_object_new_int(proc_running));
|
||||
json_object_object_add(processes, "total", json_object_new_int(proc_total));
|
||||
json_object_object_add(obj, "processes", processes);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static struct json_object * get_memory(void) {
|
||||
FILE *f = fopen("/proc/meminfo", "r");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, f) >= 0) {
|
||||
char label[32];
|
||||
unsigned value;
|
||||
|
||||
if (sscanf(line, "%31[^:]: %u", label, &value) != 2)
|
||||
continue;
|
||||
|
||||
if (!strcmp(label, "MemTotal"))
|
||||
json_object_object_add(ret, "total", json_object_new_int(value));
|
||||
else if (!strcmp(label, "MemFree"))
|
||||
json_object_object_add(ret, "free", json_object_new_int(value));
|
||||
else if (!strcmp(label, "MemAvailable"))
|
||||
json_object_object_add(ret, "available", json_object_new_int(value));
|
||||
else if (!strcmp(label, "Buffers"))
|
||||
json_object_object_add(ret, "buffers", json_object_new_int(value));
|
||||
else if (!strcmp(label, "Cached"))
|
||||
json_object_object_add(ret, "cached", json_object_new_int(value));
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * get_stat(void) {
|
||||
FILE *f = fopen("/proc/stat", "r");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
struct json_object *stat = json_object_new_object();
|
||||
struct json_object *ret = NULL;
|
||||
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, f) >= 0) {
|
||||
char label[32];
|
||||
|
||||
if (sscanf(line, "%31s", label) != 1){
|
||||
goto invalid_stat_format;
|
||||
}
|
||||
|
||||
if (!strcmp(label, "cpu")) {
|
||||
int64_t user, nice, system, idle, iowait, irq, softirq;
|
||||
if (sscanf(line, "%*s %"SCNd64" %"SCNd64" %"SCNd64" %"SCNd64" %"SCNd64" %"SCNd64" %"SCNd64,
|
||||
&user, &nice, &system, &idle, &iowait, &irq, &softirq) != 7)
|
||||
goto invalid_stat_format;
|
||||
|
||||
struct json_object *cpu = json_object_new_object();
|
||||
|
||||
json_object_object_add(cpu, "user", json_object_new_int64(user));
|
||||
json_object_object_add(cpu, "nice", json_object_new_int64(nice));
|
||||
json_object_object_add(cpu, "system", json_object_new_int64(system));
|
||||
json_object_object_add(cpu, "idle", json_object_new_int64(idle));
|
||||
json_object_object_add(cpu, "iowait", json_object_new_int64(iowait));
|
||||
json_object_object_add(cpu, "irq", json_object_new_int64(irq));
|
||||
json_object_object_add(cpu, "softirq", json_object_new_int64(softirq));
|
||||
|
||||
json_object_object_add(stat, "cpu", cpu);
|
||||
} else if (!strcmp(label, "ctxt")) {
|
||||
int64_t ctxt;
|
||||
if (sscanf(line, "%*s %"SCNd64, &ctxt) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "ctxt", json_object_new_int64(ctxt));
|
||||
} else if (!strcmp(label, "intr")) {
|
||||
int64_t total_intr;
|
||||
if (sscanf(line, "%*s %"SCNd64, &total_intr) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "intr", json_object_new_int64(total_intr));
|
||||
} else if (!strcmp(label, "softirq")) {
|
||||
int64_t total_softirq;
|
||||
if (sscanf(line, "%*s %"SCNd64, &total_softirq) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "softirq", json_object_new_int64(total_softirq));
|
||||
} else if (!strcmp(label, "processes")) {
|
||||
int64_t processes;
|
||||
if (sscanf(line, "%*s %"SCNd64, &processes) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "processes", json_object_new_int64(processes));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = stat;
|
||||
|
||||
invalid_stat_format:
|
||||
if (!ret)
|
||||
json_object_put(stat);
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct json_object * get_rootfs_usage(void) {
|
||||
struct statfs s;
|
||||
if (statfs("/", &s))
|
||||
return NULL;
|
||||
|
||||
struct json_object *jso = json_object_new_double(1 - (double)s.f_bfree / s.f_blocks);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.4f", NULL);
|
||||
return jso;
|
||||
}
|
||||
|
||||
static struct json_object * get_time(void) {
|
||||
struct timespec now;
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
||||
return NULL;
|
||||
|
||||
return json_object_new_int64(now.tv_sec);
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (entry->inactive > MAX_INACTIVITY)
|
||||
continue;
|
||||
|
||||
(*wifi)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void count_stations(size_t *wifi24, size_t *wifi5) {
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return;
|
||||
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 wifi24 = 0, wifi5 = 0;
|
||||
|
||||
count_stations(&wifi24, &wifi5);
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "wifi", json_object_new_int(wifi24 + wifi5));
|
||||
json_object_object_add(ret, "wifi24", json_object_new_int(wifi24));
|
||||
json_object_object_add(ret, "wifi5", json_object_new_int(wifi5));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct json_object * respondd_provider_statistics(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
|
||||
json_object_object_add(ret, "time", get_time());
|
||||
json_object_object_add(ret, "rootfs_usage", get_rootfs_usage());
|
||||
json_object_object_add(ret, "memory", get_memory());
|
||||
json_object_object_add(ret, "stat", get_stat());
|
||||
|
||||
json_object_object_add(ret, "clients", get_clients());
|
||||
|
||||
add_uptime(ret);
|
||||
add_loadavg(ret);
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2016-2019, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -23,316 +23,12 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "respondd-common.h"
|
||||
|
||||
#include <respondd.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <libgluonutil.h>
|
||||
#include <libplatforminfo.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
|
||||
static struct json_object * gluon_version(void) {
|
||||
char *version = gluonutil_read_line("/lib/gluon/gluon-version");
|
||||
if (!version)
|
||||
return NULL;
|
||||
|
||||
char full_version[6 + strlen(version) + 1];
|
||||
snprintf(full_version, sizeof(full_version), "gluon-%s", version);
|
||||
|
||||
free(version);
|
||||
|
||||
|
||||
return json_object_new_string(full_version);
|
||||
}
|
||||
|
||||
static struct json_object * get_site_code(void) {
|
||||
struct json_object *site = gluonutil_load_site_config();
|
||||
if (!site)
|
||||
return NULL;
|
||||
|
||||
struct json_object *ret = NULL;
|
||||
json_object_object_get_ex(site, "site_code", &ret);
|
||||
if (ret)
|
||||
json_object_get(ret);
|
||||
|
||||
json_object_put(site);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * get_domain_code(void) {
|
||||
return gluonutil_wrap_and_free_string(gluonutil_get_domain());
|
||||
}
|
||||
|
||||
static struct json_object * get_hostname(void) {
|
||||
struct json_object *ret = NULL;
|
||||
|
||||
struct uci_context *ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||
|
||||
char section[] = "system.@system[0]";
|
||||
struct uci_ptr ptr;
|
||||
if (uci_lookup_ptr(ctx, &ptr, section, true))
|
||||
goto error;
|
||||
|
||||
struct uci_section *s = ptr.s;
|
||||
|
||||
const char *hostname = uci_lookup_option_string(ctx, s, "pretty_hostname");
|
||||
|
||||
if (!hostname)
|
||||
hostname = uci_lookup_option_string(ctx, s, "hostname");
|
||||
|
||||
ret = gluonutil_wrap_string(hostname);
|
||||
|
||||
error:
|
||||
uci_free_context(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * respondd_provider_nodeinfo(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
json_object_object_add(ret, "hostname", get_hostname());
|
||||
|
||||
struct json_object *hardware = json_object_new_object();
|
||||
|
||||
const char *model = platforminfo_get_model();
|
||||
if (model)
|
||||
json_object_object_add(hardware, "model", json_object_new_string(model));
|
||||
|
||||
json_object_object_add(hardware, "nproc", json_object_new_int(sysconf(_SC_NPROCESSORS_ONLN)));
|
||||
json_object_object_add(ret, "hardware", hardware);
|
||||
|
||||
struct json_object *network = json_object_new_object();
|
||||
json_object_object_add(network, "mac", gluonutil_wrap_and_free_string(gluonutil_get_sysconfig("primary_mac")));
|
||||
json_object_object_add(ret, "network", network);
|
||||
|
||||
struct json_object *software = json_object_new_object();
|
||||
struct json_object *software_firmware = json_object_new_object();
|
||||
json_object_object_add(software_firmware, "base", gluon_version());
|
||||
json_object_object_add(software_firmware, "release", gluonutil_wrap_and_free_string(gluonutil_read_line("/lib/gluon/release")));
|
||||
json_object_object_add(software, "firmware", software_firmware);
|
||||
json_object_object_add(ret, "software", software);
|
||||
|
||||
struct json_object *system = json_object_new_object();
|
||||
json_object_object_add(system, "site_code", get_site_code());
|
||||
if (gluonutil_has_domains())
|
||||
json_object_object_add(system, "domain_code", get_domain_code());
|
||||
json_object_object_add(ret, "system", system);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void add_uptime(struct json_object *obj) {
|
||||
FILE *f = fopen("/proc/uptime", "r");
|
||||
struct json_object* jso;
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
double uptime, idletime;
|
||||
if (fscanf(f, "%lf %lf", &uptime, &idletime) == 2) {
|
||||
jso = json_object_new_double(uptime);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "uptime", jso);
|
||||
jso = json_object_new_double(idletime);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "idletime", jso);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void add_loadavg(struct json_object *obj) {
|
||||
FILE *f = fopen("/proc/loadavg", "r");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
double loadavg;
|
||||
unsigned proc_running, proc_total;
|
||||
if (fscanf(f, "%lf %*f %*f %u/%u", &loadavg, &proc_running, &proc_total) == 3) {
|
||||
struct json_object *jso = json_object_new_double(loadavg);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
|
||||
json_object_object_add(obj, "loadavg", jso);
|
||||
|
||||
struct json_object *processes = json_object_new_object();
|
||||
json_object_object_add(processes, "running", json_object_new_int(proc_running));
|
||||
json_object_object_add(processes, "total", json_object_new_int(proc_total));
|
||||
json_object_object_add(obj, "processes", processes);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static struct json_object * get_memory(void) {
|
||||
FILE *f = fopen("/proc/meminfo", "r");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, f) >= 0) {
|
||||
char label[32];
|
||||
unsigned value;
|
||||
|
||||
if (sscanf(line, "%31[^:]: %u", label, &value) != 2)
|
||||
continue;
|
||||
|
||||
if (!strcmp(label, "MemTotal"))
|
||||
json_object_object_add(ret, "total", json_object_new_int(value));
|
||||
else if (!strcmp(label, "MemFree"))
|
||||
json_object_object_add(ret, "free", json_object_new_int(value));
|
||||
else if (!strcmp(label, "MemAvailable"))
|
||||
json_object_object_add(ret, "available", json_object_new_int(value));
|
||||
else if (!strcmp(label, "Buffers"))
|
||||
json_object_object_add(ret, "buffers", json_object_new_int(value));
|
||||
else if (!strcmp(label, "Cached"))
|
||||
json_object_object_add(ret, "cached", json_object_new_int(value));
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct json_object * get_stat(void) {
|
||||
FILE *f = fopen("/proc/stat", "r");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
struct json_object *stat = json_object_new_object();
|
||||
struct json_object *ret = NULL;
|
||||
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, f) >= 0) {
|
||||
char label[32];
|
||||
|
||||
if (sscanf(line, "%31s", label) != 1){
|
||||
goto invalid_stat_format;
|
||||
}
|
||||
|
||||
if (!strcmp(label, "cpu")) {
|
||||
unsigned long long user, nice, system, idle, iowait, irq, softirq;
|
||||
if (sscanf(line, "%*s %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64,
|
||||
&user, &nice, &system, &idle, &iowait, &irq, &softirq) != 7)
|
||||
goto invalid_stat_format;
|
||||
|
||||
struct json_object *cpu = json_object_new_object();
|
||||
|
||||
json_object_object_add(cpu, "user", json_object_new_int64(user));
|
||||
json_object_object_add(cpu, "nice", json_object_new_int64(nice));
|
||||
json_object_object_add(cpu, "system", json_object_new_int64(system));
|
||||
json_object_object_add(cpu, "idle", json_object_new_int64(idle));
|
||||
json_object_object_add(cpu, "iowait", json_object_new_int64(iowait));
|
||||
json_object_object_add(cpu, "irq", json_object_new_int64(irq));
|
||||
json_object_object_add(cpu, "softirq", json_object_new_int64(softirq));
|
||||
|
||||
json_object_object_add(stat, "cpu", cpu);
|
||||
} else if (!strcmp(label, "ctxt")) {
|
||||
unsigned long long ctxt;
|
||||
if (sscanf(line, "%*s %"SCNu64, &ctxt) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "ctxt", json_object_new_int64(ctxt));
|
||||
} else if (!strcmp(label, "intr")) {
|
||||
unsigned long long total_intr;
|
||||
if (sscanf(line, "%*s %"SCNu64, &total_intr) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "intr", json_object_new_int64(total_intr));
|
||||
} else if (!strcmp(label, "softirq")) {
|
||||
unsigned long long total_softirq;
|
||||
if (sscanf(line, "%*s %"SCNu64, &total_softirq) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "softirq", json_object_new_int64(total_softirq));
|
||||
} else if (!strcmp(label, "processes")) {
|
||||
unsigned long long processes;
|
||||
if (sscanf(line, "%*s %"SCNu64, &processes) != 1)
|
||||
goto invalid_stat_format;
|
||||
|
||||
json_object_object_add(stat, "processes", json_object_new_int64(processes));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = stat;
|
||||
|
||||
invalid_stat_format:
|
||||
if (!ret)
|
||||
json_object_put(stat);
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct json_object * get_rootfs_usage(void) {
|
||||
struct statfs s;
|
||||
if (statfs("/", &s))
|
||||
return NULL;
|
||||
|
||||
struct json_object *jso = json_object_new_double(1 - (double)s.f_bfree / s.f_blocks);
|
||||
json_object_set_serializer(jso, json_object_double_to_json_string, "%.4f", NULL);
|
||||
return jso;
|
||||
}
|
||||
|
||||
static struct json_object * get_time(void) {
|
||||
struct timespec now;
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
||||
return NULL;
|
||||
|
||||
return json_object_new_int64(now.tv_sec);
|
||||
}
|
||||
|
||||
static struct json_object * respondd_provider_statistics(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
|
||||
json_object *time = get_time();
|
||||
if (time != NULL)
|
||||
json_object_object_add(ret, "time", time);
|
||||
|
||||
json_object_object_add(ret, "rootfs_usage", get_rootfs_usage());
|
||||
json_object_object_add(ret, "memory", get_memory());
|
||||
json_object_object_add(ret, "stat", get_stat());
|
||||
|
||||
add_uptime(ret);
|
||||
add_loadavg(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct json_object * respondd_provider_neighbours(void) {
|
||||
struct json_object *ret = json_object_new_object();
|
||||
json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((visibility ("default")))
|
||||
const struct respondd_provider_info respondd_providers[] = {
|
||||
{"nodeinfo", respondd_provider_nodeinfo},
|
||||
{"statistics", respondd_provider_statistics},
|
||||
|
@ -12,7 +12,7 @@ wait_setup_mode() {
|
||||
}
|
||||
|
||||
|
||||
if [ "$BUTTON" = wps -o "$BUTTON" = reset -o "$BUTTON" = phone ]; then
|
||||
if [ "$BUTTON" = wps ] || [ "$BUTTON" = reset ] || [ "$BUTTON" = phone ]; then
|
||||
case "$ACTION" in
|
||||
pressed)
|
||||
wait_setup_mode &
|
||||
@ -21,7 +21,7 @@ if [ "$BUTTON" = wps -o "$BUTTON" = reset -o "$BUTTON" = phone ]; then
|
||||
;;
|
||||
released)
|
||||
if [ -r /tmp/.wait_setup_mode ]; then
|
||||
kill $(cat /tmp/.wait_setup_mode)
|
||||
kill "$(cat /tmp/.wait_setup_mode)"
|
||||
rm /tmp/.wait_setup_mode
|
||||
fi
|
||||
;;
|
||||
|
@ -5,7 +5,7 @@ setup_mode_enable() {
|
||||
local enabled="$(uci -q get 'gluon-setup-mode.@setup_mode[0].enabled')"
|
||||
local configured="$(uci -q get 'gluon-setup-mode.@setup_mode[0].configured')"
|
||||
|
||||
if [ "$enabled" = 1 -o "$configured" != 1 ]; then
|
||||
if [ "$enabled" = 1 ] || [ "$configured" != 1 ]; then
|
||||
echo '/lib/gluon/setup-mode/rc.d' > /tmp/rc_d_path
|
||||
fi
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ PKG_VERSION:=$(if $(DUMP),x,$(GLUON_SITE_VERSION))
|
||||
|
||||
PKG_CONFIG_DEPENDS := CONFIG_GLUON_RELEASE CONFIG_GLUON_SITEDIR CONFIG_GLUON_MULTIDOMAIN
|
||||
PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/site.conf $(GLUON_SITEDIR)/domains/ $(GLUON_SITEDIR)/i18n/
|
||||
PKG_BUILD_DEPENDS := lua-cjson/host
|
||||
PKG_BUILD_DEPENDS := lua-cjson/host gluon-web/host
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
||||
<tr><th><%:Load average%></th><td><%= statistics('loadavg', 'decimal') %></td></tr>
|
||||
<tr><th><%:RAM%></th><td><%= statistics('memory', 'memory') %></td></tr>
|
||||
<tr><th><%:Filesystem%></th><td><%= statistics('rootfs_usage', 'percent') %></td></tr>
|
||||
<tr><th><%:Gateway%></th><td><%= statistics('gateway') %></td></tr>
|
||||
<tr><th><%:Gateway%></th><td><%= statistics('gateway') %><br /><%= statistics('gateway_nexthop', 'neighbour') %></td></tr>
|
||||
<tr><th><%:Clients%></th><td><%= statistics('clients/total') %></td></tr>
|
||||
</table>
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -55,6 +55,9 @@ msgstr "Weitergeleitet"
|
||||
msgid "Gateway"
|
||||
msgstr "Gateway"
|
||||
|
||||
msgid "Gateway Nexthop"
|
||||
msgstr "Gateway Nexthop"
|
||||
|
||||
msgid "IP address"
|
||||
msgstr "IP-Adresse"
|
||||
|
||||
|
@ -46,6 +46,9 @@ msgstr ""
|
||||
msgid "Gateway"
|
||||
msgstr ""
|
||||
|
||||
msgid "Gateway Nexthop"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address"
|
||||
msgstr ""
|
||||
|
||||
|
@ -112,6 +112,20 @@
|
||||
'bytes': function(bytes) {
|
||||
return prettyBytes(bytes);
|
||||
},
|
||||
'neighbour': function(addr) {
|
||||
if (!addr)
|
||||
return '';
|
||||
|
||||
for (var i in interfaces) {
|
||||
var iface = interfaces[i];
|
||||
var neigh = iface.lookup_neigh(addr);
|
||||
if (!neigh)
|
||||
continue;
|
||||
return 'via ' + neigh.get_hostname() + ' (' + i + ')';
|
||||
}
|
||||
|
||||
return 'via ' + addr + ' (unknown iface)';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -582,6 +596,9 @@
|
||||
}
|
||||
|
||||
return {
|
||||
'get_hostname': function() {
|
||||
return hostname.textContent;
|
||||
},
|
||||
'update_nodeinfo': function(nodeinfo) {
|
||||
var addr = choose_address(nodeinfo.network.addresses);
|
||||
if (addr) {
|
||||
@ -711,6 +728,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
function lookup_neigh(addr) {
|
||||
return neighs[addr];
|
||||
}
|
||||
|
||||
function get_neigh(addr) {
|
||||
var neigh = neighs[addr];
|
||||
@ -738,6 +758,7 @@
|
||||
|
||||
return {
|
||||
'get_neigh': get_neigh,
|
||||
'lookup_neigh': lookup_neigh
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ PKG_VERSION:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include ../gluon.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Package/gluon-web
|
||||
TITLE:=Minimal Lua web framework derived from LuCI
|
||||
@ -24,4 +25,18 @@ define Package/gluon-web/config
|
||||
$(foreach lang,$(GLUON_SUPPORTED_LANGS),$(call lang-config,$(lang)))
|
||||
endef
|
||||
|
||||
define Host/Prepare
|
||||
$(CP) ./src/* $(HOST_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Host/Compile
|
||||
$(call Host/Compile/Default,gluon-po2lmo)
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_DIR) $(1)/bin
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/gluon-po2lmo $(1)/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackageGluon,gluon-web))
|
||||
$(eval $(call HostBuild))
|
||||
|
@ -9,6 +9,8 @@ clean:
|
||||
parser.so: template_parser.o template_utils.o template_lmo.o template_lualib.o
|
||||
$(CC) $(LDFLAGS) -shared -o $@ $^
|
||||
|
||||
gluon-po2lmo: gluon-po2lmo.o template_lmo.o
|
||||
|
||||
compile: parser.so
|
||||
|
||||
install: compile
|
||||
|
256
package/gluon-web/src/gluon-po2lmo.c
Normal file
256
package/gluon-web/src/gluon-po2lmo.c
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - PO to LMO conversion tool
|
||||
*
|
||||
* Copyright (C) 2009-2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "template_lmo.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
__attribute__((noreturn))
|
||||
static void die(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__attribute__((noreturn))
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
{
|
||||
if( fwrite(ptr, size, nmemb, stream) == 0 )
|
||||
die("Failed to write stdout");
|
||||
}
|
||||
|
||||
static ssize_t extract_string(const char *src, char *dest, size_t len)
|
||||
{
|
||||
size_t pos = 0;
|
||||
int esc = 0;
|
||||
int off = -1;
|
||||
|
||||
for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
|
||||
{
|
||||
if( (off == -1) && (src[pos] == '"') )
|
||||
{
|
||||
off = pos + 1;
|
||||
}
|
||||
else if( off >= 0 )
|
||||
{
|
||||
if( esc == 1 )
|
||||
{
|
||||
switch (src[pos])
|
||||
{
|
||||
case '"':
|
||||
case '\\':
|
||||
off++;
|
||||
break;
|
||||
}
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 0;
|
||||
}
|
||||
else if( src[pos] == '\\' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 1;
|
||||
}
|
||||
else if( src[pos] != '"' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[pos-off] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (off > -1) ? (ssize_t) strlen(dest) : -1;
|
||||
}
|
||||
|
||||
static int cmp_index(const void *a, const void *b)
|
||||
{
|
||||
uint32_t x = ((const lmo_entry_t *)a)->key_id;
|
||||
uint32_t y = ((const lmo_entry_t *)b)->key_id;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
else if (x > y)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_uint32(uint32_t x, FILE *out)
|
||||
{
|
||||
uint32_t y = htonl(x);
|
||||
print(&y, sizeof(uint32_t), 1, out);
|
||||
}
|
||||
|
||||
static void print_index(void *array, int n, FILE *out)
|
||||
{
|
||||
lmo_entry_t *e;
|
||||
|
||||
qsort(array, n, sizeof(*e), cmp_index);
|
||||
|
||||
for (e = array; n > 0; n--, e++)
|
||||
{
|
||||
print_uint32(e->key_id, out);
|
||||
print_uint32(e->val_id, out);
|
||||
print_uint32(e->offset, out);
|
||||
print_uint32(e->length, out);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char line[4096];
|
||||
char key[4096];
|
||||
char val[4096];
|
||||
char tmp[4096];
|
||||
int state = 0;
|
||||
int offset = 0;
|
||||
int length = 0;
|
||||
int n_entries = 0;
|
||||
void *array = NULL;
|
||||
lmo_entry_t *entry = NULL;
|
||||
uint32_t key_id, val_id;
|
||||
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
|
||||
if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
|
||||
usage(argv[0]);
|
||||
|
||||
memset(line, 0, sizeof(key));
|
||||
memset(key, 0, sizeof(val));
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
|
||||
{
|
||||
if( state == 0 && strstr(line, "msgid \"") == line )
|
||||
{
|
||||
switch(extract_string(line, key, sizeof(key)))
|
||||
{
|
||||
case -1:
|
||||
die("Syntax error in msgid");
|
||||
case 0:
|
||||
state = 1;
|
||||
break;
|
||||
default:
|
||||
state = 2;
|
||||
}
|
||||
}
|
||||
else if( state == 1 || state == 2 )
|
||||
{
|
||||
if( strstr(line, "msgstr \"") == line || state == 2 )
|
||||
{
|
||||
switch(extract_string(line, val, sizeof(val)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 2;
|
||||
break;
|
||||
default:
|
||||
strcat(key, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( state == 3 )
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
strcat(val, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if( state == 4 )
|
||||
{
|
||||
if( strlen(key) > 0 && strlen(val) > 0 )
|
||||
{
|
||||
key_id = sfh_hash(key, strlen(key));
|
||||
val_id = sfh_hash(val, strlen(val));
|
||||
|
||||
if( key_id != val_id )
|
||||
{
|
||||
n_entries++;
|
||||
array = realloc(array, n_entries * sizeof(lmo_entry_t));
|
||||
entry = (lmo_entry_t *)array + n_entries - 1;
|
||||
|
||||
if (!array)
|
||||
die("Out of memory");
|
||||
|
||||
entry->key_id = key_id;
|
||||
entry->val_id = val_id;
|
||||
entry->offset = offset;
|
||||
entry->length = strlen(val);
|
||||
|
||||
length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
|
||||
|
||||
print(val, length, 1, out);
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
state = 0;
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(val, 0, sizeof(val));
|
||||
}
|
||||
|
||||
memset(line, 0, sizeof(line));
|
||||
}
|
||||
|
||||
print_index(array, n_entries, out);
|
||||
|
||||
if( offset > 0 )
|
||||
{
|
||||
print_uint32(offset, out);
|
||||
fsync(fileno(out));
|
||||
fclose(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(out);
|
||||
unlink(argv[2]);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
return(0);
|
||||
}
|
@ -25,20 +25,11 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
struct lmo_entry {
|
||||
uint32_t key_id;
|
||||
uint32_t val_id;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
static inline uint16_t get_le16(const void *data) {
|
||||
const uint8_t *d = data;
|
||||
return (((uint16_t)d[1]) << 8) | d[0];
|
||||
@ -56,7 +47,7 @@ static inline uint32_t get_be32(const void *data) {
|
||||
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
|
||||
* Copyright (C) 2004-2008 by Paul Hsieh
|
||||
*/
|
||||
static uint32_t sfh_hash(const void *input, size_t len)
|
||||
uint32_t sfh_hash(const void *input, size_t len)
|
||||
{
|
||||
const uint8_t *data = input;
|
||||
uint32_t hash = len, tmp;
|
||||
|
@ -22,8 +22,15 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
struct lmo_entry {
|
||||
uint32_t key_id;
|
||||
uint32_t val_id;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} __attribute__((packed));
|
||||
typedef struct lmo_entry lmo_entry_t;
|
||||
|
||||
|
||||
@ -37,6 +44,8 @@ struct lmo_catalog {
|
||||
typedef struct lmo_catalog lmo_catalog_t;
|
||||
|
||||
|
||||
uint32_t sfh_hash(const void *input, size_t len);
|
||||
|
||||
bool lmo_load(lmo_catalog_t *cat, const char *file);
|
||||
void lmo_unload(lmo_catalog_t *cat);
|
||||
bool lmo_translate(const lmo_catalog_t *cat, const char *key, size_t keylen, const char **out, size_t *outlen);
|
||||
|
@ -1,8 +1,7 @@
|
||||
GLUON_MK := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
PKG_FILE_DEPENDS += $(GLUON_MK)
|
||||
|
||||
# Dependencies for LuaSrcDiet
|
||||
PKG_BUILD_DEPENDS += luci-base/host
|
||||
PKG_BUILD_DEPENDS += luasrcdiet/host
|
||||
|
||||
ifneq ($(wildcard ./src/respondd.c),)
|
||||
PKG_BUILD_DEPENDS += respondd
|
||||
@ -31,6 +30,7 @@ GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_GLUON_WEB_LA
|
||||
GLUON_ENABLED_LANGS := en $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_GLUON_WEB_LANG_$(lang)),$(lang)))
|
||||
|
||||
ifneq ($(wildcard ./i18n/.),)
|
||||
PKG_BUILD_DEPENDS += gluon-web/host
|
||||
PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
|
||||
endif
|
||||
|
||||
@ -40,7 +40,7 @@ define GluonBuildI18N
|
||||
for lang in $$(GLUON_ENABLED_LANGS); do \
|
||||
if [ -e $(1)/$$$$lang.po ]; then \
|
||||
rm -f $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \
|
||||
po2lmo $(1)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \
|
||||
gluon-po2lmo $(1)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \
|
||||
fi; \
|
||||
done
|
||||
endef
|
||||
|
@ -4,10 +4,10 @@ Subject: procd: add support for alternative rc.d directories
|
||||
|
||||
diff --git a/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch b/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b973844d5
|
||||
index 0000000000000000000000000000000000000000..16d3179f05c64b7178f883745294c64a27127775
|
||||
--- /dev/null
|
||||
+++ b/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch
|
||||
@@ -0,0 +1,97 @@
|
||||
@@ -0,0 +1,80 @@
|
||||
+From 03a2bc70e4260ec9f669391c47b9a7a9ecd0b75d Mon Sep 17 00:00:00 2001
|
||||
+Message-Id: <03a2bc70e4260ec9f669391c47b9a7a9ecd0b75d.1407329621.git.mschiffer@universe-factory.net>
|
||||
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
@ -19,21 +19,10 @@ index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b
|
||||
+ rcS.c | 2 +-
|
||||
+ 2 files changed, 39 insertions(+), 1 deletion(-)
|
||||
+
|
||||
+diff --git a/initd/preinit.c b/initd/preinit.c
|
||||
+index fb94527..8b832a7 100644
|
||||
+--- a/initd/preinit.c
|
||||
++++ b/initd/preinit.c
|
||||
+@@ -12,6 +12,8 @@
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
++#define _GNU_SOURCE
|
||||
++
|
||||
+ #include <sys/stat.h>
|
||||
+ #include <sys/types.h>
|
||||
+ #include <sys/mount.h>
|
||||
+@@ -46,6 +48,35 @@ check_dbglvl(void)
|
||||
+ debug = lvl;
|
||||
+@@ -87,12 +87,42 @@ fail:
|
||||
+ free(command);
|
||||
+ }
|
||||
+
|
||||
++static char*
|
||||
@ -68,15 +57,14 @@ index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b
|
||||
+ static void
|
||||
+ spawn_procd(struct uloop_process *proc, int ret)
|
||||
+ {
|
||||
+@@ -53,6 +84,7 @@ spawn_procd(struct uloop_process *proc, int ret)
|
||||
+ char *wdt_fd = watchdog_fd();
|
||||
+ char *argv[] = { "/sbin/procd", NULL};
|
||||
+ struct stat s;
|
||||
+ char dbg[2];
|
||||
++ char *rc_d_path;
|
||||
+
|
||||
+ if (plugd_proc.pid > 0)
|
||||
+ kill(plugd_proc.pid, SIGKILL);
|
||||
+@@ -72,6 +104,12 @@ spawn_procd(struct uloop_process *proc, int ret)
|
||||
+@@ -112,6 +142,12 @@ spawn_procd(struct uloop_process *proc,
|
||||
+ setenv("DBGLVL", dbg, 1);
|
||||
+ }
|
||||
+
|
||||
@ -89,11 +77,9 @@ index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b
|
||||
+ execvp(argv[0], argv);
|
||||
+ }
|
||||
+
|
||||
+diff --git a/rcS.c b/rcS.c
|
||||
+index 0e1b0ba..1b00831 100644
|
||||
+--- a/rcS.c
|
||||
++++ b/rcS.c
|
||||
+@@ -150,7 +150,7 @@ int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *))
|
||||
+@@ -184,7 +184,7 @@ int rcS(char *pattern, char *param, void
|
||||
+ q.empty_cb = q_empty;
|
||||
+ q.max_running_tasks = 1;
|
||||
+
|
||||
@ -102,6 +88,3 @@ index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b
|
||||
+ }
|
||||
+
|
||||
+ int rc(const char *file, char *param)
|
||||
+--
|
||||
+2.0.4
|
||||
+
|
||||
|
@ -4,10 +4,10 @@ Subject: libjson-c: Add support for custom format strings for doubles
|
||||
|
||||
diff --git a/package/libs/libjson-c/patches/002-custom-format-string.patch b/package/libs/libjson-c/patches/002-custom-format-string.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e6299bd5e6f
|
||||
index 0000000000000000000000000000000000000000..b67433a7baf37654a17fa5036c4266b33bdda9f2
|
||||
--- /dev/null
|
||||
+++ b/package/libs/libjson-c/patches/002-custom-format-string.patch
|
||||
@@ -0,0 +1,98 @@
|
||||
@@ -0,0 +1,91 @@
|
||||
+From 21dc5dc92bd56f5f4dc2c90b9ea6bf1e1407714e Mon Sep 17 00:00:00 2001
|
||||
+From: Jan-Philipp Litza <janphilipp@litza.de>
|
||||
+Date: Fri, 6 May 2016 16:12:44 +0200
|
||||
@ -20,11 +20,9 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+ json_object.h | 28 ++++++++++++++++++++++++++++
|
||||
+ 2 files changed, 34 insertions(+), 6 deletions(-)
|
||||
+
|
||||
+diff --git a/json_object.c b/json_object.c
|
||||
+index 7d60884..46701e7 100644
|
||||
+--- a/json_object.c
|
||||
++++ b/json_object.c
|
||||
+@@ -55,7 +55,6 @@ static struct json_object* json_object_new(enum json_type o_type);
|
||||
+@@ -55,7 +55,6 @@ static struct json_object* json_object_n
|
||||
+ static json_object_to_json_string_fn json_object_object_to_json_string;
|
||||
+ static json_object_to_json_string_fn json_object_boolean_to_json_string;
|
||||
+ static json_object_to_json_string_fn json_object_int_to_json_string;
|
||||
@ -32,7 +30,7 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+ static json_object_to_json_string_fn json_object_string_to_json_string;
|
||||
+ static json_object_to_json_string_fn json_object_array_to_json_string;
|
||||
+
|
||||
+@@ -644,10 +643,10 @@ int64_t json_object_get_int64(const struct json_object *jso)
|
||||
+@@ -560,10 +559,10 @@ int64_t json_object_get_int64(struct jso
|
||||
+
|
||||
+ /* json_object_double */
|
||||
+
|
||||
@ -47,7 +45,7 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+ {
|
||||
+ char buf[128], *p, *q;
|
||||
+ int size;
|
||||
+@@ -663,7 +662,8 @@ static int json_object_double_to_json_string(struct json_object* jso,
|
||||
+@@ -579,7 +578,8 @@ static int json_object_double_to_json_st
|
||||
+ else
|
||||
+ size = snprintf(buf, sizeof(buf), "-Infinity");
|
||||
+ else
|
||||
@ -57,11 +55,9 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+
|
||||
+ p = strchr(buf, ',');
|
||||
+ if (p) {
|
||||
+diff --git a/json_object.h b/json_object.h
|
||||
+index 2bce454..a89de44 100644
|
||||
+--- a/json_object.h
|
||||
++++ b/json_object.h
|
||||
+@@ -614,6 +614,9 @@ extern int64_t json_object_get_int64(const struct json_object *obj);
|
||||
+@@ -515,6 +515,9 @@ extern int64_t json_object_get_int64(str
|
||||
+ /* double type methods */
|
||||
+
|
||||
+ /** Create a new empty json_object of type json_type_double
|
||||
@ -71,7 +67,7 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+ * @param d the double
|
||||
+ * @returns a json_object of type json_type_double
|
||||
+ */
|
||||
+@@ -642,6 +645,31 @@ extern struct json_object* json_object_new_double(double d);
|
||||
+@@ -543,6 +546,31 @@ extern struct json_object* json_object_n
|
||||
+ */
|
||||
+ extern struct json_object* json_object_new_double_s(double d, const char *ds);
|
||||
+
|
||||
@ -103,6 +99,3 @@ index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e62
|
||||
+ /** Get the double floating point value of a json_object
|
||||
+ *
|
||||
+ * The type is coerced to a double if the passed object is not a double.
|
||||
+--
|
||||
+2.7.4
|
||||
+
|
||||
|
@ -6,10 +6,10 @@ Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
|
||||
diff --git a/target/linux/generic/backport-4.14/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch b/target/linux/generic/backport-4.14/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f4575b5027d
|
||||
index 0000000000000000000000000000000000000000..fe9c479338a7b597be649c761c70a63085b51c5f
|
||||
--- /dev/null
|
||||
+++ b/target/linux/generic/backport-4.14/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
||||
@@ -0,0 +1,141 @@
|
||||
@@ -0,0 +1,134 @@
|
||||
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+Date: Sat, 3 Mar 2018 11:55:21 +0100
|
||||
+Subject: [PATCH 1/2] ebtables: add support for matching ICMP type and code
|
||||
@ -23,8 +23,6 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+ net/bridge/netfilter/ebt_ip.c | 43 +++++++++++++++++++++-------
|
||||
+ 2 files changed, 43 insertions(+), 13 deletions(-)
|
||||
+
|
||||
+diff --git a/include/uapi/linux/netfilter_bridge/ebt_ip.h b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+index 8e462fb1983f..4ed7fbb0a482 100644
|
||||
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+@@ -24,8 +24,9 @@
|
||||
@ -55,8 +53,6 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+ };
|
||||
+
|
||||
+ #endif
|
||||
+diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
|
||||
+index 2b46c50abce0..8cb8f8395768 100644
|
||||
+--- a/net/bridge/netfilter/ebt_ip.c
|
||||
++++ b/net/bridge/netfilter/ebt_ip.c
|
||||
+@@ -19,9 +19,15 @@
|
||||
@ -78,7 +74,7 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+ };
|
||||
+
|
||||
+ static bool
|
||||
+@@ -30,8 +36,8 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+@@ -30,8 +36,8 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
||||
+ const struct ebt_ip_info *info = par->matchinfo;
|
||||
+ const struct iphdr *ih;
|
||||
+ struct iphdr _iph;
|
||||
@ -89,7 +85,7 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+
|
||||
+ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
|
||||
+ if (ih == NULL)
|
||||
+@@ -50,29 +56,38 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+@@ -50,29 +56,38 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
||||
+ if (info->bitmask & EBT_IP_PROTO) {
|
||||
+ if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
|
||||
+ return false;
|
||||
@ -133,7 +129,7 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+@@ -101,6 +116,14 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
|
||||
+@@ -101,6 +116,14 @@ static int ebt_ip_mt_check(const struct
|
||||
+ return -EINVAL;
|
||||
+ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
|
||||
+ return -EINVAL;
|
||||
@ -148,15 +144,12 @@ index 0000000000000000000000000000000000000000..9e4d90fb3b8e2c91e4adf0e0efdb3f45
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+--
|
||||
+2.16.2
|
||||
+
|
||||
diff --git a/target/linux/generic/backport-4.14/096-0002-ebtables-add-support-for-matching-IGMP-type.patch b/target/linux/generic/backport-4.14/096-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6c53bba29
|
||||
index 0000000000000000000000000000000000000000..4c8144834d87c58ff90363cdc2f2933194e54fdc
|
||||
--- /dev/null
|
||||
+++ b/target/linux/generic/backport-4.14/096-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
||||
@@ -0,0 +1,95 @@
|
||||
@@ -0,0 +1,88 @@
|
||||
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+Date: Sat, 3 Mar 2018 12:02:21 +0100
|
||||
+Subject: [PATCH 2/2] ebtables: add support for matching IGMP type
|
||||
@ -171,8 +164,6 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ net/bridge/netfilter/ebt_ip.c | 19 +++++++++++++++++--
|
||||
+ 2 files changed, 20 insertions(+), 3 deletions(-)
|
||||
+
|
||||
+diff --git a/include/uapi/linux/netfilter_bridge/ebt_ip.h b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+index 4ed7fbb0a482..46d6261370b0 100644
|
||||
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+@@ -25,8 +25,9 @@
|
||||
@ -194,8 +185,6 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ };
|
||||
+ union {
|
||||
+ __u16 dport[2];
|
||||
+diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
|
||||
+index 8cb8f8395768..ffaa8ce2e724 100644
|
||||
+--- a/net/bridge/netfilter/ebt_ip.c
|
||||
++++ b/net/bridge/netfilter/ebt_ip.c
|
||||
+@@ -28,6 +28,9 @@ union pkthdr {
|
||||
@ -208,7 +197,7 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ };
|
||||
+
|
||||
+ static bool
|
||||
+@@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+@@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
||||
+ if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
|
||||
+ return false;
|
||||
+ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
|
||||
@ -223,7 +212,7 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ pptr = skb_header_pointer(skb, ih->ihl*4,
|
||||
+ sizeof(_pkthdr), &_pkthdr);
|
||||
+ if (pptr == NULL)
|
||||
+@@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+@@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
||||
+ pptr->icmphdr.code < info->icmp_code[0] ||
|
||||
+ pptr->icmphdr.code > info->icmp_code[1]))
|
||||
+ return false;
|
||||
@ -235,7 +224,7 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+@@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
|
||||
+@@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct
|
||||
+ info->icmp_code[0] > info->icmp_code[1])
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
@ -249,254 +238,3 @@ index 0000000000000000000000000000000000000000..35b93adc802c2850cd6ee218c3d7d6f6
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+--
|
||||
+2.16.2
|
||||
+
|
||||
diff --git a/target/linux/generic/backport-4.9/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch b/target/linux/generic/backport-4.9/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..db82fd6b69b3c4e279f39db7ca4b415498457e75
|
||||
--- /dev/null
|
||||
+++ b/target/linux/generic/backport-4.9/096-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
||||
@@ -0,0 +1,141 @@
|
||||
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+Date: Sat, 3 Mar 2018 11:55:21 +0100
|
||||
+Subject: [PATCH 1/2] ebtables: add support for matching ICMP type and code
|
||||
+
|
||||
+We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP
|
||||
+matches in the same way.
|
||||
+
|
||||
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+---
|
||||
+ include/uapi/linux/netfilter_bridge/ebt_ip.h | 13 +++++++--
|
||||
+ net/bridge/netfilter/ebt_ip.c | 43 +++++++++++++++++++++-------
|
||||
+ 2 files changed, 43 insertions(+), 13 deletions(-)
|
||||
+
|
||||
+diff --git a/include/uapi/linux/netfilter_bridge/ebt_ip.h b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+index c4bbc41b0ea4..63a2860ae1e3 100644
|
||||
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+@@ -23,8 +23,9 @@
|
||||
+ #define EBT_IP_PROTO 0x08
|
||||
+ #define EBT_IP_SPORT 0x10
|
||||
+ #define EBT_IP_DPORT 0x20
|
||||
++#define EBT_IP_ICMP 0x40
|
||||
+ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
|
||||
+- EBT_IP_SPORT | EBT_IP_DPORT )
|
||||
++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP)
|
||||
+ #define EBT_IP_MATCH "ip"
|
||||
+
|
||||
+ /* the same values are used for the invflags */
|
||||
+@@ -37,8 +38,14 @@ struct ebt_ip_info {
|
||||
+ __u8 protocol;
|
||||
+ __u8 bitmask;
|
||||
+ __u8 invflags;
|
||||
+- __u16 sport[2];
|
||||
+- __u16 dport[2];
|
||||
++ union {
|
||||
++ __u16 sport[2];
|
||||
++ __u8 icmp_type[2];
|
||||
++ };
|
||||
++ union {
|
||||
++ __u16 dport[2];
|
||||
++ __u8 icmp_code[2];
|
||||
++ };
|
||||
+ };
|
||||
+
|
||||
+ #endif
|
||||
+diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
|
||||
+index d06968bdf5ec..e4fc77072b27 100644
|
||||
+--- a/net/bridge/netfilter/ebt_ip.c
|
||||
++++ b/net/bridge/netfilter/ebt_ip.c
|
||||
+@@ -19,9 +19,15 @@
|
||||
+ #include <linux/netfilter_bridge/ebtables.h>
|
||||
+ #include <linux/netfilter_bridge/ebt_ip.h>
|
||||
+
|
||||
+-struct tcpudphdr {
|
||||
+- __be16 src;
|
||||
+- __be16 dst;
|
||||
++union pkthdr {
|
||||
++ struct {
|
||||
++ __be16 src;
|
||||
++ __be16 dst;
|
||||
++ } tcpudphdr;
|
||||
++ struct {
|
||||
++ u8 type;
|
||||
++ u8 code;
|
||||
++ } icmphdr;
|
||||
+ };
|
||||
+
|
||||
+ static bool
|
||||
+@@ -30,8 +36,8 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+ const struct ebt_ip_info *info = par->matchinfo;
|
||||
+ const struct iphdr *ih;
|
||||
+ struct iphdr _iph;
|
||||
+- const struct tcpudphdr *pptr;
|
||||
+- struct tcpudphdr _ports;
|
||||
++ const union pkthdr *pptr;
|
||||
++ union pkthdr _pkthdr;
|
||||
+
|
||||
+ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
|
||||
+ if (ih == NULL)
|
||||
+@@ -50,29 +56,38 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+ if (info->bitmask & EBT_IP_PROTO) {
|
||||
+ if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
|
||||
+ return false;
|
||||
+- if (!(info->bitmask & EBT_IP_DPORT) &&
|
||||
+- !(info->bitmask & EBT_IP_SPORT))
|
||||
++ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
|
||||
++ EBT_IP_ICMP)))
|
||||
+ return true;
|
||||
+ if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
+ return false;
|
||||
++
|
||||
++ /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
||||
+ pptr = skb_header_pointer(skb, ih->ihl*4,
|
||||
+- sizeof(_ports), &_ports);
|
||||
++ sizeof(_pkthdr), &_pkthdr);
|
||||
+ if (pptr == NULL)
|
||||
+ return false;
|
||||
+ if (info->bitmask & EBT_IP_DPORT) {
|
||||
+- u32 dst = ntohs(pptr->dst);
|
||||
++ u32 dst = ntohs(pptr->tcpudphdr.dst);
|
||||
+ if (NF_INVF(info, EBT_IP_DPORT,
|
||||
+ dst < info->dport[0] ||
|
||||
+ dst > info->dport[1]))
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (info->bitmask & EBT_IP_SPORT) {
|
||||
+- u32 src = ntohs(pptr->src);
|
||||
++ u32 src = ntohs(pptr->tcpudphdr.src);
|
||||
+ if (NF_INVF(info, EBT_IP_SPORT,
|
||||
+ src < info->sport[0] ||
|
||||
+ src > info->sport[1]))
|
||||
+ return false;
|
||||
+ }
|
||||
++ if ((info->bitmask & EBT_IP_ICMP) &&
|
||||
++ NF_INVF(info, EBT_IP_ICMP,
|
||||
++ pptr->icmphdr.type < info->icmp_type[0] ||
|
||||
++ pptr->icmphdr.type > info->icmp_type[1] ||
|
||||
++ pptr->icmphdr.code < info->icmp_code[0] ||
|
||||
++ pptr->icmphdr.code > info->icmp_code[1]))
|
||||
++ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+@@ -101,6 +116,14 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
|
||||
+ return -EINVAL;
|
||||
+ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
|
||||
+ return -EINVAL;
|
||||
++ if (info->bitmask & EBT_IP_ICMP) {
|
||||
++ if ((info->invflags & EBT_IP_PROTO) ||
|
||||
++ info->protocol != IPPROTO_ICMP)
|
||||
++ return -EINVAL;
|
||||
++ if (info->icmp_type[0] > info->icmp_type[1] ||
|
||||
++ info->icmp_code[0] > info->icmp_code[1])
|
||||
++ return -EINVAL;
|
||||
++ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+--
|
||||
+2.16.2
|
||||
+
|
||||
diff --git a/target/linux/generic/backport-4.9/096-0002-ebtables-add-support-for-matching-IGMP-type.patch b/target/linux/generic/backport-4.9/096-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5750b612fc0f322e0a257f3229b5b698328b428b
|
||||
--- /dev/null
|
||||
+++ b/target/linux/generic/backport-4.9/096-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
||||
@@ -0,0 +1,95 @@
|
||||
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+Date: Sat, 3 Mar 2018 12:02:21 +0100
|
||||
+Subject: [PATCH 2/2] ebtables: add support for matching IGMP type
|
||||
+
|
||||
+We already have ICMPv6 type/code matches (which can be used to distinguish
|
||||
+different types of MLD packets). Add support for IPv4 IGMP matches in the
|
||||
+same way.
|
||||
+
|
||||
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
+---
|
||||
+ include/uapi/linux/netfilter_bridge/ebt_ip.h | 4 +++-
|
||||
+ net/bridge/netfilter/ebt_ip.c | 19 +++++++++++++++++--
|
||||
+ 2 files changed, 20 insertions(+), 3 deletions(-)
|
||||
+
|
||||
+diff --git a/include/uapi/linux/netfilter_bridge/ebt_ip.h b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+index 63a2860ae1e3..ae5d4d108418 100644
|
||||
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
||||
+@@ -24,8 +24,9 @@
|
||||
+ #define EBT_IP_SPORT 0x10
|
||||
+ #define EBT_IP_DPORT 0x20
|
||||
+ #define EBT_IP_ICMP 0x40
|
||||
++#define EBT_IP_IGMP 0x80
|
||||
+ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
|
||||
+- EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP)
|
||||
++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
|
||||
+ #define EBT_IP_MATCH "ip"
|
||||
+
|
||||
+ /* the same values are used for the invflags */
|
||||
+@@ -41,6 +42,7 @@ struct ebt_ip_info {
|
||||
+ union {
|
||||
+ __u16 sport[2];
|
||||
+ __u8 icmp_type[2];
|
||||
++ __u8 igmp_type[2];
|
||||
+ };
|
||||
+ union {
|
||||
+ __u16 dport[2];
|
||||
+diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
|
||||
+index e4fc77072b27..57fbb13cb8e0 100644
|
||||
+--- a/net/bridge/netfilter/ebt_ip.c
|
||||
++++ b/net/bridge/netfilter/ebt_ip.c
|
||||
+@@ -28,6 +28,9 @@ union pkthdr {
|
||||
+ u8 type;
|
||||
+ u8 code;
|
||||
+ } icmphdr;
|
||||
++ struct {
|
||||
++ u8 type;
|
||||
++ } igmphdr;
|
||||
+ };
|
||||
+
|
||||
+ static bool
|
||||
+@@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+ if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
|
||||
+ return false;
|
||||
+ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
|
||||
+- EBT_IP_ICMP)))
|
||||
++ EBT_IP_ICMP | EBT_IP_IGMP)))
|
||||
+ return true;
|
||||
+ if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
+ return false;
|
||||
+
|
||||
+- /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
||||
++ /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
||||
+ pptr = skb_header_pointer(skb, ih->ihl*4,
|
||||
+ sizeof(_pkthdr), &_pkthdr);
|
||||
+ if (pptr == NULL)
|
||||
+@@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
+ pptr->icmphdr.code < info->icmp_code[0] ||
|
||||
+ pptr->icmphdr.code > info->icmp_code[1]))
|
||||
+ return false;
|
||||
++ if ((info->bitmask & EBT_IP_IGMP) &&
|
||||
++ NF_INVF(info, EBT_IP_IGMP,
|
||||
++ pptr->igmphdr.type < info->igmp_type[0] ||
|
||||
++ pptr->igmphdr.type > info->igmp_type[1]))
|
||||
++ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+@@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
|
||||
+ info->icmp_code[0] > info->icmp_code[1])
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
++ if (info->bitmask & EBT_IP_IGMP) {
|
||||
++ if ((info->invflags & EBT_IP_PROTO) ||
|
||||
++ info->protocol != IPPROTO_IGMP)
|
||||
++ return -EINVAL;
|
||||
++ if (info->igmp_type[0] > info->igmp_type[1])
|
||||
++ return -EINVAL;
|
||||
++ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+--
|
||||
+2.16.2
|
||||
+
|
||||
|
@ -0,0 +1,27 @@
|
||||
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Date: Sat, 21 Sep 2019 13:21:36 +0200
|
||||
Subject: build: set TARGET_ROOTFS_PARTSIZE to make combined image fit in 128MB
|
||||
|
||||
Change TARGET_ROOTFS_PARTSIZE from 128 to 104 MiB, so the whole image
|
||||
(bootloader + boot + root) will fit on a 128MB CF card by default.
|
||||
|
||||
With these settings, the generated images (tested on x86-generic and
|
||||
x86-64) have 126,353,408 bytes; the smallest CF card marketed as "128MB"
|
||||
that I found a datasheet for (a Transcend TS128MCF80) has 126,959,616
|
||||
bytes.
|
||||
|
||||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
|
||||
diff --git a/config/Config-images.in b/config/Config-images.in
|
||||
index 8548c7cd24742daad4fb1c64e58bad82590795c2..dc7a9cbd54ffbe3c78a7fdbd124f389c102ef6c1 100644
|
||||
--- a/config/Config-images.in
|
||||
+++ b/config/Config-images.in
|
||||
@@ -274,7 +274,7 @@ menu "Target Images"
|
||||
config TARGET_ROOTFS_PARTSIZE
|
||||
int "Root filesystem partition size (in MB)"
|
||||
depends on GRUB_IMAGES || USES_ROOTFS_PART || TARGET_ROOTFS_EXT4FS || TARGET_omap || TARGET_rb532 || TARGET_sunxi || TARGET_uml
|
||||
- default 256
|
||||
+ default 104
|
||||
help
|
||||
Select the root filesystem partition size.
|
||||
|
@ -1,87 +0,0 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Sat, 21 Sep 2019 18:59:28 +0200
|
||||
Subject: ipq-wifi: add AVM FRITZ!Repeater 1200 bdf
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
|
||||
diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile
|
||||
index 922064b7f78b80670cdb1ec7e9f86ede224cb7fb..eb7c2df1aa36ded7774a772c8a7e02b2acb81b40 100644
|
||||
--- a/package/firmware/ipq-wifi/Makefile
|
||||
+++ b/package/firmware/ipq-wifi/Makefile
|
||||
@@ -27,6 +27,7 @@ ALLWIFIBOARDS:= \
|
||||
alfa-network_ap120c-ac \
|
||||
asus_map-ac2200 \
|
||||
avm_fritzbox-7530 \
|
||||
+ avm_fritzrepeater-1200 \
|
||||
avm_fritzrepeater-3000 \
|
||||
engenius_eap1300 \
|
||||
engenius_ens620ext \
|
||||
@@ -98,6 +99,7 @@ endef
|
||||
$(eval $(call generate-ipq-wifi-package,alfa-network_ap120c-ac,ALFA Network AP120C-AC))
|
||||
$(eval $(call generate-ipq-wifi-package,asus_map-ac2200,ASUS MAP-AC2200))
|
||||
$(eval $(call generate-ipq-wifi-package,avm_fritzbox-7530,AVM FRITZ!Box 7530))
|
||||
+$(eval $(call generate-ipq-wifi-package,avm_fritzrepeater-1200,AVM FRITZRepeater 1200))
|
||||
$(eval $(call generate-ipq-wifi-package,avm_fritzrepeater-3000,AVM FRITZ!Repeater 3000))
|
||||
$(eval $(call generate-ipq-wifi-package,engenius_eap1300,EnGenius EAP1300))
|
||||
$(eval $(call generate-ipq-wifi-package,engenius_ens620ext,EnGenius ENS620EXT))
|
||||
diff --git a/package/firmware/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 b/package/firmware/ipq-wifi/board-avm_fritzrepeater-1200.qca4019
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d78a49d4dbf3fc22c40a83d052fc7c55542ff8e3
|
||||
GIT binary patch
|
||||
literal 24332
|
||||
zcmeHPTTl~O8a_d8Dk`0XTL?`^xFjwK5Lk^61wv#JXn|o7A-XOgC<!pcfLx4IQVuF&
|
||||
zL`Ib1VgxBv<kIUZ<?4*e?CQAAmZsc&nKxhdZ62h`+S>AEojsjSAdzHD5LPbzhtuaj
|
||||
zf1m&S|M|L;bocql=Nak3^a4dfe6~=Qo1QNRH8nK=N_`x$1wal<*^#>KrIlr|Wi@Ky
|
||||
zfl9Sjs4m|gZ*G;<mg>rhrZ_&fp;V_X{i1$*df_f%X1=mOm0zK)D6Oy12@}Ne@iaIN
|
||||
z2ad^!oA9U6z?$Rqq(Wl+&4a)LlmM{K$De2dxaB6o+84eYi9nD@3<W@9V&cEwya7_C
|
||||
zH+cK6^QqRdhUv)b!!{0}J$=7dCm9L+0_FXE&fA-2cKO5E5HG6`Ia>AEI@MvulP*S_
|
||||
z?YC}bNDd%hGX{&oq}y5?$9?ExTw)|*X10X^+eBeo3as3c_3Jlobj!g(XRZU=r!Z+d
|
||||
z#);F$BK8@)8kuNs*Qk}M)K?SzZO!GXY~{8`qy4Abb?VQRTON%;txlb<{OwyPx9<vK
|
||||
z!0XY8lkHXNU8=NKWBsR^D^-|M`sgOnO{G*ypu^erMrcbR9bz_v*TWOXnu}D)%2?>y
|
||||
z+I&DIhuyCCw?o%#3IEYV|Al6)Dqj+Bafq?c?*px7C?DuzzngNf$HQ@JC7|SZX3NX^
|
||||
zWU%VXEKU5Lz|`?8b!}VAqjs~hAC4aG%{<N51()=W?d{!mnp4Lpy?<GKEW3)gD=_W;
|
||||
zQ0=LdN<ncb_Vi}+H@T-pbzuj-9c%2}bynEOKKSH{_E=^GSIJ0zJY3tFRU5rKP=4dO
|
||||
zx<}Feo5s+}`x6ZVamT~8jFRPr5|ynL0WY7m>o;sd7y&^cp<&_HPyE@M_>7$utCw93
|
||||
zFNgr3(L6jnXvB8S8ZR#|Z;SYhbT*YJo}I|!Gb1B;@GpuR5y9g|aJhw^zQA&YVmBJq
|
||||
zSX2Z$I~y7b3b0HGSij!en+zopMDe)XaM)n_{O9evcL7i%ZG<t*&&R{l^S|b<G~mde
|
||||
z9A)vg+HrV20*BWg?-(Zv5s7b+=tx4ioUp*?NG_LyvRT1Uo4*Zu@_0OAAULXJypORt
|
||||
zLIpt)Bppph63_%hd*tZx)-xSlJ#!Txwa5dv6go;5(Vx>17RnN_Fn`n^2}Wh8OeA|Q
|
||||
zL$c5;Q5KelrXdPcjEY6#=VBxoO%^3%@n}3EL1&UM4mnn5a*|4CvZB;E$Hx^&7%1a4
|
||||
z0|`Y#MWI**n(;aV$wsq9*;pc)_&O0uK~qF27<mwEx8_hJ^ozbF&Ry*p<G5{!`be4m
|
||||
zW^t@JdcVxqwi2#MsX4fE^eL1ml$;<yof=Mnu`{nql<W|o8WaK)0u%xi0u%xi0;?E-
|
||||
zAaM{9PXA2&8InuiD&C5u(tWK0^2;s^-F|Glwch%>SI>>H)+!4YV-+7lYU(Qm0asTD
|
||||
zT<y2aaKZLf8YW)=0P7~h;N*+<YxtxZKBGq2Axs{RLq7b5+S0Lcp_uavHY>!#dFE2G
|
||||
zML^+%L;QlE0&60_rDR*`r|U%@1f(SaV4x$kKq#G-`l6-g`yxOJq@HO20e^oiXaOJr
|
||||
z@DRwOg2Wpx<nvgI6xwB8f|oKM!9QRjYIE`TM1W6=7iR?SfA#Wb@Y7E}n`=TR3MDHS
|
||||
zfnRR<F+DuW;R*x*G!IYTZ=hU-Vx93lC?8|Pir|Oq;N*|a>X_)L$WK|wl{<2+j$EC?
|
||||
z@(POfm6TT+IxqHI9vmJSzcqR9;a`6E@rC<4Y}WDIyK-GNy@7ch6r;CUS3=EepqQ-9
|
||||
zx(aGu|HQ;?))i3qL3HY|^3h#3r@_if)Ri^koWlJFJG!r2$L~)4&6&QkP??<#^Bogm
|
||||
zqihiyV*>d*If9{>2*czc>0J^cMWrGsmb75^*RxUG(E`PR2ujZsXCgWDE#fW64!Ww3
|
||||
zc+DNd`aNf@m&+}VyWIN(m$~;?H;o2~_f4H<CU}5_dmrFKA_Olhc?9<!08dZSV!!46
|
||||
zZZ7v8au8CjWxm{d80CBWNB}G}_nyd+h=JM#a?F9B<<#4Cp3|7^=K}ZM&f9TZcewX}
|
||||
z!C*KnY&IJZ#m~>row9cAVsh`(n1jrh4*$==4i=}4v9U3y`{wR|$J$2b?swI)DwlMr
|
||||
zNxO1-EJ2i9Nt^0JAwVHOA+TH#C@E1DlH7Yb-G2i)3pcs<C8Ym`4IXbu|APmuW3pKA
|
||||
znrgv?;@(^C%pO?p(0)y!xc4*YxI%%qLi&I2>&kN!Th=|Po6{vHxaeErjcm)iC-je`
|
||||
z-bZ0Y!~^e#FKliv?9>l^cub!$RpXd3!N8twGgaZ)MzJAm>aMX{f4DeP5;b)jA2#SU
|
||||
z#S%90|6-SWV)$UX%hZgkjA;hp^d*xX-)oc^;_yl1phi=iBZ-~*v+;tyrdTH75Dv!P
|
||||
zm>4kKXF7==GUge!PY;;R;MK<6dLjO;p<AO<$R%Rv(50`oI$Y_E5dhfj9IiFwYqm^Z
|
||||
zGj-ujh9Zp=pEC4o>J>Zr!R826n!RL7#y%n?qp2OQ(#wk@r-w}Eah+keW(WSAp;yzO
|
||||
zQ1C;i?inwcQwk?iy3)so5qeBt;Rp0P6fEf4hO6~5MJWC!<AA0{kuHfdeTNSjnl*bQ
|
||||
zEW%-+PY?~JyG<>4i9T5oGTm!x#mn_lMF>o!SAV29TOu&s#rq68O|Bx6j39t1oi{b%
|
||||
zMS8J<IsLWiD6WDUV!DrCg;=IZ&{ub+E*l#)8Hx}x0-S?8vIH;nsgztffD}p;N=^`1
|
||||
z38#jWsZr)ti@@D8$9}&vLC6mAzSdT~Z>u;WY@=^|cV?^LFssZj^ZVh7bKCX2LqWxV
|
||||
z?P^k`3Znypz3yB(R+S|a$At!;A1v%hILgs%%6WRT`a)VuR87eKXMO6ttufI-06ZEv
|
||||
zTCK<s3B$tfjU4VyJ0Z}~cRwCgccr%Qs)P4G8K^6fZHZzB`#rc;eMq4|x&918f6mE-
|
||||
z`hYzfcHX~Pb|LvVrz&9YLu2*6Jb7#+;yF3gpxde7@&j1yy}7578iI@c6nDn{a7l6^
|
||||
zye44(WKaD8<&Ib$!+X@&P^ZMil7P_30bNJNvDlix{AYj6Ivd*@a?pRzt?r|mT)BWt
|
||||
z_a5%8{UWbGm=wyr(W`FTab)u$M)viQ+P;)lo{qWy#(8a-JcY+*GyA?Suh^LtD-K|t
|
||||
z>)7*Ul7_pNo_2e*?sCpKeq(UOsy%V2iBkxy00chvmpFWE#Q`3JZCZt-NhKBYqoN|=
|
||||
zAN&;#4lg2t8&T-BWPXWbE-&6nz4u+Pb^Ez7tknCp3l_rx{FI48V15X=O8i*pe)G$A
|
||||
z#duNNd&rAlMBe^V;@LaOWvQRYBal;1a^Mj&kDlPzuWJ>w$RSsL^EPfeS;7x*-exXW
|
||||
z{XG-RTzY~}@6)ml7NYjzn7Q`^-`-2`PcsLf<l(<u>hoXC`4QZBPsoig>KXZAF}U%I
|
||||
zjjc1zz199HdG|zYihDo1G&c{8;@-~#G|FXZBjC!Ku`|BCt$k_Fa{k#--227;*8KJH
|
||||
F{|7QKi|GIW
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
92
patches/openwrt/0007-ipq-wifi-add-BDF-for-Aruba-AP-303.patch
Normal file
92
patches/openwrt/0007-ipq-wifi-add-BDF-for-Aruba-AP-303.patch
Normal file
@ -0,0 +1,92 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Sun, 15 Dec 2019 23:02:54 +0100
|
||||
Subject: ipq-wifi: add BDF for Aruba AP-303
|
||||
|
||||
The BDF originates from the vendor-firmware.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
(cherry picked from commit 4113d8a2554adf5ecee55cc07956eafad378eaff)
|
||||
|
||||
diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile
|
||||
index eb7c2df1aa36ded7774a772c8a7e02b2acb81b40..cc0505b97c6a04bafd88972cf6ce7890a637c33b 100644
|
||||
--- a/package/firmware/ipq-wifi/Makefile
|
||||
+++ b/package/firmware/ipq-wifi/Makefile
|
||||
@@ -25,6 +25,7 @@ endef
|
||||
|
||||
ALLWIFIBOARDS:= \
|
||||
alfa-network_ap120c-ac \
|
||||
+ aruba_ap-303 \
|
||||
asus_map-ac2200 \
|
||||
avm_fritzbox-7530 \
|
||||
avm_fritzrepeater-1200 \
|
||||
@@ -97,6 +98,7 @@ endef
|
||||
# Add $(eval $(call generate-ipq-wifi-package,<devicename>,<display name>))
|
||||
|
||||
$(eval $(call generate-ipq-wifi-package,alfa-network_ap120c-ac,ALFA Network AP120C-AC))
|
||||
+$(eval $(call generate-ipq-wifi-package,aruba_ap-303,Aruba AP-303))
|
||||
$(eval $(call generate-ipq-wifi-package,asus_map-ac2200,ASUS MAP-AC2200))
|
||||
$(eval $(call generate-ipq-wifi-package,avm_fritzbox-7530,AVM FRITZ!Box 7530))
|
||||
$(eval $(call generate-ipq-wifi-package,avm_fritzrepeater-1200,AVM FRITZRepeater 1200))
|
||||
diff --git a/package/firmware/ipq-wifi/board-aruba_ap-303.qca4019 b/package/firmware/ipq-wifi/board-aruba_ap-303.qca4019
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4848115cfbe3a4a0ed6b17cac929731ecbd7968c
|
||||
GIT binary patch
|
||||
literal 24316
|
||||
zcmeHPdr(tX8b1l)p-UHTNDu)pAp}Se0tBi-!W$`%6c7~&un1I<M58<m4?`F1_@EFG
|
||||
zfm#qEXc?48Q$)t%1F%?IJEP40v48CBA8luLw|}fVw5!gvGrOyM?hO}02ql3q<#9ha
|
||||
z=X~e8-#O<yzk5jTz30c>6BFeZwJ$y}AjvN}B`Pfz$mMbX<(NN~1F#FGd_`$kUSYm(
|
||||
zzFg|}UZJ$ePkJaU0I%hr$SXO7RRsaQWqBpiyyGXsqDmC`d45r;enA02aybRIXTiQ$
|
||||
z{(Fv6D8Qnc9-NN#>(d1&AQynm*7jHxFaWR*!ZjM6>t{S38|w;yprD{vFJ4eY3@h-<
|
||||
z-!4WF$pUt;M0u#+u2DM@cmo9<o32e4-TK}{-42{)MS-YT8nB=KA&y`%68dZzvGj;%
|
||||
zJAvBfnQ>V_`vZ+ET^9yjw-&*$wzjskw6xF>07kKy8YxWZr<)vMT{juo&5WBJl$pvJ
|
||||
zSBe@2uw^qXb0;%4&|Y78I5R0hICi_exl*3FFCluYul;;oiF8lGj<J5Il}ghR-u?y3
|
||||
z<F9$%VC>WOy2|{_1bA?;y|Gf7nVJwj){D78n-DgruPe_KCxqe+o_PC!v0LpI;0W&~
|
||||
zgp7R#8_4hmJ+PC)%p@TfcGpx{l$j<Bm~P-bH@-z`l~5LOnR}RQFc%NQwe^6K;hC*1
|
||||
zYj=HKdB|b!bl0Sb=920-IsYItdbF>&E$%$G#3{F}KdUX|Jgd|puct0g5t8q<cU!`P
|
||||
z#^Y7HrM_9r@UMC+KTbK%FWvUuz5epHckBJiT?>XU6jp>E=A|Pc_n}{`jGyHYexpa)
|
||||
z8eg})+@<jDr)8b~)ow)&xoZn0GFk!wOY2R)d&>@SU~bv!vW@t_*D0~j*k2Ra54<44
|
||||
zGAfly!Ey@=__b^`E!H<{G6I~Qyq_vSIUEo8>&bR^_h7rT+37SJ;+lkrg)CPdfsBl_
|
||||
zWH#Fk4)pWSFMfRe8oL4#@;p7Xw*UV4*B^9knBz8EYbuTQKj>!%PuOhxmoH!ZTkE^h
|
||||
zQ5Oxs>k&9eQFX%rmay^oy5hs-a5%Vu>&0fVaLp_>UjzM_W;28hf+9#18ifR+fk=_!
|
||||
zRP~t;8=70^D?l_Y4@^?%D4kD#N=KYgXTG!89<@iD&}cN8AN@2MNkkL*iQ-5!5{X9z
|
||||
zsDLkcDnNFjyZF1r0cZdsL}!9fUpK7I#3T~UL`ACe&W|yWIG_$w4u}it!gmqJpfOW1
|
||||
zND`XFPZ9^AK~q6UC>qKS6>Cp|ZjKM7g?`0zZ0#0(s2<Qwp34-SuNH%<p}&`<+SbE0
|
||||
zDLDsY&OV6}iP8cHkV|6$VCI-NBuaA-AS)ySBmyJ?BmyJ?Bmx^4fh~e9h#UPK!8=F_
|
||||
zeWze25<#~i1f=CRT_1X+n-jPGrj_%@*hGlg#@N88kes@S2)vvpCU&q=?$dOIMY}iF
|
||||
zZ_$ocmxDOFP&NDv09aP2x`v<WmwZ28Utjp7n}x1U4F>1q!}Wsktx^q!Hyz)q)K=GO
|
||||
zoF7djK!C#!ycz%kffr-~xxvJNR46t~SlLJq1Z=jeD_c)mpnblT&CYJ-0FjUaUY!7-
|
||||
z#TubR1_QvgL4XK|Xt`DhpfahOvtem(k8e884~Vp^8wB1A+A^rrLvRNI?k-blHXlQ|
|
||||
z28Ed52$bd6#2N6zwQKmBg-UNPPtI?dv^#g&y*lmgoH%t~Mt1I@LRDi+Ye!f2&4Iz;
|
||||
zk<l+6fAh@r13LS7rd_$N8E=5^gNo_3#7-!_2P%%PC3Zpa{ZFx=me>I`9mEA&tbcUZ
|
||||
z%raPCff}=CoSdFh&~W)`kLJ$!*9+<E3zgZ~FkUkdSJaj7DrSJ#*RhBg74ya7SP=X=
|
||||
z7!jc&zDOKww)^YZQBBbt1&#<xj}ycp$@Cq99Y{Dm^9uGezYpSjjwsj4Esm+2`@lsx
|
||||
z_pP233MAZDG~x_!W*4x)IQLBJ8XOwPV6wwG_mF@_V5M8~BrC?bzpXnCrvEDEUf+49
|
||||
zzBuO|MP{6#qUF9@TUl7rX4vll48Jjsia$KVkvGV>*BuD^e+C^f1J|FyU;r!;;^^oI
|
||||
zutbQ7^|zo9O_y4-fz<*{BN<(cKQSIMS&pfWHI9R`Q7+)GZ~m87zSOtRt#@=xPIh$J
|
||||
z+RmlJ%=Iy)wjsB2$w?ctL{=e6#)NGiAEXw5z3>BC;Y0;D{!GEsIar?io&qX3RM0m-
|
||||
z1^qu!!LtzyFeRb^yHOg52(ttT)56l)JRy+1kO+_nY&ZmFIrD}%_y76l-@pIvyT3qG
|
||||
z!a_rK!Uv_0b8llsqdtHB4`|cp+)q8%a_-ajrKM^)`>$U7G-ZAsz9G)NzdxUkC2X$&
|
||||
zduq<ccO90m`EJJ_!n5Hnfmt*|3ykF4Yws{0%-(2jK-HM%C%SBVt&T&cMQg=#Z0+ju
|
||||
z?J<3slzUHc2KJzP^x51yjM<u@zZYHGw?pGC>M~`z#Q)p7<L&AyWsXERen)*-SuBYY
|
||||
zdX5iix>ZV<MCgkBpV)(k-dq41G^-WL{SyA<pyrb5ge*-W)C{Y;WHL#z(0BZEb(2yq
|
||||
zi59Z32BQ<+-T-%#DbtndllL?oDuryXWT)ny>awgPK2|7z4Vsn5hz4U5-aIh*Kyy`9
|
||||
z2K#+`d{Fa=s!Ar2h&1D>cG=1J-CQSpgrl-7ZAjx2Fr>-5ns)VRm0Y%a{Fdgrx(+r@
|
||||
z*4$UM$;#s6xh~@)>W}b{+^~=yKH~BKoNA}$qFSNKg(0ccXH~^YiRPBNQznm(68cZx
|
||||
z*IZXs$_@yfwGDV)*c_VFr&I;XWO(qZszR13@rQx5DHW0=A#d`I=8CFBmJ-jw8hkOq
|
||||
zgDBk|Z&R15a+I-?Bk*9UGFz4i!@LHuj1;2qXotF778Ab}Z}1q-!4z4Am-=K##+*PB
|
||||
zB@(3t5LgdOV}YrW<_(KL>(KEV5iNeTE@js=e`t@r=v}q-_{qz0XL!ZV`L=NnyANLo
|
||||
zQ+gcPBDpqn@<w#Cf31sRXs|$?cxn3|T~1u=N^b}}#gf@2f7N@eDYC{>zBNZRxW7|)
|
||||
z$*qbmtL@F{5S&95^!$;V#g`*L;FZw#KkAb<N7Q&6bIPge-+$Gw*17EWd3}TBpF}or
|
||||
ztF{!X+LO-)o@5?)YxmvW{H9&itfS1VFYhY*Qrf*wJIXb;6xT!R*k$yCb!{o<g3FvF
|
||||
zw(+<74}K*4z)jA~>Cs3#V=uB4NN#U`sakZFU2HEI?ks7Dsq&ROrak#AvEH|GYk~cN
|
||||
z-oYbXaZQ|4jDps_<5wf<yeb%ZH`=7N;R>H44oN*XPh1H-<59xMxzd~07FF+FO3!KO
|
||||
zkzNs<^C)%5zR+;s{a_h8iyk@DSK5($fm`l$c*8Cna^fTc>i~h}zJUY22WwUg;4xU6
|
||||
zE40Voz~Sl1fxqzW8!QiZceZ;vST%3pn9qkNDEBsI+pnKL20^*sWVSI3z)zY;1PmfD
|
||||
zk8=M~&&^oEhq?Xq!q{llMLGBQ>t)~ra4xR!eZAQ1X^ph;*FG+*f4xJlJ!C>*eEV+r
|
||||
z#z~GXOppZ=2|4(iyLmNON}QN2ao#+YHqDy{lvv2w_X*(?ul{+G5$Yp=apGx^6Q9v~
|
||||
z^YKb>;`PTfcYPtQJz@VX`S#e@B<CLA>so3?a_*Ok9NBKwB4Es(@j^U%UHht?;4%Xv
|
||||
NIrrxNmNc!u{{!hMI2Hf^
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
@ -1,374 +0,0 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Tue, 10 Sep 2019 21:07:23 +0200
|
||||
Subject: ipq40xx: add support for AVM FRITZ!Repeater 1200
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
|
||||
diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
index 6a7b09cc603a245e98c37305c1f25c2cc11694ae..01825b8bac46eec6325de00396d96307c946f975 100755
|
||||
--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
+++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
@@ -39,10 +39,7 @@ ipq40xx_setup_interfaces()
|
||||
ucidef_add_switch "switch0" \
|
||||
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan"
|
||||
;;
|
||||
- avm,fritzrepeater-3000|\
|
||||
- compex,wpj428)
|
||||
- ucidef_set_interface_lan "eth0 eth1"
|
||||
- ;;
|
||||
+ avm,fritzrepeater-1200|\
|
||||
engenius,eap1300|\
|
||||
meraki,mr33|\
|
||||
netgear,ex6100v2|\
|
||||
@@ -50,6 +47,10 @@ ipq40xx_setup_interfaces()
|
||||
zyxel,wre6606)
|
||||
ucidef_set_interface_lan "eth0"
|
||||
;;
|
||||
+ avm,fritzrepeater-3000|\
|
||||
+ compex,wpj428)
|
||||
+ ucidef_set_interface_lan "eth0 eth1"
|
||||
+ ;;
|
||||
glinet,gl-b1300)
|
||||
ucidef_set_interfaces_lan_wan "eth0" "eth1"
|
||||
ucidef_add_switch "switch0" \
|
||||
diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
index 5f7e5f4923f19ecd78a981be55230cfcd3779146..b0035ce8a394b6e87d7d89b9f55a6ec7c66e448e 100644
|
||||
--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
+++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
@@ -148,6 +148,7 @@ case "$FIRMWARE" in
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config")
|
||||
;;
|
||||
avm,fritzbox-7530 |\
|
||||
+ avm,fritzrepeater-1200 |\
|
||||
avm,fritzrepeater-3000)
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
|
||||
@@ -209,6 +210,7 @@ case "$FIRMWARE" in
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config")
|
||||
;;
|
||||
avm,fritzbox-7530 |\
|
||||
+ avm,fritzrepeater-1200 |\
|
||||
avm,fritzrepeater-3000)
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
|
||||
diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
index 2abafabbd0589c07bcd2ceee766d3d7675ba9716..a7b7da1bf378f7cc19e960c497bc52efb3bae4fb 100644
|
||||
--- a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
+++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
@@ -49,6 +49,7 @@ platform_do_upgrade() {
|
||||
8dev,jalapeno |\
|
||||
alfa-network,ap120c-ac |\
|
||||
avm,fritzbox-7530 |\
|
||||
+ avm,fritzrepeater-1200 |\
|
||||
avm,fritzrepeater-3000 |\
|
||||
qxwlan,e2600ac-c2)
|
||||
nand_do_upgrade "$1"
|
||||
diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4d02f8a8384f386c92c70ef24b677ee95058a1bf
|
||||
--- /dev/null
|
||||
+++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts
|
||||
@@ -0,0 +1,262 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
+
|
||||
+#include "qcom-ipq4019.dtsi"
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
+#include <dt-bindings/input/input.h>
|
||||
+#include <dt-bindings/soc/qcom,tcsr.h>
|
||||
+
|
||||
+/ {
|
||||
+ model = "AVM FRITZ!Repeater 1200";
|
||||
+ compatible = "avm,fritzrepeater-1200";
|
||||
+
|
||||
+ aliases {
|
||||
+ led-boot = &power_green;
|
||||
+ led-failsafe = &power_red;
|
||||
+ led-running = &power_green;
|
||||
+ led-upgrade = &power_red;
|
||||
+ };
|
||||
+
|
||||
+ soc {
|
||||
+ mdio@90000 {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&mdio_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ };
|
||||
+
|
||||
+ tcsr@1949000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1949000 0x100>;
|
||||
+ qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
|
||||
+ };
|
||||
+
|
||||
+ ess_tcsr@1953000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1953000 0x1000>;
|
||||
+ qcom,ess-interface-select = <TCSR_ESS_PSGMII_RGMII5>;
|
||||
+ };
|
||||
+
|
||||
+ tcsr@1957000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1957000 0x100>;
|
||||
+ qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
|
||||
+ };
|
||||
+
|
||||
+ crypto@8e3a000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ watchdog@b017000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ess-switch@c000000 {
|
||||
+ switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */
|
||||
+ switch_lan_bmp = <0x0>; /* lan port bitmap */
|
||||
+ switch_wan_bmp = <0x10>; /* wan port bitmap */
|
||||
+ };
|
||||
+
|
||||
+ edma@c080000 {
|
||||
+ status = "okay";
|
||||
+ phy-mode = "rgmii-rxid";
|
||||
+ qcom,num_gmac = <1>;
|
||||
+ qcom,single-phy;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ key {
|
||||
+ compatible = "gpio-keys";
|
||||
+
|
||||
+ wps {
|
||||
+ label = "WPS button";
|
||||
+ gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ power_red: power_red {
|
||||
+ label = "fritzwlan-1200:red:power";
|
||||
+ gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ power_green: power_green {
|
||||
+ label = "fritzwlan-1200:green:power";
|
||||
+ gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ power_yellow {
|
||||
+ label = "fritzwlan-1200:yellow:power";
|
||||
+ gpios = <&tlmm 49 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&tlmm {
|
||||
+ serial_0_pins: serial_pinmux {
|
||||
+ mux {
|
||||
+ pins = "gpio16", "gpio17";
|
||||
+ function = "blsp_uart0";
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ nand_pins: nand_pins {
|
||||
+ pullups {
|
||||
+ pins = "gpio53", "gpio58", "gpio59";
|
||||
+ function = "qpic";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+
|
||||
+ pulldowns {
|
||||
+ pins = "gpio54", "gpio55", "gpio56",
|
||||
+ "gpio57", "gpio60", "gpio61",
|
||||
+ "gpio62", "gpio63", "gpio64",
|
||||
+ "gpio65", "gpio66", "gpio67",
|
||||
+ "gpio68", "gpio69";
|
||||
+ function = "qpic";
|
||||
+ bias-pull-down;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ mdio_pins: mdio_pinmux {
|
||||
+ mux_1 {
|
||||
+ pins = "gpio6";
|
||||
+ function = "mdio";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+ mux_2 {
|
||||
+ pins = "gpio7";
|
||||
+ function = "mdc";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ phy-reset {
|
||||
+ line-name = "PHY-reset";
|
||||
+ gpios = <19 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-hog;
|
||||
+ output-high;
|
||||
+ };
|
||||
+
|
||||
+ phy-reset-2 {
|
||||
+ line-name = "PHY-reset-2";
|
||||
+ gpios = <47 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-hog;
|
||||
+ output-high;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&nand {
|
||||
+ pinctrl-0 = <&nand_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ nand@0 {
|
||||
+ partitions {
|
||||
+ compatible = "fixed-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ partition@0 {
|
||||
+ label = "SBL1";
|
||||
+ reg = <0x000000 0x80000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@80000 {
|
||||
+ label = "MIBIB";
|
||||
+ reg = <0x080000 0x80000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@100000 {
|
||||
+ label = "QSEE";
|
||||
+ reg = <0x100000 0x80000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@180000 {
|
||||
+ label = "CDT";
|
||||
+ reg = <0x180000 0x40000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@1c0000 {
|
||||
+ label = "QSEE_B";
|
||||
+ reg = <0x1c0000 0x80000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@240000 {
|
||||
+ label = "urlader0";
|
||||
+ reg = <0x240000 0x40000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@280000 {
|
||||
+ label = "urlader1";
|
||||
+ reg = <0x280000 0x40000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@2c0000 {
|
||||
+ label = "nand-tffs";
|
||||
+ reg = <0x2c0000 0x840000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@b00000 {
|
||||
+ /* 'kernel1' in AVM firmware */
|
||||
+ label = "uboot0";
|
||||
+ reg = <0xb00000 0x400000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@f00000 {
|
||||
+ /* 'kernel2' in AVM firmware */
|
||||
+ label = "uboot1";
|
||||
+ reg = <0xf00000 0x400000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@1300000 {
|
||||
+ label = "ubi";
|
||||
+ reg = <0x1300000 0x6d00000>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&cryptobam {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&blsp_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&blsp1_uart1 {
|
||||
+ pinctrl-0 = <&serial_0_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&qpic_bam {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&wifi0 {
|
||||
+ status = "okay";
|
||||
+ qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200";
|
||||
+};
|
||||
+
|
||||
+&wifi1 {
|
||||
+ status = "okay";
|
||||
+ qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200";
|
||||
+};
|
||||
+
|
||||
+&gmac0 {
|
||||
+ qcom,phy_mdio_addr = <0>;
|
||||
+ qcom,poll_required = <1>;
|
||||
+ vlan_tag = <0 0x20>;
|
||||
+};
|
||||
diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile
|
||||
index 3a9b58de4f01f17ac9df368729035d630eb32b04..bdbbcbe851e60ee5a445c576a870a87a46c57fee 100644
|
||||
--- a/target/linux/ipq40xx/image/Makefile
|
||||
+++ b/target/linux/ipq40xx/image/Makefile
|
||||
@@ -138,6 +138,15 @@ define Device/avm_fritzbox-7530
|
||||
endef
|
||||
TARGET_DEVICES += avm_fritzbox-7530
|
||||
|
||||
+define Device/avm_fritzrepeater-1200
|
||||
+ $(call Device/FitImageLzma)
|
||||
+ DEVICE_DTS := qcom-ipq4019-fritzrepeater-1200
|
||||
+ DEVICE_TITLE := AVM Fritz!Repeater 1200
|
||||
+ DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand ipq-wifi-avm_fritzrepeater-1200
|
||||
+ IMAGES := sysupgrade.bin
|
||||
+endef
|
||||
+TARGET_DEVICES += avm_fritzrepeater-1200
|
||||
+
|
||||
define Device/avm_fritzrepeater-3000
|
||||
$(call Device/FitImageLzma)
|
||||
DEVICE_DTS := qcom-ipq4019-fritzrepeater-3000
|
||||
diff --git a/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
index bb539155e98b75df5dd88e39f6405af5a82e0320..f7efd415f1f1c000867793b3b133e44b3e50b0fd 100644
|
||||
--- a/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
+++ b/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
@@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
-@@ -697,7 +697,30 @@ dtb-$(CONFIG_ARCH_QCOM) += \
|
||||
+@@ -697,7 +697,31 @@ dtb-$(CONFIG_ARCH_QCOM) += \
|
||||
qcom-apq8074-dragonboard.dtb \
|
||||
qcom-apq8084-ifc6540.dtb \
|
||||
qcom-apq8084-mtp.dtb \
|
||||
@@ -30,6 +30,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+ qcom-ipq4019-a62.dtb \
|
||||
+ qcom-ipq4019-ap.dk04.1-c1.dtb \
|
||||
+ qcom-ipq4019-fritzbox-7530.dtb \
|
||||
++ qcom-ipq4019-fritzrepeater-1200.dtb \
|
||||
+ qcom-ipq4019-fritzrepeater-3000.dtb \
|
||||
+ qcom-ipq4019-linksys_ea8300.dtb \
|
||||
+ qcom-ipq4019-map-ac2200.dtb \
|
646
patches/openwrt/0008-ipq40xx-add-support-for-Aruba-AP-303.patch
Normal file
646
patches/openwrt/0008-ipq40xx-add-support-for-Aruba-AP-303.patch
Normal file
@ -0,0 +1,646 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Wed, 23 Oct 2019 22:25:14 +0200
|
||||
Subject: ipq40xx: add support for Aruba AP-303
|
||||
|
||||
Hardware
|
||||
--------
|
||||
|
||||
SoC: Qualcomm IPQ4029
|
||||
RAM: 512M DDR3
|
||||
FLASH: - 128MB NAND (Macronix MX30LF1G18AC)
|
||||
- 4MB SPI-NOR (Macronix MX25R3235F)
|
||||
TPM: Atmel AT97SC3203
|
||||
BLE: Texas Instruments CC2540T
|
||||
attached to ttyMSM0
|
||||
ETH: Atheros AR8035
|
||||
LED: WiFi (amber / green)
|
||||
System (red / green)
|
||||
BTN: Reset
|
||||
|
||||
To connect to the serial console, you can solder to the labled pads next
|
||||
to the USB port or use your Aruba supplied UARt adapter.
|
||||
|
||||
Do NOT plug a standard USB cable into the Console labled USB-port!
|
||||
Aruba/HPE simply put UART on the micro-USB pins. You can solder yourself
|
||||
an adapter cable:
|
||||
|
||||
VCC - NC
|
||||
D+ - TX
|
||||
D- - RX
|
||||
GND - GND
|
||||
|
||||
The console setting in bootloader and OS is 9600 8N1. Voltage level is
|
||||
3.3V.
|
||||
|
||||
To enable a full list of commands in the U-Boot "help" command, execute
|
||||
the literal "diag" command.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
1. Get the OpenWrt initramfs image. Rename it to ipq40xx.ari and put it
|
||||
into the TFTP server root directory. Configure the TFTP server to
|
||||
be reachable at 192.168.1.75/24. Connect the machine running the TFTP
|
||||
server to the ethernet port of the access point.
|
||||
|
||||
2. Connect to the serial console. Interrupt autobooting by pressing
|
||||
Enter when prompted.
|
||||
|
||||
3. Configure the bootargs and bootcmd for OpenWrt.
|
||||
$ setenv bootargs_openwrt "setenv bootargs console=ttyMSM1,9600n8"
|
||||
$ setenv nandboot_openwrt "run bootargs_openwrt; ubi part aos1;
|
||||
ubi read 0x85000000 kernel; bootm 0x85000000"
|
||||
$ setenv ramboot_openwrt "run bootargs_openwrt;
|
||||
setenv ipaddr 192.168.1.105; setenv serverip 192.168.1.75;
|
||||
netget; set fdt_high 0x87000000; bootm"
|
||||
$ setenv bootcmd "run nandboot_openwrt"
|
||||
$ saveenv
|
||||
|
||||
4. Load OpenWrt into RAM:
|
||||
$ run ramboot_openwrt
|
||||
|
||||
5. After OpenWrt booted, transfer the OpenWrt sysupgrade image to the
|
||||
/tmp folder on the device.
|
||||
|
||||
6. Flash OpenWrt:
|
||||
$ ubidetach -p /dev/mtd1
|
||||
$ ubiformat /dev/mtd1
|
||||
$ sysupgrade -n /tmp/openwrt-sysupgrade.bin
|
||||
|
||||
To go back to the stock firmware, simply reset the bootcmd in the
|
||||
bootloader to the original value:
|
||||
|
||||
$ setenv bootcmd "boot"
|
||||
$ saveenv
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
(cherry picked from commit 102c8c55f217606cdbdc9a449667e034676b3e75)
|
||||
|
||||
diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
index 01825b8bac46eec6325de00396d96307c946f975..49dd570242533068adf2c9df89e78560ba5f70eb 100755
|
||||
--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
+++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network
|
||||
@@ -39,6 +39,7 @@ ipq40xx_setup_interfaces()
|
||||
ucidef_add_switch "switch0" \
|
||||
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan"
|
||||
;;
|
||||
+ aruba,ap-303|\
|
||||
avm,fritzrepeater-1200|\
|
||||
engenius,eap1300|\
|
||||
meraki,mr33|\
|
||||
diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
index b0035ce8a394b6e87d7d89b9f55a6ec7c66e448e..15a2f2c09f8a92cc0accfbf9a977dbeb3355570d 100644
|
||||
--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
+++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
|
||||
@@ -137,6 +137,10 @@ case "$FIRMWARE" in
|
||||
qcom,ap-dk01.1-c1)
|
||||
ath10kcal_extract "ART" 4096 12064
|
||||
;;
|
||||
+ aruba,ap-303)
|
||||
+ ath10kcal_extract "ART" 4096 12064
|
||||
+ ath10kcal_patch_mac_crc $(mtd_get_mac_binary mfginfo 29)
|
||||
+ ;;
|
||||
asus,map-ac2200)
|
||||
ath10kcal_ubi_extract "Factory" 4096 12064
|
||||
;;
|
||||
@@ -199,6 +203,10 @@ case "$FIRMWARE" in
|
||||
qcom,ap-dk01.1-c1)
|
||||
ath10kcal_extract "ART" 20480 12064
|
||||
;;
|
||||
+ aruba,ap-303)
|
||||
+ ath10kcal_extract "ART" 20480 12064
|
||||
+ ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary mfginfo 29) +1)
|
||||
+ ;;
|
||||
asus,map-ac2200)
|
||||
ath10kcal_ubi_extract "Factory" 20480 12064
|
||||
;;
|
||||
diff --git a/target/linux/ipq40xx/base-files/etc/inittab b/target/linux/ipq40xx/base-files/etc/inittab
|
||||
index 809bba5e5ff49869429c91cf791cea73ab67d14e..3181021a0592720657b815c3eac803a57f4ea438 100644
|
||||
--- a/target/linux/ipq40xx/base-files/etc/inittab
|
||||
+++ b/target/linux/ipq40xx/base-files/etc/inittab
|
||||
@@ -2,3 +2,4 @@
|
||||
::sysinit:/etc/init.d/rcS S boot
|
||||
::shutdown:/etc/init.d/rcS K shutdown
|
||||
ttyMSM0::askfirst:/usr/libexec/login.sh
|
||||
+ttyMSM1::askfirst:/usr/libexec/login.sh
|
||||
diff --git a/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh b/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh
|
||||
index be4b6322cb6a91f489dfec237ac6b79ce079e0eb..a0dec1042a3dd7416ece3307666c8ecf9d15d277 100644
|
||||
--- a/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh
|
||||
+++ b/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh
|
||||
@@ -4,6 +4,7 @@ set_preinit_iface() {
|
||||
. /lib/functions.sh
|
||||
|
||||
case $(board_name) in
|
||||
+ aruba,ap-303| \
|
||||
asus,rt-ac58u| \
|
||||
avm,fritzbox-4040| \
|
||||
glinet,gl-b1300| \
|
||||
diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
index a7b7da1bf378f7cc19e960c497bc52efb3bae4fb..7253139497a8a8b9fab49cef3fce5eabe98d8002 100644
|
||||
--- a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
+++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
|
||||
@@ -48,6 +48,7 @@ platform_do_upgrade() {
|
||||
case "$(board_name)" in
|
||||
8dev,jalapeno |\
|
||||
alfa-network,ap120c-ac |\
|
||||
+ aruba,ap-303 |\
|
||||
avm,fritzbox-7530 |\
|
||||
avm,fritzrepeater-1200 |\
|
||||
avm,fritzrepeater-3000 |\
|
||||
diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7929494d027aca5c696910232a36d484f5ce6562
|
||||
--- /dev/null
|
||||
+++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts
|
||||
@@ -0,0 +1,418 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
+
|
||||
+#include "qcom-ipq4019.dtsi"
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
+#include <dt-bindings/input/input.h>
|
||||
+#include <dt-bindings/soc/qcom,tcsr.h>
|
||||
+
|
||||
+/ {
|
||||
+ model = "Aruba AP-303";
|
||||
+ compatible = "aruba,ap-303";
|
||||
+
|
||||
+ aliases {
|
||||
+ led-boot = &led_system_green;
|
||||
+ led-failsafe = &led_system_red;
|
||||
+ led-running = &led_system_green;
|
||||
+ led-upgrade = &led_system_red;
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ device_type = "memory";
|
||||
+ reg = <0x80000000 0x10000000>;
|
||||
+ };
|
||||
+
|
||||
+ soc {
|
||||
+ mdio@90000 {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&mdio_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ /delete-node/ ethernet-phy@0;
|
||||
+ /delete-node/ ethernet-phy@2;
|
||||
+ /delete-node/ ethernet-phy@3;
|
||||
+ /delete-node/ ethernet-phy@4;
|
||||
+
|
||||
+ ethernet-phy@5 {
|
||||
+ reg = <0x5>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ counter@4a1000 {
|
||||
+ compatible = "qcom,qca-gcnt";
|
||||
+ reg = <0x4a1000 0x4>;
|
||||
+ };
|
||||
+
|
||||
+ ess_tcsr@1953000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1953000 0x1000>;
|
||||
+ qcom,ess-interface-select = <TCSR_ESS_PSGMII_RGMII5>;
|
||||
+ };
|
||||
+
|
||||
+ tcsr@1949000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1949000 0x100>;
|
||||
+ qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
|
||||
+ };
|
||||
+
|
||||
+ tcsr@1957000 {
|
||||
+ compatible = "qcom,tcsr";
|
||||
+ reg = <0x1957000 0x100>;
|
||||
+ qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
|
||||
+ };
|
||||
+
|
||||
+ blsp1_uart2: serial@78b0000 {
|
||||
+ };
|
||||
+
|
||||
+ crypto@8e3a000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ watchdog@b017000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ess-switch@c000000 {
|
||||
+ switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */
|
||||
+ switch_lan_bmp = <0x0>; /* lan port bitmap */
|
||||
+ switch_wan_bmp = <0x10>; /* wan port bitmap */
|
||||
+ };
|
||||
+
|
||||
+ edma@c080000 {
|
||||
+ qcom,single-phy;
|
||||
+ qcom,num_gmac = <1>;
|
||||
+ phy-mode = "rgmii-id";
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ i2c_0: i2c@78b7000 {
|
||||
+ pinctrl-0 = <&i2c_0_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "ok";
|
||||
+
|
||||
+ tpm@29 {
|
||||
+ /* No Driver */
|
||||
+ compatible = "atmel,at97sc3203";
|
||||
+ reg = <0x29>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ wifi_green {
|
||||
+ label = "ap-303:green:wifi";
|
||||
+ gpios = <&tlmm 39 GPIO_ACTIVE_HIGH>;
|
||||
+ linux,default-trigger = "phy0tpt";
|
||||
+ };
|
||||
+
|
||||
+ wifi_amber {
|
||||
+ label = "ap-303:amber:wifi";
|
||||
+ gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>;
|
||||
+ linux,default-trigger = "phy1tpt";
|
||||
+ };
|
||||
+
|
||||
+ led_system_red: system_red {
|
||||
+ label = "ap-303:red:system";
|
||||
+ gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ led_system_green: system_green {
|
||||
+ label = "ap-303:green:system";
|
||||
+ gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ keys {
|
||||
+ compatible = "gpio-keys";
|
||||
+
|
||||
+ reset {
|
||||
+ label = "Reset button";
|
||||
+ gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&blsp_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&blsp1_uart1 {
|
||||
+ /* Texas Instruments CC2540T BLE radio */
|
||||
+ pinctrl-0 = <&serial_0_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&blsp1_uart2 {
|
||||
+ pinctrl-0 = <&serial_1_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&cryptobam {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&gmac0 {
|
||||
+ qcom,phy_mdio_addr = <5>;
|
||||
+ qcom,poll_required = <1>;
|
||||
+ vlan_tag = <0 0x20>;
|
||||
+};
|
||||
+
|
||||
+&qpic_bam {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&tlmm {
|
||||
+ /*
|
||||
+ * In addition to the Pins listed below,
|
||||
+ * the following GPIOs have "features":
|
||||
+ * 54 - out - active low to force HW reset
|
||||
+ * 41 - out - active low to reset TPM
|
||||
+ * 43 - out - active low to reset BLE radio
|
||||
+ * 19 - in - active high when DC powered
|
||||
+ */
|
||||
+ mdio_pins: mdio_pinmux {
|
||||
+ mux_1 {
|
||||
+ pins = "gpio6";
|
||||
+ function = "mdio";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+ mux_2 {
|
||||
+ pins = "gpio7";
|
||||
+ function = "mdc";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ nand_pins: nand_pins {
|
||||
+ pullups {
|
||||
+ pins = "gpio53", "gpio58", "gpio59";
|
||||
+ function = "qpic";
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+
|
||||
+ pulldowns {
|
||||
+ pins = "gpio54", "gpio55", "gpio56",
|
||||
+ "gpio57", "gpio60", "gpio61",
|
||||
+ "gpio62", "gpio63", "gpio64",
|
||||
+ "gpio65", "gpio66", "gpio67",
|
||||
+ "gpio68", "gpio69";
|
||||
+ function = "qpic";
|
||||
+ bias-pull-down;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ spi_0_pins: spi_0_pinmux {
|
||||
+ pin {
|
||||
+ function = "blsp_spi0";
|
||||
+ pins = "gpio13", "gpio14", "gpio15";
|
||||
+ drive-strength = <12>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ pin_cs {
|
||||
+ function = "gpio";
|
||||
+ pins = "gpio12";
|
||||
+ drive-strength = <2>;
|
||||
+ bias-disable;
|
||||
+ output-high;
|
||||
+ };
|
||||
+ };
|
||||
+ i2c_0_pins: i2c_0_pinmux {
|
||||
+ mux {
|
||||
+ pins = "gpio10", "gpio11";
|
||||
+ function = "blsp_i2c0";
|
||||
+ drive-strength = <4>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ serial_0_pins: serial_0_pinmux {
|
||||
+ mux {
|
||||
+ pins = "gpio16", "gpio17";
|
||||
+ function = "blsp_uart0";
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ serial_1_pins: serial_1_pinmux {
|
||||
+ mux {
|
||||
+ pins = "gpio8", "gpio9";
|
||||
+ function = "blsp_uart1";
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ phy-reset {
|
||||
+ line-name = "PHY-reset";
|
||||
+ gpios = <42 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-hog;
|
||||
+ output-high;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&nand {
|
||||
+ pinctrl-0 = <&nand_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ nand@0 {
|
||||
+ partitions {
|
||||
+ compatible = "fixed-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ partition@0 {
|
||||
+ /* 'aos0' in Aruba firmware */
|
||||
+ label = "aos0";
|
||||
+ reg = <0x0 0x2000000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@2000000 {
|
||||
+ /* 'aos1' in AVM firmware */
|
||||
+ label = "ubi";
|
||||
+ reg = <0x2000000 0x2000000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@4000000 {
|
||||
+ label = "aruba-ubifs";
|
||||
+ reg = <0x4000000 0x4000000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&blsp1_spi1 {
|
||||
+ pinctrl-0 = <&spi_0_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+ cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;
|
||||
+
|
||||
+ flash@0 {
|
||||
+ compatible = "jedec,spi-nor";
|
||||
+ reg = <0>;
|
||||
+ spi-max-frequency = <24000000>;
|
||||
+
|
||||
+ partitions {
|
||||
+ compatible = "fixed-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ /*
|
||||
+ * There is no partition map for the NOR flash
|
||||
+ * in the stock firmware.
|
||||
+ *
|
||||
+ * All partitions here are based on offsets
|
||||
+ * found in the U-Boot GPL code and information
|
||||
+ * from smem.
|
||||
+ */
|
||||
+
|
||||
+ partition@0 {
|
||||
+ label = "sbl1";
|
||||
+ reg = <0x0 0x40000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@40000 {
|
||||
+ label = "mibib";
|
||||
+ reg = <0x40000 0x20000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@60000 {
|
||||
+ label = "qsee";
|
||||
+ reg = <0x60000 0x60000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@c0000 {
|
||||
+ label = "cdt";
|
||||
+ reg = <0xc0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@d0000 {
|
||||
+ label = "ddrparams";
|
||||
+ reg = <0xd0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@e0000 {
|
||||
+ label = "ART";
|
||||
+ reg = <0xe0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@f0000 {
|
||||
+ label = "appsbl";
|
||||
+ reg = <0xf0000 0xf0000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@1e0000 {
|
||||
+ label = "mfginfo";
|
||||
+ reg = <0x1e0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@1f0000 {
|
||||
+ label = "apcd";
|
||||
+ reg = <0x1f0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@200000 {
|
||||
+ label = "osss";
|
||||
+ reg = <0x200000 0x180000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@380000 {
|
||||
+ /* This is empty */
|
||||
+ label = "appsblenv";
|
||||
+ reg = <0x380000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@390000 {
|
||||
+ label = "pds";
|
||||
+ reg = <0x390000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@3a0000 {
|
||||
+ label = "fcache";
|
||||
+ reg = <0x3a0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@3b0000 {
|
||||
+ /* Called osss1 in smem */
|
||||
+ label = "u-boot-env-bak";
|
||||
+ reg = <0x3b0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@3f0000 {
|
||||
+ label = "u-boot-env";
|
||||
+ reg = <0x3f0000 0x10000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&wifi0 {
|
||||
+ status = "okay";
|
||||
+ qcom,ath10k-calibration-variant = "Aruba-AP-303";
|
||||
+};
|
||||
+
|
||||
+&wifi1 {
|
||||
+ status = "okay";
|
||||
+ qcom,ath10k-calibration-variant = "Aruba-AP-303";
|
||||
+};
|
||||
diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile
|
||||
index 98c81726d9c12bd466df2150c3e98a76cfb46f78..68dcbc59a42f6d8360b87c7b4e74cd34f697b465 100644
|
||||
--- a/target/linux/ipq40xx/image/Makefile
|
||||
+++ b/target/linux/ipq40xx/image/Makefile
|
||||
@@ -85,6 +85,15 @@ define Device/alfa-network_ap120c-ac
|
||||
endef
|
||||
TARGET_DEVICES += alfa-network_ap120c-ac
|
||||
|
||||
+define Device/aruba_ap-303
|
||||
+ $(call Device/FitImageLzma)
|
||||
+ DEVICE_TITLE := Aruba AP-303
|
||||
+ DEVICE_DTS := qcom-ipq4029-ap-303
|
||||
+ DEVICE_PACKAGES := ipq-wifi-aruba_ap-303
|
||||
+ IMAGES := sysupgrade.bin
|
||||
+endef
|
||||
+TARGET_DEVICES += aruba_ap-303
|
||||
+
|
||||
define Device/asus_map-ac2200
|
||||
$(call Device/FitImageLzma)
|
||||
DEVICE_DTS := qcom-ipq4019-map-ac2200
|
||||
diff --git a/target/linux/ipq40xx/patches-4.14/304-mtd-spi-nor-Add-support-for-mx25r3235f.patch b/target/linux/ipq40xx/patches-4.14/304-mtd-spi-nor-Add-support-for-mx25r3235f.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d95923a1610d4764538e79bb783702903edcdcad
|
||||
--- /dev/null
|
||||
+++ b/target/linux/ipq40xx/patches-4.14/304-mtd-spi-nor-Add-support-for-mx25r3235f.patch
|
||||
@@ -0,0 +1,26 @@
|
||||
+From 158acdbf0336f601971637f988b57a6a67a0869b Mon Sep 17 00:00:00 2001
|
||||
+From: David Bauer <mail@david-bauer.net>
|
||||
+Date: Sun, 15 Dec 2019 13:10:50 +0100
|
||||
+Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f
|
||||
+
|
||||
+Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix.
|
||||
+The chip has 4MB of total capacity, divided into a total of 64 sectors,
|
||||
+each 64KB sized. The chip also supports 4KB large sectors.
|
||||
+Additionally, it supports dual and quad read modes.
|
||||
+
|
||||
+Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
+---
|
||||
+ drivers/mtd/spi-nor/spi-nor.c | 2 ++
|
||||
+ 1 file changed, 2 insertions(+)
|
||||
+
|
||||
+--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
++++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
+@@ -1024,6 +1024,8 @@ static const struct flash_info spi_nor_i
|
||||
+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
|
||||
+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
|
||||
+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
++ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
|
||||
++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
+ { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, 0) },
|
||||
+ { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
|
||||
+ { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
|
||||
diff --git a/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
index f7efd415f1f1c000867793b3b133e44b3e50b0fd..fc8a88336491c2ac7c2a93fafb1f2b6fd38695be 100644
|
||||
--- a/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
+++ b/target/linux/ipq40xx/patches-4.14/901-arm-boot-add-dts-files.patch
|
||||
@@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
-@@ -697,7 +697,31 @@ dtb-$(CONFIG_ARCH_QCOM) += \
|
||||
+@@ -697,7 +697,32 @@ dtb-$(CONFIG_ARCH_QCOM) += \
|
||||
qcom-apq8074-dragonboard.dtb \
|
||||
qcom-apq8084-ifc6540.dtb \
|
||||
qcom-apq8084-mtp.dtb \
|
||||
@@ -37,6 +37,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+ qcom-ipq4019-qxwlan-e2600ac-c1.dtb \
|
||||
+ qcom-ipq4019-qxwlan-e2600ac-c2.dtb \
|
||||
+ qcom-ipq4028-wpj428.dtb \
|
||||
++ qcom-ipq4029-ap-303.dtb \
|
||||
+ qcom-ipq4029-gl-b1300.dtb \
|
||||
+ qcom-ipq4029-mr33.dtb \
|
||||
qcom-ipq8064-ap148.dtb \
|
@ -31,14 +31,14 @@ sanitize() {
|
||||
echo -n "$v"
|
||||
}
|
||||
|
||||
vars=
|
||||
vars=()
|
||||
|
||||
for feature in $1; do
|
||||
if [ "$(type -t gluon_feature_nodefault_${feature})" != 'function' ]; then
|
||||
if [ "$(type -t "gluon_feature_nodefault_${feature}")" != 'function' ]; then
|
||||
echo "gluon-${feature}"
|
||||
fi
|
||||
|
||||
vars="$vars $(sanitize "$feature")=1"
|
||||
vars+=("$(sanitize "$feature")=1")
|
||||
done
|
||||
|
||||
|
||||
@ -46,18 +46,19 @@ nodefault() {
|
||||
:
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
packages() {
|
||||
local cond="$(sanitize "$1")"
|
||||
shift
|
||||
|
||||
# We only allow variable names, parentheses and the operators: & | !
|
||||
if [ "$(expr match "$cond" '.*[^A-Za-z0-9_()&|! ].*')" -gt 0 ]; then
|
||||
if grep -q '[^A-Za-z0-9_()&|! ]' <<< "$cond"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Let will return false when the result of the passed expression is 0,
|
||||
# so we always add 1. This way false is only returned for syntax errors.
|
||||
local ret="$(env -i $vars bash --norc -ec "let _result_='1+($cond)'; echo -n \"\$_result_\"" 2>/dev/null)"
|
||||
local ret="$(env -i "${vars[@]}" bash --norc -ec "let _result_='1+($cond)'; echo -n \"\$_result_\"" 2>/dev/null)"
|
||||
case "$ret" in
|
||||
2)
|
||||
for pkg in "$@"; do
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
check_command() {
|
||||
which "$1" >/dev/null 2>&1
|
||||
command -v "$1" >/dev/null
|
||||
}
|
||||
|
||||
if check_command gnustat; then
|
||||
|
5
scripts/lint-lua.sh
Executable file
5
scripts/lint-lua.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
luacheck package scripts targets
|
28
scripts/lint-sh.sh
Executable file
28
scripts/lint-sh.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
is_scriptfile() {
|
||||
echo "$1" | grep -qE '.*\.sh$' || head -n1 "$1" | grep -qE '^#.*(sh|bash)$'
|
||||
}
|
||||
|
||||
find contrib -type f | while read -r file; do
|
||||
is_scriptfile "$file" || continue
|
||||
|
||||
echo "Checking $file"
|
||||
shellcheck -f gcc "$file"
|
||||
done
|
||||
|
||||
find package -type f | while read -r file; do
|
||||
is_scriptfile "$file" || continue
|
||||
|
||||
echo "Checking $file"
|
||||
shellcheck -f gcc -x -s sh -e SC2039,SC1091,SC2155,SC2034 "$file"
|
||||
done
|
||||
|
||||
find scripts -type f | while read -r file; do
|
||||
is_scriptfile "$file" || continue
|
||||
|
||||
echo "Checking $file"
|
||||
shellcheck -f gcc -x -e SC2154,SC1090,SC2181,SC2155,SC2148,SC2034,SC2148 "$file"
|
||||
done
|
@ -1,6 +1,7 @@
|
||||
. ./modules
|
||||
[ ! -f "$GLUON_SITEDIR"/modules ] || . "$GLUON_SITEDIR"/modules
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
FEEDS="$(echo $GLUON_FEEDS $GLUON_SITE_FEEDS | tr ' ' '\n')"
|
||||
|
||||
GLUON_MODULES=openwrt
|
||||
|
@ -3,7 +3,7 @@
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
[ "$GLUON_TMPDIR" -a "$GLUON_PATCHESDIR" ] || exit 1
|
||||
[ "$GLUON_TMPDIR" ] && [ "$GLUON_PATCHESDIR" ] || exit 1
|
||||
|
||||
. scripts/modules.sh
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
check_command() {
|
||||
which "$1" >/dev/null 2>&1
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if check_command sha256sum; then
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
check_command() {
|
||||
which "$1" >/dev/null 2>&1
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if check_command sha512sum; then
|
||||
|
@ -13,13 +13,13 @@ GLUONDIR="$(pwd)"
|
||||
for module in $GLUON_MODULES; do
|
||||
echo "--- Updating patches for module '$module' ---"
|
||||
|
||||
rm -rf "${GLUON_PATCHESDIR}/$module"
|
||||
rm -rf "${GLUON_PATCHESDIR:?}/$module"
|
||||
|
||||
cd "$GLUONDIR"/"$module"
|
||||
|
||||
n=0
|
||||
for commit in $(git rev-list --reverse --no-merges base..patched); do
|
||||
let n=n+1
|
||||
(( ++n ))
|
||||
mkdir -p "${GLUON_PATCHESDIR}/$module"
|
||||
git -c core.abbrev=40 show --pretty=format:'From: %an <%ae>%nDate: %aD%nSubject: %B' --no-renames --binary "$commit" > "${GLUON_PATCHESDIR}/$module/$(printf '%04u' $n)-$(git show -s --pretty=format:%f "$commit").patch"
|
||||
done
|
||||
|
@ -10,9 +10,9 @@ GLUONDIR="$(pwd)"
|
||||
for module in $GLUON_MODULES; do
|
||||
echo "--- Updating module '$module' ---"
|
||||
var=$(echo "$module" | tr '[:lower:]/' '[:upper:]_')
|
||||
eval repo=\${${var}_REPO}
|
||||
eval branch=\${${var}_BRANCH}
|
||||
eval commit=\${${var}_COMMIT}
|
||||
eval 'repo=${'"${var}"'_REPO}'
|
||||
eval 'branch=${'"${var}"'_BRANCH}'
|
||||
eval 'commit=${'"${var}"'_COMMIT}'
|
||||
|
||||
mkdir -p "$GLUONDIR/$module"
|
||||
cd "$GLUONDIR/$module"
|
||||
|
@ -4,18 +4,21 @@ config 'CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64'
|
||||
local ATH10K_PACKAGES = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca988x',
|
||||
'-ath10k-firmware-qca988x-ct',
|
||||
}
|
||||
local ATH10K_PACKAGES_QCA9887 = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca9887',
|
||||
'-ath10k-firmware-qca9887-ct',
|
||||
}
|
||||
local ATH10K_PACKAGES_QCA9888 = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca9888',
|
||||
'-ath10k-firmware-qca9888-ct',
|
||||
}
|
||||
@ -99,7 +102,7 @@ device('d-link-dir-825-rev-b1', 'dir-825-b1', {
|
||||
})
|
||||
|
||||
|
||||
-- GL Innovations
|
||||
-- GL.iNet
|
||||
|
||||
device('gl-inet-6408a-v1', 'gl-inet-6408A-v1')
|
||||
|
||||
@ -154,6 +157,7 @@ device('netgear-wndr3700v2', 'wndr3700v2', {
|
||||
})
|
||||
|
||||
device('netgear-wndr3800', 'wndr3800', {
|
||||
aliases = {'netgear-wndr3800chmychart'},
|
||||
factory_ext = '.img',
|
||||
})
|
||||
|
||||
|
@ -1,10 +1,63 @@
|
||||
local ATH10K_PACKAGES_QCA9880 = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca988x',
|
||||
'-ath10k-firmware-qca988x-ct',
|
||||
}
|
||||
|
||||
local ATH10K_PACKAGES_QCA9888 = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca9888',
|
||||
'-ath10k-firmware-qca9888-ct',
|
||||
}
|
||||
|
||||
-- devolo
|
||||
|
||||
device('devolo-wifi-pro-1200e', 'devolo_dvl1200e', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('devolo-wifi-pro-1200i', 'devolo_dvl1200i', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('devolo-wifi-pro-1750c', 'devolo_dvl1750c', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('devolo-wifi-pro-1750e', 'devolo_dvl1750e', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('devolo-wifi-pro-1750i', 'devolo_dvl1750i', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('devolo-wifi-pro-1750x', 'devolo_dvl1750x', {
|
||||
packages = ATH10K_PACKAGES_QCA9880,
|
||||
factory = false,
|
||||
})
|
||||
|
||||
-- GL.iNet
|
||||
|
||||
device('gl.inet-gl-ar300m-lite', 'glinet_gl-ar300m-lite', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
-- OCEDO
|
||||
|
||||
device('ocedo-raccoon', 'ocedo_raccoon', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
-- TP-Link
|
||||
|
||||
device('tp-link-archer-c6-v2', 'tplink_archer-c6-v2', {
|
||||
|
@ -1,7 +1,11 @@
|
||||
include 'brcm2708.inc'
|
||||
|
||||
device('raspberry-pi', 'rpi', {
|
||||
device('raspberrypi-model-b', 'rpi', {
|
||||
manifest_aliases = {
|
||||
'raspberrypi-model-b-plus',
|
||||
'raspberrypi-model-b-rev2',
|
||||
|
||||
-- from Gluon 2019.1 and older
|
||||
'raspberry-pi-model-b-rev-2',
|
||||
'raspberry-pi-model-b-plus-rev-1.2',
|
||||
},
|
||||
|
@ -1,7 +1,8 @@
|
||||
include 'brcm2708.inc'
|
||||
|
||||
device('raspberry-pi-2', 'rpi-2', {
|
||||
device('raspberrypi-2-model-b', 'rpi-2', {
|
||||
manifest_aliases = {
|
||||
-- from Gluon 2019.1 and older
|
||||
'raspberry-pi-2-model-b-rev-1.1',
|
||||
},
|
||||
})
|
||||
|
@ -1,3 +1,10 @@
|
||||
include 'brcm2708.inc'
|
||||
|
||||
device('raspberry-pi-3', 'rpi-3')
|
||||
device('raspberrypi-3-model-b', 'rpi-3', {
|
||||
manifest_aliases = {
|
||||
'raspberrypi-3-model-b-plus',
|
||||
|
||||
-- from Gluon 2019.1 and older
|
||||
'raspberry-pi-3-model-b-rev-1.2',
|
||||
},
|
||||
})
|
||||
|
@ -56,6 +56,8 @@ if envtrue.GLUON_DEBUG then
|
||||
config 'CONFIG_NO_STRIP=y'
|
||||
config '# CONFIG_USE_STRIP is not set'
|
||||
config '# CONFIG_USE_SSTRIP is not set'
|
||||
|
||||
try_config 'CONFIG_TARGET_ROOTFS_PARTSIZE=500'
|
||||
end
|
||||
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
local ATH10K_PACKAGES_IPQ40XX = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca4019',
|
||||
'-ath10k-firmware-qca4019-ct',
|
||||
}
|
||||
local ATH10K_PACKAGES_IPQ40XX_QCA9888 = {
|
||||
'kmod-ath10k',
|
||||
'-kmod-ath10k-ct',
|
||||
'-kmod-ath10k-ct-smallbuffers',
|
||||
'ath10k-firmware-qca4019',
|
||||
'-ath10k-firmware-qca4019-ct',
|
||||
'ath10k-firmware-qca9888',
|
||||
@ -19,6 +21,14 @@ defaults {
|
||||
}
|
||||
|
||||
|
||||
-- Aruba
|
||||
|
||||
device('aruba-ap-303', 'aruba_ap-303', {
|
||||
factory = false,
|
||||
aliases = {'aruba-instant-on-ap11'},
|
||||
})
|
||||
|
||||
|
||||
-- AVM
|
||||
|
||||
device('avm-fritz-box-4040', 'avm_fritzbox-4040', {
|
||||
|
@ -1,15 +1,24 @@
|
||||
device('avm-fritz-box-7360-sl', 'avm_fritz7360sl', {
|
||||
factory = false,
|
||||
aliases = {'avm-fritz-box-7360-v1', 'avm-fritz-box-7360-v2'},
|
||||
})
|
||||
|
||||
device('avm-fritz-box-7362-sl', 'avm_fritz7362sl', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('avm-fritz-box-7412', 'avm_fritz7412', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
-- TP-Link
|
||||
|
||||
-- CAVEAT: These devices don't have a dedicated WAN port.
|
||||
-- CAVEAT: These devices don't have a dedicated WAN port.
|
||||
-- All ethernet ports on the device are bridged and
|
||||
-- used as WAN ports. Clients connected to these
|
||||
-- ports will be connected to your private network.
|
||||
|
||||
device('tp-link-td-w8970', 'tplink_tdw8970')
|
||||
device('tp-link-td-w8970', 'tplink_tdw8970')
|
||||
|
||||
device('tp-link-td-w8980', 'tplink_tdw8980', {
|
||||
aliases = {'tp-link-td-w9980'},
|
||||
|
@ -1,3 +1,8 @@
|
||||
device('avm-fritz-box-7312', 'avm_fritz7312', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('avm-fritz-box-7320', 'avm_fritz7320', {
|
||||
factory = false,
|
||||
aliases = {'avm-fritz-box-7330', 'avm-fritz-box-7330-sl'},
|
||||
})
|
||||
|
@ -4,6 +4,14 @@ device('aerohive-hiveap-330', 'hiveap-330', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
|
||||
-- Enterasys
|
||||
|
||||
device('enterasys-ws-ap3710i', 'ws-ap3710i', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
|
||||
-- OCEDO
|
||||
|
||||
device('ocedo-panda', 'panda', {
|
||||
|
@ -6,7 +6,7 @@ device('asus-rt-ac51u', 'rt-ac51u', {
|
||||
})
|
||||
|
||||
|
||||
-- GL Innovations
|
||||
-- GL.iNet
|
||||
|
||||
device('gl-mt300a', 'gl-mt300a', {
|
||||
factory = false,
|
||||
@ -31,10 +31,28 @@ device('nexx-wt3020-8m', 'wt3020-8M', {
|
||||
},
|
||||
})
|
||||
|
||||
-- TP-Link
|
||||
|
||||
local tplink_region_suffix = ''
|
||||
if (env.GLUON_REGION or '') ~= '' then
|
||||
tplink_region_suffix = '-' .. env.GLUON_REGION
|
||||
end
|
||||
|
||||
device('tp-link-archer-c2-v1', 'tplink_c2-v1', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('tp-link-archer-c20-v1', 'tplink_c20-v1')
|
||||
|
||||
device('tp-link-archer-c20i', 'ArcherC20i')
|
||||
|
||||
device('tp-link-archer-c50', 'ArcherC50v1', {
|
||||
factory = '-squashfs-factory' .. tplink_region_suffix,
|
||||
})
|
||||
|
||||
|
||||
-- Xiaomi
|
||||
|
||||
device('xiaomi-miwifi-mini', 'miwifi-mini', {
|
||||
factory = false,
|
||||
broken = true, -- 2.4GHz WiFi is unstable
|
||||
})
|
||||
|
@ -12,6 +12,10 @@ device('d-link-dir-860l-b1', 'dir-860l-b1')
|
||||
|
||||
-- Netgear
|
||||
|
||||
device('netgear-ex6150', 'netgear_ex6150', {
|
||||
factory_ext = '.chk',
|
||||
})
|
||||
|
||||
device('netgear-r6220', 'r6220', {
|
||||
factory_ext = '.img',
|
||||
})
|
||||
|
@ -29,6 +29,13 @@ device('tp-link-archer-c50-v4', 'tplink_c50-v4', {
|
||||
factory = false,
|
||||
})
|
||||
|
||||
device('tp-link-tl-mr3020-v3', 'tplink_tl-mr3020-v3', {
|
||||
factory = false,
|
||||
extra_images = {
|
||||
{'-squashfs-tftp-recovery', '-bootloader', '.bin'},
|
||||
},
|
||||
})
|
||||
|
||||
device('tp-link-tl-mr3420-v5', 'tplink_tl-mr3420-v5', {
|
||||
factory = false,
|
||||
extra_images = {
|
||||
@ -36,6 +43,13 @@ device('tp-link-tl-mr3420-v5', 'tplink_tl-mr3420-v5', {
|
||||
},
|
||||
})
|
||||
|
||||
device('tp-link-tl-wa801nd-v5', 'tplink_tl-wa801nd-v5', {
|
||||
factory = false,
|
||||
extra_images = {
|
||||
{'-squashfs-tftp-recovery', '-bootloader', '.bin'},
|
||||
},
|
||||
})
|
||||
|
||||
device('tp-link-tl-wr841n-v13', 'tl-wr841n-v13', {
|
||||
factory = false,
|
||||
extra_images = {
|
||||
@ -43,6 +57,12 @@ device('tp-link-tl-wr841n-v13', 'tl-wr841n-v13', {
|
||||
},
|
||||
})
|
||||
|
||||
device('tp-link-tl-wr902ac-v3', 'tplink_tl-wr902ac-v3', {
|
||||
factory = false,
|
||||
extra_images = {
|
||||
{'-squashfs-tftp-recovery', '-bootloader', '.bin'},
|
||||
},
|
||||
})
|
||||
|
||||
-- VoCore 2
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user