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 1112 additions and 315 deletions
#!/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 sysconfig = require 'gluon.sysconfig'
local unistd = require 'posix.unistd'
if unistd.access('/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 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')
......@@ -8,53 +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 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 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
local try_files = {
'/sys/class/net/eth0/address'
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', 'koala',
'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')
elseif platform.match('ipq40xx', nil, {'avm,fritzbox-4040',
'openmesh,a42', 'openmesh,a62'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
end
for _, file in ipairs(try_files) do
local addr = util.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 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
for _, iface in ipairs(ifaces) do
if unistd.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then
return ifaces
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')
#!/usr/bin/lua
local wireless = require 'gluon.wireless'
local uci = require('simple-uci').cursor()
local preserve_channels = wireless.preserve_channels(uci)
uci:section('gluon', 'wireless', 'wireless', {
preserve_channels = preserve_channels or false,
})
uci:save('gluon')
#!/usr/bin/lua
local util = require 'gluon.util'
local wireless = require 'gluon.wireless'
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local iwinfo = require 'iwinfo'
......@@ -10,87 +11,102 @@ local uci = require('simple-uci').cursor()
-- Initial
if not sysconfig.gluon_version then
uci:delete_all('wireless', 'wifi-iface')
-- First count all radios with a fixed frequency band.
-- This is needed to distribute devices which have radios
-- capable of operating in the 2.4 GHz and 5 GHz band need
-- to be distributed evenly.
local radio_band_count = {band24=0, band5=0}
wireless.foreach_radio(uci, function(radio)
local hwmodes = iwinfo.nl80211.hwmodelist(wireless.find_phy(radio))
if hwmodes.g and not (hwmodes.a or hwmodes.ac) then
-- 2.4 GHz
radio_band_count["band24"] = radio_band_count["band24"] + 1
elseif (hwmodes.a or hwmodes.ac) and not hwmodes.g then
-- 5 GHz
radio_band_count["band5"] = radio_band_count["band5"] + 1
end
end)
-- Use the number of all fixed 2.4G GHz and 5 GHz radios to
-- distribute dualband radios in this step.
wireless.foreach_radio(uci, function(radio)
local radio_name = radio['.name']
local hwmodes = iwinfo.nl80211.hwmodelist(wireless.find_phy(radio))
if (hwmodes.a or hwmodes.ac) and hwmodes.g then
-- Dualband radio
if radio_band_count["band24"] <= radio_band_count["band5"] then
-- Assign radio to 2.4GHz band
radio_band_count["band24"] = radio_band_count["band24"] + 1
uci:set('wireless', radio_name, 'band', '2g')
else
-- Assign radio to 5GHz band
radio_band_count["band5"] = radio_band_count["band5"] + 1
uci:set('wireless', radio_name, 'band', '5g')
end
end
end)
end
local function is_outdoor()
return uci:get_bool('gluon', 'wireless', 'outdoor')
end
local function get_channel(radio, config)
local channel
if uci:get_first('gluon-core', 'wireless', 'preserve_channels') then
channel = radio.channel
if radio.band == '5g' and is_outdoor() then
-- actual channel will be picked and probed from chanlist
return 'auto'
end
return channel or config.channel()
return config.channel()
end
local function get_htmode(radio)
local phy = util.find_phy(radio)
if wireless.preserve_channels(uci) then
return radio.htmode
end
if radio.band == '5g' and is_outdoor() then
local outdoor_htmode = uci:get('gluon', 'wireless', 'outdoor_' .. radio['.name'] .. '_htmode')
if outdoor_htmode ~= nil then
return outdoor_htmode
end
end
local phy = wireless.find_phy(radio)
if iwinfo.nl80211.hwmodelist(phy).ax then
return 'HE20'
end
if iwinfo.nl80211.hwmodelist(phy).ac then
return 'VHT20'
else
return 'HT20'
end
return 'HT20'
end
local function is_disabled(name)
if uci:get('wireless', name) then
return uci:get_bool('wireless', name, 'disabled')
else
return false
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
local function configure_ibss(config, radio, index, suffix, disabled)
local radio_name = radio['.name']
local function delete_ibss(radio_name)
local name = 'ibss_' .. radio_name
uci:delete('network', name)
uci:delete('network', name .. '_vlan')
uci:delete('wireless', name)
if not config then
return
end
local macaddr = util.get_wlan_mac(uci, radio, index, 3)
if not macaddr then
return
end
if config.vlan then
uci:section('network', 'interface', name, {
proto = 'none',
})
uci:section('network', 'interface', name .. '_vlan', {
ifname = '@' .. name .. '.' .. config.vlan,
proto = 'gluon_mesh',
})
else
uci:section('network', 'interface', name, {
proto = 'gluon_mesh',
})
end
uci:section('wireless', 'wifi-iface', name, {
device = radio_name,
network = name,
mode = 'adhoc',
ssid = config.ssid,
bssid = config.bssid,
macaddr = macaddr,
mcast_rate = config.mcast_rate,
ifname = suffix and 'ibss' .. suffix,
disabled = disabled,
})
end
local function configure_mesh(config, radio, index, suffix, disabled)
......@@ -100,15 +116,13 @@ local function configure_mesh(config, radio, index, suffix, disabled)
local macfilter = uci:get('wireless', name, 'macfilter')
local maclist = uci:get('wireless', name, 'maclist')
uci:delete('network', name)
uci:delete('network', name .. '_vlan')
uci:delete('wireless', name)
if not config then
return
end
local macaddr = util.get_wlan_mac(uci, radio, index, 2)
local macaddr = wireless.get_wlan_mac(uci, radio, index, 2)
if not macaddr then
return
end
......@@ -124,6 +138,7 @@ local function configure_mesh(config, radio, index, suffix, disabled)
mesh_id = config.id,
mesh_fwding = false,
macaddr = macaddr,
basic_rate = { config.mcast_rate },
mcast_rate = config.mcast_rate,
ifname = suffix and 'mesh' .. suffix,
disabled = disabled,
......@@ -140,7 +155,7 @@ local function fixup_wan(radio, index)
return
end
local macaddr = util.get_wlan_mac(uci, radio, index, 4)
local macaddr = wireless.get_wlan_mac(uci, radio, index, 4)
if not macaddr then
return
end
......@@ -148,9 +163,38 @@ local function fixup_wan(radio, index)
uci:set('wireless', name, 'macaddr', macaddr)
end
util.foreach_radio(uci, function(radio, index, config)
local function configure_mesh_wireless(radio, index, config, disabled)
local radio_name = radio['.name']
local suffix = radio_name:match('^radio(%d+)$')
configure_mesh(config.mesh(), radio, index, suffix,
first_non_nil(
disabled,
is_disabled('mesh_' .. radio_name),
config.mesh.disabled(false)
)
)
end
local function set_channels(radio, radio_name, config)
if wireless.preserve_channels(uci) then
return
end
local channel = get_channel(radio, config)
uci:set('wireless', radio_name, 'channel', channel)
local chanlist
if radio.band == '5g' and is_outdoor() then
chanlist = config.outdoor_chanlist()
end
uci:set('wireless', radio_name, 'channels', chanlist)
end
wireless.foreach_radio(uci, function(radio, index, config)
local radio_name = radio['.name']
delete_ibss(radio_name)
if not config() then
uci:set('wireless', radio_name, 'disabled', true)
return
......@@ -161,48 +205,52 @@ util.foreach_radio(uci, function(radio, index, config)
return
end
local channel = get_channel(radio, config)
local htmode = get_htmode(radio)
local beacon_interval = config.beacon_interval()
uci:delete('wireless', radio_name, 'disabled')
uci:set('wireless', radio_name, 'channel', channel)
set_channels(radio, radio_name, config)
uci:set('wireless', radio_name, 'htmode', htmode)
uci:set('wireless', radio_name, 'country', site.regdom())
uci:set_list('wireless', radio_name, 'supported_rates', config.supported_rates())
uci:set_list('wireless', radio_name, 'basic_rate', config.basic_rate())
local ibss_disabled = is_disabled('ibss_' .. radio_name)
local mesh_disabled = is_disabled('mesh_' .. radio_name)
uci:delete('wireless', radio_name, 'supported_rates')
uci:delete('wireless', radio_name, 'basic_rate')
local band = radio.band
if band == '2g' then
uci:set('wireless', radio_name, 'legacy_rates', false)
configure_mesh_wireless(radio, index, config)
elseif (band == '5g') then
-- ToDo: Remove in v2024.x
local hostapd_options = uci:get_list('wireless', radio_name, 'hostapd_options')
util.remove_from_set(hostapd_options, 'country3=0x4f')
uci:set_list('wireless', radio_name, 'hostapd_options', hostapd_options)
if is_outdoor() then
-- enforce outdoor channels by filtering the regdom for outdoor channels
uci:set('wireless', radio_name, 'country3', '0x4f')
configure_mesh_wireless(radio, index, config, true)
else
uci:delete('wireless', radio_name, 'country3')
configure_mesh_wireless(radio, index, config)
end
end
configure_ibss(config.ibss(), radio, index, suffix,
first_non_nil(
ibss_disabled,
mesh_disabled,
config.ibss.disabled(false)
)
)
configure_mesh(config.mesh(), radio, index, suffix,
first_non_nil(
mesh_disabled,
ibss_disabled,
config.mesh.disabled(false)
)
)
uci:set('wireless', radio_name, 'beacon_int', beacon_interval)
fixup_wan(radio, index)
end)
if uci:get('system', 'rssid_wlan0') then
if uci:get('wireless', 'mesh_radio0') then
uci:set('system', 'rssid_wlan0', 'dev', 'mesh0')
else
uci:set('system', 'rssid_wlan0', 'dev', 'ibss0')
uci:save('system')
end
if uci:get('system', 'rssid_wlan1') then
uci:set('system', 'rssid_wlan1', 'dev', 'mesh1')
uci:save('system')
end
......
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local platform = require 'gluon.platform'
-- This is a workaround to result in a configuration where all ports
-- on the DSA switch are connected to the same CPU interface.
--
-- See Gluon issue #3479 for details.
-- https://github.com/freifunk-gluon/gluon/issues/3479
if not platform.match('ipq806x', 'generic', {
'netgear,r7800',
'tplink,c2600',
}) then
return
end
local ports = {
'lan1',
'lan2',
'lan3',
'lan4',
'wan',
}
local cpu_conduit = 'eth0'
for _, port in ipairs(ports) do
local section_name = 'port_' .. port
uci:section('network', 'device', section_name, {
name = port,
conduit = cpu_conduit,
})
end
uci:save('network')
#!/usr/bin/lua
local site = require 'gluon.site'
local uci = require('simple-uci').cursor()
local util = require 'gluon.util'
local mesh_interfaces = util.get_role_interfaces(uci, 'mesh')
local uplink_interfaces = util.get_role_interfaces(uci, 'uplink')
local mesh_interfaces_uplink = {}
local mesh_interfaces_other = {}
for _, iface in ipairs(mesh_interfaces) do
if util.contains(uplink_interfaces, iface) then
table.insert(mesh_interfaces_uplink, iface)
else
table.insert(mesh_interfaces_other, iface)
end
end
if #mesh_interfaces_uplink > 0 then
uci:section('network', 'interface', 'mesh_uplink', {
ifname = 'br-wan',
proto = 'gluon_wired',
index = 0,
vxlan = site.mesh.vxlan(true),
})
end
if #mesh_interfaces_other > 0 then
local iftype, ifname
if #mesh_interfaces_other == 1 then
ifname = mesh_interfaces_other[1]
else
iftype = 'bridge'
ifname = mesh_interfaces_other
for _, iface in ipairs(ifname) do
uci:section('network', 'device', nil, {
name = iface,
isolate = true,
})
end
end
uci:section('network', 'interface', 'mesh_other', {
ifname = ifname,
type = iftype,
igmp_snooping = false,
proto = 'gluon_wired',
index = 4,
vxlan = site.mesh.vxlan(true),
})
end
uci:save('network')