Merge branch 'master' into lantiq-avm3370

This commit is contained in:
dzzinstant 2020-10-13 18:05:24 +02:00 committed by GitHub
commit 3003157272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
125 changed files with 4751 additions and 922 deletions

View File

@ -7,6 +7,10 @@ insert_final_newline = true
indent_style = tab
charset = utf-8
[*.yml]
indent_style = space
indent_size = 2
[*.py]
indent_style = space
indent_size = 4

29
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Lint
on:
push:
pull_request:
types: [opened, synchronize, reopened]
jobs:
lua:
name: Lua
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install Dependencies
run: sudo apt install lua-check
- name: Install example site
run: ln -s ./docs/site-example ./site
- name: Lint Lua code
run: make lint-lua
sh:
name: Shell
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install Dependencies
run: sudo apt install shellcheck
- name: Install example site
run: ln -s ./docs/site-example ./site
- name: Lint shell code
run: make lint-sh

View File

@ -12,6 +12,7 @@ include_files = {
"**/*.lua",
"package/**/luasrc/**/*",
"targets/*",
"package/features",
}
exclude_files = {
@ -104,3 +105,11 @@ files["targets/*"] = {
"try_config",
},
}
files["package/features"] = {
read_globals = {
"_",
"feature",
"when",
},
}

View File

@ -28,6 +28,14 @@ GLUON_RELEASE ?= $(error GLUON_RELEASE not set. GLUON_RELEASE can be set in site
GLUON_DEPRECATED ?= $(error GLUON_DEPRECATED not set. Please consult the documentation)
ifneq ($(GLUON_BRANCH),)
$(warning *** Warning: GLUON_BRANCH has been deprecated, please set GLUON_AUTOUPDATER_BRANCH and GLUON_AUTOUPDATER_ENABLED instead.)
GLUON_AUTOUPDATER_BRANCH ?= $(GLUON_BRANCH)
GLUON_AUTOUPDATER_ENABLED ?= 1
endif
GLUON_AUTOUPDATER_ENABLED ?= 0
# initialize (possibly already user set) directory variables
GLUON_TMPDIR ?= tmp
GLUON_OUTPUTDIR ?= output
@ -58,7 +66,7 @@ endef
GLUON_VARS = \
GLUON_RELEASE GLUON_REGION GLUON_MULTIDOMAIN GLUON_AUTOREMOVE GLUON_DEBUG GLUON_MINIFY GLUON_DEPRECATED \
GLUON_DEVICES GLUON_TARGETSDIR GLUON_PATCHESDIR GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR GLUON_DEBUGDIR \
GLUON_SITEDIR GLUON_RELEASE GLUON_BRANCH GLUON_LANGS GLUON_BASE_FEEDS \
GLUON_SITEDIR GLUON_RELEASE GLUON_AUTOUPDATER_BRANCH GLUON_AUTOUPDATER_ENABLED GLUON_LANGS GLUON_BASE_FEEDS \
GLUON_TARGET BOARD SUBTARGET
unexport $(GLUON_VARS)
@ -114,13 +122,6 @@ define CheckTarget
fi
endef
define CheckExternal
if [ ! -d openwrt ]; then
echo "You don't seem to have obtained the external repositories needed by Gluon; please call \`make update\` first!"
exit 1
fi
endef
define CheckSite
if ! GLUON_SITEDIR='$(GLUON_SITEDIR)' GLUON_SITE_CONFIG='$(1).conf' $(LUA) -e 'assert(dofile("scripts/site_config.lua")(os.getenv("GLUON_SITE_CONFIG")))'; then
echo 'Your site configuration ($(1).conf) did not pass validation'
@ -147,7 +148,7 @@ LUA := openwrt/staging_dir/hostpkg/bin/lua
$(LUA):
+@
$(CheckExternal)
scripts/module_check.sh
[ -e openwrt/.config ] || $(OPENWRTMAKE) defconfig
$(OPENWRTMAKE) tools/install
@ -157,7 +158,7 @@ $(LUA):
config: $(LUA) FORCE
+@
$(CheckExternal)
scripts/module_check.sh
$(CheckTarget)
$(foreach conf,site $(patsubst $(GLUON_SITEDIR)/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)),\
$(call CheckSite,$(conf)); \
@ -185,23 +186,23 @@ dirclean: FORCE
manifest: $(LUA) FORCE
@
[ '$(GLUON_BRANCH)' ] || (echo 'Please set GLUON_BRANCH to create a manifest.'; false)
[ '$(GLUON_AUTOUPDATER_BRANCH)' ] || (echo 'Please set GLUON_AUTOUPDATER_BRANCH to create a manifest.'; false)
echo '$(GLUON_PRIORITY)' | grep -qE '^([0-9]*\.)?[0-9]+$$' || (echo 'Please specify a numeric value for GLUON_PRIORITY to create a manifest.'; false)
$(CheckExternal)
scripts/module_check.sh
(
export $(GLUON_ENV)
echo 'BRANCH=$(GLUON_BRANCH)'
echo 'BRANCH=$(GLUON_AUTOUPDATER_BRANCH)'
echo "DATE=$$($(LUA) scripts/rfc3339date.lua)"
echo 'PRIORITY=$(GLUON_PRIORITY)'
echo
for target in $(GLUON_TARGETS); do
$(LUA) scripts/generate_manifest.lua "$$target"
done
) > 'tmp/$(GLUON_BRANCH).manifest.tmp'
) > 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp'
mkdir -p '$(GLUON_IMAGEDIR)/sysupgrade'
mv 'tmp/$(GLUON_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_BRANCH).manifest'
mv 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_AUTOUPDATER_BRANCH).manifest'
FORCE: ;

View File

@ -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 v2020.1.3 && make update`.
and switch to one by running `git checkout v2020.2.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.

45
docs/_static/css/custom.css vendored Normal file
View File

@ -0,0 +1,45 @@
/*
This fixes the vertical position of list markers when the first
element in the <li> is a <pre> block
Scrolling inside the <pre> block is still working as expected
*/
.rst-content pre.literal-block,
.rst-content div[class^='highlight'] pre {
overflow: visible;
}
/*
This fixes the bottom margin of paragraphs inside lists, where margins inside
a single list item would incorrectly be displayed larger than margins between
the list items.
Upstream fix (not fixed on readthedocs.io yet):
https://github.com/readthedocs/sphinx_rtd_theme/commit/ac20ce75d426efeb40fe2af1f89ea9bad285a45b
*/
.rst-content .section ol li > p,
.rst-content .section ol li > p:last-child,
.rst-content .section ul li > p,
.rst-content .section ul li > p:last-child {
margin-bottom: 12px;
}
.rst-content .section ol li > p:only-child,
.rst-content .section ol li > p:only-child:last-child,
.rst-content .section ul li > p:only-child,
.rst-content .section ul li > p:only-child:last-child {
margin-bottom: 0rem;
}
/*
This fixes the bottom margin of nested lists
Based on upstream fix (not on readthedocs.io yet):
https://github.com/readthedocs/sphinx_rtd_theme/commit/6f0de13baff93f25204aa2cdf0308aae47d71312
*/
.rst-content .section ul li > ul,
.rst-content .section ul li > ol,
.rst-content .section ol li > ul,
.rst-content .section ol li > ol {
margin-bottom: 12px;
}

View File

@ -24,7 +24,7 @@ copyright = '2015-2020, Project Gluon'
author = 'Project Gluon'
# The short X.Y version
version = '2020.1+'
version = '2020.2+'
# The full version, including alpha/beta/rc tags
release = version
@ -89,7 +89,7 @@ html_theme = 'sphinx_rtd_theme'
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#
# html_static_path = ['_static']
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@ -101,6 +101,10 @@ html_theme = 'sphinx_rtd_theme'
#
# html_sidebars = {}
# These paths are either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = ['css/custom.css']
# -- Options for HTMLHelp output ---------------------------------------------

View File

@ -23,7 +23,7 @@ GLUON_SITE_FEED
List of site feeds; defined in file *modules* in site config
\*_REPO, \*_BRANCH, \*_COMMIT
Git repository URL, branch and and
Git repository URL, branch and
commit ID of the feeds to use. The branch name may be omitted; the default
branch will be used in this case.
@ -79,7 +79,7 @@ patch.sh
- updating all git submodules
This solution with a temporary clone ensures that the timestamps of checked
out files are not changed by any intermedidate patch steps, but only when
out files are not changed by any intermediate patch steps, but only when
updating the checkout with the final result. This avoids triggering unnecessary
rebuilds.

View File

@ -7,7 +7,7 @@ Debugging
Kernel Oops
-----------
Sometimes a running Linux kernel detects an error during runtime that canot
Sometimes a running Linux kernel detects an error during runtime that can't
be corrected.
This usually generates a stack trace that points to the location in the code
that caused the oops.

View File

@ -71,44 +71,62 @@ Feature flags
=============
Feature flags provide a convenient way to define package selections without
making it necessary to list each package explicitly.
making it necessary to list each package explicitly. The list of features to
enable for a Gluon build is set by the *GLUON_FEATURES* variable in *site.mk*.
The main feature flag definition file is ``package/features``, but each package
feed can provide additional definitions in a file called ``features`` at the root
of the feed repository.
Each flag *$flag* without any explicit definition will simply include the package
with the name *gluon-$flag* by default. The feature definition file can modify
the package selection in two ways:
Each flag *$flag* will include the package the name *gluon-$flag* by default.
The feature definition file can modify the package selection by adding or removing
packages when certain combinations of flags are set.
* The *nodefault* function suppresses default of including the *gluon-$flag*
package
* The *packages* function adds a list of packages (or removes, when package
names are prepended with minus signs) when a given logical expression
is satisfied
Feature definitions use Lua syntax. Two basic functions are defined:
* *feature(name, pkgs)*: Defines a new feature. *feature()* expects a feature
(flag) name and a list of packages to add or remove when the feature is
enabled.
* Defining a feature using *feature* replaces the default definition of
just including *gluon-$flag*.
* A package is removed when the package name is prefixed with a ``-`` (after
the opening quotation mark).
* *when(expr, pkgs)*: Adds or removes packages when a given logical expression
of feature flags is satisfied.
* *expr* is a logical expression composed of feature flag names (each prefixed
with an underscore before the opening quotation mark), logical operators
(*and*, *or*, *not*) and parentheses.
* Referencing a feature flag in *expr* has no effect on the default handling
of the flag. When no *feature()* entry for a flag exists, it will still
add *gluon-$flag* by default.
* *pkgs* is handled as for *feature()*.
Example::
nodefault 'web-wizard'
feature('web-wizard', {
'gluon-config-mode-hostname',
'gluon-config-mode-geo-location',
'gluon-config-mode-contact-info',
'gluon-config-mode-outdoor',
})
packages 'web-wizard' \
'gluon-config-mode-hostname' \
'gluon-config-mode-geo-location' \
'gluon-config-mode-contact-info'
when(_'web-wizard' and (_'mesh-vpn-fastd' or _'mesh-vpn-tunneldigger'), {
'gluon-config-mode-mesh-vpn',
})
feature('no-radvd', {
'-gluon-radvd',
})
packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \
'gluon-config-mode-mesh-vpn'
This will
* disable the inclusion of a (non-existent) package called *gluon-web-wizard*
* enable three config mode packages when the *web-wizard* feature is enabled
* disable the inclusion of the (non-existent) packages *gluon-web-wizard* and *gluon-no-radvd* when their
corresponding feature flags appear in *GLUON_FEATURES*
* enable four additional config mode packages when the *web-wizard* feature is enabled
* enable *gluon-config-mode-mesh-vpn* when both *web-wizard* and one
of *mesh-vpn-fastd* and *mesh-vpn-tunneldigger* are enabled
Supported syntax elements of logical expressions are:
* \& (and)
* \| (or)
* \! (not)
* parentheses
* disable the *gluon-radvd* package when *gluon-no-radvd* is enabled

