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 811 additions and 345 deletions
#!/usr/bin/lua
local site = require 'gluon.site'
local uci = require('simple-uci').cursor()
uci:section('network', 'interface', 'mesh_wan', {
ifname = 'br-wan',
proto = 'gluon_wired',
index = 0,
})
local enable = site.mesh_on_wan(false)
local old_auto = uci:get('network', 'mesh_wan', 'auto')
local old_disabled = uci:get('network', 'mesh_wan', 'disabled')
if old_auto ~= nil or old_disabled ~= nil then
enable = old_auto ~= '0' and old_disabled ~= '1'
end
uci:set('network', 'mesh_wan', 'disabled', not enable)
if uci:get('network', 'mesh_wan', 'transitive') == nil then
uci:set('network', 'mesh_wan', 'transitive', true)
end
uci:delete('network', 'mesh_wan', 'auto')
uci:delete('network', 'mesh_wan', 'fixed_mtu')
uci:delete('network', 'mesh_wan', 'legacy')
uci:save('network')
#!/usr/bin/lua
local site = require 'gluon.site'
local util = require 'gluon.util'
local sysconfig = require 'gluon.sysconfig'
local uci = require('simple-uci').cursor()
if not sysconfig.lan_ifname then
os.exit(0)
end
uci:section('network', 'interface', 'mesh_lan', {
ifname = sysconfig.lan_ifname,
igmp_snooping = false,
proto = 'gluon_wired',
index = 4,
})
if sysconfig.lan_ifname:match(' ') then
uci:set('network', 'mesh_lan', 'type', 'bridge')
else
uci:delete('network', 'mesh_lan', 'type')
end
local enable = site.mesh_on_lan(false)
local old_auto = uci:get('network', 'mesh_lan', 'auto')
local old_disabled = uci:get('network', 'mesh_lan', 'disabled')
if old_auto ~= nil or old_disabled ~= nil then
enable = old_auto ~= '0' and old_disabled ~= '1'
end
if enable then
local interfaces = uci:get_list('network', 'client', 'ifname')
if interfaces then
for lanif in sysconfig.lan_ifname:gmatch('%S+') do
if util.contains(interfaces, lanif) then
enable = false
break
end
end
end
end
uci:set('network', 'mesh_lan', 'disabled', not enable)
if uci:get('network', 'mesh_lan', 'transitive') == nil then
uci:set('network', 'mesh_lan', 'transitive', true)
end
uci:delete('network', 'mesh_lan', 'auto')
uci:delete('network', 'mesh_lan', 'fixed_mtu')
uci:delete('network', 'mesh_lan', 'legacy')
uci:save('network')
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local platform = require 'gluon.platform'
if not platform.is_cellular_device() then
return
end
local function set_or_delete(package, section, option, val)
if val ~= nil and string.len(val) ~= 0 then
uci:set(package, section, option, val)
else
uci:delete(package, section, option)
end
end
local function setup_ncm_qmi(devpath, control_type, delay)
local pdptype = uci:get('gluon', 'cellular', 'pdptype')
local pincode = uci:get('gluon', 'cellular', 'pin')
local username = uci:get('gluon', 'cellular', 'username')
local password = uci:get('gluon', 'cellular', 'password')
local auth = uci:get('gluon', 'cellular', 'auth')
uci:section('network', 'interface', 'cellular', {
proto = control_type,
device = devpath,
disabled = not uci:get_bool('gluon', 'cellular', 'enabled'),
pdptype = pdptype,
peerdns = false,
apn = uci:get('gluon', 'cellular', 'apn'),
})
if pdptype ~= 'IP' then
uci:set('network', 'cellular', 'ipv6', 'auto')
else
uci:delete('network', 'cellular', 'ipv6')
end
set_or_delete('network', 'cellular', 'pincode', pincode)
set_or_delete('network', 'cellular', 'username', username)
set_or_delete('network', 'cellular', 'password', password)
set_or_delete('network', 'cellular', 'auth', auth)
set_or_delete('network', 'cellular', 'delay', delay)
end
if platform.match('ath79', 'nand', {
'glinet,gl-e750',
'glinet,gl-xe300',
}) then
setup_ncm_qmi('/dev/cdc-wdm0', 'qmi', 15)
elseif platform.match('ath79', 'nand', {
'zte,mf281',
}) then
setup_ncm_qmi('/dev/ttyACM0', 'ncm', 15)
elseif platform.match('ipq40xx', 'generic', {
'glinet,gl-ap1300',
'zte,mf289f',
}) then
setup_ncm_qmi('/dev/cdc-wdm0', 'qmi', 15)
elseif platform.match('ramips', 'mt7621', {
'wavlink,ws-wn572hp3-4g',
}) then
setup_ncm_qmi('/dev/ttyUSB2', 'ncm', 15)
elseif platform.match('ramips', 'mt76x8', {
'tplink,tl-mr6400-v5',
}) then
setup_ncm_qmi('/dev/cdc-wdm0', 'qmi', 15)
end
uci:save('network')
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local platform = require 'gluon.platform'
local defaults = uci:get_first('firewall', 'defaults')
......@@ -16,9 +17,19 @@ local function reject_input_on_wan(zone)
return true
end
local function add_cellular_wan(zone)
if zone.name == 'wan' then
uci:set('firewall', zone['.name'], 'network', {'wan', 'wan6', 'cellular_4', 'cellular_6'})
end
end
uci:foreach('firewall', 'zone', reject_input_on_wan)
for _, zone in ipairs({'mesh', 'local_client', 'wired_mesh'}) do
if platform.is_cellular_device() then
uci:foreach('firewall', 'zone', add_cellular_wan)
end
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 +63,10 @@ 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',
uci:section('firewall', 'rule', 'loc_client_ICMPv4_in', {
src = 'loc_client',
proto = 'icmp',
icmp_type = {
'echo-request',
......@@ -67,9 +75,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,
......@@ -80,9 +87,18 @@ for _, zone in ipairs({ 'wan', 'local_client', 'mesh' }) do
end
-- We can't put mesh_wan into this zone, as mesh_wan is the same
local wired_mesh_ifaces = {}
uci:foreach('network', 'interface',
function(iface)
-- Select all interfaces with proto gluon_wired except for
-- mesh_uplink into this zone, as mesh_uplink is the same
-- interface as wan, which has its own zone
uci:set('firewall', 'wired_mesh', 'network', {'mesh_lan'})
if iface['proto'] == 'gluon_wired' and iface['.name'] ~= 'mesh_uplink' then
table.insert(wired_mesh_ifaces, iface['.name'])
end
end
)
uci:set('firewall', 'wired_mesh', 'network', wired_mesh_ifaces)
-- VXLAN for wired meshing
for _, zone in ipairs({'wired_mesh', 'wan'}) do
......
......@@ -14,9 +14,9 @@ local util = require 'gluon.util'
local subst = {}
local f = io.popen('. /etc/os-release; echo "$ID"; echo "$VERSION_ID"; echo "$LEDE_BOARD"; echo "$LEDE_ARCH"')
local f = io.popen('. /etc/os-release; echo "$ID"; echo "$VERSION_ID"; echo "$OPENWRT_BOARD"; echo "$OPENWRT_ARCH"')
subst['%%d'] = f:read()
subst['%%v'] = f:read():gsub('-SNAPSHOT', '')
subst['%%v'] = f:read():gsub('-snapshot', '')
subst['%%S'] = f:read()
subst['%%A'] = f:read()
f:close()
......@@ -46,7 +46,7 @@ for line in io.lines('/etc/opkg/distfeeds.conf') do
table.insert(distfeeds, line)
end
local f = io.open('/etc/opkg/distfeeds.conf', 'w')
f = io.open('/etc/opkg/distfeeds.conf', 'w')
for _, line in ipairs(distfeeds) do
local name = line:match('^src/gz%s' .. prefix .. '(%S+)%s')
......@@ -62,7 +62,7 @@ end
f:close()
if next(extra) then
local f = io.open('/etc/opkg/gluon.conf', 'w')
f = io.open('/etc/opkg/gluon.conf', 'w')
for k, v in pairs(extra) do
f:write(string.format('src/gz %s %s\n', k, replace_patterns(v)))
......
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local function migrate_iface(iface)
if iface.proto ~= 'batadv' or iface.mesh ~= 'bat0' then
return
end
local s = iface['.name']
uci:set('network', s, 'proto', 'gluon_mesh')
uci:set('network', s, 'fixed_mtu', true)
if iface.mesh_no_rebroadcast then
uci:set('network', s, 'transitive', iface.mesh_no_rebroadcast)
end
uci:delete('network', s, 'mesh')
uci:delete('network', s, 'mesh_no_rebroadcast')
end
uci:foreach('network', 'interface', migrate_iface)
uci:save('network')
......@@ -12,13 +12,13 @@ uci:set('dhcp', dnsmasq, 'localise_queries', true)
uci:set('dhcp', dnsmasq, 'localservice', false)
uci:set('dhcp', dnsmasq, 'server', dns.servers)
uci:delete('dhcp', dnsmasq, 'cachesize')
uci:set('dhcp', dnsmasq, 'cachesize', dns.cacheentries)
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',
......
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
for _, config in ipairs({'system', 'network'}) do
uci:foreach(config .. '_gluon-old', nil, function(s)
if s.gluon_preserve ~= '1' then return end
-- Unnamed sections can't be preserved
if s['.anonymous'] then return end
-- We don't allow overwriting existing sections
if uci:get(config, s['.name']) then return end
uci:section(config, s['.type'], s['.name'], s)
end)
uci:save(config)
end
#!/usr/bin/lua
local info = require 'gluon.info'
local values = info.get_info_pretty()
local padTo = 24
for _, value in ipairs(values) do
local labelLen = string.len(value[1]) + 1
print(value[1] .. ':' .. string.rep(' ', padTo - labelLen), value[2])
end
#!/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})
local util = require 'gluon.util'
local unistd = require 'posix.unistd'
local dirent = require 'posix.dirent'
local uci = require('simple-uci').cursor()
local M = {}
local function has_devtype(iface_dir, devtype)
return util.file_contains_line(iface_dir..'/uevent', 'DEVTYPE='..devtype)
end
local function is_physical(iface_dir)
return unistd.access(iface_dir .. '/device') == 0
end
local function is_swconfig()
local has = false
uci:foreach("network", "switch", function()
has = true
end)
uci:foreach("network", "switch_vlan", function()
has = true
end)
return has
end
local function interfaces_raw()
local eth_ifaces = {}
local ifaces_dir = '/sys/class/net/'
for iface in dirent.files(ifaces_dir) do
if iface ~= '.' and iface ~= '..' then
local iface_dir = ifaces_dir .. iface
if is_physical(iface_dir) and not has_devtype(iface_dir, 'wlan') then
table.insert(eth_ifaces, iface)
end
end
end
return eth_ifaces
end
-- In comparison to interfaces_raw, this skips non-DSA ports on DSA devices,
-- as for ex. hap ac² has a special eth0 that shouldn't be touched
function M.interfaces()
local intfs = interfaces_raw()
if M.get_switch_type() == 'dsa' then
local new_intfs = {}
for _, intf in ipairs(intfs) do
if has_devtype('/sys/class/net/' .. intf, 'dsa') then
table.insert(new_intfs, intf)
end
end
return new_intfs
end
return intfs
end
function M.is_vlan(intf)
return has_devtype('/sys/class/net/' .. intf, 'vlan')
end
function M.get_switch_type()
if is_swconfig() then
return 'swconfig'
end
for _, intf in ipairs(interfaces_raw()) do
if has_devtype('/sys/class/net/' .. intf, 'dsa') then
return 'dsa'
end
end
return 'none'
end
return M
local uci = require('simple-uci').cursor()
local pretty_hostname = require 'pretty_hostname'
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local platform = require 'gluon.platform'
local util = require 'gluon.util'
local has_vpn, vpn = pcall(require, 'gluon.mesh-vpn')
local ethernet = require 'gluon.ethernet'
local pubkey
if has_vpn and vpn.enabled() then
local _, active_vpn = vpn.get_active_provider()
if active_vpn ~= nil then
pubkey = active_vpn.public_key()
end
end
local M = {}
function M.get_info()
local updater_enabled = uci:get_bool('autoupdater', 'settings', 'enabled')
return {
hostname = pretty_hostname.get(uci),
mac_address = sysconfig.primary_mac,
hardware_model = platform.get_model(),
gluon_version = util.trim(util.readfile('/lib/gluon/gluon-version')),
site_version = util.trim(util.readfile('/lib/gluon/site-version')),
firmware_release = util.trim(util.readfile('/lib/gluon/release')),
site = site.site_name(),
domain = uci:get('gluon', 'core', 'domain'),
public_vpn_key = pubkey,
switch_type = ethernet.get_switch_type(),
updater_branch = updater_enabled and uci:get('autoupdater', 'settings', 'branch'),
}
end
function M.get_info_pretty(i18n)
local _
if i18n then
local pkg_i18n = i18n 'gluon-core'
_ = function(s)
return pkg_i18n.translate(s)
end
else
_ = function(s)
return s
end
end
local data = M.get_info()
return {
{ _('Hostname'), data.hostname },
{ _('MAC address'), data.mac_address },
{ _('Hardware model'), data.hardware_model },
{ _('Gluon version') .. " / " .. _('Site version'), data.gluon_version .. " / " .. data.site_version },
{ _('Firmware release'), data.firmware_release },
{ _('Site'), data.site },
{ _('Domain'), data.domain or 'n/a' },
{ _('Public VPN key'), data.public_vpn_key or _('disabled') },
{ _('Switch type'), data.switch_type },
{ _('Autoupdater branch'), data.updater_branch or _('disabled') },
}
end
return M
#!/usr/bin/lua
local bit = require 'bit32'
local bit = require 'bit'
local sysconfig = require 'gluon.sysconfig'
local uci = require('simple-uci').cursor()
local site = require 'gluon.site'
local M = {}
function IPv6(address)
function M.IPv6(address)
--[[
(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
(c) 2008 Steven Barth <steven@midlink.org>
......@@ -77,10 +74,10 @@ function IPv6(address)
end
end
function mac_to_ip(prefix, mac)
function M.mac_to_ip(prefix, mac, firstbyte, secondbyte)
local m1, m2, m3, m6, m7, m8 = string.match(mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
local m4 = 0xff
local m5 = 0xfe
local m4 = firstbyte or 0xff
local m5 = secondbyte or 0xfe
m1 = bit.bxor(tonumber(m1, 16), 0x02)
local h1 = 0x100 * m1 + tonumber(m2, 16)
......@@ -88,15 +85,11 @@ function mac_to_ip(prefix, mac)
local h3 = 0x100 * m5 + tonumber(m6, 16)
local h4 = 0x100 * tonumber(m7, 16) + tonumber(m8, 16)
local prefix, plen = string.match(prefix, '(.*)/(%d+)')
plen = tonumber(plen, 10)
prefix = string.match(prefix, '(.*)/%d+')
local p1, p2, p3, p4, p5, p6, p7, p8 = IPv6(prefix)
local p1, p2, p3, p4 = M.IPv6(prefix)
return string.format("%x:%x:%x:%x:%x:%x:%x:%x/%d", p1, p2, p3, p4, h1, h2, h3, h4, 128)
end
local ip = mac_to_ip(site.node_prefix6(), sysconfig.primary_mac)
uci:set('network', 'loopback', 'ip6addr', ip)
uci:save('network')
return M
local platform_info = require 'platform_info'
local util = require 'gluon.util'
local setmetatable = setmetatable
module 'gluon.platform'
setmetatable(_M,
{
local M = setmetatable({}, {
__index = platform_info,
}
)
})
function match(target, subtarget, boards)
if get_target() ~= target then
function M.match(target, subtarget, boards)
if target and M.get_target() ~= target then
return false
end
if get_subtarget() ~= subtarget then
if subtarget and M.get_subtarget() ~= subtarget then
return false
end
if boards and not util.contains(boards, get_board_name()) then
if boards and not util.contains(boards, M.get_board_name()) then
return false
end
return true
end
function M.is_outdoor_device()
if M.match('ath79', 'generic', {
'devolo,dvl1750x',
'librerouter,librerouter-v1',
'plasmacloud,pa300',
'plasmacloud,pa300e',
'tplink,cpe210-v1',
'tplink,cpe210-v2',
'tplink,cpe210-v3',
'tplink,cpe220-v3',
'tplink,cpe510-v1',
'tplink,cpe510-v2',
'tplink,cpe510-v3',
'tplink,cpe710-v1',
'tplink,eap225-outdoor-v1',
'tplink,eap225-outdoor-v3',
'tplink,wbs210-v1',
'tplink,wbs210-v2',
'tplink,wbs510-v1',
'ubnt,nanobeam-ac-xc',
'ubnt,nanobeam-m5-xw',
'ubnt,nanostation-loco-m-xw',
'ubnt,nanostation-m-xw',
'ubnt,uk-ultra',
'ubnt,unifi-ap-outdoor-plus',
'ubnt,unifiac-mesh',
'ubnt,unifiac-mesh-pro',
}) then
return true
elseif M.match('ath79', 'mikrotik', {
'mikrotik,routerboard-wapr-2nd',
}) then
return true
elseif M.match('ipq40xx', 'generic', {
'aruba,ap-365',
'plasmacloud,pa1200',
}) then
return true
elseif M.match('ipq40xx', 'mikrotik', {
'mikrotik,sxtsq-5-ac',
}) then
return true
elseif M.match('mediatek', 'filogic', {
'cudy,ap3000outdoor-v1',
'wavlink,wl-wn573hx3',
}) then
return true
elseif M.match('ramips', 'mt7621', {
'wavlink,ws-wn572hp3-4g',
'zyxel,nwa55axe',
}) then
return true
end
return false
end
function M.is_cellular_device()
if M.match('ath79', 'nand', {
'zte,mf281',
'glinet,gl-e750',
'glinet,gl-xe300',
}) then
return true
elseif M.match('ipq40xx', 'generic', {
'glinet,gl-ap1300',
'zte,mf289f',
}) then
return true
elseif M.match('ramips', 'mt7621', {
'wavlink,ws-wn572hp3-4g',
}) then
return true
elseif M.match('ramips', 'mt76x8', {
'tplink,tl-mr6400-v5',
}) then
return true
end
return false
end
return M
......@@ -11,6 +11,10 @@ local function get(_, name)
end
local function set(_, name, val)
if val == get(nil, name) then
return
end
if val then
local f = io.open(sysconfigdir .. name, 'w+')
f:write(val, '\n')
......@@ -20,15 +24,7 @@ local function set(_, name, val)
end
end
local setmetatable = setmetatable
module 'gluon.sysconfig'
setmetatable(_M,
{
return setmetatable({}, {
__index = get,
__newindex = set,
}
)
return _M
})
local util = require 'gluon.util'
local os = os
local string = string
local M = {}
module 'gluon.users'
function remove_user(username)
function M.remove_user(username)
os.execute('exec lock /var/lock/passwd')
util.replace_prefix('/etc/passwd', username .. ':')
util.replace_prefix('/etc/shadow', username .. ':')
os.execute('exec lock -u /var/lock/passwd')
end
function remove_group(groupname)
function M.remove_group(groupname)
os.execute('exec lock /var/lock/group')
util.replace_prefix('/etc/group', groupname .. ':')
os.execute('exec lock -u /var/lock/group')
end
return M
local bit = require 'bit32'
local posix_fcntl = require 'posix.fcntl'
local posix_glob = require 'posix.glob'
local posix_syslog = require 'posix.syslog'
local posix_unistd = require 'posix.unistd'
local hash = require 'hash'
local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site'
local unistd = require 'posix.unistd'
local M = {}
-- Writes all lines from the file input to the file output except those starting with prefix
-- Doesn't close the output file, but returns the file object
local function do_filter_prefix(input, output, prefix)
......@@ -13,29 +26,11 @@ local function do_filter_prefix(input, output, prefix)
return f
end
local io = io
local os = os
local string = string
local tonumber = tonumber
local ipairs = ipairs
local pairs = pairs
local table = table
local bit = require 'bit'
local posix_glob = require 'posix.glob'
local hash = require 'hash'
local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site'
module 'gluon.util'
function trim(str)
return str:gsub("^%s*(.-)%s*$", "%1")
function M.trim(str)
return (str:gsub("^%s*(.-)%s*$", "%1"))
end
function contains(table, value)
function M.contains(table, value)
for k, v in pairs(table) do
if value == v then
return k
......@@ -44,7 +39,20 @@ function contains(table, value)
return false
end
function add_to_set(t, itm)
function M.file_contains_line(path, value)
if not unistd.access(path) then
return false
end
for line in io.lines(path) do
if line == value then
return true
end
end
return false
end
function M.add_to_set(t, itm)
for _,v in ipairs(t) do
if v == itm then return false end
end
......@@ -52,7 +60,7 @@ function add_to_set(t, itm)
return true
end
function remove_from_set(t, itm)
function M.remove_from_set(t, itm)
local i = 1
local changed = false
while i <= #t do
......@@ -67,7 +75,7 @@ function remove_from_set(t, itm)
end
-- Removes all lines starting with a prefix from a file, optionally adding a new one
function replace_prefix(file, prefix, add)
function M.replace_prefix(file, prefix, add)
local tmp = file .. '.tmp'
local f = do_filter_prefix(file, tmp, prefix)
if add then
......@@ -87,23 +95,23 @@ local function readall(f)
return data
end
function readfile(file)
function M.readfile(file)
return readall(io.open(file))
end
function exec(command)
function M.exec(command)
return readall(io.popen(command))
end
function node_id()
return string.gsub(sysconfig.primary_mac, ':', '')
function M.node_id()
return (string.gsub(sysconfig.primary_mac, ':', ''))
end
function default_hostname()
return site.hostname_prefix('') .. node_id()
function M.default_hostname()
return site.hostname_prefix('') .. M.node_id()
end
function domain_seed_bytes(key, length)
function M.domain_seed_bytes(key, length)
local ret = ''
local v = ''
local i = 0
......@@ -119,7 +127,7 @@ function domain_seed_bytes(key, length)
return ret:sub(0, 2*length)
end
function get_mesh_devices(uconn)
function M.get_mesh_devices(uconn)
local dump = uconn:call("network.interface", "dump", {})
local devices = {}
for _, interface in ipairs(dump.interface) do
......@@ -130,49 +138,39 @@ function get_mesh_devices(uconn)
return devices
end
-- Safe glob: returns an empty table when the glob fails because of
-- a non-existing path
function glob(pattern)
return posix_glob.glob(pattern) or {}
end
local function find_phy_by_path(path)
local phy = glob('/sys/devices/' .. path .. '/ieee80211/phy*')[1]
or glob('/sys/devices/platform/' .. path .. '/ieee80211/phy*')[1]
if phy then
return phy:match('([^/]+)$')
end
end
-- Returns a list of all interfaces with a given role
--
-- If exclusive is set to true, only interfaces that have no other role
-- are returned; this is used to ensure that the client role is not active
-- at the same time as any other role
function M.get_role_interfaces(uci, role, exclusive)
local ret = {}
local function find_phy_by_macaddr(macaddr)
local addr = macaddr:lower()
for _, file in ipairs(glob('/sys/class/ieee80211/*/macaddress')) do
if trim(readfile(file)) == addr then
return file:match('([^/]+)/macaddress$')
local function add(name)
-- Interface names with a / prefix refer to sysconfig interfaces
-- (lan_ifname/wan_ifname/single_ifname)
if string.sub(name, 1, 1) == '/' then
name = sysconfig[string.sub(name, 2) .. '_ifname'] or ''
end
for iface in string.gmatch(name, '%S+') do
M.add_to_set(ret, iface)
end
end
function find_phy(config)
if not config or config.type ~= 'mac80211' then
return nil
elseif config.path then
return find_phy_by_path(config.path)
elseif config.macaddr then
return find_phy_by_macaddr(config.macaddr)
else
return nil
end
uci:foreach('gluon', 'interface', function(s)
local roles = s.role or {}
if M.contains(roles, role) and (not exclusive or #roles == 1) then
add(s.name)
end
end)
local function get_addresses(uci, radio)
local phy = find_phy(radio)
if not phy then
return function() end
return ret
end
return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses')
-- Safe glob: returns an empty table when the glob fails because of
-- a non-existing path
function M.glob(pattern)
return posix_glob.glob(pattern, 0) or {}
end
-- Generates a (hopefully) unique MAC address
......@@ -181,13 +179,13 @@ end
-- IDs defined so far:
-- 0: client0; WAN
-- 1: mesh0
-- 2: ibss0
-- 2: owe0
-- 3: wan_radio0 (private WLAN); batman-adv primary address
-- 4: client1; LAN
-- 5: mesh1
-- 6: ibss1
-- 6: owe1
-- 7: wan_radio1 (private WLAN); mesh VPN
function generate_mac(i)
function M.generate_mac(i)
if i > 7 or i < 0 then return nil end -- max allowed id (0b111)
local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12)
......@@ -209,47 +207,103 @@ function generate_mac(i)
return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6)
end
local function get_wlan_mac_from_driver(uci, radio, vif)
local primary = sysconfig.primary_mac:lower()
function M.get_uptime()
local uptime_file = M.readfile("/proc/uptime")
if uptime_file == nil then
-- Something went wrong reading "/proc/uptime"
return nil
end
return tonumber(uptime_file:match('^[^ ]+'))
end
local i = 1
for addr in get_addresses(uci, radio) do
if addr:lower() ~= primary then
if i == vif then
return addr
function M.log(message, verbose)
if verbose then
io.stdout:write(message .. '\n')
end
i = i + 1
posix_syslog.syslog(posix_syslog.LOG_INFO, message)
end
local function close_fds(fds)
for _, fd in pairs(fds) do
posix_unistd.close(fd)
end
end
function get_wlan_mac(uci, radio, index, vif)
local addr = get_wlan_mac_from_driver(uci, radio, vif)
if addr then
return addr
M.subprocess = {}
M.subprocess.DEVNULL = -1
M.subprocess.PIPE = 1
-- Execute a program found using command PATH search, like the shell.
-- Return the pid, as well as the I/O streams as pipes or nil on error.
function M.subprocess.popen(path, argt, options)
argt = argt or {}
local childfds = {}
local parentfds = {}
local stdiostreams = {stdin = 0, stdout = 1, stderr = 2}
for iostream in pairs(stdiostreams) do
if options[iostream] == M.subprocess.PIPE then
local piper, pipew = posix_unistd.pipe()
if iostream == "stdin" then
childfds[iostream] = piper
parentfds[iostream] = pipew
else
childfds[iostream] = pipew
parentfds[iostream] = piper
end
end
end
return generate_mac(4*(index-1) + (vif-1))
-- childfds: r0, w1, w2
-- parentfds: w0, r1, r2
local pid, errmsg, errnum = posix_unistd.fork()
if pid == nil then
close_fds(parentfds)
close_fds(childfds)
return nil, errmsg, errnum
elseif pid == 0 then
local null = -1
if M.contains(options, M.subprocess.DEVNULL) then
-- only open if there's anything to discard
null = posix_fcntl.open('/dev/null', posix_fcntl.O_RDWR)
end
-- Iterate over all radios defined in UCI calling
-- f(radio, index, site.wifiX) for each radio found while passing
-- site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones.
function foreach_radio(uci, f)
local radios = {}
for iostream, fd in pairs(stdiostreams) do
local option = options[iostream]
if option == M.subprocess.DEVNULL then
posix_unistd.dup2(null, fd)
elseif option == M.subprocess.PIPE then
posix_unistd.dup2(childfds[iostream], fd)
end
end
close_fds(childfds)
close_fds(parentfds)
uci:foreach('wireless', 'wifi-device', function(radio)
table.insert(radios, radio)
end)
-- close potential null
if null > 2 then
posix_unistd.close(null)
end
posix_unistd.execp(path, argt)
posix_unistd._exit(127)
end
for index, radio in ipairs(radios) do
local hwmode = radio.hwmode
close_fds(childfds)
if hwmode == '11g' or hwmode == '11ng' then
f(radio, index, site.wifi24)
elseif hwmode == '11a' or hwmode == '11na' then
f(radio, index, site.wifi5)
return pid, parentfds
end
function M.get_mem_total()
for line in io.lines('/proc/meminfo') do
local match = line:match('^MemTotal:%s+(%d+)')
if match then
return tonumber(match)
end
end
end
return M
local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site'
local util = require 'gluon.util'
local unistd = require 'posix.unistd'
local iwinfo = require 'iwinfo'
local M = {}
function M.find_phy(config)
return iwinfo.nl80211.phyname(config['.name'])
end
local function get_addresses(radio)
local phy = M.find_phy(radio)
if not phy then
return function() end
end
return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses')
end
local function get_wlan_mac_from_driver(radio, vif)
local primary = sysconfig.primary_mac:lower()
local addresses = {}
for address in get_addresses(radio) do
if address:lower() ~= primary then
table.insert(addresses, address)
end
end
-- Make sure we have at least 4 addresses
if #addresses < 4 then
return nil
end
return addresses[vif]
end
function M.get_wlan_mac(_, radio, index, vif)
local addr = get_wlan_mac_from_driver(radio, vif)
if addr then
return addr
end
return util.generate_mac(4*(index-1) + (vif-1))
end
-- Iterate over all radios defined in UCI calling
-- f(radio, index, site.wifiX) for each radio found while passing
-- site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones.
function M.foreach_radio(uci, f)
local radios = {}
uci:foreach('wireless', 'wifi-device', function(radio)
table.insert(radios, radio)
end)
for index, radio in ipairs(radios) do
local band = radio.band
if band == '2g' then
f(radio, index, site.wifi24)
elseif band == '5g' then
f(radio, index, site.wifi5)
end
end
end
function M.preserve_channels(uci)
return uci:get_bool('gluon', 'wireless', 'preserve_channels')
end
function M.device_supports_wpa3()
return unistd.access('/lib/gluon/features/wpa3')
end
function M.device_supports_mfp(uci)
local supports_mfp = true
if not M.device_supports_wpa3() then
return false
end
uci:foreach('wireless', 'wifi-device', function(radio)
local phy = M.find_phy(radio)
local phypath = '/sys/kernel/debug/ieee80211/' .. phy .. '/'
if not util.file_contains_line(phypath .. 'hwflags', 'MFP_CAPABLE') then
supports_mfp = false
return false
end
end)
return supports_mfp
end
function M.device_uses_wlan(uci)
local ret = false
uci:foreach('wireless', 'wifi-device', function()
ret = true
return false
end)
return ret
end
function M.device_uses_11a(uci)
local ret = false
uci:foreach('wireless', 'wifi-device', function(radio)
if radio.band == '5g' then
ret = true
return false
end
end)
return ret
end
return M
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-filter-multicast
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk
......