Merge pull request #990 from freifunk-ffm/christf_get_mesh_interfaces
gluon-core: add function to gluon.util that returns all active mesh-devices
This commit is contained in:
		
						commit
						2ddf77fc81
					
				| @ -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 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user