View File

@ -13,7 +13,7 @@ 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.
Devices, which feature a "hybrid" port (labelled as WAN/LAN), this port is used as WAN.
This behavior can be reversed using the ``single_as_lan`` site.conf option.

View File

@ -7,8 +7,11 @@ Building Images
---------------
By default, the autoupdater is disabled (as it is usually not helpful to have unexpected updates
during development), but it can be enabled by setting the variable GLUON_BRANCH when building
to override the default branch set in the site configuration.
during development), but it can be enabled by setting the variable ``GLUON_AUTOUPDATER_ENABLED`` to ``1`` when building.
It is also possible to override the default branch during build using the variable ``GLUON_AUTOUPDATER_BRANCH``.
If a default branch is set neither in *site.conf* nor via ``GLUON_AUTOUPDATER_BRANCH``, the default branch is
implementation-defined. Currently, the branch with the first name in alphabetical order is chosen.
A manifest file for the updater can be generated with `make manifest`. A signing script (using
``ecdsautils``) can be found in the `contrib` directory. When creating the manifest, the
@ -32,15 +35,16 @@ Automated nightly builds
A fully automated nightly build could use the following commands:
::
.. code-block:: sh
git pull
(git -C site pull)
# git -C site pull
make update
make clean GLUON_TARGET=ar71xx-generic
NUM_CORES_PLUS_ONE=$(expr $(nproc) + 1)
make -j$NUM_CORES_PLUS_ONE GLUON_TARGET=ar71xx-generic GLUON_BRANCH=experimental GLUON_RELEASE=$GLUON_RELEASE
make manifest GLUON_BRANCH=experimental GLUON_RELEASE=$GLUON_RELEASE
make -j$NUM_CORES_PLUS_ONE GLUON_TARGET=ar71xx-generic GLUON_RELEASE=$GLUON_RELEASE \
GLUON_AUTOUPDATER_BRANCH=experimental GLUON_AUTOUPDATER_ENABLED=1
make manifest GLUON_RELEASE=$GLUON_RELEASE GLUON_AUTOUPDATER_BRANCH=experimental
contrib/sign.sh $SECRETKEY output/images/sysupgrade/experimental.manifest
rm -rf /where/to/put/this/experimental

View File

@ -88,18 +88,25 @@ domain of a router, if and only if one of the above conditions matches.
Switching the domain
--------------------
**via commandline**:
Via commandline
^^^^^^^^^^^^^^^
::
uci set gluon.core.domain="newdomaincode"
gluon-reconfigure
reboot
gluon-switch-domain 'newdomaincode'
**via config mode:**
When the node is not in config mode, ``gluon-switch-domain`` will automatically
reboot the node by default. This can be suppressed by passing ``--no-reboot``::
To allow switching the domain via config mode, ``config-mode-domain-select``
has to be added to GLUON_FEATURES in the site.mk.
gluon-switch-domain --no-reboot 'newdomaincode'
Switching the domain without reboot is currently **experimental**.
Via config mode
^^^^^^^^^^^^^^^
To allow switching the domain via config mode, add ``config-mode-domain-select``
to GLUON_FEATURES in site.mk.
|image0|

View File

@ -47,7 +47,7 @@ The resulting firmware will allow users to choose between secure (encrypted) and
.. image:: fastd_mode.gif
**Unix socket:**
To confirm whether the correct cipher is being used, fastds unix
To confirm whether the correct cipher is being used, fastd's unix
socket can be interrogated, after installing for example `socat`.
::

View File

@ -21,4 +21,6 @@ you can configure this via the uci section ``gluon-core.wireless``::
uci set gluon-core.@wireless[0].preserve_channels='1'
When channels should be preserved, toggling the outdoor mode will have no effect on the channel settings.
Therefore, the Outdoor mode settings won't be displayed in config mode.
Keep in mind that nodes running wifi interfaces on custom channels can't mesh with default nodes anymore!

View File

@ -78,6 +78,9 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre
:caption: Releases
:maxdepth: 1
releases/v2020.2.1
releases/v2020.2
releases/v2020.1.4
releases/v2020.1.3
releases/v2020.1.2
releases/v2020.1.1

View File

@ -66,7 +66,7 @@ and others which contain shapes.
* **default domain**
The default domain doesnt hold any shapes and represents the inverted area of
The default domain doesn't hold any shapes and represents the inverted area of
all other shapes held by other domains with geo coordinates. It will only be
entered if a node could not be matched to a geo domain. A suggested approach is
to define the "old" network as default domain and gradually migrate nodes from

View File

@ -19,7 +19,7 @@ ar71xx-generic
- DIR-615 (C1)
* GL-Inet
* GL.iNet
- 6408A (v1)
- 6416A (v1)

View File

@ -21,7 +21,7 @@ ramips-mt7620
ramips-mt76x8
^^^^^^^^^^^^^
* Gl.iNet
* GL.iNet
- MT300N (v2) [#noibss]_

View File

@ -10,7 +10,7 @@ Bugfixes
- Fixed non-working LEDs on TP-Link Archer C5 v1 and Archer C7 v2 after an upgrade to Gluon 2020.1.
- Fixed an issue which leads to AVM FRITZ!WLAN Repeater 450E devices being stuck in failsafe mode
ater an upgrade to Gluon 2020.1.
after an upgrade to Gluon 2020.1.
Other changes
-------------

View File

@ -37,7 +37,7 @@ Other changes
Internals
---------
- OpenWrt 19.07 introduced the urgnd entropy daemon that serves the same function as the haveged service, which we have been recommending. To not have two redundant entropy daemons in this release we remove urngd in favor of haveged in the v2020.1 release series.
- OpenWrt 19.07 introduced the urngd entropy daemon that serves the same function as the haveged service, which we have been recommending. To not have two redundant entropy daemons in this release we remove urngd in favor of haveged in the v2020.1 release series.
Known issues
------------

View File

@ -0,0 +1,47 @@
Gluon 2020.1.4
==============
Added hardware support
----------------------
- Added support for TP-Link CPE210 3.20 (`#2080 <https://github.com/freifunk-gluon/gluon/issues/2080>`_)
Bugfixes
--------
- Fixed a rare race-condition during mesh interface teardown (`#2057 <https://github.com/freifunk-gluon/gluon/pull/2057>`_)
- Fixed handling of mesh interfaces together with outdoor mode, site.conf defaults and config mode (`#2049 <https://github.com/freifunk-gluon/gluon/pull/2049>`_) (`#2054 <https://github.com/freifunk-gluon/gluon/pull/2054>`_)
Other changes
-------------
- Linux kernel has been updated to 4.14.193
- Backports of batman-adv bugfixes
Known issues
------------
* Upgrading EdgeRouter-X from versions before v2020.1.x may lead to a soft-bricked state due to bad blocks on the
NAND flash which the NAND driver before this release does not handle well.
(`#1937 <https://github.com/freifunk-gluon/gluon/issues/1937>`_)
* 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).

View File

@ -0,0 +1,47 @@
Gluon 2020.2.1
==============
Added hardware support
----------------------
- Added support for TP-Link CPE210 3.20 (`#2080 <https://github.com/freifunk-gluon/gluon/issues/2080>`_)
Bugfixes
--------
- Fixed handling of *mesh_on_lan* enabled in site configuration (`#2090 <https://github.com/freifunk-gluon/gluon/issues/2090>`_)
- Fixed build issues with lantiq-xrx200 target by removing unsupported DSL modem packages (`#2087 <https://github.com/freifunk-gluon/gluon/pull/2087>`_)
Other changes
-------------
- Linux kernel has been updated to 4.14.193
- Backports of batman-adv bugfixes
Known issues
------------
* Upgrading EdgeRouter-X from versions before v2020.1.x may lead to a soft-bricked state due to bad blocks on the
NAND flash which the NAND driver before this release does not handle well.
(`#1937 <https://github.com/freifunk-gluon/gluon/issues/1937>`_)
* 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.
* In configurations not using VXLAN, 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).

198
docs/releases/v2020.2.rst Normal file
View File

