Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • v2023.2.5-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • hoodselector
  • master
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.x
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
56 results
Show changes
Showing
with 906 additions and 241 deletions
#!/bin/sh
NETWORK_CFG='/etc/config/network'
NETWORK_SAVED="${NETWORK_CFG}_gluon-old"
SYSTEM_CFG='/etc/config/system'
SYSTEM_SAVED="${SYSTEM_CFG}_gluon-old"
# Make sure everything is saved before we move away the config files
uci commit
# Save old configs (unless there is already a saved config,
# which means that the previous upgrade was interrupted)
if [ -s "$NETWORK_CFG" ] && ! [ -s "$NETWORK_SAVED" ]; then
mv -f "$NETWORK_CFG" "$NETWORK_SAVED"
fi
if [ -s "$SYSTEM_CFG" ] && ! [ -s "$SYSTEM_SAVED" ]; then
mv -f "$SYSTEM_CFG" "$SYSTEM_SAVED"
fi
# Generate a new network config
rm -f /etc/board.json "$NETWORK_CFG" "$SYSTEM_CFG"
config_generate
#!/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
#!/bin/sh
exec uci commit
uci -q batch <<-EOF
delete gluon.core.reconfigure
commit
EOF
# New config is saved, we can delete the old one
rm -f /etc/config/*_gluon-old
#!/bin/sh
# shellcheck disable=SC1091
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
proto_gluon_mesh_init_config() {
proto_config_add_boolean fixed_mtu
proto_config_add_boolean transitive
}
proto_gluon_mesh_setup() {
export CONFIG="$1"
export IFNAME="$2"
local fixed_mtu transitive
json_get_vars fixed_mtu transitive
local fixed_mtu
json_get_vars fixed_mtu
export FIXED_MTU="${fixed_mtu:-0}"
export TRANSITIVE="${transitive:-0}"
for script in /lib/gluon/core/mesh/setup.d/*; do
[ ! -x "$script" ] || "$script"
......@@ -27,7 +27,6 @@ proto_gluon_mesh_setup() {
proto_add_data
json_add_boolean fixed_mtu "$FIXED_MTU"
json_add_boolean transitive "$TRANSITIVE"
[ "$IFNAME" != 'br-wan' ] && json_add_string zone 'mesh'
proto_close_data
proto_send_update "$CONFIG"
......
#!/bin/sh
# shellcheck disable=SC1091
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
proto_gluon_wired_init_config() {
proto_config_add_boolean transitive
proto_config_add_int index
proto_config_add_boolean vxlan
proto_config_add_string vxpeer6addr
}
xor2() {
......@@ -14,8 +17,27 @@ xor2() {
echo -n "${1:1:1}" | tr '0123456789abcdef' '23016745ab89efcd'
}
is_layer3_device () {
local addrlen
addrlen="$(cat "/sys/class/net/$1/addr_len")"
test "$addrlen" -eq 0
}
# shellcheck disable=SC2086
interface_linklocal() {
local macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')"
if is_layer3_device "$1"; then
if ! ubus call network.interface dump | \
jsonfilter -e "@.interface[@.l3_device='$1']['ipv6-address'][*].address" | \
grep -e '^fe[89ab][0-9a-f]' -m 1; then
proto_notify_error "$config" "MISSING_LL_ADDR_ON_LOWER_IFACE"
proto_block_restart "$config"
exit 1
fi
return
fi
local macaddr
macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')"
local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS"
echo "fe80::$(xor2 "$1")$2:$3ff:fe$4:$5$6"
......@@ -27,25 +49,28 @@ proto_gluon_wired_setup() {
local meshif="$config"
local vxlan="$(lua -e 'print(require("gluon.site").mesh.vxlan(true))')"
local index vxlan vxpeer6addr
json_get_vars index vxlan vxpeer6addr
local transitive index
json_get_vars transitive index
# default args
[ -z "$vxlan" ] && vxlan=1
[ -z "$vxpeer6addr" ] && vxpeer6addr='ff02::15c'
proto_init_update "$ifname" 1
proto_send_update "$config"
if [ "$vxlan" = 'true' ]; then
if [ "$vxlan" -eq 1 ]; then
meshif="vx_$config"
json_init
json_add_string name "$meshif"
[ -n "$index" ] && json_add_string macaddr "$(lua -lgluon.util -e "print(gluon.util.generate_mac($index))")"
[ -n "$index" ] && json_add_string macaddr "$(lua -e "print(require('gluon.util').generate_mac($index))")"
json_add_string proto 'vxlan6'
json_add_string tunlink "$config"
# ip6addr (the lower interface ip6) is used by the vxlan.sh proto
json_add_string ip6addr "$(interface_linklocal "$ifname")"
json_add_string peer6addr 'ff02::15c'
json_add_int vid "$(lua -lgluon.util -e 'print(tonumber(gluon.util.domain_seed_bytes("gluon-mesh-vxlan", 3), 16))')"
json_add_string peer6addr "$vxpeer6addr"
json_add_int vid "$(lua -e 'print(tonumber(require("gluon.util").domain_seed_bytes("gluon-mesh-vxlan", 3), 16))')"
json_add_boolean rxcsum '0'
json_add_boolean txcsum '0'
json_close_object
......@@ -57,7 +82,6 @@ proto_gluon_wired_setup() {
json_add_string ifname "@${meshif}"
json_add_string proto 'gluon_mesh'
json_add_boolean fixed_mtu 1
[ -n "$transitive" ] && json_add_boolean transitive "$transitive"
json_close_object
ubus call network add_dynamic "$(json_dump)"
}
......
#!/bin/sh
cd "/lib/gluon/reload.d" || exit 1
err=0
for script in *; do
echo "Reloading: ${script}"
./"$script" || err=1
done
if [ $err -eq 1 ]; then
echo 'One or more daemons failed to reload.' >&2
exit 1
fi
exit 0
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2025-06-06 08:00+0200\n"
"Last-Translator: Florian Maurer <fmaurer@disroot.org>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Autoupdater branch"
msgstr "Autoupdater-Branch"
msgid "Domain"
msgstr "Domäne"
msgid "Firmware release"
msgstr "Firmware-Release"
msgid "Gluon version"
msgstr "Gluon-Version"
msgid "Hardware model"
msgstr "Hardware-Modell"
msgid "Hostname"
msgstr "Hostname"
msgid "MAC address"
msgstr "MAC-Adresse"
msgid "Public VPN key"
msgstr "Öffentlicher VPN-Schlüssel"
msgid "Site"
msgstr "Site"
msgid "Site version"
msgstr "Site-Version"
msgid "Switch type"
msgstr "Switch-Typ"
msgid "disabled"
msgstr "deaktiviert"
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2015-08-19 20:20+0100\n"
"Last-Translator: Bernot Tobias <tqbs@airmail.cc>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Domain"
msgstr ""
msgid "Firmware release"
msgstr "Version de la firmware"
msgid "Gluon version"
msgstr "Version de Gluon"
msgid "Hardware model"
msgstr "Modèle du Matériel"
msgid "Hostname"
msgstr "Nom d'hôte"
msgid "MAC address"
msgstr "Adresse MAC"
msgid "Public VPN key"
msgstr "Clé VPN publique"
msgid "Site"
msgstr "Site"
msgid "Site version"
msgstr "Version de Site"
msgid "Switch type"
msgstr ""
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Autoupdater branch"
msgstr ""
msgid "Domain"
msgstr ""
msgid "Firmware release"
msgstr ""
msgid "Gluon version"
msgstr ""
msgid "Hardware model"
msgstr ""
msgid "Hostname"
msgstr ""
msgid "MAC address"
msgstr ""
msgid "Public VPN key"
msgstr ""
msgid "Site"
msgstr ""
msgid "Site version"
msgstr ""
msgid "Switch type"
msgstr ""
msgid "disabled"
msgstr ""
local cjson = require 'cjson'
local json = require 'jsonc'
local function config_error(src, ...)
error(src .. ' error: ' .. string.format(...), 0)
end
local has_domains = (os.execute('ls -d "$IPKG_INSTROOT"/lib/gluon/domains/ >/dev/null 2>&1') == 0)
local function load_json(filename)
local f = assert(io.open(filename))
local json = cjson.decode(f:read('*a'))
f:close()
return json
end
local function get_domains()
local domains = {}
local dirs = io.popen("find \"$IPKG_INSTROOT\"/lib/gluon/domains/ -name '*.json'")
for filename in dirs:lines() do
local name = string.match(filename, '([^/]+).json$')
domains[name] = load_json(filename)
domains[name] = assert(json.load(filename))
end
dirs:close()
......@@ -35,10 +26,13 @@ end
local site, domain_code, domain, conf
local M = setmetatable({}, { __index = _G })
local function merge(a, b)
local function is_array(t)
local n = 0
for k, v in pairs(t) do
for _ in pairs(t) do
n = n + 1
end
return n == #t
......@@ -61,18 +55,42 @@ local function merge(a, b)
return m
end
local function contains(table, val)
for i=1,#table do
if table[i] == val then
return true
end
end
return false
end
local function path_to_string(path)
if path.is_value then
return path.label
end
return table.concat(path, '.')
end
local function format(val)
if type(val) == 'string' then
return string.format('%q', val)
else
return tostring(val)
end
end
local function array_to_string(array)
return '[' .. table.concat(array, ', ') .. ']'
local strings = {}
for i, v in ipairs(array) do
strings[i] = format(v)
end
return '[' .. table.concat(strings, ', ') .. ']'
end
function table_keys(tbl)
function M.table_keys(tbl)
local keys = {}
for k, _ in pairs(tbl) do
for k in pairs(tbl) do
keys[#keys + 1] = k
end
return keys
......@@ -89,9 +107,9 @@ local function domain_src()
return 'domains/' .. domain_code .. '.conf'
end
local function var_error(path, val, msg)
if type(val) == 'string' then
val = string.format('%q', val)
local function conf_src(path)
if path.is_value then
return 'Configuration'
end
local src
......@@ -108,16 +126,19 @@ local function var_error(path, val, msg)
src = site_src()
end
return src
end
local function var_error(path, val, msg)
local found = 'unset'
if val ~= nil then
found = string.format('%s (a %s value)', tostring(val), type(val))
found = string.format('%s (a %s value)', format(val), type(val))
end
config_error(src, 'expected %s to %s, but it is %s', path_to_string(path), msg, found)
config_error(conf_src(path), 'expected %s to %s, but it is %s', path_to_string(path), msg, found)
end
function in_site(path)
function M.in_site(path)
if has_domains and loadpath(nil, domain, unpack(path)) ~= nil then
config_error(domain_src(), '%s is allowed in site configuration only', path_to_string(path))
end
......@@ -125,7 +146,7 @@ function in_site(path)
return path
end
function in_domain(path)
function M.in_domain(path)
if has_domains and loadpath(nil, site, unpack(path)) ~= nil then
config_error(site_src(), '%s is allowed in domain configuration only', path_to_string(path))
end
......@@ -133,12 +154,20 @@ function in_domain(path)
return path
end
function this_domain()
function M.value(label, value)
return {
is_value = true,
label = label,
value = value,
}
end
function M.this_domain()
return domain_code
end
function extend(path, c)
function M.extend(path, c)
if not path then return nil end
local p = {unpack(path)}
......@@ -162,10 +191,14 @@ function loadpath(path, base, c, ...)
end
end
return loadpath(extend(path, {c}), base[c], ...)
return loadpath(M.extend(path, {c}), base[c], ...)
end
local function loadvar(path)
if path.is_value then
return path.value
end
return loadpath({}, conf, unpack(path))
end
......@@ -187,7 +220,7 @@ local function check_one_of(array)
end
function alternatives(...)
function M.alternatives(...)
local errs = {'All of the following alternatives have failed:'}
for i, f in ipairs({...}) do
local ok, err = pcall(f)
......@@ -201,7 +234,34 @@ function alternatives(...)
end
function need(path, check, required, msg)
local function check_chanlist(channels)
local is_valid_channel = check_one_of(channels)
return function(chanlist)
for group in chanlist:gmatch("%S+") do
if group:match("^%d+$") then
local channel = tonumber(group)
if not is_valid_channel(channel) then
return false
end
elseif group:match("^%d+-%d+$") then
local from, to = group:match("^(%d+)-(%d+)$")
from = tonumber(from)
to = tonumber(to)
if from >= to then
return false
end
if not is_valid_channel(from) or not is_valid_channel(to) then
return false
end
else
return false
end
end
return true
end
end
function M.need(path, check, required, msg)
local val = loadvar(path)
if required == false and val == nil then
return nil
......@@ -215,11 +275,11 @@ function need(path, check, required, msg)
end
local function need_type(path, type, required, msg)
return need(path, check_type(type), required, msg)
return M.need(path, check_type(type), required, msg)
end
function need_alphanumeric_key(path)
function M.need_alphanumeric_key(path)
local val = path[#path]
-- We don't use character classes like %w here to be independent of the locale
if type(val) ~= 'string' or not val:match('^[0-9a-zA-Z_]+$') then
......@@ -228,12 +288,12 @@ function need_alphanumeric_key(path)
end
function need_string(path, required)
function M.need_string(path, required)
return need_type(path, 'string', required, 'be a string')
end
function need_string_match(path, pat, required)
local val = need_string(path, required)
function M.need_string_match(path, pat, required)
local val = M.need_string(path, required)
if not val then
return nil
end
......@@ -245,15 +305,28 @@ function need_string_match(path, pat, required)
return val
end
function need_number(path, required)
function M.need_number(path, required)
return need_type(path, 'number', required, 'be a number')
end
function need_boolean(path, required)
function M.need_number_range(path, min, max, required)
local val = need_type(path, 'number', required)
if not val then
return nil
end
if val < min or val > max then
var_error(path, val, "be in range [" .. min .. ", " .. max .. "]")
end
return val
end
function M.need_boolean(path, required)
return need_type(path, 'boolean', required, 'be a boolean')
end
function need_array(path, subcheck, required)
function M.need_array(path, subcheck, required)
local val = need_type(path, 'table', required, 'be an array')
if not val then
return nil
......@@ -261,14 +334,14 @@ function need_array(path, subcheck, required)
if subcheck then
for i = 1, #val do
subcheck(extend(path, {i}))
subcheck(M.extend(path, {i}))
end
end
return val
end
function need_table(path, subcheck, required)
function M.need_table(path, subcheck, required)
local val = need_type(path, 'table', required, 'be a table')
if not val then
return nil
......@@ -276,39 +349,84 @@ function need_table(path, subcheck, required)
if subcheck then
for k, _ in pairs(val) do
subcheck(extend(path, {k}))
subcheck(M.extend(path, {k}))
end
end
return val
end
function need_value(path, value, required)
return need(path, function(v)
function M.need_value(path, value, required)
return M.need(path, function(v)
return v == value
end, required, 'be ' .. tostring(value))
end
function need_one_of(path, array, required)
return need(path, check_one_of(array), required, 'be one of the given array ' .. array_to_string(array))
function M.need_one_of(path, array, required)
return M.need(path, check_one_of(array), required, 'be one of the given array ' .. array_to_string(array))
end
function M.need_string_array(path, required)
return M.need_array(path, M.need_string, required)
end
function M.need_string_array_match(path, pat, required)
return M.need_array(path, function(e) M.need_string_match(e, pat) end, required)
end
function M.need_array_of(path, array, required)
return M.need_array(path, function(e) M.need_one_of(e, array) end, required)
end
function M.need_array_elements_exclusive(path, a, b, required)
local val = need_type(path, 'table', required, 'be an array')
if not val then
return nil
end
function need_string_array(path, required)
return need_array(path, need_string, required)
if contains(val, a) and contains(val, b) then
config_error(conf_src(path),
'expected %s to contain only one of the elements %s and %s, but not both.',
path_to_string(path), format(a), format(b))
end
function need_string_array_match(path, pat, required)
return need_array(path, function(e) need_string_match(e, pat) end, required)
return val
end
function need_array_of(path, array, required)
return need_array(path, function(e) need_one_of(e, array) end, required)
function M.need_chanlist(path, channels, required)
local valid_chanlist = check_chanlist(channels)
return M.need(path, valid_chanlist, required,
'be a space-separated list of WiFi channels or channel-ranges (separated by a hyphen). '
.. 'Valid channels are: ' .. array_to_string(channels))
end
function M.need_domain_name(path)
M.need_string(path)
M.need(path, function(domain_name)
local f = io.open((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/domains/' .. domain_name .. '.json')
if not f then return false end
f:close()
return true
end, nil, 'be a valid domain name')
end
function M.obsolete(path, msg)
local val = loadvar(path)
if val == nil then
return nil
end
if not msg then
msg = 'Check the release notes and documentation for details.'
end
config_error(conf_src(path), '%s is obsolete. %s', path_to_string(path), msg)
end
local check = assert(loadfile())
local check = setfenv(assert(loadfile()), M)
site = load_json(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/site.json')
site = assert(json.load((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/site.json'))
local ok, err = pcall(function()
if has_domains then
......
#!/usr/bin/lua
local fs = require 'nixio.fs'
local sysconfig = require 'gluon.sysconfig'
if fs.stat('/lib/gluon/version/core') and not sysconfig.gluon_version then
-- This isn't an initial upgrade, so set gluon_version
sysconfig.gluon_version = ''
end
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
-- Migrate system section
local system = uci:get_all('system_gluon-old', '@system[0]')
if system then
uci:tset('system', '@system[0]', system)
end
-- Migrate ntp section
local ntp = uci:get_all('system_gluon-old', 'ntp')
if ntp then
uci:tset('system', 'ntp', ntp)
end
-- Migrate gpio_switch sections
--
-- Only the value is copied from the old config, so updates to names and
-- pins are preserved
uci:foreach('system', 'gpio_switch', function(s)
local name = s['.name']
local value = uci:get('system_gluon-old', name, 'value')
if value then
uci:set('system', name, 'value', value)
end
end)
-- No other sections are migrated, so updated LED and RSSI configs can take effect
uci:save('system')
#!/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')
#!/usr/bin/lua
local fs = require 'nixio.fs'
if not fs.access('/lib/gluon/domains/') then
return
end
local uci = require('simple-uci').cursor()
local domain = uci:get('gluon', 'core', 'domain')
if domain and not fs.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')
......@@ -8,52 +8,167 @@ if sysconfig.primary_mac then
end
local util = require 'gluon.util'
local json = require 'jsonc'
local platform = require 'gluon.platform'
local util = require 'gluon.util'
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
local function read(...)
local addr = util.readfile(string.format(...))
if addr then
return util.trim(addr)
end
end
local function get_netdev_addr(ifname)
return read('/sys/class/net/%s/address', ifname)
end
local function strip_vlan(ifname)
return (ifname:gsub('%..*', ''))
end
local fs = require 'nixio.fs'
local function netdev(ifname)
return function()
return get_netdev_addr(ifname)
end
end
local function phy(index)
return function()
return read('/sys/class/ieee80211/phy%d/macaddress', index)
end
end
local try_files = {
'/sys/class/net/eth0/address'
local function interface(name)
return function()
local ifdata = network_data[name] or {}
if ifdata.macaddr then
return ifdata.macaddr
elseif ifdata.ifname then
return get_netdev_addr(strip_vlan(ifdata.ifname))
end
end
end
local function label_mac()
return function()
local mac = util.exec('/lib/gluon/label_mac.sh')
if mac == nil then return nil end
mac = util.trim(mac)
if string.len(mac) ~= 17 then return nil end
return mac
end
end
-- Entries are matched in the order they are listed
local primary_addrs = {
{interface('lan'), {
{'ath79', 'generic', {
'glinet,gl-ar750s-nor',
'ocedo,raccoon',
'tplink,archer-a7-v5',
'tplink,archer-c2-v3',
'tplink,archer-d50-v1',
}},
{'brcm2708'},
{'ipq40xx', 'generic', {
'avm,fritzbox-4040',
'meraki,mr33',
'plasmacloud,pa1200',
'plasmacloud,pa2200',
}},
{'ipq806x', 'generic', {
'netgear,r7800',
}},
{'lantiq', 'xrx200', {
'arcadyan,vgv7510kw22-nor',
}},
{'lantiq', 'xway', {
'netgear,dgn3500b',
}},
{'mediatek', 'filogic', {
'asus,tuf-ax4200',
'asus,tuf-ax6000',
}},
{'ramips', 'mt7620', {
'netgear,ex3700',
'tplink,archer-c2-v1',
'tplink,archer-c20-v1',
'tplink,archer-c20i',
'tplink,archer-c50-v1',
}},
{'ramips', 'mt76x8', {
'xiaomi,mi-router-4a-100m',
}},
{'rockchip', 'armv8', {
'friendlyarm,nanopi-r2s',
'friendlyarm,nanopi-r3s',
'friendlyarm,nanopi-r4s',
}},
{'x86'},
}},
{interface('wan'), {
{'ipq40xx', 'generic', {
'linksys,ea6350v3',
'openmesh,a42',
'openmesh,a62',
}},
{'kirkwood', 'generic', {
'linksys,e4200-v2',
'linksys,ea4500',
}},
{'mpc85xx', 'p1020', {
'aerohive,hiveap-330',
'ocedo,panda',
}},
{'mpc85xx', 'p1010', {
'enterasys,ws-ap3715i',
}},
{'ramips', 'mt7620', {
'xiaomi,miwifi-mini',
'asus,rt-ac51u',
}},
}},
{phy(1), {
{'ramips', 'mt7621', {
'dlink,dir-860l-b1',
}},
}},
-- label-mac-device default
{label_mac(), {
{}, -- matches everything
}},
-- phy0 default
{phy(0), {
{}, -- matches everything
}},
-- eth0 fallback when phy0 does not exist
{netdev('eth0'), {
{}, -- matches everything
}},
}
if not (
util.contains({'x86', 'brcm2708'}, platform.get_target()) or
platform.match('ar71xx', 'mikrotik')
) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy0/macaddress')
end
if platform.match('ar71xx', 'generic', {'tl-wdr3600', 'tl-wdr4300'}) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress')
elseif platform.match('ramips', 'mt7621', {'dir-860l-b1'}) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress')
elseif platform.match('ar71xx', 'generic', {'unifi-outdoor-plus', 'carambola2',
'a40', 'a60',
'mr600', 'mr600v2',
'mr900', 'mr900v2',
'mr1750', 'mr1750v2',
'om2p', 'om2pv2', 'om2pv4',
'om2p-hs', 'om2p-hsv2', 'om2p-hsv3',
'om2p-hsv4',
'om2p-lc',
'om5p', 'om5p-an',
'om5p-ac', 'om5p-acv2',
'archer-c7-v4'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c58-v1',
'archer-c59-v1', 'archer-c60-v1',
'archer-c7'}) then
table.insert(try_files, 1, '/sys/class/net/eth1/address')
end
for _, file in ipairs(try_files) do
local addr = fs.readfile(file)
for _, matcher in ipairs(primary_addrs) do
local f, matches = unpack(matcher)
for _, match in ipairs(matches) do
if platform.match(unpack(match)) then
local addr = f()
if addr then
sysconfig.primary_mac = util.trim(addr)
break
sysconfig.primary_mac = addr:lower()
return
end
end
end
end
error('no primary MAC address found')
#!/usr/bin/lua
local sysconfig = require 'gluon.sysconfig'
-- Are we already set up?
if sysconfig.lan_ifname or sysconfig.wan_ifname then
os.exit(0)
end
local util = require 'gluon.util'
local platform = require 'gluon.platform'
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local fs = require 'nixio.fs'
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
local ifnames = table.concat(ifaces, ' ')
for iface in ifaces:gmatch('%S+') do
if fs.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then
return ifaces
for _, iface in ipairs(ifaces) do
if unistd.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then
return ifnames
end
end
end
local lan_data = network_data.lan or {}
local wan_data = network_data.wan or {}
local lan_interfaces = lan_data.ports
local wan_interfaces = wan_data.ports
-- In case we have a single port for either WAN or LAN,
-- add it to the respective empty table, as devices and
-- ports is XOR in board.json
if lan_data.device ~= nil then
lan_interfaces = {lan_data.device}
end
if wan_data.device ~= nil then
wan_interfaces = {wan_data.device}
end
local lan_ifname = iface_exists(lan_interfaces)
local wan_ifname = iface_exists(wan_interfaces)
local lan_ifname = iface_exists(uci:get('network', 'lan', 'ifname'))
local wan_ifname = iface_exists(uci:get('network', 'wan', 'ifname'))
if platform.match('ar71xx', 'generic', {
'cpe210',
'cpe510',
'wbs210',
'wbs510',
'airgateway',
'nanostation-m',
'nanostation-m-xw',
'unifi-outdoor-plus',
'uap-pro',
'unifiac-pro',
if platform.match('ath79', 'generic', {
'dlink,dap-2695-a1',
'tplink,cpe210-v1',
'tplink,cpe210-v2',
'tplink,cpe510-v1',
'tplink,wbs210-v1',
'tplink,wbs210-v2',
'tplink,wbs510-v1',
'ubnt,nanostation-m-xw',
'ubnt,unifi-ap-pro',
}) then
lan_ifname, wan_ifname = wan_ifname, lan_ifname
elseif platform.match('ath79', 'generic', {
'ubnt,unifi-ap-outdoor-plus',
}) then
-- Temporary solution to separate interfaces in bridged default setup
lan_ifname, wan_ifname = 'eth0', 'eth1'
elseif platform.match('ath79', 'generic', {
'ubnt,unifiac-mesh-pro',
'ubnt,unifiac-pro',
}) then
lan_ifname, wan_ifname = 'eth0.2', 'eth0.1'
elseif platform.match('ipq40xx', 'generic', {
'avm,fritzbox-7530',
}) then
lan_ifname, wan_ifname = 'lan2 lan3 lan4', 'lan1'
elseif platform.match('ipq806x', 'generic', {
'ubnt,unifi-ac-hd',
}) then
lan_ifname, wan_ifname = 'eth1', 'eth0'
elseif platform.match('ramips', 'mt7621', {
'netgear,wac104',
}) then
lan_ifname, wan_ifname = 'lan2 lan3 lan4', 'lan1'
elseif platform.match('ramips', 'mt7621', {
'tplink,eap615-wall-v1',
}) then
lan_ifname, wan_ifname = 'lan1 lan2 lan3', 'lan0'
elseif platform.match('lantiq', 'xrx200', {
'arcadyan,vgv7510kw22-nor',
}) then
lan_ifname, wan_ifname = 'lan1 lan2 lan3 lan4', 'wan'
end
if wan_ifname and lan_ifname then
sysconfig.wan_ifname = wan_ifname
sysconfig.lan_ifname = lan_ifname
sysconfig.single_ifname = nil
else
local single_ifname = lan_ifname or wan_ifname
if site.single_as_lan(false) then
sysconfig.lan_ifname = single_ifname
else
sysconfig.wan_ifname = single_ifname
end
sysconfig.wan_ifname = nil
sysconfig.lan_ifname = nil
sysconfig.single_ifname = lan_ifname or wan_ifname
end
-- Delete all UCI device sections of type 'bridge'
-- as well as the ones starting with 'br-'.
-- Preserve all others to apply MAC address stored in UCI
uci:delete_all('network', 'device', function(dev)
return (dev.type == 'bridge' or dev.name:match('^br-'))
end)
uci:delete('network', 'lan')
uci:delete('network', 'wan')
uci:delete_all('network', 'interface')
uci:save('network')
#!/usr/bin/lua
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local uci = require('simple-uci').cursor()
local util = require 'gluon.util'
-- Defaults from site.conf
local roles = {
lan = site.interfaces.lan.default_roles({'client'}),
wan = site.interfaces.wan.default_roles({'uplink'}),
}
roles.single = site.interfaces.single.default_roles({unpack(roles.wan)})
-- Migration of single to WAN/LAN or vice-versa (an interface was added or removed)
-- We identify the WAN with the single interface in this case
--
-- These settings only take effect when the section that is the target of the
-- migration does not exist yet.
if uci:get('gluon', 'iface_wan') then
roles.single = uci:get_list('gluon', 'iface_wan', 'role')
end
if uci:get('gluon', 'iface_single') then
roles.wan = uci:get_list('gluon', 'iface_single', 'role')
roles.lan = uci:get_list('gluon', 'iface_single', 'role')
end
-- Non-existing interfaces are nil, so they will not be added to the table
local interfaces = {
lan = sysconfig.lan_ifname,
wan = sysconfig.wan_ifname,
single = sysconfig.single_ifname,
}
for iface in pairs(interfaces) do
local section_name = 'iface_' .. iface
if not uci:get('gluon', section_name) then
uci:section('gluon', 'interface', section_name, {
-- / prefix refers to sysconfig ifnames
name = '/' .. iface,
role = roles[iface],
})
end
end
-- Fix invalid role configurations
uci:foreach('gluon', 'interface', function(interface)
local function has_role(role)
if interface.role == nil then
return false
end
return util.contains(interface.role, role)
end
if has_role('client') and (has_role('mesh') or has_role('uplink')) then
-- remove 'client' role
util.remove_from_set(interface.role, 'client')
uci:set('gluon', interface['.name'], 'role', interface.role)
end
end)
uci:save('gluon')
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local sysconfig = require 'gluon.sysconfig'
local util = require 'gluon.util'
local json = require 'jsonc'
local function get_network_mac(name)
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
if network_data == nil then
return nil
end
local ifdata = network_data[name] or {}
return ifdata.macaddr
end
local wan = uci:get_all('network_gluon-old', 'wan') or {}
local wan6 = uci:get_all('network_gluon-old', 'wan6') or {}
uci:section('network', 'interface', 'loopback', {
ifname = 'lo',
proto = 'static',
ipaddr = '127.0.0.1',
netmask = '255.0.0.0',
})
local wan_proto = 'dhcp'
if sysconfig.gluon_version and wan.proto ~= nil then
-- Only restore WAN proto in case this is an upgrade
wan_proto = wan.proto
end
uci:section('network', 'interface', 'wan', {
ifname = sysconfig.wan_ifname,
proto = wan_proto,
ipaddr = wan.ipaddr,
netmask = wan.netmask,
gateway = wan.gateway,
macaddr = get_network_mac('wan'),
ifname = util.get_role_interfaces(uci, 'uplink'),
type = 'bridge',
igmp_snooping = true,
multicast_querier = false,
......@@ -13,12 +49,10 @@ uci:section('network', 'interface', 'wan', {
auto = true,
})
if not uci:get('network', 'wan', 'proto') then
uci:set('network', 'wan', 'proto', 'dhcp')
end
uci:section('network', 'interface', 'wan6', {
proto = wan6.proto or 'dhcpv6',
ip6addr = wan6.ip6addr,
ip6gw = wan6.ip6gw,
ifname = 'br-wan',
peerdns = false,
ip6table = 1,
......@@ -26,11 +60,6 @@ uci:section('network', 'interface', 'wan6', {
reqprefix = 'no',
})
if not uci:get('network', 'wan6', 'proto') then
uci:set('network', 'wan6', 'proto', 'dhcpv6')
end
uci:section('network', 'rule6', 'wan6_lookup', {
mark = '0x01/0x01',
lookup = 1,
......
#!/usr/bin/lua
local platform = require 'gluon.platform'
local uci = require('simple-uci').cursor()
local switch_vlans = {
-- device identifier, lan ports, wan ports
["ubnt,unifiac-mesh-pro"] = {"3 0t", "2 0t"},
["ubnt,unifiac-pro"] = {"2 0t", "3 0t"},
}
local board_name = platform.get_board_name()
local assignments = switch_vlans[board_name]
if not platform.match('ath79', 'generic') or not assignments then
return
end
uci:delete_all('network', 'switch_vlan')
for vlan, ports in ipairs(assignments) do
uci:section("network", "switch_vlan", nil, {
device = "switch0",
vlan = vlan,
ports = ports,
})
end
uci:save('network')
#!/usr/bin/lua
-- This script needs to be sorted before 200-wireless as it affects
-- wireless channel selection and wireless mesh configuration.
local uci = require('simple-uci').cursor()
local site = require 'gluon.site'
if uci:get('gluon', 'wireless', 'outdoor') ~= nil then
-- don't overwrite existing configuration
os.exit(0)
end
local sysconfig = require 'gluon.sysconfig'
local platform = require 'gluon.platform'
local wireless = require 'gluon.wireless'
local config = site.wifi5.outdoors('preset')
local outdoor
if sysconfig.gluon_version then
-- don't enable the outdoor mode after an upgrade
outdoor = false
elseif config == 'preset' then
-- enable outdoor mode through presets on new installs
outdoor = platform.is_outdoor_device() and wireless.device_uses_11a(uci)
else
-- enable/disable outdoor mode unconditionally on new installs
outdoor = config
end
uci:section('gluon', 'wireless', 'wireless', {
outdoor = outdoor
})
uci:save('gluon')