2013-07-08 13:43:59 +02:00
|
|
|
local util = require("util.utils")
|
2013-07-17 08:25:24 +02:00
|
|
|
local l = require("util.logger")
|
2013-04-04 10:18:08 +02:00
|
|
|
local uci = require("uci").cursor()
|
|
|
|
local iwinfo = require("iwinfo")
|
|
|
|
|
|
|
|
local M = {}
|
|
|
|
|
2013-07-08 19:02:20 +02:00
|
|
|
--NOTE: fallback device 'radio0' is required because sometimes the wlan0 device disappears
|
|
|
|
M.DFL_DEVICE = "wlan0"
|
|
|
|
M.DFL_DEVICE_FALLBACK = "radio0"
|
2013-04-05 16:22:19 +02:00
|
|
|
M.NET = "wlan"
|
2013-04-04 10:18:08 +02:00
|
|
|
|
|
|
|
local dev, dev_api
|
|
|
|
|
|
|
|
|
|
|
|
--- Map device mode as reported by iwinfo to device mode as required by UCI
|
|
|
|
-- Note that this function is quite naive.
|
|
|
|
-- @param mode mode text as reported by iwinfo
|
|
|
|
-- @param masterIsAp set to true to map 'Master' to 'ap' instead of 'sta' (optional)
|
|
|
|
function M.mapDeviceMode(mode, masterIsAp)
|
|
|
|
local modeMap = {
|
|
|
|
["Master"] = masterIsAp and "ap" or "sta",
|
2013-04-05 16:22:19 +02:00
|
|
|
["Client"] = "sta",
|
2013-04-04 10:18:08 +02:00
|
|
|
["Ad-Hoc"] = "adhoc"
|
|
|
|
}
|
2013-04-05 16:22:19 +02:00
|
|
|
return modeMap[mode] or mode
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
2013-04-09 14:37:31 +02:00
|
|
|
--[[
|
|
|
|
- TODO: several modes need to be tested (wep, psk2, mixed-psk)
|
|
|
|
- See: http://wiki.openwrt.org/doc/uci/wireless#wpa.modes
|
|
|
|
]]
|
|
|
|
function M.mapEncryptionType(scanEncrTbl)
|
|
|
|
local wpaModeMap = { [1] = "psk", [2] = "psk2", [3] = "mixed-psk" }
|
|
|
|
|
|
|
|
if scanEncrTbl.enabled == false then return "none" end
|
|
|
|
if scanEncrTbl.wep == true then return "wep" end
|
|
|
|
|
|
|
|
return wpaModeMap[scanEncrTbl.wpa] or scanEncrTbl.description
|
|
|
|
end
|
|
|
|
|
2013-04-04 10:18:08 +02:00
|
|
|
|
|
|
|
--- Initialize WiFi helper library
|
|
|
|
-- @param device wireless device to operate on (optional, defaults to DFL_DEVICE)
|
|
|
|
-- @return true on success or false+error on failure
|
|
|
|
function M.init(device)
|
|
|
|
-- iwinfo = pcall(require, "iwinfo")
|
|
|
|
dev = device or M.DFL_DEVICE
|
|
|
|
dev_api = iwinfo.type(dev)
|
|
|
|
if not dev_api then
|
2013-07-08 19:02:20 +02:00
|
|
|
--TODO: warn about missing dev here?
|
|
|
|
local devInitial = dev
|
|
|
|
dev = M.DFL_DEVICE_FALLBACK
|
|
|
|
dev_api = iwinfo.type(dev)
|
|
|
|
|
|
|
|
if not dev_api then
|
|
|
|
return false, "No such wireless device: '" .. devInitial .. "' (and fallback '" .. dev .. "' does not exist either)"
|
|
|
|
end
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function M.getDeviceState()
|
|
|
|
local iw = iwinfo[dev_api]
|
|
|
|
local result = {
|
|
|
|
["ssid"] = iw.ssid(dev),
|
2013-07-08 18:12:05 +02:00
|
|
|
["bssid"] = iw.bssid(dev),
|
|
|
|
["channel"] = iw.channel(dev),
|
|
|
|
["mode"] = M.mapDeviceMode(iw.mode(dev), true),
|
|
|
|
["encryption"] = M.mapEncryptionType(iw.encryption(dev).description),
|
|
|
|
["quality"] = iw.quality(dev),
|
|
|
|
["quality_max"] = iw.quality_max(dev),
|
|
|
|
["txpower"] = iw.txpower(dev),
|
|
|
|
["signal"] = iw.signal(dev),
|
|
|
|
["noise"] = iw.noise(dev)
|
2013-04-04 10:18:08 +02:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
2013-07-11 10:30:59 +02:00
|
|
|
--returns the wireless device's MAC address (as string, without colons)
|
|
|
|
--(lua numbers on openWrt seem to be 32bit so they cannot represent a MAC address as one number)
|
|
|
|
function M.getMacAddress()
|
|
|
|
local iw = iwinfo[dev_api]
|
|
|
|
local macText = iw.bssid(dev)
|
|
|
|
local out = ""
|
|
|
|
|
|
|
|
for i = 0, 5 do
|
|
|
|
local bt = string.sub(macText, i*3+1, i*3+2)
|
|
|
|
out = out .. bt
|
|
|
|
end
|
|
|
|
|
|
|
|
return out
|
|
|
|
end
|
|
|
|
|
2013-04-04 10:18:08 +02:00
|
|
|
--- Return one or all available wifi networks resulting from an iwinfo scan
|
|
|
|
-- @param ssid return data for given SSID or for all networks if SSID not given
|
|
|
|
-- @return data for all or requested network; false+error on failure or nil when requested network not found
|
|
|
|
function M.getScanInfo(ssid)
|
|
|
|
local iw = iwinfo[dev_api]
|
|
|
|
local sr = iw.scanlist(dev)
|
|
|
|
local si, se
|
|
|
|
|
|
|
|
if ssid == nil then
|
|
|
|
return sr
|
|
|
|
else
|
|
|
|
if sr and #sr > 0 then
|
|
|
|
for _, se in ipairs(sr) do
|
|
|
|
if se.ssid == ssid then
|
|
|
|
return se
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return false, "No scan results or scanning not possible"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Return all wireless networks configured in UCI
|
|
|
|
function M.getConfigs()
|
|
|
|
local l = {}
|
|
|
|
uci.foreach("wireless", "wifi-iface", function(s) table.insert(l, s) end)
|
|
|
|
return l
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Remove UCI config for network with given SSID
|
|
|
|
-- @return true if successfully removed, false if no such config exists
|
|
|
|
function M.removeConfig(ssid)
|
|
|
|
local rv = false
|
|
|
|
uci:foreach("wireless", "wifi-iface", function(s)
|
|
|
|
if s.ssid == ssid then
|
|
|
|
uci:delete("wireless", s[".name"])
|
|
|
|
rv = true
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
uci:commit("wireless")
|
|
|
|
return rv
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Activate wireless section for given SSID and disable all others
|
|
|
|
-- @param ssid SSID of config to enable, or nil to disable all network configs
|
|
|
|
function M.activateConfig(ssid)
|
|
|
|
uci:foreach("wireless", "wifi-iface", function(s)
|
|
|
|
local disabled = s.ssid ~= ssid and "1" or "0"
|
|
|
|
uci:set("wireless", s[".name"], "disabled", disabled)
|
|
|
|
end)
|
|
|
|
uci:commit("wireless")
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Create a new UCI network from the given iwinfo data
|
|
|
|
-- http://luci.subsignal.org/trac/browser/luci/trunk/libs/iwinfo/src/iwinfo_wext.c?rev=5645 (outdated?)
|
2013-04-09 14:37:31 +02:00
|
|
|
-- TODO: delete previous network if exists (match on MAC-address)
|
2013-04-04 10:18:08 +02:00
|
|
|
-- @param info iwinfo data to create a network from
|
|
|
|
-- @param passphrase passphrase to use (optional)
|
|
|
|
-- @param disabled immediately disable the network (optional)
|
|
|
|
function M.createConfigFromScanInfo(info, passphrase, disabled)
|
|
|
|
local mode = M.mapDeviceMode(info.mode)
|
|
|
|
|
|
|
|
local apconfig = {
|
2013-04-05 16:22:19 +02:00
|
|
|
network = M.NET,
|
2013-04-04 10:18:08 +02:00
|
|
|
device = "radio0",
|
|
|
|
ssid = info.ssid,
|
|
|
|
bssid = info.bssid,
|
2013-04-09 14:37:31 +02:00
|
|
|
encryption = M.mapEncryptionType(info.encryption),
|
2013-04-04 10:18:08 +02:00
|
|
|
mode = mode,
|
|
|
|
}
|
|
|
|
if passphrase ~= nil then apconfig.key = passphrase end
|
|
|
|
apconfig.disabled = disabled ~= nil and disabled and 1 or 0
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
uci:foreach("wireless", "wifi-iface", function(s)
|
|
|
|
if s.bssid == info.bssid then
|
2013-06-30 19:06:55 +02:00
|
|
|
l:debug("removing old wireless config for net '" .. s.ssid .. "(bssid: " .. s.bssid .. ")'")
|
2013-04-18 11:30:48 +02:00
|
|
|
uci:delete("wireless", s[".name"])
|
|
|
|
-- return false --keep looking, just in case multiple entries with this bssid exist
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2013-04-04 10:18:08 +02:00
|
|
|
local sname = uci:add("wireless", "wifi-iface");
|
|
|
|
for k, v in pairs(apconfig) do
|
|
|
|
uci:set("wireless", sname, k, v)
|
|
|
|
end
|
|
|
|
uci:commit("wireless")
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Reload network config to reflect contents of config
|
|
|
|
-- @see http://wiki.openwrt.org/doc/techref/netifd)
|
|
|
|
-- * Network reload only restarts interfaces which need to be restarted so no
|
|
|
|
-- unneccesary interruptions there.
|
|
|
|
-- * ubus does not seem to work -- local c=ubus.connect();
|
|
|
|
-- c:call("network.interface.wlan", "down"); c:call("network.interface.wlan", "up"); c:close()
|
2013-04-05 16:22:19 +02:00
|
|
|
-- @param dhcpToo also reload dnsmasq if true
|
|
|
|
function M.restart(dhcpToo)
|
|
|
|
os.execute("/etc/init.d/network reload") --always seems to return 0
|
|
|
|
if dhcpToo ~= nil and dhcpToo then os.execute("/etc/init.d/dnsmasq reload") end
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
2013-04-04 10:18:08 +02:00
|
|
|
return M
|