local i=require
local m=setmetatable
local t=ipairs
local h=pairs
local f,I=string.format,string.gmatch
local T=io.open
local n=i'transformer.mapper.ucihelper'local o=i'transformer.mapper.nwcommon'local _=i'transformer.shared.models.igd.xtmconnection'local r=i'transformer.shared.models.igd.activedevice'local a={config="network"}local l={}local p={}local c={config='wanconfig',sectionname='wanconfig'}local function g(o)local e={}n.foreach_on_uci(c,function(n)if not o or n.proto==o then
e[#e+1]=n
end
end)return e
end
l.get_wanconfig=g
local e={config="network"}local s={config="network",sectionname="globals",option="vlanmode",default="linux"}local d={config="network",sectionname="device"}local c={config="network",sectionname="bcmvopi"}local function w(o,t,a)e.sectionname=o
e.option=t
e.default=a
return n.get_from_uci(e)end
local function u()local t={}local e=n.get_from_uci(s)if e=="linux"then
n.foreach_on_uci(d,function(n)local o=n.name or n[".name"]local a=nil
if n.type=="macvlan"then
a=n.name
e="macvlan"end
t[o]={name=o,device=n.ifname or o,vid=n.vid or"-1",sectionname=n['.name'],vlanmode=e,physicdevice=a,}end)elseif e=="bcmvopi"then
n.foreach_on_uci(c,function(n)local o=n[".name"]t[o]={name=o,device=n['if'],vid=n.vid or'1',sectionname=o,vlanmode=e,}end)end
return t,e
end
l.get_vlans=u
local e={}e.__index=e
local function s(i,n)n=n:match("^%s*(.*)%s*$")local t
local a
local o
local c
local e=i.vlans[n]if e then
t=e.device
a=e.vid
o=e.vlanmode
c=e.physicdevice
else
o="linux-inline"local e="^([^.]*)%.(%d+)$"if n:match("^veip")then
e="^([^_]*)_(%d+)$"o="veip"end
local e,c=n:match(e)if e then
t=e
a=c
else
t=n
o=i.vlanmode
end
end
return{vlandevice=n,devname=t,vlanid=a,vlantype=o,physicdevice=c,}end
local c={config="network",sectionname="interface"}local function v(e)return n.foreach_on_uci(c,e)end
local function d(o,e,a)local t=o.entries
local n=t[e]if not n then
local o=o.keys
o[#o+1]=e
n=a or{}t[e]=n
end
return n
end
local c={ip={"static","dhcp","dhcpv6","mobiled"},ppp={"pppoe","pppoa","dhcpv6"},ipv6={"static","dhcp","dhcpv6","mobiled","pppoe","pppoa","6rd"}}local function y(n,e)local n=c[n.connType]if n then
for o,n in t(n)do
if n==e then
return true
end
end
end
end
local function c(e,n)local n=_.get_static_key(n)return f("%s|%s",e,n)end
local function x(o)local e
if p[o]then
e=p[o]else
e=string.gsub(o,"%_ppp$","")if e==o then
e=string.gsub(o,"%_4$","")end
a.sectionname=e
a.option="proto"local n=n.get_from_uci(a)if n~="mobiled"then
return
end
end
return e
end
local i=i"transformer.shared.mappings.wan.wandevice"local function k()local e={}local n=i.listDevices()for o,n in t(n)do
e[n.name]=n.type
end
return e
end
local function b(n)local c,l=o.get_lower_layers_with_status(n)if#c>1 then
local r=k()local i
local a
local e
for t,n in t(c)do
local t=r[n]if t then
if o.getIntfInfo(n,"carrier")=="1"then
i=n
break
elseif not a and(t=="ETH")then
a=n
elseif not e then
e=n
end
end
end
return i or a or e,true,l
else
return c[1],false,l
end
end
local function k(e)a.sectionname=e
a.option="proto"local a=n.get_from_uci(a)if not r.isActiveInterface(e)then
local n,i
local t={}t.vlans,t.vlanmode=u()local r,d,l=b(e)local o
if a==""then
o=x(e)end
if r then
i=s(t,r)if o then
n=c(e,o)else
n=c(e,i.devname)end
end
if not d then
return n,l
else
return nil,l,n
end
else
local n="ACTIVE|"..e
return n,{proto=a}end
end
l.get_connection_key=k
local function a(n)if type(n)=="table"then
for e,o in t(n)do
n[o]=true
n[e]=nil
end
end
end
local function k(e,n)if n and#n>0 then
a(n)local o={}for a,t in t(e)do
if not n[t]then
o[#o+1]=t
end
end
e=o
end
return e
end
local function i(n,e)for o,e in t(e)do
if n==e then
return true
end
end
return false
end
local function b(e,a)local n=g(e.connType)local l=a:match("^([^|]+)")for n,o in t(n)do
local n=s(e,o.ifname)if n.devname==l then
n.wanconfig=o
n.interface=o.interface
d(e,c(o.interface,a),n)end
end
local f=o.findLanWanInterfaces(true)v(function(n)if y(e,n.proto)and not r.isActiveInterface(n['.name'])and i(n['.name'],f)then
local i=n.ifname and n.ifname:match("^@(.*)")or n.device and n.device:match("^@(.*)")if n.proto=="mobiled"and n[".name"]==a then
local t={{v4="_4",v6="_6"},{v4="_ppp",v6="_ppp_6"}}for t,i in h(t)do
local t=n[".name"]..i.v4
local o,l=o.get_lower_layers_with_status(t)if o and next(o)then
local o=d(e,c(t,a))p[t]=a
o.active=true
o.status=l
if not o.interface then
o.interface=t
end
e.interfaces_dhcp6[o.interface]=n[".name"]..i.v6
end
end
end
if i and(n.proto=="dhcpv6"or n.proto=="6rd")then
e.interfaces_dhcp6[i]=n[".name"]else
local i=n['.name']local o,r=o.get_lower_layers_with_status(i)o=k(o,n.pppoerelay)for o,n in t(o)do
local n=s(e,n)if n.devname==l then
local n=d(e,c(i,a),n)n.active=true
n.status=r
if not n.interface then
n.interface=i
end
end
end
end
end
end)end
local function i(n,e)local e=w(e,"proto")local n=y(n,e)return n
end
local t={ip=r.interfaceHasIP,ppp=r.interfaceHasPPP,ipv6=function()return false end}local function r(e,n)local t=t[e.connType]if t and t(n)then
local c
local a
local t
if i(e,n)then
local n,o=o.get_lower_layers_with_status(n)if#n>0 then
c=s(e,n[1])end
t=o
a=true
end
local e=d(e,"ACTIVE|"..n,c or{})e.active=a
e.status=t
if not e.interace then
e.interface=n
end
end
end
function e:getKeys(n)local n=_.resolve_key(n)local n,e=o.split_key(n)self.devType=n
self.keys={}self.entries={}self.interfaces_dhcp6={}self.vlans,self.vlanmode=u()if n=="ACTIVE"then
r(self,e)else
b(self,e)end
return self.keys
end
function e:getPhysicalInfo(n,c,e,a)e=e or"L2"local n=self.entries[n]local t
if e=="L2"then
t=n.physicdevice or n.devname
elseif e=="L3"and n.status then
t=n.status.l3_device or n.vlandevice
end
if t then
return o.getIntfInfo(t,c,a)end
return a or""end
function e:isActive(n)return self.entries[n].active==true
end
function e:getDeviceStatus(n)return o.get_ubus_device_status(self.entries[n].vlandevice)end
function e:getInterfaceStatus(n)local n=self.entries[n]if n.active then
return n.status
end
end
function e:getDevice(n)local n=self.entries[n]return n.devname
end
function e:getInterface(n)local n=self.entries[n]return n.interface
end
local o={config="network",sectionname="interface",option="dontknow",default="notset"}function e:getInterfaceOption(i,c,a,l)local e=self.entries[i]local t
if e.active then
t=e.interface
else
t=e.wanconfig and e.wanconfig.sdev
end
if t then
o.sectionname=t
o.option=c
o.default=a
local e=n.get_from_uci(o)if e==""then
local n=self:getInterfaceStatus(i)if n and n.dynamic then
return n[c]or a or""end
end
return e
end
return l or a or""end
function e:setInterfaceOption(e,c,a)local e=self.entries[e]local t
if e.active then
o.sectionname=e.interface
o.option=c
n.set_on_uci(o,a,self.commitapply)t=true
end
local e=e.wanconfig and e.wanconfig.sdev
if e then
for e in I(e,"([^,%s]+)")do
o.sectionname=e
o.option=c
n.set_on_uci(o,a,self.commitapply)end
t=true
end
if t then
self.transactions[o.config]=true
return o.config
end
end
function e:getPPPoEInfo(n)if(self.connType~='ppp')then
return
end
local e=self:getInterfaceOption(n,"proto")if e=="pppoe"then
local o=T('/proc/net/pppoe')if o then
local t=self.entries[n].vlandevice
local e,a,n
repeat
local c=o:read("*l")or""e,a,n=c:match("(%S*)%s*(%S*)%s*(%S*)")until(n==t)or(e=="")o:close()if n==t then
return{ID=e,Address=a}end
end
end
end
function e:getName(e)local e=self.entries[e]if not e.wanconfig then
return n.get_from_uci{config="network",sectionname=e.interface,option="alias",default=e.interface}else
return n.get_from_uci{config='wanconfig',sectionname=e.wanconfig['.name'],option='alias',default=e.interface}end
end
function e:setName(o,t)local e
local o=self.entries[o]if not o.wanconfig then
e={config="network",sectionname=o.interface,option="alias",}else
e={config='wanconfig',sectionname=o.wanconfig['.name'],option='alias'}end
n.set_on_uci(e,t,self.commitapply)self.transactions[e.config]=true
return e.config
end
local function i(t,o)local a=t.vlans[o]if not a then
return
end
local e=false
v(function(n)if n.ifname==a.name then
e=true
return false
end
end)if not e then
local e
n.foreach_on_uci({config="network",sectionname="device"},function(n)if n.name==o then
e=n['.name']return false
end
end)if e then
n.delete_on_uci({config="network";sectionname=e},t.commitapply)t.vlans[o]=nil
end
end
end
local function c(o,e,a)local t=f("vlan_%s",e)if o.vlans[t]then
local n=1
while o.vlans[t]do
t=f("vlan_%s_%d",e,n)n=n+1
end
end
local e={config="network",sectionname="device"}e.sectionname=n.add_on_uci(e,o.commitapply)e.option="type"n.set_on_uci(e,"8021q",o.commitapply)e.option="name"n.set_on_uci(e,t,o.commitapply)e.option="ifname"n.set_on_uci(e,a,o.commitapply)local n={name=t,sectionname=e.sectionname,device=a,vlanmode='linux',}o.vlans[t]=n
return n
end
function e:setVlan(a,t)local e=self.entries[a]local o=e.vlanid or"-1"if t==o then
return
end
if self.devType~="ETH"then
return nil,"Only supported for ETH devices"end
if e.wanconfig then
return nil,"not supported on wansensing devices"end
if e.vlantype~="linux"then
return nil,f("not supported for vlan type %s",e.vlanmode)end
if t=="-1"then
local n=self:setInterfaceOption(a,"ifname",e.devname)i(self,e.vlandevice)return n
else
local o=self.vlans[e.vlandevice]if not o then
o=c(self,e.interface,e.devname)self:setInterfaceOption(a,"ifname",o.name)end
local e={config="network",sectionname=o.sectionname,option="vid"}n.set_on_uci(e,t,self.commitapply)o.vid=t
self.transactions[e.config]=true
return e.config
end
end
function e:getInterfaceDhcp6(n)local n=self.entries[n].interface
return self.interfaces_dhcp6[n]end
local function a(n,o)local e={}for t in h(n.transactions)do
e.config=t
o(e)end
n.transactions={}end
local function t(o,n)local n={connType=o,commitapply=n,transactions={}}m(n,e)return n
end
local e={}e.__index=e
function e:load(e)local n
local o
n=self._conn_cache[e]if not n then
n=t(self.connType,self.commitapply)self._conn_cache[e]=n
end
if n then
o=n:getKeys(e)end
return n,o
end
local function o(n,e)for o,n in h(n._conn_cache)do
a(n,e)end
end
function e:commit()o(self,n.commit)end
function e:revert()o(self,n.revert)end
local n={__mode='v'}function l.Connection(t,o)return m({connType=t,commitapply=o,_conn_cache=m({},n)},e)end
return l