diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua index 0ae50b4d..f07f0ab1 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -1,25 +1,25 @@ -- 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) - local f = io.open(output, 'w+') - local l = prefix:len() + local f = io.open(output, 'w+') + local l = prefix:len() - for line in io.lines(input) do - if line:sub(1, l) ~= prefix then - f:write(line, '\n') - end - end + for line in io.lines(input) do + if line:sub(1, l) ~= prefix then + f:write(line, '\n') + end + end - return f + return f end local function escape_args(ret, arg0, ...) - if not arg0 then - return ret - end + if not arg0 then + return ret + end - return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...) + return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...) end @@ -38,79 +38,88 @@ local uci = require('luci.model.uci').cursor() local lutil = require 'luci.util' local fs = require 'nixio.fs' - module 'gluon.util' function exec(...) - return os.execute(escape_args('', 'exec', ...)) + return os.execute(escape_args('', 'exec', ...)) end -- Removes all lines starting with a prefix from a file, optionally adding a new one function replace_prefix(file, prefix, add) - local tmp = file .. '.tmp' - local f = do_filter_prefix(file, tmp, prefix) - if add then - f:write(add) - end - f:close() - os.rename(tmp, file) + local tmp = file .. '.tmp' + local f = do_filter_prefix(file, tmp, prefix) + if add then + f:write(add) + end + f:close() + os.rename(tmp, file) end function readline(fd) - local line = fd:read('*l') - fd:close() - return line + local line = fd:read('*l') + fd:close() + return line end function lock(file) - exec('lock', file) + exec('lock', file) end function unlock(file) - exec('lock', '-u', file) + exec('lock', '-u', file) end function node_id() - return string.gsub(sysconfig.primary_mac, ':', '') + return string.gsub(sysconfig.primary_mac, ':', '') end +function get_mesh_devices(uconn) + local dump = uconn:call("network.interface", "dump", {}) + local devices = {} + for _, interface in ipairs(dump.interface) do + if ( (interface.proto == "gluon_mesh") and interface.up ) then + table.insert(devices, interface.device) + end + end + return devices +end local function find_phy_by_path(path) - for phy in fs.glob('/sys/devices/' .. path .. '/ieee80211/phy*') do - return phy:match('([^/]+)$') - end + for phy in fs.glob('/sys/devices/' .. path .. '/ieee80211/phy*') do + return phy:match('([^/]+)$') + end end local function find_phy_by_macaddr(macaddr) - local addr = macaddr:lower() - for file in fs.glob('/sys/class/ieee80211/*/macaddress') do - if lutil.trim(fs.readfile(file)) == addr then - return file:match('([^/]+)/macaddress$') - end - end + local addr = macaddr:lower() + for file in fs.glob('/sys/class/ieee80211/*/macaddress') do + if lutil.trim(fs.readfile(file)) == addr then + return file:match('([^/]+)/macaddress$') + end + end end local function find_phy(radio) - local config = uci:get_all('wireless', radio) + local config = uci:get_all('wireless', radio) - 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 + 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 end local function get_addresses(radio) - local phy = find_phy(radio) - if not phy then - return function() end - end + local phy = find_phy(radio) + if not phy then + return function() end + end - return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses') + return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses') end -- Generates a (hopefully) unique MAC address @@ -126,70 +135,70 @@ end -- 6: ibss1 -- 7: wan_radio1 (private WLAN); mesh VPN function generate_mac(i) - if i > 7 or i < 0 then return nil end -- max allowed id (0b111) + 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) - local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)') + local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12) + local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)') - m1 = tonumber(m1, 16) - m6 = tonumber(m6, 16) + m1 = tonumber(m1, 16) + m6 = tonumber(m6, 16) - m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit - m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit + m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit + m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit - -- It's necessary that the first 45 bits of the MAC address don't - -- vary on a single hardware interface, since some chips are using - -- a hardware MAC filter. (e.g 'rt305x') + -- It's necessary that the first 45 bits of the MAC address don't + -- vary on a single hardware interface, since some chips are using + -- a hardware MAC filter. (e.g 'rt305x') - m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) - m6 = m6 + i -- add virtual interface id + m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) + m6 = m6 + i -- add virtual interface id - return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) + return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) end local function get_wlan_mac_from_driver(radio, vif) - local primary = sysconfig.primary_mac:lower() + local primary = sysconfig.primary_mac:lower() - local i = 1 - for addr in get_addresses(radio) do - if addr:lower() ~= primary then - if i == vif then - return addr - end + local i = 1 + for addr in get_addresses(radio) do + if addr:lower() ~= primary then + if i == vif then + return addr + end - i = i + 1 - end - end + i = i + 1 + end + end end function get_wlan_mac(radio, index, vif) - local addr = get_wlan_mac_from_driver(radio, vif) - if addr then - return addr - end + local addr = get_wlan_mac_from_driver(radio, vif) + if addr then + return addr + end - return generate_mac(4*(index-1) + (vif-1)) + return 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 iterate_radios(f) - local radios = {} + local radios = {} - uci:foreach('wireless', 'wifi-device', - function(s) - table.insert(radios, s['.name']) - end - ) + uci:foreach('wireless', 'wifi-device', + function(s) + table.insert(radios, s['.name']) + end + ) - for index, radio in ipairs(radios) do - local hwmode = uci:get('wireless', radio, 'hwmode') + for index, radio in ipairs(radios) do + local hwmode = uci:get('wireless', radio, 'hwmode') - if hwmode == '11g' or hwmode == '11ng' then - f(radio, index, site.wifi24) - elseif hwmode == '11a' or hwmode == '11na' then - f(radio, index, site.wifi5) - end - end + if hwmode == '11g' or hwmode == '11ng' then + f(radio, index, site.wifi24) + elseif hwmode == '11a' or hwmode == '11na' then + f(radio, index, site.wifi5) + end + end end