local n={}local r=string.match
local i=io.popen
local h=require('uci')local e={}local t
function n.init(n)for n,r in pairs(n)do
e[n]=r
end
t=e.uci.cursor()end
local function o(e)if e then
return r(e,"^[^<>%s%*%(%)%|&;~!?\\$]+$")and not(r(e,"^-")or r(e,"-$"))else
return false
end
end
local function s(e,n)if e and type(e)=='table'then
for t,e in ipairs(e)do
if e==n then
return true
end
end
end
return false
end
local function d(e,n)if n then
return r(e,"^[a-f0-9:]+$")else
return r(e,"^%d+%.%d+%.%d+%.%d+$")end
end
local function f(a,d,c,t,l)if o(a)then
if type(t)~='number'then
t=1
end
if type(l)~='number'then
l=1
end
local n
if d~=nil then
n='dnsget -n '..d
else
n='dnsget'end
if c then
n=n..' -t AAAA'else
n=n..' -t A'end
n=n..' -o timeout:'..l..' -o attempts:'..t..' '..a..' 2>/dev/null'e.logger:notice("run_dnsget::trigger dns query by "..n)local i=i(n,'r')if i then
local t,e,n,a,l
for o in i:lines()do
t=r(o,"([^%s]+)%.%s")if t then
if c==nil then
a=r(o,"%s+(%d+%.%d+%.%d+%.%d+)")if a then
if not e then
e={}end
e[#e+1]=a
end
else
l=r(o,"%s+([a-f0-9]*:[a-f0-9:]*:[a-f0-9]*)")if l then
if not n then
n={}end
n[#n+1]=l
end
end
end
end
i:close()if t and(e or n)then
return t,e,n
else
return nil
end
else
error("Failed to run dnsget")end
else
error("Invalid query '"..tostring(a).."'")end
end
function n.dns_lookup(i,l,r,o,n)if not e or not t then
return false,"Library was not properly initialized"end
local r,n,e,t=pcall(f,i,l,r,o,n)return r,n,e,t
end
function n.dns_check(u,f,c,r,o,i,l,a)if not e or not t then
return false,"Library was not properly initialized"end
if c==nil and r==nil and o==nil then
return false,"Please specify at least one parameter to be resolved"end
if(r and not d(r,i))or(o and not d(o,i))then
return false,"Wrong format for expected address or expected spoofed address"end
if l and type(l)~='number'then
return false,"Wrong format for attempts"end
if a and type(a)~='number'then
return false,"Wrong format for timeout"end
local n,e,t,l=n.dns_lookup(u,f,i,l,a)if not n then
return n,e
end
if e then
local n=(e==c)local e=t
if i then
e=l
end
if r and s(e,r)then
return true,n,true,false
elseif o and s(e,o)then
return true,n,false,true
else
return true,n,false,false
end
end
return true,false,false,false
end
local function c(t,n,l,a)if not t or not o(t)or(n and not o(n))then
error("Invalid parameters, address = '"..tostring(t).."', source = '"..tostring(n).."'")end
local e='ping'if a then
e='ping -6'end
if type(l)~='number'then
l=1
end
e=e..' '..t..' -c '..l
if n and type(n)=='string'then
e=e..' -I '..n
end
e=e..' 2>/dev/null'local n=i(e,'r')if n then
for e in n:lines()do
local t,e=r(e,"(%d+) packets transmitted, (%d+) packets received")if t and e then
n:close()return tonumber(e),tonumber(t)-tonumber(e)end
end
n:close()error('Ping command generated an error '..tostring(e))else
error('Failed to launch ping command '..tostring(e))end
end
function n.ping(r,n,o,i)if not e or not t then
return false,"Library was not properly initialized"end
local t,e,n=pcall(c,r,n,o,i)return t,e,n
end
function n.ping_check(o,i,l,r,a)if not e or not t then
return false,"Library was not properly initialized"end
if not r then
r=0
end
local e,t,n=n.ping(o,i,l,a)if not e then
return e,t
end
if tonumber(n)>tonumber(r)then
return true,false
else
return true,true
end
end
local function c(a,n,t,l,d)if not a or not o(a)or(n and not o(n))or(t and not o(t))then
error("Invalid parameters, address = '"..tostring(a).."', src_intf = '"..tostring(n).."', src_address = '"..tostring(t).."'")end
if not l then
l=1
end
local e='arping 'if d then
e=e..'-b 'end
if n and type(n)=='string'then
e=e..'-I '..n..' 'end
if t and type(t)=='string'then
e=e..'-s '..t..' 'end
if l and type(l)=='number'then
e=e..'-c '..l..' 'end
e=e..a..' 2>/dev/null'local o=i(e,'r')if o then
local t,n
for e in o:lines()do
if not t then
t=r(e,"^Sent (%d+)")end
if not n then
n=r(e,"^Received (%d+)")end
if t and n then
o:close()return tonumber(n),tonumber(t)-tonumber(n)end
end
o:close()error(tostring(e)..' failed')else
error(tostring(e)..' can not be launched')end
end
function n.arping(i,o,r,n,l)if not e or not t then
return false,"Library was not properly initialized"end
if n and tonumber(n)==nil then
return false,"Parameter '"..tostring(n).."' is not a number"end
local e,n,t=pcall(c,i,o,r,n,l)return e,n,t
end
local function l(n,t)if not n or not o(n)or(t and not o(t))then
error("Invalid parameters, address = '"..tostring(n).."', src_intf = '"..tostring(t).."'")end
local e='ip neigh show 'e=e..' to '..n
if t then
e=e..' dev '..t
end
e=e..' 2>/dev/null'local t=i(e,'r')if t then
for e in t:lines()do
if string.find(e,n,1,false)and string.find(e," REACHABLE$")then
t:close()return true
end
end
t:close()return false
else
error(tostring(e)..' can not be launched')end
end
function n.is_reachable(t,n)if not e then
return false,"Library was not properly initialized"end
local e,n=pcall(l,t,n)return e,n
end
local function o(n)local e='network'if not n then
error("intf must be filled in")end
t:load(e)t:delete(e,n)t:commit(e)end
function n.delete_interface(n)if not e or not t then
return false,"Library was not properly initialized"end
local e,n=pcall(o,n)return e,n
end
local function l(i,r,n)local e=t
local o=true
if n~=nil then
e=n
o=false
end
if not i or not r then
error("src or dst not filled in")end
local n='network'e:load(n)local t
local i=e:foreach(n,'interface',function(e)if e['.name']==i then
t=e
return false
end
end)if i and t and type(t)=='table'then
e:set(n,r,'interface')for t,o in pairs(t)do
if t and o and not string.match(t,"^%.")then
e:set(n,r,t,o)end
end
if o then
e:commit(n)end
else
error('Failed to find source interface or its attributes')end
end
function n.copy_interface(r,n)if not e or not t then
return false,"Library was not properly initialized"end
local e,n=pcall(l,r,n)return e,n
end
function n.copy_interface_cursor_provided(o,r,t)if not e or not t then
return false,"Library was not properly initialized"end
local e,t=pcall(l,o,r,t)return e,t
end
n.checkIfCurrentL2WentDown=function(e,t,r)local r='network_device_'..r..'_down'if t=='xdsl_0'and(e=="ADSL"or e=="VDSL")then
return true
elseif t==r and e=="ETH"then
return true
end
return false
end
n.checkIfAnyL2WentUp=function(e,t)if e=='xdsl_5'or e=='network_device_'..t..'_up'then
return true
end
return false
end
n.checkIf3GBackupIsEnabled=function()local e="mobiledongle"t:load(e)local e=t:get(e,"config","enabled")return e=="1"end
n.checkIfInterfaceIsUp=function(t)local r=e.ubus
local e
e=r:call("network.interface."..t,"status",{})if e and e.up then
return true
end
return false
end
n.checkIfInterfaceHasIP=function(t,r)local o=e.ubus
local e
if n.checkIfInterfaceIsUp(t)then
e=o:call("network.interface."..t,"status",{})local n=#e["ipv4-address"]>0 and e["ipv4-address"][1].address
local e=#e["ipv6-address"]>0 and e["ipv6-address"][1].address
if r then
return e
else
return n
end
end
return false
end
n.checkIfGPONInterfaceIsUp=function()local n=e.ubus
local e
e=n:call("gpon.omciport","state",{})if e and e.statuscode then
return e.statuscode==1
end
return false
end
local function l(o)local t=io.open('/sys/class/net/'..o..'/carrier')local e=nil
if t then
local n=t:read(1)if n=='1'then
e='up'elseif n=='0'then
e='down'end
t:close()end
if not e then
local t=i('ethctl '..o..' media-type 2>&1','r')if t then
for n in t:lines()do
if not e then
n=n:gsub("^%s*","")e=r(n,"^Link is%s+([^%s]+)")end
end
t:close()end
end
return e or'down'end
n.l2HasCarrier=function(e)local e,n=pcall(l,e)local t=h.cursor():get("ethernet","eth4","wan")if e and(n=='up')and(t=='1')then
return true
else
return false
end
end
local function r(e)local e=io.open('/sys/class/net/'..e..'/speed')local t=nil
if e then
t=e:read("*number")e:close()end
return t or 0
end
n.l2GetLinkSpeed=function(e)local e,n=pcall(r,e)return e and n or 0
end
function n.set_state(e,t,r)if type(t)~="string"or type(r)~="string"then
error("both param and value parameter should be of type string")end
local n,o="wansensing","state"local e=e.cursor(UCI_CONFIG,"/var/state")e:load(n)e:revert(n,o,t)e:set(n,o,t,r)e:save(n)end
function n.clear_state(n,t)if type(t)~="string"then
error("param parameter should be of type string")end
local e,r="wansensing","state"local n=n.cursor(UCI_CONFIG,"/var/state")n:load(e)n:revert(e,r,t)n:save(e)end
function n.formatNetworkNeighborEventName(t,e,n)local e=(e and"_add_")or"_delete_"return"network_neigh_"..t:gsub("[^%a%d_]",'_')..e..tostring(n)end
function n.configureTcpAckPrioritization(n,t,e)local c={"prio_inc","prio_max","count"}local r={n,t,e}local t={}local d="/etc/sysctl-tch.conf"local a=false
local e,i,l,e
local e=io.open(d,"r")local o={}if e then
for n in e:lines()do
for e in pairs(r)do
i,l=string.find(n,"%s*net%.core%.blog_xtm_tcpack_"..c[e].."%s*=%s*")if i==1 then
if t[e]~=nil then
t[e]=true
n=nil
elseif tonumber(string.sub(n,l+1))~=r[e]then
t[e]=true
n=string.sub(n,i,l)..tostring(r[e])else
t[e]=false
end
break
end
end
if n~=nil then
table.insert(o,n)end
end
e:close()end
for e in pairs(r)do
if t[e]==nil then
table.insert(o,"net.core.blog_xtm_tcpack_"..c[e].."="..tostring(r[e]))a=true
elseif t[e]then
a=true
end
end
if not a then
return true
end
e=io.open(d,"w")if e==nil then
return false
end
for t,n in ipairs(o)do
e:write(n.."\n")end
e:close()return os.execute("sysctl -p "..d.." >/dev/null")==0
end
function n.getNextHop(t)local r=nil
local n=nil
if t==nil then
error("intf argument cannot be nil")elseif type(t)=="string"then
local r=e.ubus
n=r:call("network.interface."..t,"status",{})if not n then
e.logger:notice("nextHop("..t..") not found")elseif not n.up then
e.logger:warning("nextHop("..t..") down")end
elseif type(t)=="table"then
n=t
end
if n and n.up then
for n,e in pairs(n.route)do
if(e.nexthop and e.nexthop~="0.0.0.0")then
if(e.mask==0)then
return e.nexthop
elseif(r==nil)then
r=e.nexthop
end
end
end
end
return r
end
function n.create_ipv4_neighbour_monitor(t,r,l,i,o)local a=e.ubus
local c=e.repeatedcheck
if(t==nil)then
error("create_ipv4_neighbour_monitor(..)  arg name cannot be nil")end
if(r==nil)then
error("create)ipv4_neighbour_monitor(..)  arg intf cannot be nil")end
if(l==nil)then
error("create_ipv4_neighbour_monitor(..)  arg ipv4address cannot be nil")end
if(type(i)~="table")then
error("create_ipv4_neighbour_monitor("..t..","..r.."..) arg interval_table must be a table (not "..type(i)..")")end
if(o==nil or type(o)~="string")then
error("create_ipv4_neighbour_monitor("..t..","..r..",..) fail_evt has to be a string")end
if type(e.event_cb)~="function"then
error("create_ipv4_neighbour_monitor: missing runtime.event_cb function")end
e.logger:debug("create_ipv4_neighbour_monitor("..r..",{"..table.concat(i,", ").."},"..o..")")local function d()local o=a:call("network.interface."..r,"status",{})if o and o.up then
local o=o.device
local a,n,i=n.arping(l,o,nil,1,1)if a and type(n)=="number"and i==0 then
e.logger:notice("ipv4_neighbour_monitor '"..t.."' arping via "..r.."("..o..") to "..l.." was successful")return true
end
if type(n)=="string"then
e.logger:error("ipv4_neighbour_monitor '"..t.."' arping via "..r.." returned "..n)end
e.logger:warning("ipv4_neighbour_monitor '"..t.."' arping via "..r.."("..o..") to "..l.." failed")return false
else
e.logger:notice("ipv4_neighbour_monitor '"..t.."' fails, since interface "..r.." is down")return false
end
end
local function n()e.logger:debug("ipv4_neighbour_monitor '"..t.."' emits "..o)e.event_cb(o)end
local n=c.RepeatedCheck(i,d,n)if not n then
e.logger:error("create_ipv4_neighbour_monitor "..t.." failed")return nil
end
e.logger:debug("create_ipv4_neighbour_monitor "..t.." successful")return n
end
local function r(e)if not e then
error("run_flush_conntrack(...)  arg ipaddr cannot be nil")end
if not(d(e,false)or d(e,true))then
error("run_flush_conntrack(...)  arg ipaddr is not a valid IP address")end
local n=io.open("/proc/net/nf_conntrack","w")if n then
n:write(e)n:close()else
error("unable to open /proc/net/nf_conntrack")end
return true
end
function n.flushConntrack(n)if not e or not t then
return false,"Library was not properly initialized"end
local e,n=pcall(r,n)return e,n
end
function n.fire_timed_event(t,n,r)if not e then
return nil
end
local e=e.timedevent.TimedEvent(t,n,r)e:start()return e
end
return n