2015-01-16 22:38:38 +00:00
|
|
|
-- Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
|
|
|
|
-- Licensed to the public under the Apache License 2.0.
|
2009-10-08 09:32:00 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
local type, next, pairs, ipairs, loadfile, table, select
|
|
|
|
= type, next, pairs, ipairs, loadfile, table, select
|
2011-12-05 19:36:50 +00:00
|
|
|
|
2012-09-15 14:02:27 +00:00
|
|
|
local tonumber, tostring, math = tonumber, tostring, math
|
2009-10-08 09:32:00 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local pcall, require, setmetatable = pcall, require, setmetatable
|
2011-10-03 13:57:11 +00:00
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
local nxo = require "nixio"
|
2011-10-03 13:57:11 +00:00
|
|
|
local nfs = require "nixio.fs"
|
2009-10-08 09:32:00 +00:00
|
|
|
local ipc = require "luci.ip"
|
|
|
|
local utl = require "luci.util"
|
2010-10-28 18:30:15 +00:00
|
|
|
local uci = require "luci.model.uci"
|
2012-09-15 14:02:27 +00:00
|
|
|
local lng = require "luci.i18n"
|
2015-11-20 23:31:06 +00:00
|
|
|
local jsc = require "luci.jsonc"
|
2009-10-08 09:32:00 +00:00
|
|
|
|
|
|
|
module "luci.model.network"
|
|
|
|
|
2009-10-15 16:30:17 +00:00
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
IFACE_PATTERNS_VIRTUAL = { }
|
2016-04-26 19:01:08 +00:00
|
|
|
IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^gre%d", "^gretap%d", "^ip6gre%d", "^ip6tnl%d", "^tunl%d", "^lo$" }
|
2011-10-03 13:57:11 +00:00
|
|
|
IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
IFACE_ERRORS = {
|
|
|
|
CONNECT_FAILED = lng.translate("Connection attempt failed"),
|
|
|
|
INVALID_ADDRESS = lng.translate("IP address in invalid"),
|
|
|
|
INVALID_GATEWAY = lng.translate("Gateway address is invalid"),
|
|
|
|
INVALID_LOCAL_ADDRESS = lng.translate("Local IP address is invalid"),
|
|
|
|
MISSING_ADDRESS = lng.translate("IP address is missing"),
|
|
|
|
MISSING_PEER_ADDRESS = lng.translate("Peer address is missing"),
|
|
|
|
NO_DEVICE = lng.translate("Network device is not present"),
|
|
|
|
NO_IFACE = lng.translate("Unable to determine device name"),
|
|
|
|
NO_IFNAME = lng.translate("Unable to determine device name"),
|
|
|
|
NO_WAN_ADDRESS = lng.translate("Unable to determine external IP address"),
|
|
|
|
NO_WAN_LINK = lng.translate("Unable to determine upstream interface"),
|
|
|
|
PEER_RESOLVE_FAIL = lng.translate("Unable to resolve peer host name"),
|
|
|
|
PIN_FAILED = lng.translate("PIN code rejected")
|
|
|
|
}
|
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
protocol = utl.class()
|
|
|
|
|
|
|
|
local _protocols = { }
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2016-08-15 15:52:28 +00:00
|
|
|
local _interfaces, _bridge, _switch, _tunnel, _swtopo
|
2015-01-15 10:10:02 +00:00
|
|
|
local _ubusnetcache, _ubusdevcache, _ubuswificache
|
2015-11-17 16:35:02 +00:00
|
|
|
local _uci
|
2011-10-03 13:57:11 +00:00
|
|
|
|
|
|
|
function _filter(c, s, o, r)
|
2015-11-17 16:35:02 +00:00
|
|
|
local val = _uci:get(c, s, o)
|
2010-10-28 18:30:15 +00:00
|
|
|
if val then
|
|
|
|
local l = { }
|
|
|
|
if type(val) == "string" then
|
|
|
|
for val in val:gmatch("%S+") do
|
|
|
|
if val ~= r then
|
|
|
|
l[#l+1] = val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #l > 0 then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set(c, s, o, table.concat(l, " "))
|
2010-10-28 18:30:15 +00:00
|
|
|
else
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete(c, s, o)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
elseif type(val) == "table" then
|
|
|
|
for _, val in ipairs(val) do
|
|
|
|
if val ~= r then
|
|
|
|
l[#l+1] = val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #l > 0 then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set(c, s, o, l)
|
2010-10-28 18:30:15 +00:00
|
|
|
else
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete(c, s, o)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
function _append(c, s, o, a)
|
2015-11-17 16:35:02 +00:00
|
|
|
local val = _uci:get(c, s, o) or ""
|
2010-10-28 18:30:15 +00:00
|
|
|
if type(val) == "string" then
|
|
|
|
local l = { }
|
|
|
|
for val in val:gmatch("%S+") do
|
|
|
|
if val ~= a then
|
|
|
|
l[#l+1] = val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
l[#l+1] = a
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set(c, s, o, table.concat(l, " "))
|
2010-10-28 18:30:15 +00:00
|
|
|
elseif type(val) == "table" then
|
|
|
|
local l = { }
|
|
|
|
for _, val in ipairs(val) do
|
|
|
|
if val ~= a then
|
|
|
|
l[#l+1] = val
|
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
l[#l+1] = a
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set(c, s, o, l)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function _stror(s1, s2)
|
|
|
|
if not s1 or #s1 == 0 then
|
|
|
|
return s2 and #s2 > 0 and s2
|
|
|
|
else
|
|
|
|
return s1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function _get(c, s, o)
|
2015-11-17 16:35:02 +00:00
|
|
|
return _uci:get(c, s, o)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function _set(c, s, o, v)
|
|
|
|
if v ~= nil then
|
|
|
|
if type(v) == "boolean" then v = v and "1" or "0" end
|
2015-11-17 16:35:02 +00:00
|
|
|
return _uci:set(c, s, o, v)
|
2010-10-30 00:40:07 +00:00
|
|
|
else
|
2015-11-17 16:35:02 +00:00
|
|
|
return _uci:delete(c, s, o)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local function _wifi_state()
|
|
|
|
if not next(_ubuswificache) then
|
|
|
|
_ubuswificache = utl.ubus("network.wireless", "status", {}) or {}
|
|
|
|
end
|
|
|
|
return _ubuswificache
|
|
|
|
end
|
|
|
|
|
2018-01-01 23:30:53 +00:00
|
|
|
local function _wifi_state_by_sid(sid)
|
|
|
|
local t1, n1 = _uci:get("wireless", sid)
|
|
|
|
if t1 == "wifi-iface" and n1 ~= nil then
|
|
|
|
local radioname, radiostate
|
|
|
|
for radioname, radiostate in pairs(_wifi_state()) do
|
|
|
|
if type(radiostate) == "table" and
|
|
|
|
type(radiostate.interfaces) == "table"
|
|
|
|
then
|
|
|
|
local netidx, netstate
|
|
|
|
for netidx, netstate in ipairs(radiostate.interfaces) do
|
|
|
|
if type(netstate) == "table" and
|
|
|
|
type(netstate.section) == "string"
|
|
|
|
then
|
|
|
|
local t2, n2 = _uci:get("wireless", netstate.section)
|
|
|
|
if t1 == t2 and n1 == n2 then
|
|
|
|
return radioname, radiostate, netstate
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function _wifi_state_by_ifname(ifname)
|
|
|
|
if type(ifname) == "string" then
|
|
|
|
local radioname, radiostate
|
|
|
|
for radioname, radiostate in pairs(_wifi_state()) do
|
|
|
|
if type(radiostate) == "table" and
|
|
|
|
type(radiostate.interfaces) == "table"
|
|
|
|
then
|
|
|
|
local netidx, netstate
|
|
|
|
for netidx, netstate in ipairs(radiostate.interfaces) do
|
|
|
|
if type(netstate) == "table" and
|
|
|
|
type(netstate.ifname) == "string" and
|
|
|
|
netstate.ifname == ifname
|
|
|
|
then
|
|
|
|
return radioname, radiostate, netstate
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function _wifi_iface(x)
|
2011-10-03 13:57:11 +00:00
|
|
|
local _, p
|
|
|
|
for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
|
|
|
|
if x:match(p) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
2019-11-14 10:12:40 +00:00
|
|
|
return (nfs.access("/sys/class/net/%s/phy80211" % x) == true)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local function _wifi_iwinfo_by_ifname(ifname, force_phy_only)
|
|
|
|
local stat, iwinfo = pcall(require, "iwinfo")
|
|
|
|
local iwtype = stat and type(ifname) == "string" and iwinfo.type(ifname)
|
|
|
|
local is_nonphy_op = {
|
|
|
|
bitrate = true,
|
|
|
|
quality = true,
|
|
|
|
quality_max = true,
|
|
|
|
mode = true,
|
|
|
|
ssid = true,
|
|
|
|
bssid = true,
|
|
|
|
assoclist = true,
|
|
|
|
encryption = true
|
|
|
|
}
|
2014-10-21 21:38:51 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
if iwtype then
|
|
|
|
-- if we got a type but no real netdev, we're referring to a phy
|
|
|
|
local phy_only = force_phy_only or (ipc.link(ifname).type ~= 1)
|
|
|
|
|
|
|
|
return setmetatable({}, {
|
|
|
|
__index = function(t, k)
|
|
|
|
if k == "ifname" then
|
|
|
|
return ifname
|
|
|
|
elseif phy_only and is_nonphy_op[k] then
|
|
|
|
return nil
|
|
|
|
elseif iwinfo[iwtype][k] then
|
|
|
|
return iwinfo[iwtype][k](ifname)
|
2014-10-21 21:38:51 +00:00
|
|
|
end
|
|
|
|
end
|
2018-01-01 23:24:10 +00:00
|
|
|
})
|
2013-12-03 15:04:34 +00:00
|
|
|
end
|
2018-01-01 23:24:10 +00:00
|
|
|
end
|
2013-12-03 15:04:34 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local function _wifi_sid_by_netid(netid)
|
|
|
|
if type(netid) == "string" then
|
|
|
|
local radioname, netidx = netid:match("^(%w+)%.network(%d+)$")
|
|
|
|
if radioname and netidx then
|
|
|
|
local i, n = 0, nil
|
|
|
|
|
|
|
|
netidx = tonumber(netidx)
|
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
|
|
|
function(s)
|
|
|
|
if s.device == radioname then
|
|
|
|
i = i + 1
|
|
|
|
if i == netidx then
|
|
|
|
n = s[".name"]
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
return n
|
2013-12-03 15:04:34 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
function _wifi_sid_by_ifname(ifn)
|
|
|
|
local sid = _wifi_sid_by_netid(ifn)
|
|
|
|
if sid then
|
|
|
|
return sid
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local _, _, netstate = _wifi_state_by_ifname(ifn)
|
|
|
|
if netstate and type(netstate.section) == "string" then
|
|
|
|
return netstate.section
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function _wifi_netid_by_sid(sid)
|
|
|
|
local t, n = _uci:get("wireless", sid)
|
|
|
|
if t == "wifi-iface" and n ~= nil then
|
|
|
|
local radioname = _uci:get("wireless", n, "device")
|
|
|
|
if type(radioname) == "string" then
|
|
|
|
local i, netid = 0, nil
|
|
|
|
|
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
|
|
|
function(s)
|
|
|
|
if s.device == radioname then
|
|
|
|
i = i + 1
|
|
|
|
if s[".name"] == n then
|
|
|
|
netid = "%s.network%d" %{ radioname, i }
|
|
|
|
return false
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
2018-01-01 23:24:10 +00:00
|
|
|
end)
|
|
|
|
|
|
|
|
return netid, radioname
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function _wifi_netid_by_netname(name)
|
|
|
|
local netid = nil
|
|
|
|
|
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
|
|
|
function(s)
|
|
|
|
local net
|
|
|
|
for net in utl.imatch(s.network) do
|
|
|
|
if net == name then
|
|
|
|
netid = _wifi_netid_by_sid(s[".name"])
|
|
|
|
return false
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
2018-01-01 23:24:10 +00:00
|
|
|
end
|
|
|
|
end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
return netid
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-03-11 23:11:34 +00:00
|
|
|
function _iface_virtual(x)
|
2011-10-03 13:57:11 +00:00
|
|
|
local _, p
|
|
|
|
for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
|
|
|
|
if x:match(p) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
2011-03-11 23:11:34 +00:00
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function _iface_ignore(x)
|
2011-10-03 13:57:11 +00:00
|
|
|
local _, p
|
|
|
|
for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
|
|
|
|
if x:match(p) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
2016-04-26 18:54:52 +00:00
|
|
|
return false
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function init(cursor)
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci = cursor or _uci or uci.cursor()
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
_interfaces = { }
|
|
|
|
_bridge = { }
|
|
|
|
_switch = { }
|
|
|
|
_tunnel = { }
|
2016-08-15 15:52:28 +00:00
|
|
|
_swtopo = { }
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2013-12-03 15:04:34 +00:00
|
|
|
_ubusnetcache = { }
|
|
|
|
_ubusdevcache = { }
|
|
|
|
_ubuswificache = { }
|
2012-05-31 10:05:31 +00:00
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
-- read interface information
|
|
|
|
local n, i
|
|
|
|
for n, i in ipairs(nxo.getifaddrs()) do
|
|
|
|
local name = i.name:match("[^:]+")
|
|
|
|
|
2011-09-24 00:57:59 +00:00
|
|
|
if _iface_virtual(name) then
|
2011-10-03 13:57:11 +00:00
|
|
|
_tunnel[name] = true
|
2011-09-24 00:57:59 +00:00
|
|
|
end
|
|
|
|
|
2016-04-26 18:54:52 +00:00
|
|
|
if _tunnel[name] or not (_iface_ignore(name) or _iface_virtual(name)) then
|
2011-10-03 13:57:11 +00:00
|
|
|
_interfaces[name] = _interfaces[name] or {
|
2010-10-30 00:40:07 +00:00
|
|
|
idx = i.ifindex or n,
|
|
|
|
name = name,
|
|
|
|
rawname = i.name,
|
|
|
|
flags = { },
|
|
|
|
ipaddrs = { },
|
|
|
|
ip6addrs = { }
|
|
|
|
}
|
|
|
|
|
|
|
|
if i.family == "packet" then
|
2011-10-03 13:57:11 +00:00
|
|
|
_interfaces[name].flags = i.flags
|
|
|
|
_interfaces[name].stats = i.data
|
2018-03-12 15:12:18 +00:00
|
|
|
_interfaces[name].macaddr = ipc.checkmac(i.addr)
|
2010-10-30 00:40:07 +00:00
|
|
|
elseif i.family == "inet" then
|
2011-10-03 13:57:11 +00:00
|
|
|
_interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
|
2010-10-30 00:40:07 +00:00
|
|
|
elseif i.family == "inet6" then
|
2011-10-03 13:57:11 +00:00
|
|
|
_interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
-- read bridge informaton
|
|
|
|
local b, l
|
|
|
|
for l in utl.execi("brctl show") do
|
|
|
|
if not l:match("STP") then
|
|
|
|
local r = utl.split(l, "%s+", nil, true)
|
|
|
|
if #r == 4 then
|
|
|
|
b = {
|
|
|
|
name = r[1],
|
|
|
|
id = r[2],
|
|
|
|
stp = r[3] == "yes",
|
2011-10-03 13:57:11 +00:00
|
|
|
ifnames = { _interfaces[r[4]] }
|
2010-10-30 00:40:07 +00:00
|
|
|
}
|
|
|
|
if b.ifnames[1] then
|
|
|
|
b.ifnames[1].bridge = b
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
2011-10-03 13:57:11 +00:00
|
|
|
_bridge[r[1]] = b
|
2010-10-30 00:40:07 +00:00
|
|
|
elseif b then
|
2011-10-03 13:57:11 +00:00
|
|
|
b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
|
2010-10-30 00:40:07 +00:00
|
|
|
b.ifnames[#b.ifnames].bridge = b
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2016-08-15 15:52:28 +00:00
|
|
|
-- read switch topology
|
|
|
|
local boardinfo = jsc.parse(nfs.readfile("/etc/board.json") or "")
|
|
|
|
if type(boardinfo) == "table" and type(boardinfo.switch) == "table" then
|
|
|
|
local switch, layout
|
|
|
|
for switch, layout in pairs(boardinfo.switch) do
|
|
|
|
if type(layout) == "table" and type(layout.ports) == "table" then
|
|
|
|
local _, port
|
|
|
|
local ports = { }
|
|
|
|
local nports = { }
|
|
|
|
local netdevs = { }
|
|
|
|
|
|
|
|
for _, port in ipairs(layout.ports) do
|
|
|
|
if type(port) == "table" and
|
|
|
|
type(port.num) == "number" and
|
|
|
|
(type(port.role) == "string" or
|
|
|
|
type(port.device) == "string")
|
|
|
|
then
|
|
|
|
local spec = {
|
|
|
|
num = port.num,
|
|
|
|
role = port.role or "cpu",
|
|
|
|
index = port.index or port.num
|
|
|
|
}
|
|
|
|
|
|
|
|
if port.device then
|
|
|
|
spec.device = port.device
|
|
|
|
spec.tagged = port.need_tag
|
|
|
|
netdevs[tostring(port.num)] = port.device
|
|
|
|
end
|
|
|
|
|
|
|
|
ports[#ports+1] = spec
|
|
|
|
|
|
|
|
if port.role then
|
|
|
|
nports[port.role] = (nports[port.role] or 0) + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
table.sort(ports, function(a, b)
|
|
|
|
if a.role ~= b.role then
|
|
|
|
return (a.role < b.role)
|
|
|
|
end
|
|
|
|
|
|
|
|
return (a.index < b.index)
|
|
|
|
end)
|
|
|
|
|
|
|
|
local pnum, role
|
|
|
|
for _, port in ipairs(ports) do
|
|
|
|
if port.role ~= role then
|
|
|
|
role = port.role
|
|
|
|
pnum = 1
|
|
|
|
end
|
|
|
|
|
|
|
|
if role == "cpu" then
|
|
|
|
port.label = "CPU (%s)" % port.device
|
|
|
|
elseif nports[role] > 1 then
|
|
|
|
port.label = "%s %d" %{ role:upper(), pnum }
|
|
|
|
pnum = pnum + 1
|
|
|
|
else
|
|
|
|
port.label = role:upper()
|
|
|
|
end
|
|
|
|
|
|
|
|
port.role = nil
|
|
|
|
port.index = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
_swtopo[switch] = {
|
|
|
|
ports = ports,
|
|
|
|
netdevs = netdevs
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
return _M
|
|
|
|
end
|
|
|
|
|
|
|
|
function save(self, ...)
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:save(...)
|
|
|
|
_uci:load(...)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function commit(self, ...)
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:commit(...)
|
|
|
|
_uci:load(...)
|
2011-10-03 13:57:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ifnameof(self, x)
|
|
|
|
if utl.instanceof(x, interface) then
|
|
|
|
return x:name()
|
2011-10-04 13:32:18 +00:00
|
|
|
elseif utl.instanceof(x, protocol) then
|
2011-10-03 13:57:11 +00:00
|
|
|
return x:ifname()
|
|
|
|
elseif type(x) == "string" then
|
|
|
|
return x:match("^[^:]+")
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2011-10-09 21:16:59 +00:00
|
|
|
function get_protocol(self, protoname, netname)
|
|
|
|
local v = _protocols[protoname]
|
|
|
|
if v then
|
|
|
|
return v(netname or "__dummy__")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function get_protocols(self)
|
|
|
|
local p = { }
|
|
|
|
local _, v
|
|
|
|
for _, v in ipairs(_protocols) do
|
|
|
|
p[#p+1] = v("__dummy__")
|
|
|
|
end
|
|
|
|
return p
|
|
|
|
end
|
|
|
|
|
|
|
|
function register_protocol(self, protoname)
|
|
|
|
local proto = utl.class(protocol)
|
|
|
|
|
|
|
|
function proto.__init__(self, name)
|
|
|
|
self.sid = name
|
|
|
|
end
|
|
|
|
|
|
|
|
function proto.proto(self)
|
|
|
|
return protoname
|
|
|
|
end
|
|
|
|
|
|
|
|
_protocols[#_protocols+1] = proto
|
|
|
|
_protocols[protoname] = proto
|
|
|
|
|
|
|
|
return proto
|
|
|
|
end
|
|
|
|
|
|
|
|
function register_pattern_virtual(self, pat)
|
|
|
|
IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
|
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function register_error_code(self, code, message)
|
|
|
|
if type(code) == "string" and
|
|
|
|
type(message) == "string" and
|
|
|
|
not IFACE_ERRORS[code]
|
|
|
|
then
|
|
|
|
IFACE_ERRORS[code] = message
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
2011-10-04 13:32:18 +00:00
|
|
|
|
2009-10-10 04:46:26 +00:00
|
|
|
function has_ipv6(self)
|
|
|
|
return nfs.access("/proc/net/ipv6_route")
|
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function add_network(self, n, options)
|
2011-01-20 23:24:02 +00:00
|
|
|
local oldnet = self:get_network(n)
|
|
|
|
if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
|
2015-11-17 16:35:02 +00:00
|
|
|
if _uci:section("network", "interface", n, options) then
|
2009-10-08 09:32:00 +00:00
|
|
|
return network(n)
|
|
|
|
end
|
2011-01-20 23:24:02 +00:00
|
|
|
elseif oldnet and oldnet:is_empty() then
|
|
|
|
if options then
|
|
|
|
local k, v
|
|
|
|
for k, v in pairs(options) do
|
|
|
|
oldnet:set(k, v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return oldnet
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_network(self, n)
|
2015-11-17 16:35:02 +00:00
|
|
|
if n and _uci:get("network", n) == "interface" then
|
2009-10-08 09:32:00 +00:00
|
|
|
return network(n)
|
2018-07-12 14:43:23 +00:00
|
|
|
elseif n then
|
|
|
|
local stat = utl.ubus("network.interface", "status", { interface = n })
|
|
|
|
if type(stat) == "table" and
|
|
|
|
type(stat.proto) == "string"
|
|
|
|
then
|
|
|
|
return network(n, stat.proto)
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_networks(self)
|
|
|
|
local nets = { }
|
2010-10-30 00:40:07 +00:00
|
|
|
local nls = { }
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "interface",
|
2009-10-08 09:32:00 +00:00
|
|
|
function(s)
|
2010-10-30 00:40:07 +00:00
|
|
|
nls[s['.name']] = network(s['.name'])
|
2009-10-08 09:32:00 +00:00
|
|
|
end)
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
local dump = utl.ubus("network.interface", "dump", { })
|
|
|
|
if type(dump) == "table" and
|
|
|
|
type(dump.interface) == "table"
|
|
|
|
then
|
|
|
|
local _, net
|
|
|
|
for _, net in ipairs(dump.interface) do
|
|
|
|
if type(net) == "table" and
|
|
|
|
type(net.proto) == "string" and
|
|
|
|
type(net.interface) == "string"
|
|
|
|
then
|
|
|
|
if not nls[net.interface] then
|
|
|
|
nls[net.interface] = network(net.interface, net.proto)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
local n
|
|
|
|
for n in utl.kspairs(nls) do
|
|
|
|
nets[#nets+1] = nls[n]
|
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
return nets
|
|
|
|
end
|
|
|
|
|
|
|
|
function del_network(self, n)
|
2015-11-17 16:35:02 +00:00
|
|
|
local r = _uci:delete("network", n)
|
2009-10-08 09:32:00 +00:00
|
|
|
if r then
|
2018-03-02 11:23:55 +00:00
|
|
|
_uci:delete_all("luci", "ifstate",
|
|
|
|
function(s) return (s.interface == n) end)
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete_all("network", "alias",
|
2010-11-15 22:03:45 +00:00
|
|
|
function(s) return (s.interface == n) end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete_all("network", "route",
|
2010-11-15 22:03:45 +00:00
|
|
|
function(s) return (s.interface == n) end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete_all("network", "route6",
|
2010-11-15 22:03:45 +00:00
|
|
|
function(s) return (s.interface == n) end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
2010-10-28 18:30:15 +00:00
|
|
|
function(s)
|
2012-09-15 13:10:27 +00:00
|
|
|
local net
|
|
|
|
local rest = { }
|
|
|
|
for net in utl.imatch(s.network) do
|
|
|
|
if net ~= n then
|
|
|
|
rest[#rest+1] = net
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #rest > 0 then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set("wireless", s['.name'], "network",
|
2012-09-15 13:10:27 +00:00
|
|
|
table.concat(rest, " "))
|
|
|
|
else
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete("wireless", s['.name'], "network")
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end)
|
2019-05-06 06:22:39 +00:00
|
|
|
|
|
|
|
local ok, fw = pcall(require, "luci.model.firewall")
|
|
|
|
if ok then
|
|
|
|
fw.init()
|
|
|
|
fw:del_network(n)
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
return r
|
|
|
|
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
|
2015-11-17 16:35:02 +00:00
|
|
|
r = _uci:section("network", "interface", new, _uci:get_all("network", old))
|
2009-10-08 09:32:00 +00:00
|
|
|
|
|
|
|
if r then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "alias",
|
2009-10-08 09:32:00 +00:00
|
|
|
function(s)
|
|
|
|
if s.interface == old then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set("network", s['.name'], "interface", new)
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "route",
|
2009-10-08 09:32:00 +00:00
|
|
|
function(s)
|
|
|
|
if s.interface == old then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set("network", s['.name'], "interface", new)
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end)
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "route6",
|
2009-10-08 09:32:00 +00:00
|
|
|
function(s)
|
|
|
|
if s.interface == old then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set("network", s['.name'], "interface", new)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
2010-10-28 18:30:15 +00:00
|
|
|
function(s)
|
2012-09-15 13:10:27 +00:00
|
|
|
local net
|
|
|
|
local list = { }
|
|
|
|
for net in utl.imatch(s.network) do
|
|
|
|
if net == old then
|
|
|
|
list[#list+1] = new
|
|
|
|
else
|
|
|
|
list[#list+1] = net
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #list > 0 then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:set("wireless", s['.name'], "network",
|
2012-09-15 13:10:27 +00:00
|
|
|
table.concat(list, " "))
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end)
|
2009-10-15 16:30:17 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete("network", old)
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
return r or false
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_interface(self, i)
|
2011-10-03 13:57:11 +00:00
|
|
|
if _interfaces[i] or _wifi_iface(i) then
|
2009-10-27 21:34:06 +00:00
|
|
|
return interface(i)
|
|
|
|
else
|
2018-03-31 05:06:52 +00:00
|
|
|
local netid = _wifi_netid_by_sid(i)
|
2018-01-01 23:24:10 +00:00
|
|
|
return netid and interface(netid)
|
2009-10-27 21:34:06 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function get_interfaces(self)
|
|
|
|
local iface
|
2010-10-28 18:30:15 +00:00
|
|
|
local ifaces = { }
|
2010-10-31 22:38:07 +00:00
|
|
|
local nfs = { }
|
2010-10-28 18:30:15 +00:00
|
|
|
|
|
|
|
-- find normal interfaces
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "interface",
|
2010-10-31 21:38:36 +00:00
|
|
|
function(s)
|
|
|
|
for iface in utl.imatch(s.ifname) do
|
2016-04-26 18:54:52 +00:00
|
|
|
if not _iface_ignore(iface) and not _iface_virtual(iface) and not _wifi_iface(iface) then
|
2010-10-31 22:38:07 +00:00
|
|
|
nfs[iface] = interface(iface)
|
2010-10-31 21:38:36 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
for iface in utl.kspairs(_interfaces) do
|
2016-08-15 15:52:28 +00:00
|
|
|
if not (nfs[iface] or _iface_ignore(iface) or _iface_virtual(iface) or _wifi_iface(iface)) then
|
2010-10-31 22:38:07 +00:00
|
|
|
nfs[iface] = interface(iface)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-09-14 09:36:55 +00:00
|
|
|
-- find vlan interfaces
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("network", "switch_vlan",
|
2011-09-14 09:36:55 +00:00
|
|
|
function(s)
|
2016-08-15 15:52:28 +00:00
|
|
|
if type(s.ports) ~= "string" or
|
|
|
|
type(s.device) ~= "string" or
|
|
|
|
type(_swtopo[s.device]) ~= "table"
|
|
|
|
then
|
2011-10-09 22:02:46 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2016-08-15 15:52:28 +00:00
|
|
|
local pnum, ptag
|
|
|
|
for pnum, ptag in s.ports:gmatch("(%d+)([tu]?)") do
|
|
|
|
local netdev = _swtopo[s.device].netdevs[pnum]
|
|
|
|
if netdev then
|
|
|
|
if not nfs[netdev] then
|
|
|
|
nfs[netdev] = interface(netdev)
|
2011-10-09 22:02:46 +00:00
|
|
|
end
|
2016-08-15 15:52:28 +00:00
|
|
|
_switch[netdev] = true
|
|
|
|
|
|
|
|
if ptag == "t" then
|
|
|
|
local vid = tonumber(s.vid or s.vlan)
|
|
|
|
if vid ~= nil and vid >= 0 and vid <= 4095 then
|
|
|
|
local iface = "%s.%d" %{ netdev, vid }
|
|
|
|
if not nfs[iface] then
|
|
|
|
nfs[iface] = interface(iface)
|
|
|
|
end
|
|
|
|
_switch[iface] = true
|
|
|
|
end
|
2011-10-09 22:02:46 +00:00
|
|
|
end
|
2011-09-14 09:36:55 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2010-10-31 22:38:07 +00:00
|
|
|
for iface in utl.kspairs(nfs) do
|
|
|
|
ifaces[#ifaces+1] = nfs[iface]
|
|
|
|
end
|
|
|
|
|
2010-10-28 18:30:15 +00:00
|
|
|
-- find wifi interfaces
|
|
|
|
local num = { }
|
|
|
|
local wfs = { }
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
2010-10-28 18:30:15 +00:00
|
|
|
function(s)
|
|
|
|
if s.device then
|
|
|
|
num[s.device] = num[s.device] and num[s.device] + 1 or 1
|
|
|
|
local i = "%s.network%d" %{ s.device, num[s.device] }
|
|
|
|
wfs[i] = interface(i)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
for iface in utl.kspairs(wfs) do
|
|
|
|
ifaces[#ifaces+1] = wfs[iface]
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
return ifaces
|
|
|
|
end
|
|
|
|
|
|
|
|
function ignore_interface(self, x)
|
2010-10-30 00:40:07 +00:00
|
|
|
return _iface_ignore(x)
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_wifidev(self, dev)
|
2015-11-17 16:35:02 +00:00
|
|
|
if _uci:get("wireless", dev) == "wifi-device" then
|
2010-10-30 00:40:07 +00:00
|
|
|
return wifidev(dev)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_wifidevs(self)
|
|
|
|
local devs = { }
|
|
|
|
local wfd = { }
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-device",
|
2010-10-30 00:40:07 +00:00
|
|
|
function(s) wfd[#wfd+1] = s['.name'] end)
|
|
|
|
|
|
|
|
local dev
|
|
|
|
for _, dev in utl.vspairs(wfd) do
|
|
|
|
devs[#devs+1] = wifidev(dev)
|
|
|
|
end
|
|
|
|
|
|
|
|
return devs
|
|
|
|
end
|
|
|
|
|
|
|
|
function get_wifinet(self, net)
|
2018-01-01 23:24:10 +00:00
|
|
|
local wnet = _wifi_sid_by_ifname(net)
|
2010-10-30 00:40:07 +00:00
|
|
|
if wnet then
|
|
|
|
return wifinet(wnet)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function add_wifinet(self, net, options)
|
|
|
|
if type(options) == "table" and options.device and
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:get("wireless", options.device) == "wifi-device"
|
2010-10-30 00:40:07 +00:00
|
|
|
then
|
2015-11-17 16:35:02 +00:00
|
|
|
local wnet = _uci:section("wireless", "wifi-iface", nil, options)
|
2010-10-30 00:40:07 +00:00
|
|
|
return wifinet(wnet)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function del_wifinet(self, net)
|
2018-01-01 23:24:10 +00:00
|
|
|
local wnet = _wifi_sid_by_ifname(net)
|
2010-10-30 00:40:07 +00:00
|
|
|
if wnet then
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:delete("wireless", wnet)
|
2010-10-30 00:40:07 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2012-06-26 22:19:27 +00:00
|
|
|
function get_status_by_route(self, addr, mask)
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
local route_statuses = { }
|
2012-06-26 22:19:27 +00:00
|
|
|
local _, object
|
2015-01-15 10:10:02 +00:00
|
|
|
for _, object in ipairs(utl.ubus()) do
|
2012-06-26 22:19:27 +00:00
|
|
|
local net = object:match("^network%.interface%.(.+)")
|
|
|
|
if net then
|
2015-01-15 10:10:02 +00:00
|
|
|
local s = utl.ubus(object, "status", {})
|
2012-06-26 22:19:27 +00:00
|
|
|
if s and s.route then
|
|
|
|
local rt
|
|
|
|
for _, rt in ipairs(s.route) do
|
2013-04-04 14:06:12 +00:00
|
|
|
if not rt.table and rt.target == addr and rt.mask == mask then
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
route_statuses[net] = s
|
2012-06-26 22:19:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
|
|
|
|
return route_statuses
|
2012-06-26 22:19:27 +00:00
|
|
|
end
|
|
|
|
|
2012-11-21 20:13:53 +00:00
|
|
|
function get_status_by_address(self, addr)
|
|
|
|
local _, object
|
2015-01-15 10:10:02 +00:00
|
|
|
for _, object in ipairs(utl.ubus()) do
|
2012-11-21 20:13:53 +00:00
|
|
|
local net = object:match("^network%.interface%.(.+)")
|
|
|
|
if net then
|
2015-01-15 10:10:02 +00:00
|
|
|
local s = utl.ubus(object, "status", {})
|
2012-11-21 20:13:53 +00:00
|
|
|
if s and s['ipv4-address'] then
|
|
|
|
local a
|
|
|
|
for _, a in ipairs(s['ipv4-address']) do
|
|
|
|
if a.address == addr then
|
|
|
|
return net, s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if s and s['ipv6-address'] then
|
|
|
|
local a
|
|
|
|
for _, a in ipairs(s['ipv6-address']) do
|
|
|
|
if a.address == addr then
|
|
|
|
return net, s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-11-05 13:03:35 +00:00
|
|
|
if s and s['ipv6-prefix-assignment'] then
|
|
|
|
local a
|
|
|
|
for _, a in ipairs(s['ipv6-prefix-assignment']) do
|
|
|
|
if a and a['local-address'] and a['local-address'].address == addr then
|
|
|
|
return net, s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2012-11-21 20:13:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
function get_wan_networks(self)
|
|
|
|
local k, v
|
|
|
|
local wan_nets = { }
|
|
|
|
local route_statuses = self:get_status_by_route("0.0.0.0", 0)
|
2012-06-26 22:19:27 +00:00
|
|
|
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
for k, v in pairs(route_statuses) do
|
|
|
|
wan_nets[#wan_nets+1] = network(k, v.proto)
|
|
|
|
end
|
2012-06-26 22:19:27 +00:00
|
|
|
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
return wan_nets
|
2012-06-26 22:19:27 +00:00
|
|
|
end
|
|
|
|
|
luci-base: Show multiple upstream interface
Several devices have multiple upstream interfaces, for example a fixed
and a mobile broadband connection. Currently, only one upstream
interface is shown per address family in Luci. So in my example, one of
the interfaces would not appear on the Status-page.
This PR introduces support for showing multiple upstream interfaces on
the Status-page. The code is not very complicated. get_status_by_route()
has been extended to return a list of all routes, and
get_wannet()/get_wan6net() now returns all upstream interfaces.
I could not find any other (active) users of these three functions than
calls triggered from the Status-page, so changing the default behavior
should be fine. get_wandev()/get_wan6dev() called get_status_by_route(),
but I could not find any place where those functions were called. I
removed the dev-functions instead of keeping the old
get_status_by_route().
On the status page, the wan/wan6-variables have been replaced with
arrays. When populating the html, we now iterate through these arrays
and create one element for each interface.
I have tested the code with different interface types, v4, v6, as well as
disconnecting and connecting interfaces. The status is updated and the
correct interfaces (or sometimes none at all) are shown.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2018-09-09 15:27:28 +00:00
|
|
|
function get_wan6_networks(self)
|
|
|
|
local k, v
|
|
|
|
local wan6_nets = { }
|
|
|
|
local route_statuses = self:get_status_by_route("::", 0)
|
|
|
|
|
|
|
|
for k, v in pairs(route_statuses) do
|
|
|
|
wan6_nets[#wan6_nets+1] = network(k, v.proto)
|
|
|
|
end
|
|
|
|
|
|
|
|
return wan6_nets
|
2012-06-26 22:19:27 +00:00
|
|
|
end
|
|
|
|
|
2016-08-15 15:52:28 +00:00
|
|
|
function get_switch_topologies(self)
|
|
|
|
return _swtopo
|
|
|
|
end
|
|
|
|
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function network(name, proto)
|
2011-10-03 13:57:11 +00:00
|
|
|
if name then
|
2015-11-17 16:35:02 +00:00
|
|
|
local p = proto or _uci:get("network", name, "proto")
|
2011-10-04 13:32:18 +00:00
|
|
|
local c = p and _protocols[p] or protocol
|
2011-10-03 13:57:11 +00:00
|
|
|
return c(name)
|
|
|
|
end
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.__init__(self, name)
|
2010-10-28 18:30:15 +00:00
|
|
|
self.sid = name
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol._get(self, opt)
|
2015-11-17 16:35:02 +00:00
|
|
|
local v = _uci:get("network", self.sid, opt)
|
2010-10-28 18:30:15 +00:00
|
|
|
if type(v) == "table" then
|
|
|
|
return table.concat(v, " ")
|
|
|
|
end
|
|
|
|
return v or ""
|
|
|
|
end
|
|
|
|
|
2012-05-31 10:05:31 +00:00
|
|
|
function protocol._ubus(self, field)
|
|
|
|
if not _ubusnetcache[self.sid] then
|
2015-01-15 10:10:02 +00:00
|
|
|
_ubusnetcache[self.sid] = utl.ubus("network.interface.%s" % self.sid,
|
|
|
|
"status", { })
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
2012-05-31 17:24:13 +00:00
|
|
|
if _ubusnetcache[self.sid] and field then
|
|
|
|
return _ubusnetcache[self.sid][field]
|
|
|
|
end
|
|
|
|
return _ubusnetcache[self.sid]
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.get(self, opt)
|
2010-10-30 00:40:07 +00:00
|
|
|
return _get("network", self.sid, opt)
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.set(self, opt, val)
|
2010-10-30 00:40:07 +00:00
|
|
|
return _set("network", self.sid, opt, val)
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.ifname(self)
|
2012-05-31 17:24:13 +00:00
|
|
|
local ifname
|
|
|
|
if self:is_floating() then
|
|
|
|
ifname = self:_ubus("l3_device")
|
2009-10-15 16:30:17 +00:00
|
|
|
else
|
2012-05-31 17:24:13 +00:00
|
|
|
ifname = self:_ubus("device")
|
|
|
|
end
|
|
|
|
if not ifname then
|
2018-01-01 23:24:10 +00:00
|
|
|
ifname = _wifi_netid_by_netname(self.sid)
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
2012-05-31 17:24:13 +00:00
|
|
|
return ifname
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.proto(self)
|
|
|
|
return "none"
|
|
|
|
end
|
|
|
|
|
|
|
|
function protocol.get_i18n(self)
|
|
|
|
local p = self:proto()
|
|
|
|
if p == "none" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Unmanaged")
|
2011-10-04 13:32:18 +00:00
|
|
|
elseif p == "static" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Static address")
|
2011-10-04 13:32:18 +00:00
|
|
|
elseif p == "dhcp" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("DHCP client")
|
2011-10-04 13:32:18 +00:00
|
|
|
else
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Unknown")
|
2011-10-04 13:32:18 +00:00
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.type(self)
|
2010-10-28 18:30:15 +00:00
|
|
|
return self:_get("type")
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.name(self)
|
2009-10-08 09:32:00 +00:00
|
|
|
return self.sid
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.uptime(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
return self:_ubus("uptime") or 0
|
2010-12-01 21:15:59 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.expires(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
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
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
2015-11-17 16:35:02 +00:00
|
|
|
|
2011-02-11 04:50:56 +00:00
|
|
|
return -1
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.metric(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self:_ubus("metric") or 0
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function protocol.zonename(self)
|
|
|
|
local d = self:_ubus("data")
|
|
|
|
|
|
|
|
if type(d) == "table" and type(d.zone) == "string" then
|
|
|
|
return d.zone
|
|
|
|
end
|
|
|
|
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.ipaddr(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local addrs = self:_ubus("ipv4-address")
|
|
|
|
return addrs and #addrs > 0 and addrs[1].address
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
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
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.netmask(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local addrs = self:_ubus("ipv4-address")
|
|
|
|
return addrs and #addrs > 0 and
|
|
|
|
ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.gwaddr(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local _, route
|
2012-05-31 17:24:13 +00:00
|
|
|
for _, route in ipairs(self:_ubus("route") or { }) do
|
2012-05-31 10:05:31 +00:00
|
|
|
if route.target == "0.0.0.0" and route.mask == 0 then
|
|
|
|
return route.nexthop
|
|
|
|
end
|
|
|
|
end
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.dnsaddrs(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local dns = { }
|
|
|
|
local _, addr
|
2012-05-31 17:24:13 +00:00
|
|
|
for _, addr in ipairs(self:_ubus("dns-server") or { }) do
|
2012-05-31 10:05:31 +00:00
|
|
|
if not addr:match(":") then
|
|
|
|
dns[#dns+1] = addr
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return dns
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.ip6addr(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local addrs = self:_ubus("ipv6-address")
|
2013-03-19 17:26:01 +00:00
|
|
|
if addrs and #addrs > 0 then
|
|
|
|
return "%s/%d" %{ addrs[1].address, addrs[1].mask }
|
|
|
|
else
|
|
|
|
addrs = self:_ubus("ipv6-prefix-assignment")
|
|
|
|
if addrs and #addrs > 0 then
|
|
|
|
return "%s/%d" %{ addrs[1].address, addrs[1].mask }
|
|
|
|
end
|
|
|
|
end
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
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
|
2018-03-02 13:42:52 +00:00
|
|
|
if type(addr["local-address"]) == "table" and
|
|
|
|
type(addr["local-address"].mask) == "number" and
|
|
|
|
type(addr["local-address"].address) == "string"
|
|
|
|
then
|
2018-02-16 16:04:13 +00:00
|
|
|
rv[#rv+1] = "%s/%d" %{
|
|
|
|
addr["local-address"].address,
|
|
|
|
addr["local-address"].mask
|
|
|
|
}
|
|
|
|
end
|
2015-11-17 16:35:02 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return rv
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.gw6addr(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local _, route
|
2012-06-17 11:18:58 +00:00
|
|
|
for _, route in ipairs(self:_ubus("route") or { }) do
|
2012-05-31 10:05:31 +00:00
|
|
|
if route.target == "::" and route.mask == 0 then
|
|
|
|
return ipc.IPv6(route.nexthop):string()
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.dns6addrs(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local dns = { }
|
|
|
|
local _, addr
|
2012-06-17 11:18:58 +00:00
|
|
|
for _, addr in ipairs(self:_ubus("dns-server") or { }) do
|
2012-05-31 10:05:31 +00:00
|
|
|
if addr:match(":") then
|
|
|
|
dns[#dns+1] = addr
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return dns
|
2011-02-11 04:50:56 +00:00
|
|
|
end
|
|
|
|
|
mod-admin-full: Add IPv6 Prefix Delegation information to Status Pages
The Overview page and Network>Interfaces page currently do not give much information about IPv6, particularly with Prefix Delegated setups. In these setups, ISP will delegate a prefix to the router. Currently LuCI doesn't display this Prefix Delegation from the ISP anywhere. A number of changes was added to this commit:
1) self:_ubus("ipv6-prefix") was extracted and put into protocol.ip6prefix.
2) Network>Interfaces page, if a .ip6prefix is present, show it under Status. (IPv6-PD).
3) On the Overview page, "Type" and "Prefix Delegated" has been added to the IPv6 Network Overview Status:
- Type will display the .proto, similar to the IPv4 case. If a .ip6prefix is present, it'll display a "-pd" at the end of the Type: i.e. dhcpv6-pd vs. dhcpv6.
- If no .ip6prefix is present, it'll do what it does currently, and just show Address, or :: if no address is present.
- If .ip6prefix is present, it'll show the "Prefix Delegated", it'll also hide "Address" if no address is present, else it'll show ifc6.ip6addr as well.
Signed-off-by: Cody R. Brown <dev@codybrown.ca>
2017-01-28 09:38:06 +00:00
|
|
|
function protocol.ip6prefix(self)
|
|
|
|
local prefix = self:_ubus("ipv6-prefix")
|
|
|
|
if prefix and #prefix > 0 then
|
|
|
|
return "%s/%d" %{ prefix[1].address, prefix[1].mask }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function protocol.errors(self)
|
|
|
|
local _, err, rv
|
|
|
|
local errors = self:_ubus("errors")
|
|
|
|
if type(errors) == "table" then
|
|
|
|
for _, err in ipairs(errors) do
|
|
|
|
if type(err) == "table" and
|
|
|
|
type(err.code) == "string"
|
|
|
|
then
|
|
|
|
rv = rv or { }
|
|
|
|
rv[#rv+1] = IFACE_ERRORS[err.code] or lng.translatef("Unknown error (%s)", err.code)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return rv
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.is_bridge(self)
|
|
|
|
return (not self:is_virtual() and self:type() == "bridge")
|
|
|
|
end
|
|
|
|
|
|
|
|
function protocol.opkg_package(self)
|
|
|
|
return nil
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.is_installed(self)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function protocol.is_virtual(self)
|
2011-10-03 13:57:11 +00:00
|
|
|
return false
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.is_floating(self)
|
2011-10-03 13:57:11 +00:00
|
|
|
return false
|
2011-09-22 01:39:35 +00:00
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function protocol.is_dynamic(self)
|
|
|
|
return (self:_ubus("dynamic") == true)
|
|
|
|
end
|
|
|
|
|
2018-08-29 13:14:27 +00:00
|
|
|
function protocol.is_auto(self)
|
2019-04-30 07:05:16 +00:00
|
|
|
return (self:_get("auto") ~= "0")
|
2018-08-29 13:14:27 +00:00
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function protocol.is_alias(self)
|
|
|
|
local ifn, parent = nil, nil
|
|
|
|
|
|
|
|
for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do
|
|
|
|
if #ifn > 1 and ifn:byte(1) == 64 then
|
|
|
|
parent = ifn:sub(2)
|
|
|
|
elseif parent ~= nil then
|
|
|
|
parent = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return parent
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.is_empty(self)
|
2011-10-11 01:14:11 +00:00
|
|
|
if self:is_floating() then
|
2010-10-28 18:30:15 +00:00
|
|
|
return false
|
2009-10-15 16:30:17 +00:00
|
|
|
else
|
2018-01-01 23:24:10 +00:00
|
|
|
local empty = true
|
2010-10-28 18:30:15 +00:00
|
|
|
|
|
|
|
if (self:_get("ifname") or ""):match("%S+") then
|
2018-01-01 23:24:10 +00:00
|
|
|
empty = false
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
if empty and _wifi_netid_by_netname(self.sid) then
|
|
|
|
empty = false
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
return empty
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2018-07-12 14:43:23 +00:00
|
|
|
function protocol.is_up(self)
|
|
|
|
return (self:_ubus("up") == true)
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.add_interface(self, ifname)
|
2011-10-03 13:57:11 +00:00
|
|
|
ifname = _M:ifnameof(ifname)
|
|
|
|
if ifname and not self:is_floating() then
|
2010-10-28 18:30:15 +00:00
|
|
|
-- if its a wifi interface, change its network option
|
2018-01-01 23:24:10 +00:00
|
|
|
local wif = _wifi_sid_by_ifname(ifname)
|
2010-10-28 18:30:15 +00:00
|
|
|
if wif then
|
2012-06-26 21:49:07 +00:00
|
|
|
_append("wireless", wif, "network", self.sid)
|
2009-10-15 16:30:17 +00:00
|
|
|
|
2010-10-28 18:30:15 +00:00
|
|
|
-- add iface to our iface list
|
|
|
|
else
|
2011-10-03 13:57:11 +00:00
|
|
|
_append("network", self.sid, "ifname", ifname)
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.del_interface(self, ifname)
|
2011-10-03 13:57:11 +00:00
|
|
|
ifname = _M:ifnameof(ifname)
|
|
|
|
if ifname and not self:is_floating() then
|
2010-10-28 18:30:15 +00:00
|
|
|
-- if its a wireless interface, clear its network option
|
2018-01-01 23:24:10 +00:00
|
|
|
local wif = _wifi_sid_by_ifname(ifname)
|
2012-06-26 21:49:07 +00:00
|
|
|
if wif then _filter("wireless", wif, "network", self.sid) end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
|
|
|
-- remove the interface
|
2011-10-03 13:57:11 +00:00
|
|
|
_filter("network", self.sid, "ifname", ifname)
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.get_interface(self)
|
2010-10-28 18:30:15 +00:00
|
|
|
if self:is_virtual() then
|
2011-10-03 13:57:11 +00:00
|
|
|
_tunnel[self:proto() .. "-" .. self.sid] = true
|
2011-09-24 00:57:59 +00:00
|
|
|
return interface(self:proto() .. "-" .. self.sid, self)
|
2011-09-22 01:39:35 +00:00
|
|
|
elseif self:is_bridge() then
|
2011-10-03 13:57:11 +00:00
|
|
|
_bridge["br-" .. self.sid] = true
|
2011-09-24 00:57:59 +00:00
|
|
|
return interface("br-" .. self.sid, self)
|
2010-10-28 18:30:15 +00:00
|
|
|
else
|
2018-07-12 14:43:23 +00:00
|
|
|
local ifn = self:_ubus("l3_device") or self:_ubus("device")
|
|
|
|
if ifn then
|
|
|
|
return interface(ifn, self)
|
|
|
|
end
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do
|
2011-09-22 01:39:35 +00:00
|
|
|
ifn = ifn:match("^[^:/]+")
|
2011-09-24 00:57:59 +00:00
|
|
|
return ifn and interface(ifn, self)
|
2011-09-22 01:39:35 +00:00
|
|
|
end
|
2018-07-12 14:43:23 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
ifn = _wifi_netid_by_netname(self.sid)
|
2011-09-24 00:57:59 +00:00
|
|
|
return ifn and interface(ifn, self)
|
2011-09-22 01:39:35 +00:00
|
|
|
end
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.get_interfaces(self)
|
2011-09-25 11:58:24 +00:00
|
|
|
if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
|
|
|
|
local ifaces = { }
|
2011-09-22 01:39:35 +00:00
|
|
|
|
2011-09-25 11:58:24 +00:00
|
|
|
local ifn
|
|
|
|
local nfs = { }
|
|
|
|
for ifn in utl.imatch(self:get("ifname")) do
|
|
|
|
ifn = ifn:match("^[^:/]+")
|
|
|
|
nfs[ifn] = interface(ifn, self)
|
|
|
|
end
|
2011-09-22 01:39:35 +00:00
|
|
|
|
2011-09-25 11:58:24 +00:00
|
|
|
for ifn in utl.kspairs(nfs) do
|
|
|
|
ifaces[#ifaces+1] = nfs[ifn]
|
|
|
|
end
|
2011-09-22 01:39:35 +00:00
|
|
|
|
2011-09-24 03:31:00 +00:00
|
|
|
local wfs = { }
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
2011-09-24 03:31:00 +00:00
|
|
|
function(s)
|
|
|
|
if s.device then
|
2012-09-15 13:10:27 +00:00
|
|
|
local net
|
|
|
|
for net in utl.imatch(s.network) do
|
|
|
|
if net == self.sid then
|
2018-01-01 23:24:10 +00:00
|
|
|
ifn = _wifi_netid_by_sid(s[".name"])
|
|
|
|
if ifn then
|
|
|
|
wfs[ifn] = interface(ifn, self)
|
|
|
|
end
|
2012-09-15 13:10:27 +00:00
|
|
|
end
|
2011-09-24 03:31:00 +00:00
|
|
|
end
|
2011-09-22 01:39:35 +00:00
|
|
|
end
|
2011-09-24 03:31:00 +00:00
|
|
|
end)
|
2011-09-22 01:39:35 +00:00
|
|
|
|
2011-09-24 03:31:00 +00:00
|
|
|
for ifn in utl.kspairs(wfs) do
|
|
|
|
ifaces[#ifaces+1] = wfs[ifn]
|
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-09-25 11:58:24 +00:00
|
|
|
return ifaces
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.contains_interface(self, ifname)
|
2011-10-03 13:57:11 +00:00
|
|
|
ifname = _M:ifnameof(ifname)
|
|
|
|
if not ifname then
|
|
|
|
return false
|
|
|
|
elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
|
2011-09-22 01:39:35 +00:00
|
|
|
return true
|
|
|
|
elseif self:is_bridge() and "br-" .. self.sid == ifname then
|
|
|
|
return true
|
2010-10-28 18:30:15 +00:00
|
|
|
else
|
2011-09-22 01:39:35 +00:00
|
|
|
local ifn
|
2010-10-30 17:56:06 +00:00
|
|
|
for ifn in utl.imatch(self:get("ifname")) do
|
2010-10-28 18:30:15 +00:00
|
|
|
ifn = ifn:match("[^:]+")
|
|
|
|
if ifn == ifname then
|
|
|
|
return true
|
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local wif = _wifi_sid_by_ifname(ifname)
|
2010-10-28 18:30:15 +00:00
|
|
|
if wif then
|
2012-06-26 21:49:07 +00:00
|
|
|
local n
|
2015-11-17 16:35:02 +00:00
|
|
|
for n in utl.imatch(_uci:get("wireless", wif, "network")) do
|
2012-06-26 21:49:07 +00:00
|
|
|
if n == self.sid then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
function protocol.adminlink(self)
|
2018-01-01 23:24:10 +00:00
|
|
|
local stat, dsp = pcall(require, "luci.dispatcher")
|
|
|
|
return stat and dsp.build_url("admin", "network", "network", self.sid)
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
|
|
|
|
interface = utl.class()
|
2011-10-03 13:57:11 +00:00
|
|
|
|
2011-09-24 00:57:59 +00:00
|
|
|
function interface.__init__(self, ifname, network)
|
2018-01-01 23:24:10 +00:00
|
|
|
local wif = _wifi_sid_by_ifname(ifname)
|
2012-05-31 10:05:31 +00:00
|
|
|
if wif then
|
|
|
|
self.wif = wifinet(wif)
|
2018-01-01 23:24:10 +00:00
|
|
|
self.ifname = self.wif:ifname()
|
2011-10-28 22:36:15 +00:00
|
|
|
end
|
2010-10-28 18:30:15 +00:00
|
|
|
|
2011-09-24 00:57:59 +00:00
|
|
|
self.ifname = self.ifname or ifname
|
2011-10-03 13:57:11 +00:00
|
|
|
self.dev = _interfaces[self.ifname]
|
2011-09-24 00:57:59 +00:00
|
|
|
self.network = network
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2012-05-31 10:05:31 +00:00
|
|
|
function interface._ubus(self, field)
|
|
|
|
if not _ubusdevcache[self.ifname] then
|
2015-01-15 10:10:02 +00:00
|
|
|
_ubusdevcache[self.ifname] = utl.ubus("network.device", "status",
|
|
|
|
{ name = self.ifname })
|
2012-05-31 10:05:31 +00:00
|
|
|
end
|
2012-05-31 17:24:13 +00:00
|
|
|
if _ubusdevcache[self.ifname] and field then
|
|
|
|
return _ubusdevcache[self.ifname][field]
|
|
|
|
end
|
|
|
|
return _ubusdevcache[self.ifname]
|
2012-05-31 10:05:31 +00:00
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function interface.name(self)
|
2010-10-30 00:40:07 +00:00
|
|
|
return self.wif and self.wif:ifname() or self.ifname
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
2009-10-10 04:46:26 +00:00
|
|
|
function interface.mac(self)
|
2018-03-12 15:12:18 +00:00
|
|
|
return ipc.checkmac(self:_ubus("macaddr"))
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.ipaddrs(self)
|
2010-10-28 18:30:15 +00:00
|
|
|
return self.dev and self.dev.ipaddrs or { }
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.ip6addrs(self)
|
2010-10-28 18:30:15 +00:00
|
|
|
return self.dev and self.dev.ip6addrs or { }
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function interface.type(self)
|
2018-07-15 15:07:28 +00:00
|
|
|
if self.ifname and self.ifname:byte(1) == 64 then
|
|
|
|
return "alias"
|
|
|
|
elseif self.wif or _wifi_iface(self.ifname) then
|
2010-10-28 18:30:15 +00:00
|
|
|
return "wifi"
|
2011-10-03 13:57:11 +00:00
|
|
|
elseif _bridge[self.ifname] then
|
2009-10-08 09:32:00 +00:00
|
|
|
return "bridge"
|
2011-10-03 13:57:11 +00:00
|
|
|
elseif _tunnel[self.ifname] then
|
2011-09-24 00:57:59 +00:00
|
|
|
return "tunnel"
|
2011-09-14 09:36:55 +00:00
|
|
|
elseif self.ifname:match("%.") then
|
|
|
|
return "vlan"
|
2011-10-03 13:57:11 +00:00
|
|
|
elseif _switch[self.ifname] then
|
2009-10-08 09:32:00 +00:00
|
|
|
return "switch"
|
|
|
|
else
|
|
|
|
return "ethernet"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-15 16:30:17 +00:00
|
|
|
function interface.shortname(self)
|
2010-10-30 00:40:07 +00:00
|
|
|
if self.wif then
|
2016-08-04 09:40:34 +00:00
|
|
|
return self.wif:shortname()
|
2009-10-15 16:30:17 +00:00
|
|
|
else
|
|
|
|
return self.ifname
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function interface.get_i18n(self)
|
2010-10-30 00:40:07 +00:00
|
|
|
if self.wif then
|
2010-10-28 18:30:15 +00:00
|
|
|
return "%s: %s %q" %{
|
2012-09-15 14:02:27 +00:00
|
|
|
lng.translate("Wireless Network"),
|
2010-10-30 00:40:07 +00:00
|
|
|
self.wif:active_mode(),
|
2018-05-19 20:11:05 +00:00
|
|
|
self.wif:active_ssid() or self.wif:active_bssid() or self.wif:id() or "?"
|
2010-10-28 18:30:15 +00:00
|
|
|
}
|
2009-10-15 16:30:17 +00:00
|
|
|
else
|
|
|
|
return "%s: %q" %{ self:get_type_i18n(), self:name() }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-08 10:25:52 +00:00
|
|
|
function interface.get_type_i18n(self)
|
|
|
|
local x = self:type()
|
2018-07-15 15:07:28 +00:00
|
|
|
if x == "alias" then
|
|
|
|
return lng.translate("Alias Interface")
|
|
|
|
elseif x == "wifi" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Wireless Adapter")
|
2009-10-08 10:25:52 +00:00
|
|
|
elseif x == "bridge" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Bridge")
|
2009-10-08 10:25:52 +00:00
|
|
|
elseif x == "switch" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Ethernet Switch")
|
2011-09-14 09:36:55 +00:00
|
|
|
elseif x == "vlan" then
|
2016-08-15 15:52:28 +00:00
|
|
|
if _switch[self.ifname] then
|
|
|
|
return lng.translate("Switch VLAN")
|
|
|
|
else
|
|
|
|
return lng.translate("Software VLAN")
|
|
|
|
end
|
2011-09-24 00:57:59 +00:00
|
|
|
elseif x == "tunnel" then
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Tunnel Interface")
|
2009-10-08 10:25:52 +00:00
|
|
|
else
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate("Ethernet Adapter")
|
2009-10-08 10:25:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-28 18:30:15 +00:00
|
|
|
function interface.adminlink(self)
|
2010-10-30 00:40:07 +00:00
|
|
|
if self.wif then
|
|
|
|
return self.wif:adminlink()
|
2010-10-28 18:30:15 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function interface.ports(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local members = self:_ubus("bridge-members")
|
|
|
|
if members then
|
|
|
|
local _, iface
|
2009-10-08 09:32:00 +00:00
|
|
|
local ifaces = { }
|
2012-05-31 10:05:31 +00:00
|
|
|
for _, iface in ipairs(members) do
|
|
|
|
ifaces[#ifaces+1] = interface(iface)
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-10 04:46:26 +00:00
|
|
|
function interface.bridge_id(self)
|
|
|
|
if self.br then
|
|
|
|
return self.br.id
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function interface.bridge_stp(self)
|
|
|
|
if self.br then
|
|
|
|
return self.br.stp
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function interface.is_up(self)
|
2018-07-15 15:07:28 +00:00
|
|
|
local up = self:_ubus("up")
|
|
|
|
if up == nil then
|
|
|
|
up = (self:type() == "alias")
|
|
|
|
end
|
|
|
|
return up or false
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.is_bridge(self)
|
|
|
|
return (self:type() == "bridge")
|
|
|
|
end
|
|
|
|
|
2009-10-10 04:46:26 +00:00
|
|
|
function interface.is_bridgeport(self)
|
|
|
|
return self.dev and self.dev.bridge and true or false
|
|
|
|
end
|
|
|
|
|
|
|
|
function interface.tx_bytes(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local stat = self:_ubus("statistics")
|
2013-01-13 21:03:28 +00:00
|
|
|
return stat and stat.tx_bytes or 0
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.rx_bytes(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local stat = self:_ubus("statistics")
|
2013-01-13 21:03:28 +00:00
|
|
|
return stat and stat.rx_bytes or 0
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.tx_packets(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local stat = self:_ubus("statistics")
|
2013-01-13 21:03:28 +00:00
|
|
|
return stat and stat.tx_packets or 0
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function interface.rx_packets(self)
|
2012-05-31 10:05:31 +00:00
|
|
|
local stat = self:_ubus("statistics")
|
2013-01-13 21:03:28 +00:00
|
|
|
return stat and stat.rx_packets or 0
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
|
|
|
|
2009-10-08 09:32:00 +00:00
|
|
|
function interface.get_network(self)
|
2012-06-26 21:49:07 +00:00
|
|
|
return self:get_networks()[1]
|
|
|
|
end
|
2009-10-15 16:30:17 +00:00
|
|
|
|
2012-06-26 21:49:07 +00:00
|
|
|
function interface.get_networks(self)
|
|
|
|
if not self.networks then
|
|
|
|
local nets = { }
|
|
|
|
local _, net
|
2009-10-10 04:46:26 +00:00
|
|
|
for _, net in ipairs(_M:get_networks()) do
|
2011-02-06 04:12:41 +00:00
|
|
|
if net:contains_interface(self.ifname) or
|
|
|
|
net:ifname() == self.ifname
|
|
|
|
then
|
2012-06-26 21:49:07 +00:00
|
|
|
nets[#nets+1] = net
|
2009-10-10 04:46:26 +00:00
|
|
|
end
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
2012-06-26 21:49:07 +00:00
|
|
|
table.sort(nets, function(a, b) return a.sid < b.sid end)
|
|
|
|
self.networks = nets
|
|
|
|
return nets
|
2009-10-10 04:46:26 +00:00
|
|
|
else
|
2012-06-26 21:49:07 +00:00
|
|
|
return self.networks
|
2009-10-08 09:32:00 +00:00
|
|
|
end
|
|
|
|
end
|
2010-10-30 00:40:07 +00:00
|
|
|
|
|
|
|
function interface.get_wifinet(self)
|
|
|
|
return self.wif
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
wifidev = utl.class()
|
2011-10-03 13:57:11 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
function wifidev.__init__(self, name)
|
|
|
|
local t, n = _uci:get("wireless", name)
|
|
|
|
if t == "wifi-device" and n ~= nil then
|
|
|
|
self.sid = n
|
|
|
|
self.iwinfo = _wifi_iwinfo_by_ifname(self.sid, true)
|
|
|
|
end
|
|
|
|
self.sid = self.sid or name
|
|
|
|
self.iwinfo = self.iwinfo or { ifname = self.sid }
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.get(self, opt)
|
|
|
|
return _get("wireless", self.sid, opt)
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.set(self, opt, val)
|
|
|
|
return _set("wireless", self.sid, opt, val)
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.name(self)
|
|
|
|
return self.sid
|
|
|
|
end
|
|
|
|
|
2011-02-26 01:34:58 +00:00
|
|
|
function wifidev.hwmodes(self)
|
|
|
|
local l = self.iwinfo.hwmodelist
|
|
|
|
if l and next(l) then
|
|
|
|
return l
|
|
|
|
else
|
|
|
|
return { b = true, g = true }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.get_i18n(self)
|
2018-05-05 18:20:41 +00:00
|
|
|
local t = self.iwinfo.hardware_name or "Generic"
|
2011-02-26 01:34:58 +00:00
|
|
|
if self.iwinfo.type == "wl" then
|
|
|
|
t = "Broadcom"
|
|
|
|
end
|
|
|
|
|
|
|
|
local m = ""
|
|
|
|
local l = self:hwmodes()
|
|
|
|
if l.a then m = m .. "a" end
|
|
|
|
if l.b then m = m .. "b" end
|
|
|
|
if l.g then m = m .. "g" end
|
|
|
|
if l.n then m = m .. "n" end
|
2014-10-04 09:38:10 +00:00
|
|
|
if l.ac then m = "ac" end
|
2011-02-26 01:34:58 +00:00
|
|
|
|
|
|
|
return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function wifidev.is_up(self)
|
2013-12-03 15:04:34 +00:00
|
|
|
if _ubuswificache[self.sid] then
|
|
|
|
return (_ubuswificache[self.sid].up == true)
|
|
|
|
end
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
return false
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.get_wifinet(self, net)
|
2015-11-17 16:35:02 +00:00
|
|
|
if _uci:get("wireless", net) == "wifi-iface" then
|
2010-10-30 00:40:07 +00:00
|
|
|
return wifinet(net)
|
|
|
|
else
|
2018-01-01 23:24:10 +00:00
|
|
|
local wnet = _wifi_sid_by_ifname(net)
|
2010-10-30 00:40:07 +00:00
|
|
|
if wnet then
|
|
|
|
return wifinet(wnet)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.get_wifinets(self)
|
|
|
|
local nets = { }
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
_uci:foreach("wireless", "wifi-iface",
|
2010-10-30 00:40:07 +00:00
|
|
|
function(s)
|
|
|
|
if s.device == self.sid then
|
|
|
|
nets[#nets+1] = wifinet(s['.name'])
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
return nets
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.add_wifinet(self, options)
|
|
|
|
options = options or { }
|
|
|
|
options.device = self.sid
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
local wnet = _uci:section("wireless", "wifi-iface", nil, options)
|
2010-10-30 00:40:07 +00:00
|
|
|
if wnet then
|
2010-10-30 02:33:06 +00:00
|
|
|
return wifinet(wnet, options)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifidev.del_wifinet(self, net)
|
|
|
|
if utl.instanceof(net, wifinet) then
|
|
|
|
net = net.sid
|
2015-11-17 16:35:02 +00:00
|
|
|
elseif _uci:get("wireless", net) ~= "wifi-iface" then
|
2018-01-01 23:24:10 +00:00
|
|
|
net = _wifi_sid_by_ifname(net)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
2015-11-17 16:35:02 +00:00
|
|
|
if net and _uci:get("wireless", net, "device") == self.sid then
|
|
|
|
_uci:delete("wireless", net)
|
2010-10-30 00:40:07 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
wifinet = utl.class()
|
2011-10-03 13:57:11 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
function wifinet.__init__(self, name, data)
|
|
|
|
local sid, netid, radioname, radiostate, netstate
|
2010-12-05 03:57:29 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
-- lookup state by radio#.network# notation
|
|
|
|
sid = _wifi_sid_by_netid(name)
|
2015-11-17 16:35:02 +00:00
|
|
|
if sid then
|
2018-01-01 23:24:10 +00:00
|
|
|
netid = name
|
|
|
|
radioname, radiostate, netstate = _wifi_state_by_sid(sid)
|
|
|
|
else
|
|
|
|
-- lookup state by ifname (e.g. wlan0)
|
|
|
|
radioname, radiostate, netstate = _wifi_state_by_ifname(name)
|
|
|
|
if radioname and radiostate and netstate then
|
|
|
|
sid = netstate.section
|
|
|
|
netid = _wifi_netid_by_sid(sid)
|
|
|
|
else
|
|
|
|
-- lookup state by uci section id (e.g. cfg053579)
|
|
|
|
radioname, radiostate, netstate = _wifi_state_by_sid(name)
|
|
|
|
if radioname and radiostate and netstate then
|
|
|
|
sid = name
|
|
|
|
netid = _wifi_netid_by_sid(sid)
|
|
|
|
else
|
|
|
|
-- no state available, try to resolve from uci
|
|
|
|
netid, radioname = _wifi_netid_by_sid(name)
|
|
|
|
if netid and radioname then
|
|
|
|
sid = name
|
2015-11-17 16:35:02 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
local iwinfo =
|
|
|
|
(netstate and _wifi_iwinfo_by_ifname(netstate.ifname)) or
|
|
|
|
(radioname and _wifi_iwinfo_by_ifname(radioname)) or
|
|
|
|
{ ifname = (netid or sid or name) }
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2018-01-01 23:24:10 +00:00
|
|
|
self.sid = sid or name
|
|
|
|
self.wdev = iwinfo.ifname
|
|
|
|
self.iwinfo = iwinfo
|
|
|
|
self.netid = netid
|
|
|
|
self._ubusdata = {
|
|
|
|
radio = radioname,
|
|
|
|
dev = radiostate,
|
|
|
|
net = netstate
|
|
|
|
}
|
2015-11-17 16:35:02 +00:00
|
|
|
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
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get(self, opt)
|
|
|
|
return _get("wireless", self.sid, opt)
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.set(self, opt, val)
|
|
|
|
return _set("wireless", self.sid, opt, val)
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.mode(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self:ubus("net", "config", "mode") or self:get("mode") or "ap"
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.ssid(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self:ubus("net", "config", "ssid") or self:get("ssid")
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.bssid(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self:ubus("net", "config", "bssid") or self:get("bssid")
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.network(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
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
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
2011-03-13 17:22:52 +00:00
|
|
|
function wifinet.id(self)
|
|
|
|
return self.netid
|
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function wifinet.name(self)
|
|
|
|
return self.sid
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.ifname(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
local ifname = self:ubus("net", "ifname") or self.iwinfo.ifname
|
2010-11-15 22:03:45 +00:00
|
|
|
if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
|
2018-07-12 14:43:23 +00:00
|
|
|
ifname = self.netid
|
2010-11-15 22:03:45 +00:00
|
|
|
end
|
|
|
|
return ifname
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get_device(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
local dev = self:ubus("radio") or self:get("device")
|
|
|
|
return dev and wifidev(dev) or nil
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.is_up(self)
|
2013-12-03 15:23:09 +00:00
|
|
|
local ifc = self:get_interface()
|
|
|
|
return (ifc and ifc:is_up() or false)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.active_mode(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
local m = self.iwinfo.mode or self:ubus("net", "config", "mode") or self:get("mode") or "ap"
|
2010-10-30 00:40:07 +00:00
|
|
|
|
2011-01-20 23:24:02 +00:00
|
|
|
if m == "ap" then m = "Master"
|
2010-10-30 00:40:07 +00:00
|
|
|
elseif m == "sta" then m = "Client"
|
|
|
|
elseif m == "adhoc" then m = "Ad-Hoc"
|
|
|
|
elseif m == "mesh" then m = "Mesh"
|
|
|
|
elseif m == "monitor" then m = "Monitor"
|
|
|
|
end
|
|
|
|
|
|
|
|
return m
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.active_mode_i18n(self)
|
2012-09-15 14:02:27 +00:00
|
|
|
return lng.translate(self:active_mode())
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.active_ssid(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self.iwinfo.ssid or self:ubus("net", "config", "ssid") or self:get("ssid")
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.active_bssid(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self.iwinfo.bssid or self:ubus("net", "config", "bssid") or self:get("bssid")
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.active_encryption(self)
|
|
|
|
local enc = self.iwinfo and self.iwinfo.encryption
|
|
|
|
return enc and enc.description or "-"
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.assoclist(self)
|
|
|
|
return self.iwinfo.assoclist or { }
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.frequency(self)
|
|
|
|
local freq = self.iwinfo.frequency
|
|
|
|
if freq and freq > 0 then
|
|
|
|
return "%.03f" % (freq / 1000)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.bitrate(self)
|
|
|
|
local rate = self.iwinfo.bitrate
|
|
|
|
if rate and rate > 0 then
|
|
|
|
return (rate / 1000)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.channel(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self.iwinfo.channel or self:ubus("dev", "config", "channel") or
|
|
|
|
tonumber(self:get("channel"))
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.signal(self)
|
|
|
|
return self.iwinfo.signal or 0
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.noise(self)
|
|
|
|
return self.iwinfo.noise or 0
|
|
|
|
end
|
|
|
|
|
2011-03-13 17:09:26 +00:00
|
|
|
function wifinet.country(self)
|
2015-11-17 16:35:02 +00:00
|
|
|
return self.iwinfo.country or self:ubus("dev", "config", "country") or "00"
|
2011-03-13 17:09:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.txpower(self)
|
2011-12-05 18:34:22 +00:00
|
|
|
local pwr = (self.iwinfo.txpower or 0)
|
|
|
|
return pwr + self:txpower_offset()
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.txpower_offset(self)
|
|
|
|
return self.iwinfo.txpower_offset or 0
|
2011-03-13 17:09:26 +00:00
|
|
|
end
|
|
|
|
|
2010-10-30 00:40:07 +00:00
|
|
|
function wifinet.signal_level(self, s, n)
|
|
|
|
if self:active_bssid() ~= "00:00:00:00:00:00" then
|
|
|
|
local signal = s or self:signal()
|
|
|
|
local noise = n or self:noise()
|
|
|
|
|
|
|
|
if signal < 0 and noise < 0 then
|
|
|
|
local snr = -1 * (noise - signal)
|
|
|
|
return math.floor(snr / 5)
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return -1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.signal_percent(self)
|
|
|
|
local qc = self.iwinfo.quality or 0
|
|
|
|
local qm = self.iwinfo.quality_max or 0
|
|
|
|
|
|
|
|
if qc > 0 and qm > 0 then
|
|
|
|
return math.floor((100 / qm) * qc)
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.shortname(self)
|
|
|
|
return "%s %q" %{
|
2012-09-15 14:02:27 +00:00
|
|
|
lng.translate(self:active_mode()),
|
2016-08-04 09:40:34 +00:00
|
|
|
self:active_ssid() or self:active_bssid() or self:id()
|
2010-10-30 00:40:07 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get_i18n(self)
|
|
|
|
return "%s: %s %q (%s)" %{
|
2012-09-15 14:02:27 +00:00
|
|
|
lng.translate("Wireless Network"),
|
|
|
|
lng.translate(self:active_mode()),
|
2016-08-04 09:40:34 +00:00
|
|
|
self:active_ssid() or self:active_bssid() or self:id(),
|
2010-10-30 00:40:07 +00:00
|
|
|
self:ifname()
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.adminlink(self)
|
2018-01-01 23:24:10 +00:00
|
|
|
local stat, dsp = pcall(require, "luci.dispatcher")
|
|
|
|
return dsp and dsp.build_url("admin", "network", "wireless", self.netid)
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get_network(self)
|
2012-06-26 21:49:07 +00:00
|
|
|
return self:get_networks()[1]
|
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get_networks(self)
|
|
|
|
local nets = { }
|
|
|
|
local net
|
2015-11-17 16:35:02 +00:00
|
|
|
for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
|
|
|
|
if _uci:get("network", net) == "interface" then
|
2012-06-26 21:49:07 +00:00
|
|
|
nets[#nets+1] = network(net)
|
|
|
|
end
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
2012-06-26 21:49:07 +00:00
|
|
|
table.sort(nets, function(a, b) return a.sid < b.sid end)
|
|
|
|
return nets
|
2010-10-30 00:40:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function wifinet.get_interface(self)
|
|
|
|
return interface(self:ifname())
|
|
|
|
end
|
2011-10-03 13:57:11 +00:00
|
|
|
|
|
|
|
|
2011-10-04 13:32:18 +00:00
|
|
|
-- setup base protocols
|
|
|
|
_M:register_protocol("static")
|
|
|
|
_M:register_protocol("dhcp")
|
|
|
|
_M:register_protocol("none")
|
|
|
|
|
2011-10-03 13:57:11 +00:00
|
|
|
-- load protocol extensions
|
|
|
|
local exts = nfs.dir(utl.libpath() .. "/model/network")
|
|
|
|
if exts then
|
|
|
|
local ext
|
|
|
|
for ext in exts do
|
|
|
|
if ext:match("%.lua$") then
|
|
|
|
require("luci.model.network." .. ext:gsub("%.lua$", ""))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|