@ -0,0 +1,198 @@
Gluon 2020.2
============
Added hardware support
----------------------
ath79-generic
~~~~~~~~~~~~~
* GL.iNet
- GL-AR750S
* TP-Link
- CPE220 (v3)
ipq40xx-generic
~~~~~~~~~~~~~~~
* EnGenius
- ENS620EXT [#outdoor]_
* Linksys
- EA6350 (v3)
lantiq-xrx200
~~~~~~~~~~~~~
* TP-Link
- TD-W8970
lantiq-xway
~~~~~~~~~~~
* NETGEAR
- DGN3500B
ramips-mt76x8
~~~~~~~~~~~~~
* Cudy
- WR1000
x86-legacy [#newtarget]_
~~~~~~~~~~~~~~~~~~~~~~~~
* Devices older than the Pentium 4
.. [#newtarget]
This is a new target.
.. [#outdoor]
This device is supposed to be set up outdoors and will therefore have its outdoor mode flag automatically enabled.
Major changes
-------------
Device Classes
~~~~~~~~~~~~~~
Devices are now categorized into device classes. This device class can determine which features
as well as packages are installed on the device when building images.
Currently there are two classes used in Gluon, *tiny* and *standard*. All devices with less than 64M of RAM or
less than 7M of usable firmware space are assigned to the tiny class.
WPA3 support for Private WLAN
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The private WLAN now supports WPA3-SAE key exchange as well as management frame protection (802.11w).
For this to work, the firmware needs to be built with the *wireless-encryption-wpa3* feature.
OWE on Client Network
~~~~~~~~~~~~~~~~~~~~~
Gluon now allows to configure a VAP for the client network which supports opportunistic encryption on the
client network for devices which support the OWE security type (also known as Enhanced Open).
This encrypted VAP can be the only available access point or be configured in addition to an unencrypted VAP.
In the latter case, the transition mode can be enabled, which enables compatible devices to automatically
connect to the encrypted VAP while legacy devices continue to use the unencrypted connection.
There are issues with some devices running Android 9 when connecting to a transition mode enabled network. See the site documentation for more information.
SAE Encrypted Mesh Links
~~~~~~~~~~~~~~~~~~~~~~~~
Mesh links can now be operated in an encrypted mode using SAE authentication. For this to work, a common shared secret
has to be distributed to all participating nodes using the site.conf.
Responsive status page
~~~~~~~~~~~~~~~~~~~~~~
The status page design is now responsive and reflows better on mobile devices.
Primary domain code
~~~~~~~~~~~~~~~~~~~
The primary domain code is now visible on the node status page as well as in the respondd information
emitted by the node.
Logging
~~~~~~~
The new *gluon-logging* package allows to configure a remote syslog server using the site.conf.
This package can only be included when *gluon-web-logging* is excluded.
Peer cleanup in fastd
~~~~~~~~~~~~~~~~~~~~~
fastd peers and groups are now removed on update in case they do not exist in the new site configuration.
To preserve a custom peer across updates, add the *preserve* key to the peer's UCI configuration and set it to ``1``.
Bugfixes
--------
- The WAN MAC address now matches the one defined in OpenWrt if VXLAN is enabled for the selected domain.
- *gluon-reload* now reloads all relevant services.
- Disabling outdoor mode and enabling meshing in the config mode can now be performed in a single step.
- Fixed section visibility with enabled outdoor mode in config mode.
Site changes
------------
site.mk
~~~~~~~
Starting with version 19.07 OpenWrt ships the urngd entropy daemon by default.
It replaces the haveged daemon, for which we removed the support in Gluon. Remove ``haveged`` from your package selection.
Internal
--------
Editorconfig
~~~~~~~~~~~~
Gluon now ships a *editorconfig* file to allow compatible editors to automatically apply key aspects of Gluon's code style.
Continuous Integration
~~~~~~~~~~~~~~~~~~~~~~
* Jenkins
- The CI now has a test stage to verify Gluons runtime functionality.
* GitHub Actions
- GitHub actions is now enabled for the Gluon project, build-testing all available targets.
Build system
~~~~~~~~~~~~
- Source code minification can now be skipped by enabling the GLUON_MINIFY flag.
- Enabling the GLUON_AUTOREMOVE flag will remove package build directories after they are built.
This reduces space consumption at the expense of subsequent builds being slower.
Known issues
------------
* Upgrading EdgeRouter-X from versions before v2020.1.x may lead to a soft-bricked state due to bad blocks on the
NAND flash which the NAND driver before this release does not handle well.
(`#1937 <https://github.com/freifunk-gluon/gluon/issues/1937>`_)
* 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.
* In configurations not using VXLAN, 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).

View File

@ -1,4 +1,4 @@
-- This is an example site configuration for Gluon v2020.1.3
-- This is an example site configuration for Gluon v2020.2.1
--
-- Take a look at the documentation located at
-- https://gluon.readthedocs.io/ for details.
@ -164,7 +164,8 @@
},
autoupdater = {
-- Default branch. Don't forget to set GLUON_BRANCH when building!
-- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
-- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
branch = 'stable',
-- List of branches. You may define multiple branches.

View File

@ -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. *v2020.1.3*. Always get Gluon using git and don't try to download it
e.g. *v2020.2.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. *v2020.1.3*.
version you'd like to checkout, e.g. *v2020.2.1*.
::
@ -171,10 +171,12 @@ usually be set on the command line or in ``site.mk``.
Common variables
................
GLUON_BRANCH
Sets the default branch of the autoupdater. If unset, the autoupdater is disabled
by default. For the ``make manifest`` command, GLUON_BRANCH defines the branch to
generate a manifest for.
GLUON_AUTOUPDATER_BRANCH
Overrides the default branch of the autoupdater set in ``site.conf``. For the ``make manifest`` command,
``GLUON_AUTOUPDATER_BRANCH`` defines the branch to generate a manifest for.
GLUON_AUTOUPDATER_ENABLED
Set to ``1`` to enable the autoupdater by default for newly installed nodes.
GLUON_DEPRECATED
Controls whether images for deprecated devices should be built. The following
@ -225,7 +227,7 @@ GLUON_DEBUG
similar tools. Requires a device or target with at least 16 MB of flash space, e.g. `x86-64`. Unset by default.
GLUON_MINIFY
Setting ``GLUON_MINIFY=0`` will omit the minification of scripts during the build process. By
Setting ``GLUON_MINIFY=0`` will omit the minification of scripts during the build process. By
default the flag is set to ``1``. Disabling the flag is handy if human readable scripts on the
devices are desired for development purposes. Be aware that this will increase the size of the
resulting images and is therefore not suitable for devices with small flash chips.

View File

@ -176,7 +176,7 @@ wifi24 \: optional
.. _user-site-wifi5:
wifi5 \: optional
Same as `wifi24` but for the 5Ghz radio.
Same as `wifi24` but for the 5 GHz radio.
Additionally a range of channels that are safe to use outsides on the 5 GHz band can
be set up through ``outdoor_chanlist``, which allows for a space-separated list of
@ -326,7 +326,7 @@ mesh_vpn
implementation.
**Note:** It may be interesting to include the package *gluon-iptables-clamp-mss-to-pmtu*
in the build when using *gluon-mesh-babel* to work around icmp blackholes on the internet.
in the build when using *gluon-mesh-babel* to work around ICMP blackholes on the internet.
::
@ -418,12 +418,16 @@ poe_passthrough \: optional
autoupdater \: package
Configuration for the autoupdater feature of Gluon.
Specifying a default branch in *site.conf* is optional. See
:doc:`../features/autoupdater` for information how to change the behaviour
of the autoupdater during image build.
The mirrors are checked in random order until the manifest could be downloaded
successfully or all mirrors have been tried.
::
autoupdater = {
branch = 'stable',
branch = 'stable', -- optional
branches = {
stable = {
name = 'stable',
@ -464,9 +468,14 @@ config_mode \: optional
The *geo_location.osm* section is only relevant when the *gluon-config-mode-geo-location-osm*
package is used. The *center.lon* and *center.lat* values are mandatory in this case and
define the default center of the map when no position has been picked yet. The *zoom* level
defaults to 12 in this case. *openlayers_url* allows to override the base URL of the
defaults to 12 in this case.
*openlayers_url* allows to override the base URL of the
*build/ol.js* and *css/ol.css* files (the default is
``https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0``).
It is also possible to replace the default tile layer (which is OpenStreetMap)
with a custom one using the *tile_layer* section. Only XYZ layers are supported
at this point.
The remote login page only shows SSH key configuration by default. A
password form can be displayed by setting *remote_login.show_password_form*
@ -488,6 +497,11 @@ config_mode \: optional
},
zoom = 13,
-- openlayers_url = 'http://ffac.example.org/openlayer',
-- tile_layer = {
-- type = 'XYZ',
-- url = 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
-- attributions = '&#169; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors.',
-- },
},
},
remote_login = {

View File

@ -44,6 +44,7 @@ ar71xx-generic
- GL-AR150
- GL-AR300M
- GL-AR750
- GL-USB150 (Microuter)
* Linksys
@ -107,9 +108,9 @@ ar71xx-generic
- Nanostation M2/M5 [#device-class-tiny]_
- Nanostation M2/M5 XW
- Picostation M2 [#device-class-tiny]_
- Rocket M2/M5
- Rocket M2/M5 Ti
- Rocket M2/M5 XW
- Rocket M2
- Rocket M2 Ti
- Rocket M2 XW
- UniFi AC Mesh
- UniFi AC Mesh Pro
- UniFi AP
@ -229,6 +230,7 @@ ipq40xx-generic
* AVM
- FRITZ!Box 4040 [#avmflash]_
- FRITZ!Box 7530 [#eva_ramboot]_
- FRITZ!Repeater 1200 [#eva_ramboot]_
* EnGenius
@ -317,6 +319,11 @@ ramips-mt7620
- GL-MT300N
- GL-MT750
* NETGEAR
- EX3700
- EX3800
* Nexx
- WT3020AD/F/H

View File

@ -2,15 +2,15 @@ GLUON_FEEDS='packages routing gluon'
OPENWRT_REPO=https://github.com/openwrt/openwrt.git
OPENWRT_BRANCH=openwrt-19.07
OPENWRT_COMMIT=9cafcbe0bdd601d07ed55bee0136f5d8393c37a8
OPENWRT_COMMIT=29b4104d69bf91db17764dd885e9e111a373f08c
PACKAGES_PACKAGES_REPO=https://github.com/openwrt/packages.git
PACKAGES_PACKAGES_BRANCH=openwrt-19.07
PACKAGES_PACKAGES_COMMIT=e76090945523c71c2406276f6d42b2e7f078a2d8
PACKAGES_PACKAGES_COMMIT=03425a0d2f5967639d15a3ef1f0407859768917d
PACKAGES_ROUTING_REPO=https://github.com/openwrt-routing/packages.git
PACKAGES_ROUTING_BRANCH=openwrt-19.07
PACKAGES_ROUTING_COMMIT=9b42e24a54f03ebb6f58224b49036e8f739b175f
PACKAGES_ROUTING_COMMIT=b77498bd56d5e45ab4577a1f4ad6ffc55b4a86b7
PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git
PACKAGES_GLUON_COMMIT=12e41d0ff07ec54bbd67a31ab50d12ca04f2238c

View File

@ -1,37 +1,52 @@
nodefault 'web-wizard'
packages 'web-wizard' \
'gluon-config-mode-hostname' \
'gluon-config-mode-geo-location' \
'gluon-config-mode-contact-info' \
'gluon-config-mode-outdoor'
packages 'web-wizard & autoupdater' \
'gluon-config-mode-autoupdater'
packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \
'gluon-config-mode-mesh-vpn'
-- GLUON_FEATURES definition file
--
-- See the page `dev/packages` (Developer Documentation / Package development)
-- in the `docs` directory or on gluon.readthedocs.io for information on the
-- file format
nodefault 'web-advanced'
feature('web-wizard', {
'gluon-config-mode-hostname',
'gluon-config-mode-geo-location',
'gluon-config-mode-contact-info',
'gluon-config-mode-outdoor',
})
packages 'web-advanced' \
'gluon-web-admin' \
'gluon-web-network' \
'gluon-web-wifi-config'
when(_'web-wizard' and _'autoupdater', {
'gluon-config-mode-autoupdater',
})
packages 'web-advanced & autoupdater' \
'gluon-web-autoupdater'
when(_'web-wizard' and (_'mesh-vpn-fastd' or _'mesh-vpn-tunneldigger'), {
'gluon-config-mode-mesh-vpn',
})
packages 'status-page & mesh-batman-adv-15' \
'gluon-status-page-mesh-batman-adv'
packages 'mesh-batman-adv-15' \
'gluon-ebtables-limit-arp' \
'gluon-radvd'
feature('web-advanced', {
'gluon-web-admin',
'gluon-web-network',
'gluon-web-wifi-config',
})
packages 'mesh-babel' \
'gluon-radvd'
when(_'web-advanced' and _'autoupdater', {
'gluon-web-autoupdater',
})
packages '!wireless-encryption-wpa3' \
'hostapd-mini'
when(_'mesh-batman-adv-15', {
'gluon-ebtables-limit-arp',
'gluon-radvd',
})
when(_'status-page' and _'mesh-batman-adv-15', {
'gluon-status-page-mesh-batman-adv',
})
when(_'mesh-babel', {
'gluon-radvd',
})
when(not _'wireless-encryption-wpa3', {
'hostapd-mini',
})

View File

@ -0,0 +1,10 @@
if PACKAGE_gluon-autoupdater
config GLUON_AUTOUPDATER_BRANCH
string "Autoupdater branch"
default ""
config GLUON_AUTOUPDATER_ENABLED
bool "Enable autoupdater by default"
endif

View File

@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-autoupdater
PKG_VERSION:=4
PKG_CONFIG_DEPENDS := CONFIG_GLUON_BRANCH
PKG_CONFIG_DEPENDS := CONFIG_GLUON_AUTOUPDATER_BRANCH CONFIG_GLUON_AUTOUPDATER_ENABLED
include ../gluon.mk
@ -13,19 +13,19 @@ define Package/gluon-autoupdater
endef
define Package/gluon-autoupdater/config
config GLUON_BRANCH
string "Gluon autoupdater branch"
depends on PACKAGE_gluon-autoupdater
default ""
source "$(SOURCE)/Config.in"
endef
define Package/gluon-autoupdater/install
$(Gluon/Build/Install)
ifneq ($(CONFIG_GLUON_BRANCH),"")
$(INSTALL_DIR) $(1)/lib/gluon/autoupdater
echo '$(call qstrip,$(CONFIG_GLUON_BRANCH))' > $(1)/lib/gluon/autoupdater/default_branch
endif
ifneq ($(CONFIG_GLUON_AUTOUPDATER_BRANCH),"")
echo '$(call qstrip,$(CONFIG_GLUON_AUTOUPDATER_BRANCH))' > $(1)/lib/gluon/autoupdater/default_branch
endif
ifneq ($(CONFIG_GLUON_AUTOUPDATER_ENABLED),)
touch $(1)/lib/gluon/autoupdater/default_enabled
endif
endef
$(eval $(call BuildPackageGluon,gluon-autoupdater))

View File

@ -1,4 +1,4 @@
need_string(in_site({'autoupdater', 'branch'}))
need_string(in_site({'autoupdater', 'branch'}), false)
need_table({'autoupdater', 'branches'}, function(branch)
need_alphanumeric_key(branch)

View File

@ -2,8 +2,11 @@
local site = require 'gluon.site'
local uci = require('simple-uci').cursor()
local unistd = require 'posix.unistd'
local min_branch
for name, config in pairs(site.autoupdater.branches()) do
uci:delete('autoupdater', name)
uci:section('autoupdater', 'branch', name, {
@ -12,19 +15,26 @@ for name, config in pairs(site.autoupdater.branches()) do
good_signatures = config.good_signatures,
pubkey = config.pubkeys,
})
if not min_branch or (name < min_branch) then
min_branch = name
end
end
if not uci:get('autoupdater', 'settings') then
local enabled = false
local branch = site.autoupdater.branch()
local enabled = unistd.access('/lib/gluon/autoupdater/default_enabled') ~= nil
local branch = site.autoupdater.branch(min_branch)
local f = io.open('/lib/gluon/autoupdater/default_branch')
if f then
enabled = true
branch = f:read('*line')
f:close()
end
if not branch then
enabled = false
end
uci:section('autoupdater', 'autoupdater', 'settings', {
enabled = enabled,
branch = branch,

View File

@ -40,9 +40,6 @@ uci:section('network', 'interface', 'client', {
uci:save('network')
-- TODO: remove this line and the next in 2019. Firewall zones have been renamed in 2017.
uci:delete('firewall', 'client')
uci:section('firewall', 'zone', 'drop', {
name = 'drop',
network = {'client'},
@ -51,9 +48,9 @@ uci:section('firewall', 'zone', 'drop', {
forward = 'DROP',
})
local networks = uci:get_list('firewall', 'local_client', 'network')
local networks = uci:get_list('firewall', 'loc_client', 'network')
util.add_to_set(networks, 'local_node')
uci:set_list('firewall', 'local_client', 'network', networks)
uci:set_list('firewall', 'loc_client', 'network', networks)
local dnsmasq = uci:get_first('dhcp', 'dnsmasq')
@ -61,10 +58,6 @@ uci:set('dhcp', dnsmasq, 'boguspriv', false)
uci:set('dhcp', dnsmasq, 'localise_queries', false)
uci:set('dhcp', dnsmasq, 'rebind_protection', false)
-- TODO: remove this line and the next two in 2019 the zones were removed in 2017
uci:delete('dhcp', 'client')
uci:delete('firewall', 'local_node')
uci:section('dhcp', 'dhcp', 'local_client', {
interface = 'client',
ignore = true,

View File

@ -2,3 +2,9 @@ need_number(in_site({'config_mode', 'geo_location', 'osm', 'center', 'lon'}))
need_number(in_site({'config_mode', 'geo_location', 'osm', 'center', 'lat'}))
need_number(in_site({'config_mode', 'geo_location', 'osm', 'zoom'}), false)
need_string(in_site({'config_mode', 'geo_location', 'osm', 'openlayers_url'}), false)
if need_table(in_site({'config_mode', 'geo_location', 'osm', 'tile_layer'}), nil, false) then
need_one_of(in_site({'config_mode', 'geo_location', 'osm', 'tile_layer', 'type'}), {'XYZ'})
need_string(in_site({'config_mode', 'geo_location', 'osm', 'tile_layer', 'url'}))
need_string(in_site({'config_mode', 'geo_location', 'osm', 'tile_layer', 'attributions'}))
end

View File

@ -19,6 +19,7 @@ function M.options()
return {
openlayers_url = config.openlayers_url(),
tile_layer = config.tile_layer(),
zoom = config.zoom(12),
pos = config.center(),
}

View File

@ -1,11 +1,17 @@
return function(form, uci)
local platform = require 'gluon.platform'
local wireless = require 'gluon.wireless'
if not (platform.is_outdoor_device() and platform.device_uses_11a(uci)) then
-- only visible on wizard for outdoor devices
return
end
if wireless.preserve_channels(uci) then
-- Don't show if channel should be preserved
return
end
local pkg_i18n = i18n 'gluon-config-mode-outdoor'
local section = form:section(Section, nil, pkg_i18n.translate(

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,13 @@
/*
ATTENTION: This file is not compiled when building gluon.
The compiled version is at ../files/lib/gluon/config-mode/www/static/gluon.css
ATTENTION: This file is not compiled when building gluon.
The compiled version is at ../files/lib/gluon/config-mode/www/static/gluon.css
Use sass like this to update it:
Use sass like this to update it:
sass --sourcemap=none -C -t compressed sass/gluon.scss files/lib/gluon/config-mode/www/static/gluon.css
sass --sourcemap=none -C -t compressed sass/gluon.scss files/lib/gluon/config-mode/www/static/gluon.css
When commiting changes to this file make sure to commit the respective
changes to the compilid version within the same commit!
When commiting changes to this file make sure to commit the respective
changes to the compilid version within the same commit!
*/
@charset "utf-8";
@ -18,624 +18,530 @@ $ffzusatz: #009ee0;
$red: #ee3300;
@mixin button {
&::-moz-focus-inner {
padding: 0;
border: 0;
}
&::-moz-focus-inner {
padding: 0;
border: 0;
}
display: inline-block;
zoom: 1;
line-height: normal;
white-space: nowrap;
vertical-align: baseline;
text-align: center;
cursor: pointer;
user-select: none;
display: inline-block;
line-height: normal;
white-space: nowrap;
vertical-align: baseline;
text-align: center;
cursor: pointer;
user-select: none;
font-size: 100%;
padding: 0.5em 1em;
color: rgba(0, 0, 0, 0.80);
border: none rgba(0, 0, 0, 0);
background-color: #E6E6E6;
text-decoration: none;
border-radius: 2px;
font-size: 100%;
padding: 0.5em 1em;
color: rgba(0, 0, 0, 0.80);
background-color: #E6E6E6;
border: none;
text-decoration: none;
border-radius: 2px;
/* Transitions */
transition: 0.1s linear box-shadow;
/* Transitions */
transition: 0.1s linear box-shadow;
&:active {
box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
}
&:active {
box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
}
&:focus {
outline: 0;
}
&:focus {
outline: 0;
}
&:hover, &:focus {
background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
}
&:hover, &:focus {
background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
}
&[disabled] {
border: none;
background-image: none;
opacity: 0.40;
cursor: not-allowed;
box-shadow: none;
}
}
@mixin button-primary {
background-color: $ffzusatz;
color: #fff;
}
.lang_he {
direction: RTL;
unicode-bidi: embed;
}
.hidden {
display: none;
&[disabled] {
border: none;
background-image: none;
opacity: 0.40;
cursor: not-allowed;
box-shadow: none;
}
}
html {
min-height: 100%;
height: auto;
position:relative;
min-height: 100%;
height: auto;
position: relative;
}
body, input, select, option {
font-family: 'Open Sans', Arial, sans-serif;
font-size: 12pt;
font-family: 'Open Sans', Arial, sans-serif;
font-size: 12pt;
}
body {
color: rgb(77, 78, 83);
line-height: 1.5em;
margin: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #f3f3f3;
}
a img {
border: none;
text-decoration: none;
color: rgb(77, 78, 83);
line-height: 1.5em;
margin: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #f3f3f3;
}
.tabmenu1 {
text-align: center;
text-align: center;
}
ul.tabmenu {
list-style: none;
padding: 0;
margin: 2em 0;
display: inline-flex;
list-style: none;
padding: 0;
margin: 2em 0;
display: inline-flex;
}
ul.tabmenu li {
white-space: nowrap;
margin: 0 0.5em;
padding: 0;
text-align: center;
white-space: nowrap;
margin: 0 0.5em;
padding: 0;
text-align: center;
a {
display: block;
text-decoration: none;
padding: 1em;
margin: 0;
color: #333;
border-radius: 2em;
a {
display: block;
text-decoration: none;
padding: 1em;
margin: 0;
color: #333;
border-radius: 2em;
&:hover {
background: lighten($ffyellow, 35);
}
}
&:hover {
background: lighten($ffyellow, 35);
}
}
&.active a {
font-weight: bold;
background: white;
color: #333;
}
}
abbr,
acronym {
font-style: normal;
font-variant: normal;
}
abbr[title],
acronym[title] {
border-bottom: 1px dotted;
cursor: help;
}
a:link abbr[title],
a:visited abbr[title],
a:link acronym[title],
a:visited acronym[title] {
cursor: pointer;
}
code {
font-family: monospace;
white-space: pre;
&.active a {
font-weight: bold;
background: white;
color: #333;
}
}
#maincontent ul {
margin-left: 2em;
}
.clear {
clear: both;
margin-left: 2em;
}
.error {
color: #ff0000;
background-color: white;
color: #ff0000;
background-color: white;
}
#menubar {
display: flex;
background: $ffmagenta;
color: #ffffff;
display: flex;
background: $ffmagenta;
color: #ffffff;
}
#menubar a:link.topcat,
#menubar a:visited.topcat {
position: relative;
display: block;
padding: 0.5em;
text-decoration: none;
font-size: 80%;
font-weight: normal;
color: white;
position: relative;
display: block;
padding: 0.5em;
text-decoration: none;
font-size: 80%;
font-weight: normal;
color: white;
&:hover, &:focus {
background: $ffyellow;
color: black;
}
&:hover, &:focus {
background: $ffyellow;
color: black;
}
&.active {
background: $ffyellow;
color: black;
font-weight: bold;
}
&.active {
background: $ffyellow;
color: black;
font-weight: bold;
}
}
#menubar div.hostinfo {
position: relative;
margin: 0;
padding: 0.5em;
flex: 1;
font-weight: bold;
font-size: 80%;
#menubar .hostinfo {
position: relative;
margin: 0;
padding: 0.5em;
flex: 1;
font-weight: bold;
font-size: 80%;
}
#menubar div.hostinfo a {
&:link, &:visited {
text-decoration: none;
font-weight: bold;
color: white;
#menubar .hostinfo a {
&:link, &:visited {
text-decoration: none;
font-weight: bold;
color: white;
&:hover, &:focus {
text-decoration: underline;
}
}
&:hover, &:focus {
text-decoration: underline;
}
}
}
#topmenu {
list-style: none;
margin: 0;
padding: 0;
list-style: none;
margin: 0;
padding: 0;
}
#topmenu li {
display: inline-block;
display: inline-block;
}
#maincontent {
padding: 0 1em 2em;
max-width: 60em;
min-width: 40em;
margin: 1em auto;
padding: 0 1em 2em;
max-width: 60em;
min-width: 40em;
margin: 1em auto;
}
#maincontent p {
margin-bottom: 1em;
margin-bottom: 1em;
}
.gluon-section {
margin: 0;
padding: 0;
border: none;
margin-bottom: 1.3em;
margin: 0;
padding: 0;
border: none;
margin-bottom: 1.3em;
}
.gluon-section:last-child {
margin-bottom: 0.7em;
margin-bottom: 0.7em;
}
.gluon-section legend {
font-size: 1.4em;
font-weight: bold;
position: relative;
padding: 0;
margin-bottom: 0.5em;
font-size: 1.4em;
font-weight: bold;
position: relative;
padding: 0;
margin-bottom: 0.5em;
}
.gluon-section h2 {
margin: 0em 0 0.5em -0.5em !important;
margin: 0em 0 0.5em -0.5em;
}
.gluon-section h3 {
text-decoration: none !important;
font-weight: bold !important;
color: #555555 !important;
margin: 0.25em !important;
font-size: 100% !important;
text-decoration: none;
font-weight: bold;
color: #555555;
margin: 0.25em;
font-size: 100%;
}
.gluon-section-descr {
margin-bottom: 2em;
margin-bottom: 2em;
}
.gluon-osm-map {
width: 100%;
height: 40em;
margin-bottom: 1em;
width: 100%;
height: 40em;
margin-bottom: 1em;
}
input:placeholder {
color: #aaaaaa;
input::placeholder {
color: #aaaaaa;
}
input:-webkit-input-placeholder {
color: #aaaaaa;
}
input:-moz-placeholder {
color: #aaaaaa;
}
input:-ms-input-placeholder {
color: #aaaaaa;
input::-webkit-input-placeholder {
color: #aaaaaa;
}
input[type=checkbox] {
display: none;
display: none;
& + label {
display: inline-block;
position: relative;
width: 1em;
height: 1em;
margin: 0;
}
& + label {
display: inline-block;
position: relative;
width: 1em;
height: 1em;
margin: 0;
}
&:checked + label:after {
content: '';
color: $ffmagenta;
vertical-align: middle;
position: absolute;
top: 50%;
left: 0;
margin-top: -0.5em;
width: 100%;
text-align: center;
font-size: 1.7em;
}
&:checked + label::after {
content: '';
color: $ffmagenta;
vertical-align: middle;
position: absolute;
top: 50%;
left: 0;
margin-top: -0.5em;
width: 100%;
text-align: center;
font-size: 1.7em;
}
}
input[type=radio] {
display: none;
display: none;
& + label {
display: inline-block;
position: relative;
width: 0.8em;
height: 0.8em;
padding: 0.5em;
margin: 0.2em 0.2em 0.2em 0.1em;
border: none;
background: lighten($ffyellow, 30);
vertical-align: middle;
border-radius: 50%;
}
& + label {
display: inline-block;
position: relative;
width: 0.8em;
height: 0.8em;
padding: 0.5em;
margin: 0.2em 0.2em 0.2em 0.1em;
border: none;
background: lighten($ffyellow, 30);
vertical-align: middle;
border-radius: 50%;
}
&:checked + label:after {
content: '';
color: $ffmagenta;
vertical-align: middle;
position: absolute;
top: 50%;
left: 0;
margin-top: -0.4em;
width: 100%;
text-align: center;
font-size: 2em;
}
&:checked + label::after {
content: '';
color: $ffmagenta;
vertical-align: middle;
position: absolute;
top: 50%;
left: 0;
margin-top: -0.4em;
width: 100%;
text-align: center;
font-size: 2em;
}
}
input[type=submit],
input[type=reset],
input[type=image],
input[type=button] {
cursor: pointer;
cursor: pointer;
}
select,
input,
textarea,
input[type=checkbox] + label {
color: darken($ffzusatz, 30);
border: none;
background: lighten($ffyellow, 30);
border-radius: 3pt;
padding: 0.5em;
margin-top: 1px;
margin-bottom: 2px;
box-sizing: content-box;
outline: 0;
color: darken($ffzusatz, 30);
border: none;
background: lighten($ffyellow, 30);
border-radius: 3pt;
padding: 0.5em;
margin-top: 1px;
margin-bottom: 2px;
box-sizing: content-box;
outline: 0;
}
.select-wrapper {
position: relative;
display: inline-block;
&::before {
position: absolute;
z-index: 1;
right: 0.05em;
top: calc(2px + 0.1em);
bottom: calc(2px + 0.1em);
width: 1.4em;
border-left: 0.05em solid rgba(0, 0, 0, 0.25);
pointer-events: none;
background:
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="8" height="5"><path fill="none" stroke="black" stroke-linejoin="bevel" d="M1,1L4,4L7,1"/></svg>')
center / 0.8em 0.5em
no-repeat
;
content: '';
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
cursor: pointer;
}
}
option {
color: darken($ffzusatz, 30);
background: lighten($ffyellow, 30);
}
input[type=image] {
border: none;
color: darken($ffzusatz, 30);
background: lighten($ffyellow, 30);
}
select,
input[type=text],
input[type=password] {
min-width: 20em;
min-width: 20em;
}
input.gluon-button {
@include button;
.gluon-button {
@include button;
margin-left: 0.5em;
background-repeat: no-repeat;
margin-left: 0.5em;
background-repeat: no-repeat;
}
input.gluon-button-reset {
background-color: $red;
color: #fff;
}
input.gluon-button-submit {
@include button-primary;
.gluon-button-reset {
background-color: $red;
color: #fff;
}
input.gluon-button-submit:active {
background: grey;
.gluon-button-submit {
background-color: $ffzusatz;
color: #fff;
}
.gluon-button-submit:active {
background: grey;
}
.gluon-input-invalid {
background: $red !important;
color: white;
}
div.gluon-section-remove input {
border-bottom: none;
background: $red !important;
color: white;
}
textarea {
margin-left: -1px;
margin-bottom: 0.5em;
margin-left: -1px;
margin-bottom: 0.5em;
}
.gluon-section .gluon-rowstyle-1 h3 {
background-color: #eeeeff;
color: #555555;
}
.gluon-rowstyle-2 {
color: #000000;
}
div.gluon-value {
display: flex;
flex-direction: row;
margin-bottom: 0.5em;
.gluon-value {
display: flex;
flex-direction: row;
margin-bottom: 0.5em;
}
.gluon-section-node .gluon-value:last-child {
margin-bottom: 0;
margin-bottom: 0;
}
.gluon-value-title {
flex: 2;
text-align: right;
padding-top: 0.39em;
padding-right: 1em;
font-weight: bold;
flex: 2;
text-align: right;
padding-top: 0.39em;
padding-right: 1em;
font-weight: bold;
}
div.gluon-value-field {
flex: 3;
position: relative;
.gluon-value-field {
flex: 3;
position: relative;
input, select, input + label {
position: relative;
}
input, select, input + label {
position: relative;
}
}
div.gluon-value-field-text {
flex: 3;
padding-top: 0.39em;
.gluon-value-field-text {
flex: 3;
padding-top: 0.39em;
}
div.gluon-value-field-long {
flex: 10;
position: relative;
margin-top: 0.65em;
.gluon-value-field-long {
flex: 10;
position: relative;
margin-top: 0.65em;
input, select, input + label {
position: relative;
}
input, select, input + label {
position: relative;
}
}
div.gluon-value-field-long-after {
flex: 2;
.gluon-value-field-long-after {
flex: 2;
}
div.gluon-value-description {
font-size: 8pt;
.gluon-value-description {
font-size: 8pt;
}
div.gluon-section-create {
clear: left;
white-space: nowrap;
vertical-align: top;
}
div.gluon-section-create .gluon-button {
margin: 0.25em;
}
input.gluon-section-create-name {
margin-right: -0.25em;
}
div.gluon-form-descr {
margin-bottom: 1em;
.gluon-form-descr {
margin-bottom: 1em;
}
.gluon-form-descr:empty, .gluon-section-descr:empty {
display: none;
display: none;
}
.gluon-form-descr, .gluon-section-descr, .gluon-page-actions {
padding: 1em;
background: #ececec;
padding: 1em;
background: #ececec;
}
.gluon-page-actions {
text-align: right;
display: flex;
flex-flow: row-reverse;
}
div.gluon-optionals {
padding: 0.25em;
border-bottom: 1px dotted #bbbbbb;
}
div.gluon-section-remove {
float: right;
text-align: right;
display: flex;
flex-flow: row-reverse;
}
.gluon-section-node {
clear: both;
position: relative;
border: none;
}
.gluon-section-node-tabbed {
border-top-left-radius: 0;
}
div.gluon-error {
font-size: 95%;
font-weight: bold;
color: #ff0000;
background-color: #ffffff;
clear: both;
position: relative;
border: none;
}
.gluon-value-error input,
.gluon-value-error select {
background-color: #ffcccc;
background-color: #ffcccc;
}
.gluon-value-field var {
color: #2222FF;
}
.gluon-add:after, .gluon-remove:after {
cursor: pointer;
display: inline-block;
text-align: center;
vertical-align: middle;
font-size: 180%;
width: 1.2em;
height: 1em;
.gluon-add::after, .gluon-remove::after {
cursor: pointer;
display: inline-block;
text-align: center;
vertical-align: middle;
font-size: 180%;
width: 1.2em;
height: 1em;
}
.gluon-add {
color: #008000;
color: #008000;
position: relative;
left: 21em;
position: relative;
left: 21em;
input + & {
left: 0;
top: 0.04em;
}
input + & {
left: 0;
top: 0.04em;
}
&:first-child {
top: 0.53em;
left: -0.08em;
}
&:first-child {
top: 0.53em;
left: -0.08em;
}
&:after {
content: '+';
}
&::after {
content: '+';
}
}
.gluon-remove {
color: #800000;
color: #800000;
position: relative;
top: -0.03em;
position: relative;
top: -0.03em;
&:after {
content: '';
}
}
.left {
text-align: left !important;
}
.right {
text-align: right !important;
}
.inline {
display: inline;
&::after {
content: '';
}
}
.error500 {
border: 1px dotted #ff0000;
background-color: #ffffff;
color: #000000;
padding: 0.5em;
border: 1px dotted #ff0000;
background-color: #ffffff;
color: #000000;
padding: 0.5em;
}
.errorbox {
border: 1px solid #FF0000;
background-color: #FFCCCC;
padding: 5px;
margin-bottom: 5px;
border: 1px solid #FF0000;
background-color: #FFCCCC;
padding: 5px;
margin-bottom: 5px;
}
.errorbox a {
color: #000000 !important;
color: #000000 !important;
}
.the-key {
text-align: left;
font-size: 1.4em;
background: lighten($ffyellow, 35);
border: 3pt dashed $ffmagenta;
margin-bottom: 0.5em;
padding: 0.5em
text-align: left;
font-size: 1.4em;
background: lighten($ffyellow, 35);
border: 3pt dashed $ffmagenta;
margin-bottom: 0.5em;
padding: 0.5em
}

View File

@ -0,0 +1,12 @@
#!/bin/sh /etc/rc.common
# Start right after S10boot
START=10
start() {
config_load gluon
config_get_bool reconfigure core reconfigure 0
if [ "$reconfigure" = 1 ]; then
gluon-reconfigure
fi
}

View File

@ -0,0 +1,2 @@
#!/bin/sh
/etc/init.d/gluon-core-reconfigure start

View File

@ -1,8 +0,0 @@
#!/bin/sh
# This script can be removed after Gluon v2018.2
# Check for a random line that always was in /etc/sysctl.conf
if grep -qxF 'net.ipv4.ip_forward=1' /etc/sysctl.conf; then
echo '# Defaults are configured in /etc/sysctl.d/* and can be customized in this file' >/etc/sysctl.conf
fi

View File

@ -1,3 +1,6 @@
#!/bin/sh
exec uci commit
uci -q batch <<-EOF
delete gluon.core.reconfigure
commit
EOF

View File

@ -0,0 +1,48 @@
#!/usr/bin/lua
local unistd = require 'posix.unistd'
if not unistd.access('/lib/gluon/domains/') then
return
end
local function domain_exists(domain)
return unistd.access('/lib/gluon/domains/' .. domain .. '.json') == 0
end
local uci = require('simple-uci').cursor()
local domain = uci:get('gluon', 'core', 'switch_domain')
if domain and not domain_exists(domain) then
io.stderr:write(
string.format("Warning: invalid mesh domain switch to '%s' configured, not switching\n", domain)
)
domain = nil
end
if not domain then
domain = uci:get('gluon', 'core', 'domain')
end
if domain and not domain_exists(domain) then
io.stderr:write(
string.format("Warning: invalid mesh domain '%s' configured, resetting to default...\n", domain)
)
domain = nil
end
if not domain then
-- We can't use gluon.site yet, as it depends on gluon.core.domain to be set
local json = require 'jsonc'
local site = assert(json.load('/lib/gluon/site.json'))
domain = site.default_domain
end
uci:set('gluon', 'core', 'domain', domain)
uci:delete('gluon', 'core', 'switch_domain')
uci:save('gluon')

View File

@ -1,27 +0,0 @@
#!/usr/bin/lua
local unistd = require 'posix.unistd'
if not unistd.access('/lib/gluon/domains/') then
return
end
local uci = require('simple-uci').cursor()
local domain = uci:get('gluon', 'core', 'domain')
if domain and not unistd.access('/lib/gluon/domains/' .. domain .. '.json') then
io.stderr:write(string.format("Warning: invalid mesh domain '%s' configured, resetting to default...\n", domain))
domain = nil
end
if domain then return end
-- We can't use gluon.site yet, as it depends on gluon.core.domain to be set
local json = require 'jsonc'
local site = assert(json.load('/lib/gluon/site.json'))
uci:set('gluon', 'core', 'domain', site.default_domain)
uci:commit('gluon')

View File

@ -111,6 +111,7 @@ local primary_addrs = {
'c20i',
'c50',
'tplink,c2-v1',
'ex3700'
}},
{'x86'},
}},

View File

@ -11,9 +11,12 @@ end
local platform = require 'gluon.platform'
local site = require 'gluon.site'
local json = require 'jsonc'
local uci = require('simple-uci').cursor()
local unistd = require 'posix.unistd'
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
local function iface_exists(ifaces)
if not ifaces then return nil end
@ -26,8 +29,8 @@ local function iface_exists(ifaces)
end
local lan_ifname = iface_exists(uci:get('network', 'lan', 'ifname'))
local wan_ifname = iface_exists(uci:get('network', 'wan', 'ifname'))
local lan_ifname = iface_exists((network_data.lan or {}).ifname)
local wan_ifname = iface_exists((network_data.wan or {}).ifname)
if platform.match('ar71xx', 'generic', {
'cpe210',
@ -42,6 +45,16 @@ if platform.match('ar71xx', 'generic', {
'unifiac-pro',
}) then
lan_ifname, wan_ifname = wan_ifname, lan_ifname
elseif platform.match('lantiq') then
local switch_data = board_data.switch or {}
local switch0_data = switch_data.switch0 or {}
local roles_data = switch0_data.roles or {}
for _, role_data in ipairs(roles_data) do
if role_data.role == 'wan' then
wan_ifname = iface_exists(role_data.device)
break
end
end
end
if wan_ifname and lan_ifname then

View File

@ -54,7 +54,7 @@ end
local function get_channel(radio, config)
local channel
if uci:get_first('gluon-core', 'wireless', 'preserve_channels') then
if wireless.preserve_channels(uci) then
-- preserved channel always wins
channel = radio.channel
elseif (radio.hwmode == '11a' or radio.hwmode == '11na') and is_outdoor() then
@ -82,20 +82,20 @@ local function get_htmode(radio)
end
local function is_disabled(name)
if uci:get('wireless', name) then
return uci:get_bool('wireless', name, 'disabled')
else
if not uci:get('wireless', name) then
return nil
end
return uci:get_bool('wireless', name, 'disabled')
end
-- Returns the first argument that is not nil; don't call without any non-nil arguments!
local function first_non_nil(first, ...)
if first ~= nil then
return first
else
return first_non_nil(...)
end
return first_non_nil(...)
end

View File

@ -18,7 +18,7 @@ end
uci:foreach('firewall', 'zone', reject_input_on_wan)
for _, zone in ipairs({'mesh', 'local_client', 'wired_mesh'}) do
for _, zone in ipairs({'mesh', 'loc_client', 'wired_mesh'}) do
-- Other packages assign interfaces to these zones
uci:section('firewall', 'zone', zone, {
name = zone,
@ -52,13 +52,16 @@ for _, zone in ipairs({'mesh', 'local_client', 'wired_mesh'}) do
family = 'ipv6',
target = 'ACCEPT',
})
-- Can be removed soon: was never in a release
uci:delete('firewall', zone .. '_ICMPv6_out')
end
uci:section('firewall', 'rule', 'local_client_ICMPv4_in', {
src = 'local_client',
-- ToDo Remove in v2022.x
uci:delete('firewall', 'local_client')
uci:delete('firewall', 'local_client_ssh')
uci:delete('firewall', 'local_client_ICMPv4_in')
uci:delete('firewall', 'local_client_ICMPv6_in')
uci:section('firewall', 'rule', 'loc_client_ICMPv4_in', {
src = 'loc_client',
proto = 'icmp',
icmp_type = {
'echo-request',
@ -67,9 +70,8 @@ uci:section('firewall', 'rule', 'local_client_ICMPv4_in', {
target = 'ACCEPT',
})
-- allow inbound SSH from anywhere
for _, zone in ipairs({ 'wan', 'local_client', 'mesh' }) do
for _, zone in ipairs({ 'wan', 'loc_client', 'mesh' }) do
uci:section('firewall', 'rule', zone .. '_ssh', {
name = zone .. '_ssh',
src = zone,

View File

@ -18,7 +18,7 @@ uci:delete('firewall', 'client_dns')
if dns.servers then
-- allow inbound traffic for dns from client zone
uci:section('firewall', 'rule', 'client_dns', {
src = 'local_client',
src = 'loc_client',
dest_port = '53',
proto = 'tcpudp',
target = 'ACCEPT',

View File

@ -0,0 +1,56 @@
#!/usr/bin/lua
local unistd = require 'posix.unistd'
local function shift()
table.remove(arg, 1)
end
local reboot = true
if arg[1] == '--no-reboot' then
reboot = false
shift()
end
local setup_mode = unistd.access('/var/gluon/setup-mode') == 0
if #arg ~= 1 then
io.stderr:write('Usage: gluon-switch-domain [--no-reboot] <domain>\n')
os.exit(1)
end
local domain = arg[1]
if not unistd.access('/lib/gluon/domains/') then
io.stderr:write('This Gluon firmware does not support multiple mesh domains.\n')
os.exit(1)
end
local function domain_exists(dom)
return unistd.access('/lib/gluon/domains/' .. dom .. '.json') == 0
end
if not domain_exists(domain) then
io.stderr:write(string.format("Error: invalid mesh domain '%s'\n", domain))
os.exit(1)
end
local uci = require('simple-uci').cursor()
uci:set('gluon', 'core', 'switch_domain', domain)
uci:set('gluon', 'core', 'reconfigure', true)
uci:save('gluon')
local cmd
if setup_mode then
cmd = 'gluon-reconfigure'
elseif reboot then
uci:commit('gluon')
cmd = 'reboot'
else
cmd = 'gluon-reload'
end
unistd.execp(cmd, {[0] = cmd})

View File

@ -66,7 +66,7 @@ end
function M.device_supports_wpa3()
-- rt2x00 crashes when enabling WPA3 personal / OWE VAP
if M.match('ramips', 'rt305x') or M.match('ramips', 'mt7620') then
if M.match('ramips', 'rt305x') then
return false
end

View File

@ -96,4 +96,8 @@ function M.foreach_radio(uci, f)
end
end
function M.preserve_channels(uci)
return uci:get_first('gluon-core', 'wireless', 'preserve_channels')
end
return M

View File

@ -0,0 +1 @@
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol udp --ip6-destination-port 1001 --ip6-dst ff05::2:1001 -j RETURN'

View File

@ -67,9 +67,7 @@ end
function M.set_domain_config(domain)
if uci:get('gluon', 'core', 'domain') ~= domain.domain_code then
uci:set('gluon', 'core', 'domain', domain.domain_code)
uci:commit('gluon')
os.execute('gluon-reconfigure')
os.execute(string.format("exec gluon-switch-domain --no-reboot '%s'", domain.domain_code))
M.log('Set domain "'..domain.domain.domain_names[domain.domain_code]..'"')
return true
end

View File

@ -40,7 +40,6 @@ if geo.lat ~= nil and geo.lon ~= nil then
local geo_base_domain = hoodutil.get_domain_by_geo(jdomains, geo)
if geo_base_domain ~= nil then
if hoodutil.set_domain_config(geo_base_domain) then
os.execute("gluon-reload")
hoodutil.log('Domain set by geolocation mode.\n')
end
return
@ -51,6 +50,4 @@ else
end
-- default domain mode
if hoodutil.set_domain_config(hoodutil.get_default_domain(hoodutil.get_domains())) then
os.execute("gluon-reload")
end
hoodutil.set_domain_config(hoodutil.get_default_domain(hoodutil.get_domains()))

View File

@ -23,18 +23,18 @@ uci:section('firewall', 'zone', 'mmfd', {
-- forwardings and respective rules
uci:section('firewall', 'forwarding', 'fcc', {
src = 'local_client',
dest = 'local_client',
src = 'loc_client',
dest = 'loc_client',
})
uci:section('firewall', 'forwarding', 'fcm', {
src = 'local_client',
src = 'loc_client',
dest = 'mesh',
})
uci:section('firewall', 'forwarding', 'fmc', {
src = 'mesh',
dest = 'local_client',
dest = 'loc_client',
})
uci:section('firewall', 'forwarding', 'fmm', {
@ -44,11 +44,11 @@ uci:section('firewall', 'forwarding', 'fmm', {
uci:section('firewall', 'forwarding', 'flc', {
src = 'l3roamd',
dest = 'local_client',
dest = 'loc_client',
})
uci:section('firewall', 'forwarding', 'fcl', {
src = 'local_client',
src = 'loc_client',
dest = 'l3roamd',
})

View File

@ -62,38 +62,40 @@
static struct babelhelper_ctx bhelper_ctx = {};
static void obtain_if_addr(const char *ifname, char *lladdr) {
static bool get_linklocal_address(const char *ifname, char lladdr[INET6_ADDRSTRLEN]) {
struct ifaddrs *ifaddr, *ifa;
int family, n;
bool ret = false;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
return false;
}
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (ifa->ifa_addr == NULL)
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
family = ifa->ifa_addr->sa_family;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
if ( (family == AF_INET6) && ( ! strncmp(ifname, ifa->ifa_name, strlen(ifname)) ) ) {
char lhost[INET6_ADDRSTRLEN];
struct in6_addr *address = &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr;
if (inet_ntop(AF_INET6, address, lhost, INET6_ADDRSTRLEN) == NULL) {
fprintf(stderr, "obtain_if_addr: could not convert ip to string\n");
goto cleanup;
}
if (strcmp(ifname, ifa->ifa_name) != 0)
continue;
if (! strncmp("fe80:", lhost, 5) ) {
snprintf( lladdr, NI_MAXHOST, "%s", lhost );
goto cleanup;
}
const struct in6_addr *address = &((const struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
if (!IN6_IS_ADDR_LINKLOCAL(address))
continue;
if (!inet_ntop(AF_INET6, address, lladdr, INET6_ADDRSTRLEN)) {
perror("inet_ntop");
continue;
}
ret = true;
break;
}
cleanup:
freeifaddrs(ifaddr);
return ret;
}
@ -154,29 +156,32 @@ free:
return retval;
}
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)+1];
snprintf(path, sizeof(path), format, ifname, name);
return !access(path, F_OK);
}
static void mesh_add_if(const char *ifname, struct json_object *wireless,
struct json_object *tunnel, struct json_object *other) {
char str_ip[NI_MAXHOST] = {};
char str_ip[INET6_ADDRSTRLEN];
obtain_if_addr(ifname, str_ip);
if (!get_linklocal_address(ifname, str_ip))
return;
struct json_object *address = json_object_new_string(str_ip);
if (interface_file_exists(ifname, "wireless"))
json_object_array_add(wireless, address);
else if (interface_file_exists(ifname, "tun_flags"))
json_object_array_add(tunnel, address);
else
json_object_array_add(other, address);
/* In case of VLAN and bridge interfaces, we want the lower interface
* to determine the interface type (but not for the interface address) */
char lowername[IF_NAMESIZE];
gluonutil_get_interface_lower(lowername, ifname);
switch(gluonutil_get_interface_type(lowername)) {
case GLUONUTIL_INTERFACE_TYPE_WIRELESS:
json_object_array_add(wireless, address);
break;
case GLUONUTIL_INTERFACE_TYPE_TUNNEL:
json_object_array_add(tunnel, address);
break;
default:
json_object_array_add(other, address);
}
}
@ -193,24 +198,26 @@ static bool handle_neighbour(char **data, void *obj) {
if (data[REACH])
json_object_object_add(neigh, "reachability", json_object_new_double(strtod(data[REACH], NULL)));
struct json_object *nif = 0;
if (data[IF] && !json_object_object_get_ex(obj, data[IF], &nif)) {
char str_ip[NI_MAXHOST] = {};
obtain_if_addr( (const char*)data[IF], str_ip );
if (!data[IF])
return true;
struct json_object *nif;
if (!json_object_object_get_ex(obj, data[IF], &nif)) {
char str_ip[INET6_ADDRSTRLEN];
nif = json_object_new_object();
json_object_object_add(nif, "ll-addr", json_object_new_string(str_ip));
if (get_linklocal_address(data[IF], str_ip))
json_object_object_add(nif, "ll-addr", json_object_new_string(str_ip));
json_object_object_add(nif, "protocol", json_object_new_string("babel"));
json_object_object_add(obj, data[IF], nif);
}
struct json_object *neighborcollector = 0;
if (!json_object_object_get_ex(nif, "neighbours", &neighborcollector)) {
neighborcollector = json_object_new_object();
json_object_object_add(nif, "neighbours", neighborcollector);
json_object_object_add(nif, "neighbours", json_object_new_object());
}
struct json_object *neighborcollector;
json_object_object_get_ex(nif, "neighbours", &neighborcollector);
json_object_object_add(neighborcollector, data[ADDRESS], neigh);
}
@ -277,6 +284,13 @@ static void blobmsg_handle_list(struct blob_attr *attr, int len, bool array, str
free(proto);
}
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 void receive_call_result_data(struct ubus_request *req, int type, struct blob_attr *msg) {
struct json_object *ret = json_object_new_object();
struct json_object *wireless = json_object_new_array();
@ -298,9 +312,9 @@ static void receive_call_result_data(struct ubus_request *req, int type, struct
blobmsg_handle_list(blobmsg_data(msg), blobmsg_data_len(msg), false, wireless, tunnel, other);
json_object_object_add(ret, "wireless", wireless);
json_object_object_add(ret, "tunnel", tunnel);
json_object_object_add(ret, "other", other);
add_if_not_empty(ret, "wireless", wireless);
add_if_not_empty(ret, "tunnel", tunnel);
add_if_not_empty(ret, "other", other);
*((struct json_object**)(req->priv)) = ret;
}

View File

@ -1,5 +1,5 @@
#!/bin/sh
lock /var/lock/gluon_bat0.lock
batctl interface del "$IFNAME" 2>/dev/null
batctl interface -M del "$IFNAME" 2>/dev/null
lock -u /var/lock/gluon_bat0.lock

View File

@ -131,35 +131,23 @@ 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);
char lowername[IF_NAMESIZE];
gluonutil_get_interface_lower(lowername, ifname);
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"))
switch(gluonutil_get_interface_type(lowername)) {
case GLUONUTIL_INTERFACE_TYPE_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);
break;
case GLUONUTIL_INTERFACE_TYPE_TUNNEL:
json_object_array_add(tunnel, address);
break;
default:
json_object_array_add(other, address);
}
}
static struct json_object * get_mesh_subifs(const char *ifname) {

View File

@ -7,7 +7,7 @@ include ../gluon.mk
define Package/gluon-mesh-wireless-sae
TITLE:=Encryption of 802.11s Mesh Links through SAE
DEPENDS:=+gluon-core +wpa-supplicant-openssl
DEPENDS:=+gluon-core +wpa-supplicant-mesh-wolfssl
endef
$(eval $(call BuildPackageGluon,gluon-mesh-wireless-sae))

View File

@ -559,14 +559,13 @@ static int parse_tt_local(struct nl_msg *msg,
}
static void update_tqs(void) {
static const struct ether_addr unspec = {};
struct router *router;
bool update_originators = false;
struct ether_addr unspec;
struct batadv_nlquery_opts opts;
int ret;
// reset TQs
memset(&unspec, 0, sizeof(unspec));
foreach(router, G.routers) {
router->tq = 0;
if (ether_addr_equal(router->originator, unspec))
@ -609,12 +608,12 @@ static void update_tqs(void) {
foreach(router, G.routers) {
if (router->tq == 0) {
if (ether_addr_equal(router->originator, unspec))
fprintf(stderr,
"Unable to find router " F_MAC " in transtable_{global,local}\n",
DEBUG_MSG(
"Unable to find router " F_MAC " in transtable_{global,local}",
F_MAC_VAR(router->src));
else
fprintf(stderr,
"Unable to find TQ for originator " F_MAC " (router " F_MAC ")\n",
DEBUG_MSG(
"Unable to find TQ for originator " F_MAC " (router " F_MAC ")",
F_MAC_VAR(router->originator),
F_MAC_VAR(router->src));
}

View File

@ -1,4 +1,7 @@
#pragma once
#include <stdint.h>
#include <string.h>
#include <linux/if_ether.h>
#define F_MAC "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"

View File

@ -18,7 +18,7 @@ uci:section('firewall', 'rule', 'wan_respondd', {
-- Allow respondd-access for local clients
uci:section('firewall', 'rule', 'client_respondd', {
name = 'client_respondd',
src = 'local_client',
src = 'loc_client',
src_ip = 'fe80::/64',
dest_port = '1001',
proto = 'udp',

View File

@ -60,8 +60,5 @@ if not switch_after_min_reached() and not switch_time_passed() then
os.exit(0)
end
uci:set("gluon", "core", "domain", target_domain)
uci:commit("gluon")
os.execute("gluon-reconfigure")
os.execute("reboot")
local cmd = {[0] = 'gluon-switch-domain', target_domain}
unistd.execp(cmd[0], cmd)

View File

@ -14,5 +14,5 @@ end
-- Only in case domain switch is scheduled
local f = io.open(cronfile, "w")
f:write("* * * * * /usr/bin/gluon-check-connection\n")
f:write("*/5 * * * * /usr/bin/gluon-switch-domain\n")
f:write("*/5 * * * * /lib/gluon/scheduled-domain-switch/switch-domain\n")
f:close()

View File

@ -17,4 +17,26 @@ define Package/gluon-setup-mode/description
Offline mode to perform basic setup in a secure manner.
endef
init_links := \
K89log \
K98boot \
K99umount \
S00sysfixtime \
S10boot \
S10gluon-core-reconfigure \
S10system \
S11sysctl \
S12log \
S95done
define Package/gluon-setup-mode/install
$(Gluon/Build/Install)
$(LN) S20network $(1)/lib/gluon/setup-mode/rc.d/K90network
for link in $(init_links); do \
$(LN) "/etc/init.d/$$$${link:3}" "$(1)/lib/gluon/setup-mode/rc.d/$$$${link}"; \
done
endef
$(eval $(call BuildPackageGluon,gluon-setup-mode))

View File

@ -1 +0,0 @@
/etc/init.d/log

View File

@ -1 +0,0 @@
/etc/init.d/boot

View File

@ -1 +0,0 @@
/etc/init.d/umount

View File

@ -1 +0,0 @@
/etc/init.d/sysfixtime

View File

@ -1 +0,0 @@
/etc/init.d/boot

View File

@ -1 +0,0 @@
/etc/init.d/system

View File

@ -1 +0,0 @@
/etc/init.d/sysctl

View File

@ -1 +0,0 @@
/etc/init.d/log

View File

@ -1 +0,0 @@
/etc/init.d/done

View File

@ -7,6 +7,10 @@ setup_mode_enable() {
if [ "$enabled" = 1 ] || [ "$configured" != 1 ]; then
echo '/lib/gluon/setup-mode/rc.d' > /tmp/rc_d_path
# This directory is a marker for scripts to know that we're
# in config mode, but it is also used for temporary files
mkdir -p /var/gluon/setup-mode
fi
}

View File

@ -49,7 +49,14 @@ define Build/Compile
rm -rf $(PKG_BUILD_DIR)/domains
mkdir -p $(PKG_BUILD_DIR)/domains
$(foreach domain,$(patsubst $(GLUON_SITEDIR)/domains/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)),
[ ! -e '$(PKG_BUILD_DIR)/domains/$(domain).json' ]
@if [ -e '$(PKG_BUILD_DIR)/domains/$(domain).json' ]; then \
link='$(PKG_BUILD_DIR)/domains/$(domain).json'; \
other="$$$$(basename $$$$(readlink -f "$$$$link") .json)"; \
if [ "$$$$other" ]; then \
echo >&2 "Error: Failed to install domain '"'$(domain)'"', name already taken by domain '$$$$other'."; \
fi; \
exit 1; \
fi
$(call GenerateJSON,domains/$(domain))
@lua ../../scripts/domain_aliases.lua '$(PKG_BUILD_DIR)/domains/$(domain).json' | while read alias; do \
[ "$$$${alias}" != '$(domain)' ] || continue; \
@ -57,7 +64,7 @@ define Build/Compile
if ! ln -s '$(domain).json' "$$$$link"; then \
other="$$$$(basename $$$$(readlink -f "$$$$link") .json)"; \
if [ "$$$$other" ]; then \
echo >&2 "Failed to alias domain '"'$(domain)'"' as '$$$$alias', name already taken by domain '$$$$other'."; \
echo >&2 "Error: Failed to alias domain '"'$(domain)'"' as '$$$$alias', name already taken by domain '$$$$other'."; \
fi; \
exit 1; \
fi; \

View File

@ -142,7 +142,13 @@
<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') %><br /><%= statistics('gateway_nexthop', 'neighbour') %></td></tr>
<tr><th><%:Clients%></th><td><%= statistics('clients/total') %></td></tr>
</table>
<h3><%:Clients%></h3>
<table>
<tr><th><%:Total%></th><td><%= statistics('clients/total') %></td></tr>
<tr><th><%:Wireless 2.4 GHz%></th><td><%= statistics('clients/wifi24') %></td></tr>
<tr><th><%:Wireless 5 GHz%></th><td><%= statistics('clients/wifi5') %></td></tr>
</table>
<h3><%:Traffic%></h3>

View File

@ -55,9 +55,6 @@ msgstr "Weitergeleitet"
msgid "Gateway"
msgstr "Gateway"
msgid "Gateway Nexthop"
msgstr "Gateway Nexthop"
msgid "IP address"
msgstr "IP-Adresse"
@ -106,6 +103,9 @@ msgstr "Site"
msgid "Status"
msgstr "Status"
msgid "Total"
msgstr "Gesamt"
msgid "Traffic"
msgstr ""
@ -115,6 +115,12 @@ msgstr "Gesendet"
msgid "Uptime"
msgstr "Laufzeit"
msgid "Wireless 2.4 GHz"
msgstr ""
msgid "Wireless 5 GHz"
msgstr ""
msgid "connected"
msgstr "verbunden"
@ -126,3 +132,6 @@ msgstr "aktiviert"
msgid "not connected"
msgstr "nicht verbunden"
#~ msgid "Gateway Nexthop"
#~ msgstr "Gateway Nexthop"

View File

@ -46,9 +46,6 @@ msgstr ""
msgid "Gateway"
msgstr ""
msgid "Gateway Nexthop"
msgstr ""
msgid "IP address"
msgstr ""
@ -97,6 +94,9 @@ msgstr ""
msgid "Status"
msgstr ""
msgid "Total"
msgstr ""
msgid "Traffic"
msgstr ""
@ -106,6 +106,12 @@ msgstr ""
msgid "Uptime"
msgstr ""
msgid "Wireless 2.4 GHz"
msgstr ""
msgid "Wireless 5 GHz"
msgstr ""
msgid "connected"
msgstr ""

View File

@ -27,7 +27,7 @@ uci:section('uhttpd', 'uhttpd', 'main', {
uci:save('uhttpd')
for _, zone in ipairs({'mesh', 'local_client'}) do
for _, zone in ipairs({'mesh', 'loc_client'}) do
uci:section('firewall', 'rule', zone .. '_http', {
src = zone,
dest_port = '80',
@ -35,4 +35,8 @@ for _, zone in ipairs({'mesh', 'local_client'}) do
target = 'ACCEPT',
})
end
-- ToDo remove in v2022.x
uci:delete('firewall', 'local_client_http')
uci:save('firewall')

View File

@ -16,6 +16,19 @@ local function append_server(server)
end
local function handled_interfaces()
local interfaces = {}
for _, path in ipairs(util.glob('/lib/gluon/wan-dnsmasq/interface.d/*')) do
for interface in io.lines(path) do
table.insert(interfaces, interface)
end
end
return interfaces
end
local function handle_interface(status)
local ifname = status.device
local servers = status.inactive['dns-server']
@ -41,8 +54,9 @@ if type(static) == 'table' and #static > 0 then
append_server(server)
end
else
pcall(append_interface_servers, 'wan6')
pcall(append_interface_servers, 'wan')
for _, interface in ipairs(handled_interfaces()) do
pcall(append_interface_servers, interface)
end
end

View File

@ -26,7 +26,7 @@ $Id$
<%:Firmware image%>
</label>
<div class="gluon-value-field">
<input class="gluon-input-file" type="file" name="image" />
<input type="file" name="image" />
</div>
</div>
@ -36,13 +36,13 @@ $Id$
</label>
<div class="gluon-value-field">
<input id="keepcfg" class="gluon-input-checkbox" type="checkbox" name="keepcfg" value="1" checked="checked" />
<input id="keepcfg" type="checkbox" name="keepcfg" value="1" checked="checked" />
<label for="keepcfg"></label>
</div>
</div>
</div>
<div class="gluon-page-actions right">
<div class="gluon-page-actions">
<input type="hidden" name="step" value="2" />
<input type="hidden" name="token" value="<%=token%>" />
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Upload image%>" />

View File

@ -1,6 +1,6 @@
<div class="gluon-value">
<div class="gluon-value-title">
<input class="gluon-input-radio" data-update="change" type="radio" value="security"<%= attr("id", id..'.1') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "security") and "checked") %> />
<input data-update="change" type="radio" value="security"<%= attr("id", id..'.1') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "security") and "checked") %> />
<label<%= attr("for", id..'.1')%>></label>
</div>
<div class="gluon-value-field-long">
@ -18,7 +18,7 @@
<div class="gluon-value gluon-value-last">
<div class="gluon-value-title">
<input class="gluon-input-radio" data-update="change" type="radio" value="performance"<%= attr("id", id..'.2') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "performance") and "checked") %> />
<input data-update="change" type="radio" value="performance"<%= attr("id", id..'.2') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "performance") and "checked") %> />
<label<%= attr("for", id..'.2')%>></label>
</div>
<div class="gluon-value-field-long">

View File

@ -10,7 +10,7 @@
<%
for i, val in ipairs(self:cfgvalue()) do
%>
<input class="gluon-input-text" value="<%|val%>" data-update="change" type="text"<%=
<input value="<%|val%>" data-update="change" type="text"<%=
attr("id", id .. "." .. i) ..
attr("name", id) ..
attr("size", self.size) ..

View File

@ -1,4 +1,4 @@
<input class="gluon-input-checkbox" data-update="click change" type="checkbox" value="1"<%=
<input data-update="click change" type="checkbox" value="1"<%=
attr("id", id) .. attr("name", id) ..
attr("checked", self:cfgvalue() and "checked")
%> />

View File

@ -4,23 +4,25 @@
%>
<% if self.widget == "select" then %>
<select class="gluon-input-select" data-update="change"<%=
attr("id", id) ..
attr("name", id) ..
attr("size", self.size) ..
attr("data-type", "minlength(1)") ..
attr("data-optional", self.optional)
%>>
<% for i, entry in pairs(entries) do -%>
<option<%=
attr("id", id.."."..entry.key) ..
attr("value", entry.key) ..
attr("data-index", i) ..
attr("data-depends", self:deplist(entry.deps)) ..
attr("selected", (self:cfgvalue() == entry.key) and "selected")
%>><%|entry.value%></option>
<%- end %>
</select>
<div class="select-wrapper">
<select data-update="change"<%=
attr("id", id) ..
attr("name", id) ..
attr("size", self.size) ..
attr("data-type", "minlength(1)") ..
attr("data-optional", self.optional)
%>>
<% for i, entry in pairs(entries) do -%>
<option<%=
attr("id", id.."."..entry.key) ..
attr("value", entry.key) ..
attr("data-index", i) ..
attr("data-depends", self:deplist(entry.deps)) ..
attr("selected", (self:cfgvalue() == entry.key) and "selected")
%>><%|entry.value%></option>
<%- end %>
</select>
</div>
<% elseif self.widget == "radio" then %>
<div>
<% for i, entry in pairs(entries) do %>
@ -28,7 +30,7 @@
attr("data-index", i) ..
attr("data-depends", self:deplist(entry.deps))
%>>
<input class="gluon-input-radio" data-update="click change" type="radio"<%=
<input data-update="click change" type="radio"<%=
attr("id", id.."."..entry.key) ..
attr("name", id) ..
attr("value", entry.key) ..

View File

@ -1,3 +1,3 @@
<textarea class="gluon-input-textarea" <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", id) .. attr("id", id) .. attr("rows", self.rows) .. attr("wrap", self.wrap) %>>
<textarea <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", id) .. attr("id", id) .. attr("rows", self.rows) .. attr("wrap", self.wrap) %>>
<%-|self:cfgvalue()-%>
</textarea>

View File

@ -2,7 +2,6 @@
attr("id", id) ..
attr("name", id) ..
attr("type", self.password and "password" or "text") ..
attr("class", self.password and "gluon-input-password" or "gluon-input-text") ..
attr("value", self:cfgvalue()) ..
attr("size", self.size) ..
attr("placeholder", self.placeholder) ..

File diff suppressed because one or more lines are too long

View File

@ -276,7 +276,6 @@
t.value = values[i-1];
t.type = 'text';
t.index = i;
t.className = 'gluon-input-text';
if (attr.size)
t.size = attr.size;

View File

@ -15,7 +15,7 @@
<%- end %>
}, {once: true});
initOSM(<%=json(self.openlayers_url)%>, function(createMap) {
initOSM(<%=json(self.options)%>, function(createMap) {
elMap.style.display = '';
var pos = <%=json(self:cfgvalue().pos)%>;

View File

@ -1 +1 @@
"use strict";function initOSM(e,o){var t=document.createElement("link");t.rel="stylesheet",t.type="text/css",t.href=e+"/css/ol.css",document.head.appendChild(t);var n=document.createElement("script"),r=!1;n.onload=n.onreadystatechange=function(){if(!(r||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){r=!0;var t=new Image;t.onload=function(){var e=new ol.style.Style({image:new ol.style.Icon({img:t,imgSize:[30,45],anchor:[.5,1]})}),c=new ol.Feature;c.setStyle(e),o(function(e,t,o,n,r){var a=new ol.Map({target:e,layers:[new ol.layer.Tile({source:new ol.source.OSM}),new ol.layer.Vector({source:new ol.source.Vector({features:[c]})})],view:new ol.View({center:ol.proj.fromLonLat(t),zoom:o})}),l=function(e){c.setGeometry(new ol.geom.Point(e))};return a.addEventListener("click",function(e){l(e.coordinate),r(ol.proj.toLonLat(e.coordinate))}),n&&l(ol.proj.fromLonLat(t)),a})},t.src="data:image/svg+xml,"+escape('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="45"><path d="M2,15A13,13,0,0,1,28,13Q28,28,15,45Q2,28,2,15" fill="#48b" stroke="#369" stroke-width="1.5" /><circle cx="15" cy="15" r="6" fill="#fff" /></svg>')}},n.src=e+"/build/ol.js",document.head.appendChild(n)}
"use strict";function initOSM(o,r){var e=document.createElement("link");e.rel="stylesheet",e.type="text/css",e.href=o.openlayers_url+"/css/ol.css",document.head.appendChild(e);var t=document.createElement("script"),l=!1;t.onload=t.onreadystatechange=function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){l=!0;var t=new Image;t.onload=function(){var i,e=new ol.style.Style({image:new ol.style.Icon({img:t,imgSize:[30,45],anchor:[.5,1]})}),s=new ol.Feature;s.setStyle(e),i=o.tile_layer&&"XYZ"===o.tile_layer.type?new ol.source.XYZ({url:o.tile_layer.url,attributions:o.tile_layer.attributions}):new ol.source.OSM,r(function(e,t,o,r,l){function n(e){s.setGeometry(new ol.geom.Point(e))}var a=new ol.Map({target:e,layers:[new ol.layer.Tile({source:i}),new ol.layer.Vector({source:new ol.source.Vector({features:[s]})})],view:new ol.View({center:ol.proj.fromLonLat(t),zoom:o})});return a.addEventListener("click",function(e){n(e.coordinate),l(ol.proj.toLonLat(e.coordinate))}),r&&n(ol.proj.fromLonLat(t)),a})},t.src="data:image/svg+xml,"+escape('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="45"><path d="M2,15A13,13,0,0,1,28,13Q28,28,15,45Q2,28,2,15" fill="#48b" stroke="#369" stroke-width="1.5" /><circle cx="15" cy="15" r="6" fill="#fff" /></svg>')}},t.src=o.openlayers_url+"/build/ol.js",document.head.appendChild(t)}

View File

@ -6,7 +6,7 @@
'use strict';
function initOSM(openlayers_url, ready) {
function initOSM(options, ready) {
var markerSvg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="45">'
+ '<path d="M2,15A13,13,0,0,1,28,13Q28,28,15,45Q2,28,2,15" fill="#48b" stroke="#369" stroke-width="1.5" />'
+ '<circle cx="15" cy="15" r="6" fill="#fff" />'
@ -15,7 +15,7 @@ function initOSM(openlayers_url, ready) {
var style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = openlayers_url + '/css/ol.css';
style.href = options.openlayers_url + '/css/ol.css';
document.head.appendChild(style);
var script = document.createElement('script');
@ -42,12 +42,22 @@ function initOSM(openlayers_url, ready) {
var marker = new ol.Feature();
marker.setStyle(markerStyle);
var source;
if (options.tile_layer && options.tile_layer.type === 'XYZ') {
source = new ol.source.XYZ({
url: options.tile_layer.url,
attributions: options.tile_layer.attributions,
});
} else {
source = new ol.source.OSM();
}
ready(function(elMap, pos, zoom, set, onUpdate) {
var map = new ol.Map({
target: elMap,
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
source: source
}),
new ol.layer.Vector({
source: new ol.source.Vector({
@ -79,6 +89,6 @@ function initOSM(openlayers_url, ready) {
markerImg.src = 'data:image/svg+xml,' + escape(markerSvg);
};
script.src = openlayers_url + '/build/ol.js';
script.src = options.openlayers_url + '/build/ol.js';
document.head.appendChild(script);
}

View File

@ -15,7 +15,10 @@ M.MapValue = MapValue
function MapValue:__init__(title, options)
classes.AbstractValue.__init__(self, title)
self.subtemplate = "model/osm/map"
self.openlayers_url = options.openlayers_url or DEFAULT_URL
self.options = {
openlayers_url = options.openlayers_url or DEFAULT_URL,
tile_layer = options.tile_layer,
}
self.lon = options.lon
self.lat = options.lat

Some files were not shown because too many files have changed in this diff Show More