-- Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
-local type, next, pairs, ipairs, loadfile, table
- = type, next, pairs, ipairs, loadfile, table
+local type, next, pairs, ipairs, loadfile, table, select
+ = type, next, pairs, ipairs, loadfile, table, select
local tonumber, tostring, math = tonumber, tostring, math
local _interfaces, _bridge, _switch, _tunnel
local _ubusnetcache, _ubusdevcache, _ubuswificache
-local _uci_real, _uci_state
+local _uci
function _filter(c, s, o, r)
- local val = _uci_real:get(c, s, o)
+ local val = _uci:get(c, s, o)
if val then
local l = { }
if type(val) == "string" then
end
end
if #l > 0 then
- _uci_real:set(c, s, o, table.concat(l, " "))
+ _uci:set(c, s, o, table.concat(l, " "))
else
- _uci_real:delete(c, s, o)
+ _uci:delete(c, s, o)
end
elseif type(val) == "table" then
for _, val in ipairs(val) do
end
end
if #l > 0 then
- _uci_real:set(c, s, o, l)
+ _uci:set(c, s, o, l)
else
- _uci_real:delete(c, s, o)
+ _uci:delete(c, s, o)
end
end
end
end
function _append(c, s, o, a)
- local val = _uci_real:get(c, s, o) or ""
+ local val = _uci:get(c, s, o) or ""
if type(val) == "string" then
local l = { }
for val in val:gmatch("%S+") do
end
end
l[#l+1] = a
- _uci_real:set(c, s, o, table.concat(l, " "))
+ _uci:set(c, s, o, table.concat(l, " "))
elseif type(val) == "table" then
local l = { }
for _, val in ipairs(val) do
end
end
l[#l+1] = a
- _uci_real:set(c, s, o, l)
+ _uci:set(c, s, o, l)
end
end
end
function _get(c, s, o)
- return _uci_real:get(c, s, o)
+ return _uci:get(c, s, o)
end
function _set(c, s, o, v)
if v ~= nil then
if type(v) == "boolean" then v = v and "1" or "0" end
- return _uci_real:set(c, s, o, v)
+ return _uci:set(c, s, o, v)
else
- return _uci_real:delete(c, s, o)
+ return _uci:delete(c, s, o)
end
end
for radio, radiostate in pairs(_ubuswificache) do
for ifc, ifcstate in pairs(radiostate.interfaces) do
if ifcstate.section and ifcstate.section:sub(1, 1) == '@' then
- local s = _uci_real:get_all('wireless.%s' % ifcstate.section)
+ local s = _uci:get_all('wireless.%s' % ifcstate.section)
if s then
ifcstate.section = s['.name']
end
local num = 0
ifnidx = tonumber(ifnidx)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device == radio then
num = num + 1
return sid
- -- looks like wifi, try to locate the section via state vars
+ -- looks like wifi, try to locate the section via ubus state
elseif _wifi_iface(ifn) then
- local sid = _wifi_state("ifname", ifn, "section")
- if not sid then
- _uci_state:foreach("wireless", "wifi-iface",
- function(s)
- if s.ifname == ifn then
- sid = s['.name']
- return false
- end
- end)
- end
-
- return sid
+ return _wifi_state("ifname", ifn, "section")
end
end
function init(cursor)
- _uci_real = cursor or _uci_real or uci.cursor()
- _uci_state = _uci_real:substate()
+ _uci = cursor or _uci or uci.cursor()
_interfaces = { }
_bridge = { }
end
function save(self, ...)
- _uci_real:save(...)
- _uci_real:load(...)
+ _uci:save(...)
+ _uci:load(...)
end
function commit(self, ...)
- _uci_real:commit(...)
- _uci_real:load(...)
+ _uci:commit(...)
+ _uci:load(...)
end
function ifnameof(self, x)
function add_network(self, n, options)
local oldnet = self:get_network(n)
if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
- if _uci_real:section("network", "interface", n, options) then
+ if _uci:section("network", "interface", n, options) then
return network(n)
end
elseif oldnet and oldnet:is_empty() then
end
function get_network(self, n)
- if n and _uci_real:get("network", n) == "interface" then
+ if n and _uci:get("network", n) == "interface" then
return network(n)
end
end
local nets = { }
local nls = { }
- _uci_real:foreach("network", "interface",
+ _uci:foreach("network", "interface",
function(s)
nls[s['.name']] = network(s['.name'])
end)
end
function del_network(self, n)
- local r = _uci_real:delete("network", n)
+ local r = _uci:delete("network", n)
if r then
- _uci_real:delete_all("network", "alias",
+ _uci:delete_all("network", "alias",
function(s) return (s.interface == n) end)
- _uci_real:delete_all("network", "route",
+ _uci:delete_all("network", "route",
function(s) return (s.interface == n) end)
- _uci_real:delete_all("network", "route6",
+ _uci:delete_all("network", "route6",
function(s) return (s.interface == n) end)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local net
local rest = { }
end
end
if #rest > 0 then
- _uci_real:set("wireless", s['.name'], "network",
+ _uci:set("wireless", s['.name'], "network",
table.concat(rest, " "))
else
- _uci_real:delete("wireless", s['.name'], "network")
+ _uci:delete("wireless", s['.name'], "network")
end
end)
end
function rename_network(self, old, new)
local r
if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
- r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
+ r = _uci:section("network", "interface", new, _uci:get_all("network", old))
if r then
- _uci_real:foreach("network", "alias",
+ _uci:foreach("network", "alias",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("network", "route",
+ _uci:foreach("network", "route",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("network", "route6",
+ _uci:foreach("network", "route6",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local net
local list = { }
end
end
if #list > 0 then
- _uci_real:set("wireless", s['.name'], "network",
+ _uci:set("wireless", s['.name'], "network",
table.concat(list, " "))
end
end)
- _uci_real:delete("network", old)
+ _uci:delete("network", old)
end
end
return r or false
else
local ifc
local num = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
local baseof = { }
-- find normal interfaces
- _uci_real:foreach("network", "interface",
+ _uci:foreach("network", "interface",
function(s)
for iface in utl.imatch(s.ifname) do
if not _iface_ignore(iface) and not _wifi_iface(iface) then
end
-- find vlan interfaces
- _uci_real:foreach("network", "switch_vlan",
+ _uci:foreach("network", "switch_vlan",
function(s)
if not s.device then
return
-- find wifi interfaces
local num = { }
local wfs = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
end
function get_wifidev(self, dev)
- if _uci_real:get("wireless", dev) == "wifi-device" then
+ if _uci:get("wireless", dev) == "wifi-device" then
return wifidev(dev)
end
end
local devs = { }
local wfd = { }
- _uci_real:foreach("wireless", "wifi-device",
+ _uci:foreach("wireless", "wifi-device",
function(s) wfd[#wfd+1] = s['.name'] end)
local dev
function add_wifinet(self, net, options)
if type(options) == "table" and options.device and
- _uci_real:get("wireless", options.device) == "wifi-device"
+ _uci:get("wireless", options.device) == "wifi-device"
then
- local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
+ local wnet = _uci:section("wireless", "wifi-iface", nil, options)
return wifinet(wnet)
end
end
function del_wifinet(self, net)
local wnet = _wifi_lookup(net)
if wnet then
- _uci_real:delete("wireless", wnet)
+ _uci:delete("wireless", wnet)
return true
end
return false
function network(name, proto)
if name then
- local p = proto or _uci_real:get("network", name, "proto")
+ local p = proto or _uci:get("network", name, "proto")
local c = p and _protocols[p] or protocol
return c(name)
end
end
function protocol._get(self, opt)
- local v = _uci_real:get("network", self.sid, opt)
+ local v = _uci:get("network", self.sid, opt)
if type(v) == "table" then
return table.concat(v, " ")
end
end
if not ifname then
local num = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device]
end
function protocol.expires(self)
- local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
- local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
- if a and l then
- l = l - (nxo.sysinfo().uptime - a)
- return l > 0 and l or 0
+ local u = self:_ubus("uptime")
+ local d = self:_ubus("data")
+
+ if type(u) == "number" and type(d) == "table" and
+ type(d.leasetime) == "number"
+ then
+ local r = (d.leasetime - (u % d.leasetime))
+ return r > 0 and r or 0
end
+
return -1
end
function protocol.metric(self)
- return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
+ return self:_ubus("metric") or 0
end
function protocol.ipaddr(self)
return addrs and #addrs > 0 and addrs[1].address
end
+function protocol.ipaddrs(self)
+ local addrs = self:_ubus("ipv4-address")
+ local rv = { }
+
+ if type(addrs) == "table" then
+ local n, addr
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ return rv
+end
+
function protocol.netmask(self)
local addrs = self:_ubus("ipv4-address")
return addrs and #addrs > 0 and
end
end
+function protocol.ip6addrs(self)
+ local addrs = self:_ubus("ipv6-address")
+ local rv = { }
+ local n, addr
+
+ if type(addrs) == "table" then
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ addrs = self:_ubus("ipv6-prefix-assignment")
+
+ if type(addrs) == "table" then
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s1/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ return rv
+end
+
function protocol.gw6addr(self)
local _, route
for _, route in ipairs(self:_ubus("route") or { }) do
rv = false
end
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local n
for n in utl.imatch(s.network) do
else
local ifn = nil
local num = { }
- for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
+ for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do
ifn = ifn:match("^[^:/]+")
return ifn and interface(ifn, self)
end
ifn = nil
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
local num = { }
local wfs = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
local wif = _wifi_lookup(ifname)
if wif then
local n
- for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do
+ for n in utl.imatch(_uci:get("wireless", wif, "network")) do
if n == self.sid then
return true
end
end
function interface.mac(self)
- return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
+ local mac = self:_ubus("macaddr")
+ return mac and mac:upper()
end
function interface.ipaddrs(self)
return (_ubuswificache[self.sid].up == true)
end
- local up = false
- _uci_state:foreach("wireless", "wifi-iface",
- function(s)
- if s.device == self.sid then
- if s.up == "1" then
- up = true
- return false
- end
- end
- end)
-
- return up
+ return false
end
function wifidev.get_wifinet(self, net)
- if _uci_real:get("wireless", net) == "wifi-iface" then
+ if _uci:get("wireless", net) == "wifi-iface" then
return wifinet(net)
else
local wnet = _wifi_lookup(net)
function wifidev.get_wifinets(self)
local nets = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device == self.sid then
nets[#nets+1] = wifinet(s['.name'])
options = options or { }
options.device = self.sid
- local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
+ local wnet = _uci:section("wireless", "wifi-iface", nil, options)
if wnet then
return wifinet(wnet, options)
end
function wifidev.del_wifinet(self, net)
if utl.instanceof(net, wifinet) then
net = net.sid
- elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
+ elseif _uci:get("wireless", net) ~= "wifi-iface" then
net = _wifi_lookup(net)
end
- if net and _uci_real:get("wireless", net, "device") == self.sid then
- _uci_real:delete("wireless", net)
+ if net and _uci:get("wireless", net, "device") == self.sid then
+ _uci:delete("wireless", net)
return true
end
function wifinet.__init__(self, net, data)
self.sid = net
+ local n = 0
local num = { }
- local netid
- _uci_real:foreach("wireless", "wifi-iface",
+ local netid, sid
+ _uci:foreach("wireless", "wifi-iface",
function(s)
+ n = n + 1
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
if s['.name'] == self.sid then
+ sid = "@wifi-iface[%d]" % n
netid = "%s.network%d" %{ s.device, num[s.device] }
return false
end
end
end)
+ if sid then
+ local _, k, r, i
+ for k, r in pairs(_ubuswificache) do
+ if type(r) == "table" and
+ type(r.interfaces) == "table"
+ then
+ for _, i in ipairs(r.interfaces) do
+ if type(i) == "table" and i.section == sid then
+ self._ubusdata = {
+ radio = k,
+ dev = r,
+ net = i
+ }
+ end
+ end
+ end
+ end
+ end
+
local dev = _wifi_state("section", self.sid, "ifname") or netid
self.netid = netid
self.wdev = dev
self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
- self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
- _uci_real:get_all("wireless", self.sid) or { }
+end
+
+function wifinet.ubus(self, ...)
+ local n, v = self._ubusdata
+ for n = 1, select('#', ...) do
+ if type(v) == "table" then
+ v = v[select(n, ...)]
+ else
+ return nil
+ end
+ end
+ return v
end
function wifinet.get(self, opt)
end
function wifinet.mode(self)
- return _uci_state:get("wireless", self.sid, "mode") or "ap"
+ return self:ubus("net", "config", "mode") or self:get("mode") or "ap"
end
function wifinet.ssid(self)
- return _uci_state:get("wireless", self.sid, "ssid")
+ return self:ubus("net", "config", "ssid") or self:get("ssid")
end
function wifinet.bssid(self)
- return _uci_state:get("wireless", self.sid, "bssid")
+ return self:ubus("net", "config", "bssid") or self:get("bssid")
end
function wifinet.network(self)
- return _uci_state:get("wifinet", self.sid, "network")
+ local net, networks = nil, { }
+ for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
+ networks[#networks+1] = net
+ end
+ return networks
end
function wifinet.id(self)
end
function wifinet.ifname(self)
- local ifname = self.iwinfo.ifname
+ local ifname = self:ubus("net", "ifname") or self.iwinfo.ifname
if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
ifname = self.wdev
end
end
function wifinet.get_device(self)
- if self.iwdata.device then
- return wifidev(self.iwdata.device)
- end
+ local dev = self:ubus("radio") or self:get("device")
+ return dev and wifidev(dev) or nil
end
function wifinet.is_up(self)
end
function wifinet.active_mode(self)
- local m = _stror(self.iwdata.mode, self.iwinfo.mode) or "ap"
+ local m = self.iwinfo.mode or self:ubus("net", "config", "mode") or self:get("mode") or "ap"
if m == "ap" then m = "Master"
elseif m == "sta" then m = "Client"
end
function wifinet.active_ssid(self)
- return _stror(self.iwdata.ssid, self.iwinfo.ssid)
+ return self.iwinfo.ssid or self:ubus("net", "config", "ssid") or self:get("ssid")
end
function wifinet.active_bssid(self)
- return _stror(self.iwdata.bssid, self.iwinfo.bssid) or "00:00:00:00:00:00"
+ return self.iwinfo.bssid or self:ubus("net", "config", "bssid") or self:get("bssid")
end
function wifinet.active_encryption(self)
end
function wifinet.channel(self)
- return self.iwinfo.channel or
- tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
+ return self.iwinfo.channel or self:ubus("dev", "config", "channel") or
+ tonumber(self:get("channel"))
end
function wifinet.signal(self)
end
function wifinet.country(self)
- return self.iwinfo.country or "00"
+ return self.iwinfo.country or self:ubus("dev", "config", "country") or "00"
end
function wifinet.txpower(self)
function wifinet.get_networks(self)
local nets = { }
local net
- for net in utl.imatch(tostring(self.iwdata.network)) do
- if _uci_real:get("network", net) == "interface" then
+ for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
+ if _uci:get("network", net) == "interface" then
nets[#nets+1] = network(net)
end
end