local e={}local n,t=math,string
local l=require("transformer.mapper.ucihelper")local f=require("tch.posix")local T=f.inet_pton
local D=f.inet_ntop
local v=f.AF_INET
local A=f.AF_INET6
local s=l.foreach_on_uci
local c=require("io")local P=c.open
local p=c.popen
local i=t.match
local N=t.gmatch
local g=t.gsub
local y=t.format
local w=n.min
local d=t.sub
local k=n.max
local r,h,b,u,m=type,pairs,ipairs,tonumber,tostring
local S={config="ethernet",sectionname="port"}local _={config="xtm"}local I={[1]='interface',[3]='rx_pckts',[9]='multicast',[11]='tx_pckts',[18]='txpckt',[21]='rx_unicast',[22]='tx_unicast',[23]='rx_broadcast',[24]='tx_broadcast',[25]='rxerr',}local n=require("bit")local o=require("ubus")local o=o.connect()if not o then
error("Failed to connect to ubusd")end
local a={config="firewall",sectionname="zone"}function e.interface2zone(t)local n={}local o=l.get_from_uci({config="network",sectionname=t,option="zone"})if o~=""then
s(a,function(e)if e.name==o then
n=e
return false
end
end)else
s(a,function(e)if(e.network==nil and e.name==t)then
n=e
return false
end
if(r(e.network)=="table")then
for r,s in h(e.network)do
if(s==t)then
n=e
return false
end
end
end
end)end
return n
end
function e.zoneToInterfaces(t)local e={}s(a,function(n)if n.name==t then
e=n.network
return false
end
end)return e
end
function e.get_lan_zones()local n={}local e=0
s(a,function(t)if t['wan']~='1'then
n[t['name']]=true
e=e+1
end
end)return n,e
end
function e.findLanWanInterfaces(t)local e={}l.foreach_on_uci(a,function(n)if(n['wan']=='1')==t then
if r(n['network'])=="table"then
for t,n in h(n['network'])do
e[#e+1]=n
end
elseif not(n['network']=="")then
e[#e+1]=n['network']else
e[#e+1]=n['name']end
end
end)return e
end
local function L(t,n)if not n then
return false
end
local e=e.get_ubus_device_status(n)if(e and e['bridge-members'])then
for n,e in b(e['bridge-members'])do
if(e==t)then
return true
end
end
end
return false
end
local function a(n)return o:call("network.device","status",{name=n})end
e.get_ubus_device_status=a
local function x(n)return o:call("network.interface."..n,"status",{})end
e.get_ubus_interface_status=x
local function a(n,s)local t={}local n=x(n)if n then
local n=n['device']or n['l3_device']if n then
if(s~=1)and i(n,"^br%-")then
local e=o:call("network.device","status",{name=n})if e then
local e=e['bridge-members']if e then
if r(e)=='table'then
t=e
elseif r(e)=='string'then
t[1]=e
end
end
end
else
t[1]=n
end
end
end
return t,n
end
e.get_lower_layers_with_status=a
function e.get_lower_layers(n,e)local e,n=a(n,e)return e
end
function e.dev2interface(n)local e=o:objects()for t,e in h(e)do
local t=i(e,"^network%.interface%.(.*)")if(t)then
local e=o:call(e,"status",{})if(e and(e['device']==n or e['l3_device']==n or L(n,e['device'])))then
return t
end
end
end
return nil
end
function e.split_key(e)return i(e,"^([^|]*)|(.*)")end
function e.intf2device(n,t)local n=e.get_lower_layers(n)local e,t=e.split_key(t)for n,e in b(n)do
local n=g(e,'%.%d+','')if n==t then
return e
end
end
return nil
end
local a={["operstate"]="/sys/class/net/%s/operstate",["address"]="/sys/class/net/%s/address",["carrier"]="/sys/class/net/%s/carrier",["multicast"]="/sys/class/net/%s/statistics/multicast",["rx_bytes"]="/sys/class/net/%s/statistics/rx_bytes",["rx_compressed"]="/sys/class/net/%s/statistics/rx_compressed",["rx_crc_errors"]="/sys/class/net/%s/statistics/rx_crc_errors",["rx_dropped"]="/sys/class/net/%s/statistics/rx_dropped",["rx_errors"]="/sys/class/net/%s/statistics/rx_errors",["rx_fifo_errors"]="/sys/class/net/%s/statistics/rx_fifo_errors",["rx_frame_errors"]="/sys/class/net/%s/statistics/rx_frame_errors",["rx_length_errors"]="/sys/class/net/%s/statistics/rx_length_errors",["rx_missed_errors"]="/sys/class/net/%s/statistics/rx_missed_errors",["rx_over_errors"]="/sys/class/net/%s/statistics/rx_over_errors",["rx_packets"]="/sys/class/net/%s/statistics/rx_packets",["tx_aborted_errors"]="/sys/class/net/%s/statistics/tx_aborted_errors",["tx_bytes"]="/sys/class/net/%s/statistics/tx_bytes",["tx_carrier_errors"]="/sys/class/net/%s/statistics/tx_carrier_errors",["tx_compressed"]="/sys/class/net/%s/statistics/tx_compressed",["tx_dropped"]="/sys/class/net/%s/statistics/tx_dropped",["tx_errors"]="/sys/class/net/%s/statistics/tx_errors",["tx_fifo_errors"]="/sys/class/net/%s/statistics/tx_fifo_errors",["tx_heartbeat_errors"]="/sys/class/net/%s/statistics/tx_heartbeat_errors",["tx_packets"]="/sys/class/net/%s/statistics/tx_packets",["tx_window_errors"]="/sys/class/net/%s/statistics/tx_window_errors",["mtu"]="/sys/class/net/%s/mtu",["type"]="/sys/class/net/%s/type",["speed"]="/sys/class/net/%s/speed",}function e.getIntfInfo(s,e,t)local n=t
local e=a[e]if e then
local e=y(e,s)local e=P(e)if e then
n=e:read("*line")e:close()end
end
return n or t or""end
local a={config="network",sectionname="",option=""}function e.is_alias(e)a.sectionname=e
a.option="ifname"local e=l.get_from_uci(a)a.option="device"local t=l.get_from_uci(a)local n="^@"if r(e)=='string'and r(t)=='string'and(i(t,n)or i(e,n))then
return true
end
return false
end
function e.get_intf_stat(n,s)local n=e.get_ubus_interface_status(n)if n then
local t=n.l3_device
if t then
n=e.get_ubus_device_status(t)if n.statistics and n.statistics[s]then
return m(n.statistics[s])end
local e=e.getIntfInfo(t,s)if e then
return e
end
end
end
return"0"end
function e.device_in_use(n)local t=e.getIntfInfo(n,"operstate")local e=e.getIntfInfo(n,"rx_bytes")return(t=="up"and e and u(e)>0)end
local a={["0"]=0,["1"]=1,["2"]=2,["3"]=3,["4"]=4,["5"]=5,["6"]=6,["7"]=7,["8"]=8,["9"]=9,["A"]=10,["B"]=11,["C"]=12,["D"]=13,["E"]=14,["F"]=15,["a"]=10,["b"]=11,["c"]=12,["d"]=13,["e"]=14,["f"]=15,}function e.hex2Decimal(t)local n=0
local e=1
if t then
local t=t:reverse()for t in N(t,"%x")do
n=n+a[t]*e
e=e*16
end
end
return y("%.0f",n)end
function e.hex2String(e)return e:gsub('(..)',function(e)return t.char(u(e,16))end)end
function e.string2Hex(e)return(e:gsub('.',function(e)return t.format('%02X',t.byte(e))end))end
function e.netmask2mask(n)if(r(n)~="number")then
return nil
end
local e=""for t=1,4 do
e=e..m(256-2^(8-w(8,n)))if(t<4)then
e=e.."."end
n=k(0,n-8)end
return e
end
function e.mask2netmask(e)local s=0
for e in t.gmatch(e,"(%d+).?")do
e=u(e)local t=0
if e>0 then
while n.band(e,1)==0 do
return nil,"Not a valid mask"end
s=s+8-t
else
break
end
end
return s
end
function e.ipv4ToNum(e)local e=f.inet_pton(v,e)if e then
local n,t,s,e=e:byte(1,4)return(n*(256^3))+(t*(256^2))+(s*256)+e
end
end
function e.numToIPv4(e)if e>0 then
local t=n.band(e,255)local e=n.rshift(e,8)for s=1,3 do
t=n.band(e,255).."."..t
e=n.rshift(e,8)end
return t
end
end
function e.isMAC(e)if not e then
return false
end
local n="^(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)$"local e={e:match(n)}if#e==6 then
return true
end
return false
end
function e.get_dhcp_tag_value(n)local t={}while n and d(n,1,2)~=""do
local s=e.hex2Decimal(d(n,1,2))local e=e.hex2Decimal(d(n,3,4))t[s]=d(n,5,(2*e)+4)n=d(n,(2*e)+5)end
return t
end
function e.get_devices_for_lowerlayers()local e={}s(S,function(n)e[n[".name"]]="Device.Ethernet.Link.{i}."end)_.sectionname="atmdevice"s(_,function(n)e[n[".name"]]="Device.ATM.Link.{i}."end)_.sectionname="ptmdevice"s(_,function(n)e[n[".name"]]="Device.PTM.Link.{i}."end)return e
end
function e.getIntfName(e)local e=o:call("network.interface."..e,"status",{})return e and(e.device or e.l3_device)or""end
function e.getIntfStats(s,o,n)local t,e,r=0
n=n or'0's=s:gsub("%-","%%-")if o=="multicast"then
e=c.open("/proc/net/dev")else
e=c.open("/proc/net/dev_extstats")end
if e then
for a in e:lines()do
if a:match("^%s*"..s..":")then
t=1
for e in a:gmatch("[^%s:]+")do
if I[t]==o then
r=e~="-"and e or n
break
end
t=t+1
end
end
if r then
break
end
end
e:close()end
return r or n
end
function e.loadRoutes(c)local s={}local a={}local o,t
local r=p("ip -4 route show table all")if r then
for n in r:lines()do
local e={}e.destip=n:match("^broadcast%s(%d%S+)")or n:match("^local%s(%d%S+)")or n:match("^(%S+)")if e.destip=="default"then
e.destip="0.0.0.0/0"end
e.gateway=n:match("via%s(%S+)")or"0.0.0.0"e.ifname=n:match("dev%s(%S+)")e.metric=n:match("metric%s+(%d+)%s$")or"0"t=e.destip..e.ifname
if c and e.destip=="0.0.0.0/0"then
o=e.ifname
break
end
if not a[t]then
a[t]=true
s[#s+1]=e
end
end
r:close()end
if c then
return o
else
return s
end
end
function e.getip6DefaultRoutes()local e={}local n=p("ip -6 route show table all")if n then
for t in n:lines()do
local n,t,s=t:match("^default from (%S+) .* dev (%S+) .* proto (%S+)")if n then
e[#e+1]={ipv6addr=n,device=t,proto=s}end
end
n:close()end
return e
end
local function s(e)return e%(2^32)end
function e.getLinkLocalAddress(r)local s=""local n=c.open("/proc/net/if_inet6","r")if n then
for e in n:lines()do
local e,o,n=e:match("(%S+)%s+%S+%s+%S+%s+(%S+)%s+%S+%s+(%S+)")if n==r and o=="20"then
e=g(e,"..",function(e)return t.char(u(e,16))end)s=D(A,e)or""end
end
n:close()end
return s
end
function e.extractNetworkAddress(t,e)local e=s(n.band(t,e))return e
end
function e.extractBroadcastAddress(t,e)local e=s(n.bor(t,n.bnot(e)))return e
end
function e.getStartAddress(r,e,t)local e=n.bor(e,s(n.band(r,n.bnot(t))))e=s(e)return e
end
function e.isValidIPv4AddressForDevice(n,t)n=n and e.ipv4ToNum(n)t=t and e.ipv4ToNum(t)if not t then
return nil,"Invalid SubnetMask"end
if not n then
return nil,"Invalid BaseIP"end
local s=e.extractNetworkAddress(n,t)if n==s then
return nil,"IP address is same as network address"end
local e=e.extractBroadcastAddress(s,t)if n==e then
return nil,"IP address is same as broadcast address"end
return true
end
function e.isValidIPv4SubnetMask(e)local t=T(v,e)if not t then
return false
end
local e=0
for n=1,4 do
e=(e*256)+t:byte(n)end
e=n.bnot(e)return n.band(e,e+1)==0
end
return e