libs/core: clean up network model, make it modular and move protocol deviations into submodules, fix recognition of pptp and properly implement relayd protocol awareness

This commit is contained in:
Jo-Philipp Wich 2011-10-03 13:57:11 +00:00
parent f3690b2e03
commit 35137845dd
4 changed files with 494 additions and 204 deletions

View file

@ -20,7 +20,10 @@ limitations under the License.
local type, next, pairs, ipairs, loadfile, table, tonumber, math, i18n local type, next, pairs, ipairs, loadfile, table, tonumber, math, i18n
= type, next, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n = type, next, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n
local require = require
local nxo = require "nixio" local nxo = require "nixio"
local nfs = require "nixio.fs"
local ipc = require "luci.ip" local ipc = require "luci.ip"
local sys = require "luci.sys" local sys = require "luci.sys"
local utl = require "luci.util" local utl = require "luci.util"
@ -30,10 +33,19 @@ local uci = require "luci.model.uci"
module "luci.model.network" module "luci.model.network"
local ifs, brs, sws, tns, uci_r, uci_s IFACE_PATTERNS_VIRTUAL = { }
IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^lo$" }
IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
function _list_del(c, s, o, r)
local val = uci_r:get(c, s, o) proto = { }
proto.generic = utl.class()
local _interfaces, _bridge, _switch, _tunnel
local _uci_real, _uci_state
function _filter(c, s, o, r)
local val = _uci_real:get(c, s, o)
if val then if val then
local l = { } local l = { }
if type(val) == "string" then if type(val) == "string" then
@ -43,9 +55,9 @@ function _list_del(c, s, o, r)
end end
end end
if #l > 0 then if #l > 0 then
uci_r:set(c, s, o, table.concat(l, " ")) _uci_real:set(c, s, o, table.concat(l, " "))
else else
uci_r:delete(c, s, o) _uci_real:delete(c, s, o)
end end
elseif type(val) == "table" then elseif type(val) == "table" then
for _, val in ipairs(val) do for _, val in ipairs(val) do
@ -54,16 +66,16 @@ function _list_del(c, s, o, r)
end end
end end
if #l > 0 then if #l > 0 then
uci_r:set(c, s, o, l) _uci_real:set(c, s, o, l)
else else
uci_r:delete(c, s, o) _uci_real:delete(c, s, o)
end end
end end
end end
end end
function _list_add(c, s, o, a) function _append(c, s, o, a)
local val = uci_r:get(c, s, o) or "" local val = _uci_real:get(c, s, o) or ""
if type(val) == "string" then if type(val) == "string" then
local l = { } local l = { }
for val in val:gmatch("%S+") do for val in val:gmatch("%S+") do
@ -72,7 +84,7 @@ function _list_add(c, s, o, a)
end end
end end
l[#l+1] = a l[#l+1] = a
uci_r:set(c, s, o, table.concat(l, " ")) _uci_real:set(c, s, o, table.concat(l, " "))
elseif type(val) == "table" then elseif type(val) == "table" then
local l = { } local l = { }
for _, val in ipairs(val) do for _, val in ipairs(val) do
@ -81,7 +93,7 @@ function _list_add(c, s, o, a)
end end
end end
l[#l+1] = a l[#l+1] = a
uci_r:set(c, s, o, l) _uci_real:set(c, s, o, l)
end end
end end
@ -94,23 +106,26 @@ function _stror(s1, s2)
end end
function _get(c, s, o) function _get(c, s, o)
return uci_r:get(c, s, o) return _uci_real:get(c, s, o)
end end
function _set(c, s, o, v) function _set(c, s, o, v)
if v ~= nil then if v ~= nil then
if type(v) == "boolean" then v = v and "1" or "0" end if type(v) == "boolean" then v = v and "1" or "0" end
return uci_r:set(c, s, o, v) return _uci_real:set(c, s, o, v)
else else
return uci_r:delete(c, s, o) return _uci_real:delete(c, s, o)
end end
end end
function _wifi_iface(x) function _wifi_iface(x)
return ( local _, p
x:match("^wlan%d") or x:match("^wl%d") or x:match("^ath%d") or for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
x:match("^%w+%.network%d") if x:match(p) then
) return true
end
end
return false
end end
function _wifi_lookup(ifn) function _wifi_lookup(ifn)
@ -121,7 +136,7 @@ function _wifi_lookup(ifn)
local num = 0 local num = 0
ifnidx = tonumber(ifnidx) ifnidx = tonumber(ifnidx)
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device == radio then if s.device == radio then
num = num + 1 num = num + 1
@ -138,7 +153,7 @@ function _wifi_lookup(ifn)
elseif _wifi_iface(ifn) then elseif _wifi_iface(ifn) then
local sid = nil local sid = nil
uci_s:foreach("wireless", "wifi-iface", _uci_state:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.ifname == ifn then if s.ifname == ifn then
sid = s['.name'] sid = s['.name']
@ -151,30 +166,34 @@ function _wifi_lookup(ifn)
end end
function _iface_virtual(x) function _iface_virtual(x)
return ( local _, p
x:match("^6in4-%w") or x:match("^6to4-%w") or x:match("^3g-%w") or for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
x:match("^ppp-%w") or x:match("^pppoe-%w") or x:match("^pppoa-%w") or if x:match(p) then
x:match("^relay-%w") return true
) end
end
return false
end end
function _iface_ignore(x) function _iface_ignore(x)
return ( local _, p
x:match("^wmaster%d") or x:match("^wifi%d") or x:match("^hwsim%d") or for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
x:match("^imq%d") or x:match("^mon.wlan%d") or if x:match(p) then
x == "sit0" or x == "lo" or _iface_virtual(x) return true
) end
end
return _iface_virtual(x)
end end
function init(cursor) function init(cursor)
uci_r = cursor or uci_r or uci.cursor() _uci_real = cursor or _uci_real or uci.cursor()
uci_s = uci_r:substate() _uci_state = _uci_real:substate()
ifs = { } _interfaces = { }
brs = { } _bridge = { }
sws = { } _switch = { }
tns = { } _tunnel = { }
-- read interface information -- read interface information
local n, i local n, i
@ -183,11 +202,11 @@ function init(cursor)
local prnt = name:match("^([^%.]+)%.") local prnt = name:match("^([^%.]+)%.")
if _iface_virtual(name) then if _iface_virtual(name) then
tns[name] = true _tunnel[name] = true
end end
if tns[name] or not _iface_ignore(name) then if _tunnel[name] or not _iface_ignore(name) then
ifs[name] = ifs[name] or { _interfaces[name] = _interfaces[name] or {
idx = i.ifindex or n, idx = i.ifindex or n,
name = name, name = name,
rawname = i.name, rawname = i.name,
@ -197,18 +216,18 @@ function init(cursor)
} }
if prnt then if prnt then
sws[name] = true _switch[name] = true
sws[prnt] = true _switch[prnt] = true
end end
if i.family == "packet" then if i.family == "packet" then
ifs[name].flags = i.flags _interfaces[name].flags = i.flags
ifs[name].stats = i.data _interfaces[name].stats = i.data
ifs[name].macaddr = i.addr _interfaces[name].macaddr = i.addr
elseif i.family == "inet" then elseif i.family == "inet" then
ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask) _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
elseif i.family == "inet6" then elseif i.family == "inet6" then
ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask) _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
end end
end end
end end
@ -223,14 +242,14 @@ function init(cursor)
name = r[1], name = r[1],
id = r[2], id = r[2],
stp = r[3] == "yes", stp = r[3] == "yes",
ifnames = { ifs[r[4]] } ifnames = { _interfaces[r[4]] }
} }
if b.ifnames[1] then if b.ifnames[1] then
b.ifnames[1].bridge = b b.ifnames[1].bridge = b
end end
brs[r[1]] = b _bridge[r[1]] = b
elseif b then elseif b then
b.ifnames[#b.ifnames+1] = ifs[r[2]] b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
b.ifnames[#b.ifnames].bridge = b b.ifnames[#b.ifnames].bridge = b
end end
end end
@ -240,13 +259,23 @@ function init(cursor)
end end
function save(self, ...) function save(self, ...)
uci_r:save(...) _uci_real:save(...)
uci_r:load(...) _uci_real:load(...)
end end
function commit(self, ...) function commit(self, ...)
uci_r:commit(...) _uci_real:commit(...)
uci_r:load(...) _uci_real:load(...)
end
function ifnameof(self, x)
if utl.instanceof(x, interface) then
return x:name()
elseif utl.instanceof(x, proto.generic) then
return x:ifname()
elseif type(x) == "string" then
return x:match("^[^:]+")
end
end end
function has_ipv6(self) function has_ipv6(self)
@ -256,7 +285,7 @@ end
function add_network(self, n, options) function add_network(self, n, options)
local oldnet = self:get_network(n) local oldnet = self:get_network(n)
if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
if uci_r:section("network", "interface", n, options) then if _uci_real:section("network", "interface", n, options) then
return network(n) return network(n)
end end
elseif oldnet and oldnet:is_empty() then elseif oldnet and oldnet:is_empty() then
@ -271,7 +300,7 @@ function add_network(self, n, options)
end end
function get_network(self, n) function get_network(self, n)
if n and uci_r:get("network", n) == "interface" then if n and _uci_real:get("network", n) == "interface" then
return network(n) return network(n)
end end
end end
@ -280,7 +309,7 @@ function get_networks(self)
local nets = { } local nets = { }
local nls = { } local nls = { }
uci_r:foreach("network", "interface", _uci_real:foreach("network", "interface",
function(s) function(s)
nls[s['.name']] = network(s['.name']) nls[s['.name']] = network(s['.name'])
end) end)
@ -294,21 +323,21 @@ function get_networks(self)
end end
function del_network(self, n) function del_network(self, n)
local r = uci_r:delete("network", n) local r = _uci_real:delete("network", n)
if r then if r then
uci_r:delete_all("network", "alias", _uci_real:delete_all("network", "alias",
function(s) return (s.interface == n) end) function(s) return (s.interface == n) end)
uci_r:delete_all("network", "route", _uci_real:delete_all("network", "route",
function(s) return (s.interface == n) end) function(s) return (s.interface == n) end)
uci_r:delete_all("network", "route6", _uci_real:delete_all("network", "route6",
function(s) return (s.interface == n) end) function(s) return (s.interface == n) end)
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.network == n then if s.network == n then
uci_r:delete("wireless", s['.name'], "network") _uci_real:delete("wireless", s['.name'], "network")
end end
end) end)
end end
@ -318,50 +347,50 @@ end
function rename_network(self, old, new) function rename_network(self, old, new)
local r local r
if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
r = uci_r:section("network", "interface", new, uci_r:get_all("network", old)) r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
if r then if r then
uci_r:foreach("network", "alias", _uci_real:foreach("network", "alias",
function(s) function(s)
if s.interface == old then if s.interface == old then
uci_r:set("network", s['.name'], "interface", new) _uci_real:set("network", s['.name'], "interface", new)
end end
end) end)
uci_r:foreach("network", "route", _uci_real:foreach("network", "route",
function(s) function(s)
if s.interface == old then if s.interface == old then
uci_r:set("network", s['.name'], "interface", new) _uci_real:set("network", s['.name'], "interface", new)
end end
end) end)
uci_r:foreach("network", "route6", _uci_real:foreach("network", "route6",
function(s) function(s)
if s.interface == old then if s.interface == old then
uci_r:set("network", s['.name'], "interface", new) _uci_real:set("network", s['.name'], "interface", new)
end end
end) end)
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.network == old then if s.network == old then
uci_r:set("wireless", s['.name'], "network", new) _uci_real:set("wireless", s['.name'], "network", new)
end end
end) end)
uci_r:delete("network", old) _uci_real:delete("network", old)
end end
end end
return r or false return r or false
end end
function get_interface(self, i) function get_interface(self, i)
if ifs[i] or _wifi_iface(i) then if _interfaces[i] or _wifi_iface(i) then
return interface(i) return interface(i)
else else
local ifc local ifc
local num = { } local num = { }
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1 num[s.device] = num[s.device] and num[s.device] + 1 or 1
@ -383,7 +412,7 @@ function get_interfaces(self)
local nfs = { } local nfs = { }
-- find normal interfaces -- find normal interfaces
uci_r:foreach("network", "interface", _uci_real:foreach("network", "interface",
function(s) function(s)
for iface in utl.imatch(s.ifname) do for iface in utl.imatch(s.ifname) do
if not _iface_ignore(iface) and not _wifi_iface(iface) then if not _iface_ignore(iface) and not _wifi_iface(iface) then
@ -393,14 +422,14 @@ function get_interfaces(self)
end end
end) end)
for iface in utl.kspairs(ifs) do for iface in utl.kspairs(_interfaces) do
if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
nfs[iface] = interface(iface) nfs[iface] = interface(iface)
end end
end end
-- find vlan interfaces -- find vlan interfaces
uci_r:foreach("network", "switch_vlan", _uci_real:foreach("network", "switch_vlan",
function(s) function(s)
local base = s.device or "-" local base = s.device or "-"
if not base:match("^eth%d") then if not base:match("^eth%d") then
@ -424,7 +453,7 @@ function get_interfaces(self)
-- find wifi interfaces -- find wifi interfaces
local num = { } local num = { }
local wfs = { } local wfs = { }
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1 num[s.device] = num[s.device] and num[s.device] + 1 or 1
@ -445,7 +474,7 @@ function ignore_interface(self, x)
end end
function get_wifidev(self, dev) function get_wifidev(self, dev)
if uci_r:get("wireless", dev) == "wifi-device" then if _uci_real:get("wireless", dev) == "wifi-device" then
return wifidev(dev) return wifidev(dev)
end end
end end
@ -454,7 +483,7 @@ function get_wifidevs(self)
local devs = { } local devs = { }
local wfd = { } local wfd = { }
uci_r:foreach("wireless", "wifi-device", _uci_real:foreach("wireless", "wifi-device",
function(s) wfd[#wfd+1] = s['.name'] end) function(s) wfd[#wfd+1] = s['.name'] end)
local dev local dev
@ -474,9 +503,9 @@ end
function add_wifinet(self, net, options) function add_wifinet(self, net, options)
if type(options) == "table" and options.device and if type(options) == "table" and options.device and
uci_r:get("wireless", options.device) == "wifi-device" _uci_real:get("wireless", options.device) == "wifi-device"
then then
local wnet = uci_r:section("wireless", "wifi-iface", nil, options) local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
return wifinet(wnet) return wifinet(wnet)
end end
end end
@ -484,29 +513,35 @@ end
function del_wifinet(self, net) function del_wifinet(self, net)
local wnet = _wifi_lookup(net) local wnet = _wifi_lookup(net)
if wnet then if wnet then
uci_r:delete("wireless", wnet) _uci_real:delete("wireless", wnet)
return true return true
end end
return false return false
end end
network = utl.class() function network(name)
if name then
local p = _uci_real:get("network", name, "proto")
local c = p and proto[p] or proto.generic
return c(name)
end
end
function network.__init__(self, name) function proto.generic.__init__(self, name)
self.sid = name self.sid = name
end end
function network._get(self, opt) function proto.generic._get(self, opt)
local v = uci_r:get("network", self.sid, opt) local v = _uci_real:get("network", self.sid, opt)
if type(v) == "table" then if type(v) == "table" then
return table.concat(v, " ") return table.concat(v, " ")
end end
return v or "" return v or ""
end end
function network._ip(self, opt, family, list) function proto.generic._ip(self, opt, family, list)
local ip = uci_s:get("network", self.sid, opt) local ip = _uci_state:get("network", self.sid, opt)
local fc = (family == 6) and ipc.IPv6 or ipc.IPv4 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
if ip or list then if ip or list then
if list then if list then
@ -523,32 +558,30 @@ function network._ip(self, opt, family, list)
end end
end end
function network.get(self, opt) function proto.generic.get(self, opt)
return _get("network", self.sid, opt) return _get("network", self.sid, opt)
end end
function network.set(self, opt, val) function proto.generic.set(self, opt, val)
return _set("network", self.sid, opt, val) return _set("network", self.sid, opt, val)
end end
function network.ifname(self) function proto.generic.ifname(self)
local p = self:proto() local p = self:proto()
if self:is_bridge() then if self:is_bridge() then
return "br-" .. self.sid return "br-" .. self.sid
elseif self:proto() == "relay" then
return uci_s:get("network", self.sid, "up") == "1" and "lo" or nil
elseif self:is_virtual() then elseif self:is_virtual() then
return p .. "-" .. self.sid return p .. "-" .. self.sid
else else
local num = { } local num = { }
local dev = uci_r:get("network", self.sid, "ifname") or local dev = _uci_real:get("network", self.sid, "ifname") or
uci_s:get("network", self.sid, "ifname") _uci_state:get("network", self.sid, "ifname")
dev = (type(dev) == "table") and dev[1] or dev dev = (type(dev) == "table") and dev[1] or dev
dev = (dev ~= nil) and dev:match("%S+") dev = (dev ~= nil) and dev:match("%S+")
if not dev then if not dev then
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] num[s.device] = num[s.device]
@ -566,38 +599,20 @@ function network.ifname(self)
end end
end end
function network.device(self) function proto.generic.proto(self)
local dev = uci_r:get("network", self.sid, "device") or
uci_s:get("network", self.sid, "device")
dev = (type(dev) == "table") and dev[1] or dev
if not dev or dev:match("[^%w%-%.%s]") then
dev = uci_r:get("network", self.sid, "ifname") or
uci_s:get("network", self.sid, "ifname")
dev = (type(dev) == "table") and dev[1] or dev
end
for dev in utl.imatch(dev) do
return dev
end
end
function network.proto(self)
return self:_get("proto") or "none" return self:_get("proto") or "none"
end end
function network.type(self) function proto.generic.type(self)
return self:_get("type") return self:_get("type")
end end
function network.name(self) function proto.generic.name(self)
return self.sid return self.sid
end end
function network.uptime(self) function proto.generic.uptime(self)
local cnt = tonumber(uci_s:get("network", self.sid, "connect_time")) local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
if cnt ~= nil then if cnt ~= nil then
return nxo.sysinfo().uptime - cnt return nxo.sysinfo().uptime - cnt
else else
@ -605,9 +620,9 @@ function network.uptime(self)
end end
end end
function network.expires(self) function proto.generic.expires(self)
local a = tonumber(uci_s:get("network", self.sid, "lease_acquired")) local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
local l = tonumber(uci_s:get("network", self.sid, "lease_lifetime")) local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
if a and l then if a and l then
l = l - (nxo.sysinfo().uptime - a) l = l - (nxo.sysinfo().uptime - a)
return l > 0 and l or 0 return l > 0 and l or 0
@ -615,30 +630,30 @@ function network.expires(self)
return -1 return -1
end end
function network.metric(self) function proto.generic.metric(self)
return tonumber(uci_s:get("network", self.sid, "metric")) or 0 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
end end
function network.ipaddr(self) function proto.generic.ipaddr(self)
return self:_ip("ipaddr", 4) return self:_ip("ipaddr", 4)
end end
function network.netmask(self) function proto.generic.netmask(self)
return self:_ip("netmask", 4) return self:_ip("netmask", 4)
end end
function network.gwaddr(self) function proto.generic.gwaddr(self)
return self:_ip("gateway", 4) return self:_ip("gateway", 4)
end end
function network.dnsaddrs(self) function proto.generic.dnsaddrs(self)
return self:_ip("dns", 4, true) return self:_ip("dns", 4, true)
end end
function network.ip6addr(self) function proto.generic.ip6addr(self)
local ip6 = self:_ip("ip6addr", 6) local ip6 = self:_ip("ip6addr", 6)
if not ip6 then if not ip6 then
local ifc = ifs[self:ifname()] local ifc = _interfaces[self:ifname()]
if ifc and ifc.ip6addrs then if ifc and ifc.ip6addrs then
local a local a
for _, a in ipairs(ifc.ip6addrs) do for _, a in ipairs(ifc.ip6addrs) do
@ -652,7 +667,7 @@ function network.ip6addr(self)
return ip6 return ip6
end end
function network.gw6addr(self) function proto.generic.gw6addr(self)
local ip6 = self:_ip("ip6gw", 6) local ip6 = self:_ip("ip6gw", 6)
if not ip6 then if not ip6 then
local dr6 = sys.net.defaultroute6() local dr6 = sys.net.defaultroute6()
@ -663,27 +678,23 @@ function network.gw6addr(self)
return ip6 return ip6
end end
function network.dns6addrs(self) function proto.generic.dns6addrs(self)
return self:_ip("dns", 6, true) return self:_ip("dns", 6, true)
end end
function network.is_bridge(self) function proto.generic.is_bridge(self)
return (self:type() == "bridge") return (self:type() == "bridge")
end end
function network.is_virtual(self) function proto.generic.is_virtual(self)
local p = self:proto() return false
return (
p == "3g" or p == "6in4" or p == "6to4" or p == "ppp" or
p == "pppoe" or p == "pppoa" or p == "relay"
)
end end
function network.is_floating(self) function proto.generic.is_floating(self)
return (self:is_virtual() and self:proto() ~= "pppoe") return false
end end
function network.is_empty(self) function proto.generic.is_empty(self)
if self:is_virtual() then if self:is_virtual() then
return false return false
else else
@ -693,7 +704,7 @@ function network.is_empty(self)
rv = false rv = false
end end
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.network == self.sid then if s.network == self.sid then
rv = false rv = false
@ -705,65 +716,55 @@ function network.is_empty(self)
end end
end end
function network.add_interface(self, ifname) function proto.generic.add_interface(self, ifname)
if not self:is_floating() then ifname = _M:ifnameof(ifname)
if type(ifname) ~= "string" then if ifname and not self:is_floating() then
ifname = ifname:name()
else
ifname = ifname:match("[^%s:]+")
end
-- remove the interface from all ifaces -- remove the interface from all ifaces
uci_r:foreach("network", "interface", _uci_real:foreach("network", "interface",
function(s) function(s)
_list_del("network", s['.name'], "ifname", ifname) _filter("network", s['.name'], "ifname", ifname)
end) end)
-- if its a wifi interface, change its network option -- if its a wifi interface, change its network option
local wif = _wifi_lookup(ifname) local wif = _wifi_lookup(ifname)
if wif then if wif then
uci_r:set("wireless", wif, "network", self.sid) _uci_real:set("wireless", wif, "network", self.sid)
-- add iface to our iface list -- add iface to our iface list
else else
_list_add("network", self.sid, "ifname", ifname) _append("network", self.sid, "ifname", ifname)
end end
end end
end end
function network.del_interface(self, ifname) function proto.generic.del_interface(self, ifname)
if not self:is_floating() then ifname = _M:ifnameof(ifname)
if utl.instanceof(ifname, interface) then if ifname and not self:is_floating() then
ifname = ifname:name()
else
ifname = ifname:match("[^%s:]+")
end
-- if its a wireless interface, clear its network option -- if its a wireless interface, clear its network option
local wif = _wifi_lookup(ifname) local wif = _wifi_lookup(ifname)
if wif then uci_r:delete("wireless", wif, "network") end if wif then _uci_real:delete("wireless", wif, "network") end
-- remove the interface -- remove the interface
_list_del("network", self.sid, "ifname", ifname) _filter("network", self.sid, "ifname", ifname)
end end
end end
function network.get_interface(self) function proto.generic.get_interface(self)
if self:is_virtual() then if self:is_virtual() then
tns[self:proto() .. "-" .. self.sid] = true _tunnel[self:proto() .. "-" .. self.sid] = true
return interface(self:proto() .. "-" .. self.sid, self) return interface(self:proto() .. "-" .. self.sid, self)
elseif self:is_bridge() then elseif self:is_bridge() then
brs["br-" .. self.sid] = true _bridge["br-" .. self.sid] = true
return interface("br-" .. self.sid, self) return interface("br-" .. self.sid, self)
else else
local ifn = nil local ifn = nil
local num = { } local num = { }
for ifn in utl.imatch(uci_s:get("network", self.sid, "ifname")) do for ifn in utl.imatch(_uci_state:get("network", self.sid, "ifname")) do
ifn = ifn:match("^[^:/]+") ifn = ifn:match("^[^:/]+")
return ifn and interface(ifn, self) return ifn and interface(ifn, self)
end end
ifn = nil ifn = nil
uci_s:foreach("wireless", "wifi-iface", _uci_state:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1 num[s.device] = num[s.device] and num[s.device] + 1 or 1
@ -777,7 +778,7 @@ function network.get_interface(self)
end end
end end
function network.get_interfaces(self) function proto.generic.get_interfaces(self)
if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
local ifaces = { } local ifaces = { }
@ -794,7 +795,7 @@ function network.get_interfaces(self)
local num = { } local num = { }
local wfs = { } local wfs = { }
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1 num[s.device] = num[s.device] and num[s.device] + 1 or 1
@ -813,14 +814,11 @@ function network.get_interfaces(self)
end end
end end
function network.contains_interface(self, ifname) function proto.generic.contains_interface(self, ifname)
if type(ifname) ~= "string" then ifname = _M:ifnameof(ifname)
ifname = ifname:name() if not ifname then
else return false
ifname = ifname:match("[^%s:]+") elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
end
if self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
return true return true
elseif self:is_bridge() and "br-" .. self.sid == ifname then elseif self:is_bridge() and "br-" .. self.sid == ifname then
return true return true
@ -835,25 +833,26 @@ function network.contains_interface(self, ifname)
local wif = _wifi_lookup(ifname) local wif = _wifi_lookup(ifname)
if wif then if wif then
return (uci_r:get("wireless", wif, "network") == self.sid) return (_uci_real:get("wireless", wif, "network") == self.sid)
end end
end end
return false return false
end end
function network.adminlink(self) function proto.generic.adminlink(self)
return dsp.build_url("admin", "network", "network", self.sid) return dsp.build_url("admin", "network", "network", self.sid)
end end
interface = utl.class() interface = utl.class()
function interface.__init__(self, ifname, network) function interface.__init__(self, ifname, network)
local wif = _wifi_lookup(ifname) local wif = _wifi_lookup(ifname)
if wif then self.wif = wifinet(wif) end if wif then self.wif = wifinet(wif) end
self.ifname = self.ifname or ifname self.ifname = self.ifname or ifname
self.dev = ifs[self.ifname] self.dev = _interfaces[self.ifname]
self.network = network self.network = network
end end
@ -876,13 +875,13 @@ end
function interface.type(self) function interface.type(self)
if self.wif or _wifi_iface(self.ifname) then if self.wif or _wifi_iface(self.ifname) then
return "wifi" return "wifi"
elseif brs[self.ifname] then elseif _bridge[self.ifname] then
return "bridge" return "bridge"
elseif tns[self.ifname] then elseif _tunnel[self.ifname] then
return "tunnel" return "tunnel"
elseif self.ifname:match("%.") then elseif self.ifname:match("%.") then
return "vlan" return "vlan"
elseif sws[self.ifname] then elseif _switch[self.ifname] then
return "switch" return "switch"
else else
return "ethernet" return "ethernet"
@ -1026,6 +1025,7 @@ end
wifidev = utl.class() wifidev = utl.class()
function wifidev.__init__(self, dev) function wifidev.__init__(self, dev)
self.sid = dev self.sid = dev
self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { } self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
@ -1073,7 +1073,7 @@ end
function wifidev.is_up(self) function wifidev.is_up(self)
local up = false local up = false
uci_s:foreach("wireless", "wifi-iface", _uci_state:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device == self.sid then if s.device == self.sid then
if s.up == "1" then if s.up == "1" then
@ -1087,7 +1087,7 @@ function wifidev.is_up(self)
end end
function wifidev.get_wifinet(self, net) function wifidev.get_wifinet(self, net)
if uci_r:get("wireless", net) == "wifi-iface" then if _uci_real:get("wireless", net) == "wifi-iface" then
return wifinet(net) return wifinet(net)
else else
local wnet = _wifi_lookup(net) local wnet = _wifi_lookup(net)
@ -1100,7 +1100,7 @@ end
function wifidev.get_wifinets(self) function wifidev.get_wifinets(self)
local nets = { } local nets = { }
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device == self.sid then if s.device == self.sid then
nets[#nets+1] = wifinet(s['.name']) nets[#nets+1] = wifinet(s['.name'])
@ -1114,7 +1114,7 @@ function wifidev.add_wifinet(self, options)
options = options or { } options = options or { }
options.device = self.sid options.device = self.sid
local wnet = uci_r:section("wireless", "wifi-iface", nil, options) local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
if wnet then if wnet then
return wifinet(wnet, options) return wifinet(wnet, options)
end end
@ -1123,12 +1123,12 @@ end
function wifidev.del_wifinet(self, net) function wifidev.del_wifinet(self, net)
if utl.instanceof(net, wifinet) then if utl.instanceof(net, wifinet) then
net = net.sid net = net.sid
elseif uci_r:get("wireless", net) ~= "wifi-iface" then elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
net = _wifi_lookup(net) net = _wifi_lookup(net)
end end
if net and uci_r:get("wireless", net, "device") == self.sid then if net and _uci_real:get("wireless", net, "device") == self.sid then
uci_r:delete("wireless", net) _uci_real:delete("wireless", net)
return true return true
end end
@ -1137,12 +1137,13 @@ end
wifinet = utl.class() wifinet = utl.class()
function wifinet.__init__(self, net, data) function wifinet.__init__(self, net, data)
self.sid = net self.sid = net
local num = { } local num = { }
local netid local netid
uci_r:foreach("wireless", "wifi-iface", _uci_real:foreach("wireless", "wifi-iface",
function(s) function(s)
if s.device then if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1 num[s.device] = num[s.device] and num[s.device] + 1 or 1
@ -1153,13 +1154,13 @@ function wifinet.__init__(self, net, data)
end end
end) end)
local dev = uci_s:get("wireless", self.sid, "ifname") or netid local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
self.netid = netid self.netid = netid
self.wdev = dev self.wdev = dev
self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { } self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
self.iwdata = data or uci_s:get_all("wireless", self.sid) or self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
uci_r:get_all("wireless", self.sid) or { } _uci_real:get_all("wireless", self.sid) or { }
end end
function wifinet.get(self, opt) function wifinet.get(self, opt)
@ -1171,19 +1172,19 @@ function wifinet.set(self, opt, val)
end end
function wifinet.mode(self) function wifinet.mode(self)
return uci_s:get("wireless", self.sid, "mode") or "ap" return _uci_state:get("wireless", self.sid, "mode") or "ap"
end end
function wifinet.ssid(self) function wifinet.ssid(self)
return uci_s:get("wireless", self.sid, "ssid") return _uci_state:get("wireless", self.sid, "ssid")
end end
function wifinet.bssid(self) function wifinet.bssid(self)
return uci_s:get("wireless", self.sid, "bssid") return _uci_state:get("wireless", self.sid, "bssid")
end end
function wifinet.network(self) function wifinet.network(self)
return uci_s:get("wifinet", self.sid, "network") return _uci_state:get("wifinet", self.sid, "network")
end end
function wifinet.id(self) function wifinet.id(self)
@ -1262,7 +1263,7 @@ end
function wifinet.channel(self) function wifinet.channel(self)
return self.iwinfo.channel or return self.iwinfo.channel or
tonumber(uci_s:get("wireless", self.iwdata.device, "channel")) tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
end end
function wifinet.signal(self) function wifinet.signal(self)
@ -1329,7 +1330,7 @@ function wifinet.adminlink(self)
end end
function wifinet.get_network(self) function wifinet.get_network(self)
if uci_r:get("network", self.iwdata.network) == "interface" then if _uci_real:get("network", self.iwdata.network) == "interface" then
return network(self.iwdata.network) return network(self.iwdata.network)
end end
end end
@ -1337,3 +1338,15 @@ end
function wifinet.get_interface(self) function wifinet.get_interface(self)
return interface(self:ifname()) return interface(self:ifname())
end end
-- 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

View file

@ -0,0 +1,52 @@
--[[
LuCI - Network model - 6to4 & 6in4 protocol extension
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
local netmod = luci.model.network
local proto = luci.util.class(netmod.proto.generic)
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^6to4-%w"
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^6in4-%w"
function proto.__init__(self, name)
self.sid = name
end
function proto.ifname(self)
return self:proto() .. "-" .. self.sid
end
function proto.is_floating(self)
return true
end
function proto.is_virtual(self)
return true
end
function proto.get_interfaces(self)
return nil
end
function proto.contains_interface(self, ifname)
return (netmod:ifnameof(ifc) == self:ifname())
end
netmod.proto["6to4"] = proto
netmod.proto["6in4"] = proto

View file

@ -0,0 +1,66 @@
--[[
LuCI - Network model - 3G, PPP, PPtP, PPPoE and PPPoA protocol extension
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
local netmod = luci.model.network
local proto = luci.util.class(netmod.proto.generic)
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^3g-%w"
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^ppp-%w"
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^pptp-%w"
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^pppoe-%w"
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^pppoa-%w"
function proto.__init__(self, name)
self.sid = name
end
function proto.ifname(self)
return self:proto() .. "-" .. self.sid
end
function proto.is_floating(self)
return (self:proto() ~= "pppoe")
end
function proto.is_virtual(self)
return true
end
function proto.get_interfaces(self)
if self:is_floating() then
return nil
else
return netmod.proto.generic.get_interfaces(self)
end
end
function proto.contains_interface(self, ifc)
if self:is_floating() then
return (netmod:ifnameof(ifc) == self:ifname())
else
return netmod.proto.generic.contains_interface(self, ifname)
end
end
netmod.proto["3g"] = proto
netmod.proto["ppp"] = proto
netmod.proto["pptp"] = proto
netmod.proto["pppoe"] = proto
netmod.proto["pppoa"] = proto

View file

@ -0,0 +1,159 @@
--[[
LuCI - Network model - relay protocol extension
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
local netmod = luci.model.network
local proto = luci.util.class(netmod.proto.generic)
local device = luci.util.class(netmod.interface)
netmod.IFACE_PATTERNS_VIRTUAL[#netmod.IFACE_PATTERNS_VIRTUAL+1] = "^relay-%w"
function proto.__init__(self, name)
self.sid = name
end
function proto.ifname(self)
return "relay-" .. self.sid
end
function proto.is_floating(self)
return false
end
function proto.is_virtual(self)
return true
end
function proto.get_interface(self)
return device(self.sid, self)
end
function proto.get_interfaces(self)
if not self.ifaces then
local ifs = { }
local _, net, dev
for net in luci.util.imatch(self:_get("network")) do
net = netmod:get_network(net)
if net then
dev = net:get_interface()
if dev then
ifs[dev:name()] = dev
end
end
end
for dev in luci.util.imatch(self:_get("ifname")) do
dev = netmod:get_interface(dev)
if dev then
ifs[dev:name()] = dev
end
end
self.ifaces = { }
for _, dev in luci.util.kspairs(ifs) do
self.ifaces[#self.ifaces+1] = dev
end
end
return self.ifaces
end
function proto.uptime(self)
local net
local upt = 0
for net in luci.util.imatch(self:_get("network")) do
net = netmod:get_network(net)
if net then
upt = math.max(upt, net:uptime())
end
end
return upt
end
function device.__init__(self, ifname, network)
self.ifname = ifname
self.network = network
end
function device.type(self)
return "tunnel"
end
function device.is_up(self)
if self.network then
local _, dev
for _, dev in ipairs(self.network:get_interfaces()) do
if not dev:is_up() then
return false
end
end
return true
end
return false
end
function device._stat(self, what)
local v = 0
if self.network then
local _, dev
for _, dev in ipairs(self.network:get_interfaces()) do
v = v + dev[what](dev)
end
end
return v
end
function device.rx_bytes(self) return self:_stat("rx_bytes") end
function device.tx_bytes(self) return self:_stat("tx_bytes") end
function device.rx_packets(self) return self:_stat("rx_packets") end
function device.tx_packets(self) return self:_stat("tx_packets") end
function device.mac(self)
if self.network then
local _, dev
for _, dev in ipairs(self.network:get_interfaces()) do
return dev:mac()
end
end
end
function device.ipaddrs(self)
local addrs = { }
if self.network then
addrs[1] = luci.ip.IPv4(self.network:_get("ipaddr"))
end
return addrs
end
function device.ip6addrs(self)
return { }
end
function device.shortname(self)
return "%s %q" % { luci.i18n.translate("Relay"), self.ifname }
end
function device.get_type_i18n(self)
return luci.i18n.translate("Relay Bridge")
end
netmod.proto.relay = proto