mirror of https://github.com/aredn/aredn.git
655 lines
16 KiB
Lua
Executable File
655 lines
16 KiB
Lua
Executable File
#!/usr/bin/lua
|
|
--[[
|
|
|
|
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
|
|
Copyright (C) 2016 Darryl Quinn
|
|
See Contributors file for additional contributors
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation version 3 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Additional Terms:
|
|
|
|
Additional use restrictions exist on the AREDN(TM) trademark and logo.
|
|
See AREDNLicense.txt for more info.
|
|
|
|
Attributions to the AREDN Project must be retained in the source code.
|
|
If importing this code into a new or existing project attribution
|
|
to the AREDN project must be added to the source code.
|
|
|
|
You must not misrepresent the origin of the material contained within.
|
|
|
|
Modified versions must be modified to attribute to the original source
|
|
and be marked in reasonable ways as differentiate it from the original
|
|
version.
|
|
|
|
--]]
|
|
|
|
require("uci")
|
|
local aredn_uci = require("aredn.uci")
|
|
require("aredn.utils")
|
|
|
|
local lip=require("luci.ip")
|
|
require("nixio")
|
|
require("ubus")
|
|
require("iwinfo")
|
|
|
|
-------------------------------------
|
|
-- Public API is attached to table
|
|
-------------------------------------
|
|
local model = {}
|
|
|
|
|
|
-------------------------------------
|
|
-- Get FIRST_BOOT status
|
|
-------------------------------------
|
|
function model.getFirstBoot()
|
|
return (model.getNodeName()=="NOCALL")
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns WAN Address
|
|
-------------------------------------
|
|
local function getWAN()
|
|
local cubus = ubus.connect()
|
|
niws=cubus:call("network.interface.wan","status",{})
|
|
if niws['ipv4-address'] == nil or niws['ipv4-address'][1] == nil then
|
|
return ""
|
|
end
|
|
return niws['ipv4-address'][1]['address']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns build target type
|
|
-------------------------------------
|
|
function model.getTargetType()
|
|
local cubus = ubus.connect()
|
|
sb=cubus:call("system","board",{})
|
|
if sb['release']['target'] == nil then
|
|
return ""
|
|
end
|
|
return sb['release']['target']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns name of the node
|
|
-------------------------------------
|
|
function model.getNodeName()
|
|
css=aredn_uci.getUciConfType("system", "system")
|
|
return css[1]['hostname']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns tactical name of the node
|
|
-------------------------------------
|
|
function model.getTacticalName()
|
|
css=aredn_uci.getNonStandardUciConfType("/etc/local/uci/", "hsmmmesh", "settings")
|
|
return css[1]['tactical']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns description of the node
|
|
-------------------------------------
|
|
function model.getNodeDescription()
|
|
css=aredn_uci.getUciConfType("system", "system")
|
|
return css[1]['description']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns array [Latitude, Longitude]
|
|
-------------------------------------
|
|
function model.getLatLon()
|
|
loc=aredn_uci.getUciConfType("aredn", "location")
|
|
return loc[1]['lat'], loc[1]['lon']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Grid Square of Node
|
|
-------------------------------------
|
|
function model.getGridSquare()
|
|
loc=aredn_uci.getUciConfType("aredn", "location")
|
|
return loc[1]['gridsquare']
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns AREDN Alert (if exists)
|
|
-------------------------------------
|
|
function model.getArednAlert()
|
|
local fname="/tmp/aredn_message"
|
|
local alert=""
|
|
if file_exists(fname) then
|
|
afile=io.open(fname,"r")
|
|
if afile~=nil then
|
|
alert=afile:read("*a")
|
|
afile:close()
|
|
end
|
|
end
|
|
if #alert~=0 then return alert
|
|
else return ""
|
|
end
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns LOCAL Alert (if exists)
|
|
-------------------------------------
|
|
function model.getLocalAlert()
|
|
local fname="/tmp/local_message"
|
|
local alert=""
|
|
if file_exists(fname) then
|
|
afile=io.open(fname,"r")
|
|
if afile~=nil then
|
|
alert=afile:read("*a")
|
|
afile:close()
|
|
end
|
|
end
|
|
if #alert~=0 then return alert
|
|
else return ""
|
|
end
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Returns Current Firmware Version
|
|
-------------------------------------
|
|
function model.getFirmwareVersion()
|
|
local relfile=io.open("/etc/mesh-release","r")
|
|
local fv=""
|
|
if relfile~=nil then
|
|
fv=relfile:read():chomp()
|
|
relfile:close()
|
|
end
|
|
return fv
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Retuns Model / Device name
|
|
-------------------------------------
|
|
function model.getModel()
|
|
m=os.capture("/usr/local/bin/get_model")
|
|
return m:chomp()
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns current SSID
|
|
-------------------------------------
|
|
function model.getSSID()
|
|
-- SSID
|
|
local myssid=""
|
|
local wif=aredn_uci.getUciConfType("wireless", "wifi-iface")
|
|
for pos, t in pairs(wif) do
|
|
if wif[pos]['network']=="wifi" then
|
|
myssid=wif[pos]['ssid']
|
|
break
|
|
end
|
|
end
|
|
return myssid
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Determine Radio Device for Mesh
|
|
-------------------------------------
|
|
function model.getMeshRadioDevice()
|
|
--Determine radio device for mesh
|
|
local radio=""
|
|
local wifiinterfaces=aredn_uci.getUciConfType("wireless","wifi-iface")
|
|
for pos,i in pairs(wifiinterfaces) do
|
|
if wifiinterfaces[pos]['mode']=="adhoc" then
|
|
radio=wifiinterfaces[pos]['device']
|
|
break
|
|
end
|
|
end
|
|
return radio
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Determine if Radio Device for Mesh is enabled
|
|
-------------------------------------
|
|
function model.isMeshRadioEnabled(radio)
|
|
local wifidevice=aredn_uci.getUciConfType("wireless","wifi-device")
|
|
for pos,i in pairs(wifidevice) do
|
|
if wifidevice[pos]['.name']==radio then
|
|
disabled=wifidevice[pos]['disabled']
|
|
break
|
|
end
|
|
end
|
|
|
|
if disabled == "0" then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Determine distance value for Mesh radio
|
|
-------------------------------------
|
|
function model.getMeshRadioDistance(radio)
|
|
local distance = ""
|
|
local wifidevice=aredn_uci.getUciConfType("wireless","wifi-device")
|
|
for pos,i in pairs(wifidevice) do
|
|
if wifidevice[pos]['.name']==radio then
|
|
distance=wifidevice[pos]['distance']
|
|
break
|
|
end
|
|
end
|
|
return distance
|
|
end
|
|
|
|
-------------------------------------
|
|
-- TODO: Return Band
|
|
-------------------------------------
|
|
function model.getBand(radio)
|
|
return ""
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return TX Power
|
|
-------------------------------------
|
|
function model.getTXPower()
|
|
local wlanInf=get_ifname('wifi')
|
|
local api=iwinfo.type(wlanInf)
|
|
local iw = iwinfo[api]
|
|
local power = iw.txpower(wlanInf)
|
|
return tostring(power)
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return Frequency
|
|
-------------------------------------
|
|
function model.getFreq()
|
|
local wlanInf=get_ifname('wifi')
|
|
local api=iwinfo.type(wlanInf)
|
|
local iw = iwinfo[api]
|
|
local freq = iw.frequency(wlanInf)
|
|
local radio = wlanInf:match("wlan(%d+)")
|
|
if radio then
|
|
local chan = tonumber(uci.cursor():get("wireless", "radio" .. radio, "channel") or 0)
|
|
-- 3GHZ channel -> Freq conversion
|
|
if (chan >= 76 and chan <= 99) then
|
|
freq = freq - 2000
|
|
end
|
|
end
|
|
return tostring(freq)
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return locally hosted services (for sysinfo.json)
|
|
-------------------------------------
|
|
function model.local_services()
|
|
local filelines={}
|
|
local lclsrvs={}
|
|
local lclsrvfile=io.open("/etc/config/services", "r")
|
|
if lclsrvfile~=nil then
|
|
for line in lclsrvfile:lines() do
|
|
table.insert(filelines, line)
|
|
end
|
|
lclsrvfile:close()
|
|
for pos,val in pairs(filelines) do
|
|
local service={}
|
|
local link,protocol,name = string.match(val,"^([^|]*)|(.+)|([^\t]*).*")
|
|
if link and protocol and name then
|
|
service['name']=name
|
|
service['protocol']=protocol
|
|
service['link']=link
|
|
table.insert(lclsrvs, service)
|
|
end
|
|
end
|
|
else
|
|
service['error']="Cannot read local services file"
|
|
table.insert(lclsrvs, service)
|
|
end
|
|
return lclsrvs
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return *All* Network Services
|
|
-------------------------------------
|
|
function model.all_services()
|
|
local services={}
|
|
local lines={}
|
|
local pos, val
|
|
local hfile=io.open("/var/run/services_olsr","r")
|
|
if hfile~=nil then
|
|
for line in hfile:lines() do
|
|
table.insert(lines,line)
|
|
end
|
|
hfile:close()
|
|
for pos,val in pairs(lines) do
|
|
local service={}
|
|
local link,protocol,name,ip = string.match(val,"^([^|]*)|(.+)|([^\t]*)\t#(.*)")
|
|
if link and protocol and name then
|
|
if string.match(link,":0/") then
|
|
service['link']=""
|
|
else
|
|
service['link']=link
|
|
end
|
|
service['protocol']=protocol
|
|
service['name']=name
|
|
if ip==" my own service" then
|
|
service['ip']=model.getInterfaceIPAddress("wifi")
|
|
else
|
|
service['ip']=ip
|
|
end
|
|
table.insert(services,service)
|
|
end
|
|
end
|
|
else
|
|
service['error']="Cannot read services file"
|
|
table.insert(services,service)
|
|
end
|
|
return services
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return *All* Hosts
|
|
-------------------------------------
|
|
function model.all_hosts()
|
|
local hosts={}
|
|
local lines={}
|
|
local pos, val
|
|
local hfile=io.open("/var/run/hosts_olsr.stable","r")
|
|
if hfile~=nil then
|
|
for line in hfile:lines() do
|
|
table.insert(lines,line)
|
|
end
|
|
hfile:close()
|
|
for pos,val in pairs(lines) do
|
|
local host={}
|
|
|
|
-- local data,comment = string.match(val,"^([^#;]+)[#;]*(.*)$")
|
|
local data,comment = string.match(val,"^([^#;]+)[#;]*(.*)$")
|
|
|
|
if data then
|
|
--local ip, name=string.match(data,"^%s*([%x%.%:]+)%s+(%S.*)\t%s*$")
|
|
local ip, name=string.match(data,"^([%x%.%:]+)%s+(%S.*)\t%s*$")
|
|
if ip and name then
|
|
if not string.match(name,"^(dtdlink[.]).*") then
|
|
if not string.match(name,"^(mid%d+[.]).*") then
|
|
host['name']=name
|
|
host['ip']=ip
|
|
table.insert(hosts,host)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
host['error']="Cannot read hosts file"
|
|
table.insert(hosts,host)
|
|
end
|
|
return hosts
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Return Channel for Radio
|
|
-- @param radio Radio Device.
|
|
-------------------------------------
|
|
function model.getChannel(radio)
|
|
--Wifi Channel Number
|
|
local ctx = uci.cursor()
|
|
if not ctx then
|
|
error("Failed to get uci cursor")
|
|
end
|
|
local chan=""
|
|
chan = tonumber(ctx:get("wireless", radio, "channel"))
|
|
-- 3GHZ channel -> Freq conversion
|
|
if (chan >= 76 and chan <= 99) then
|
|
chan=(chan * 5) + 3000
|
|
end
|
|
return tostring(chan)
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Return Channel BW for Radio
|
|
-- @param radio Radio Device.
|
|
-------------------------------------
|
|
function model.getChannelBW(radio)
|
|
--Wifi Bandwidth
|
|
ctx = uci.cursor()
|
|
if not ctx then
|
|
error("Failed to get uci cursor")
|
|
end
|
|
local chanbw=""
|
|
chanbw = ctx:get("wireless", radio, "chanbw")
|
|
return chanbw
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Current System Uptime
|
|
-------------------------------------
|
|
function model.getUptime()
|
|
local mynix=nixio.sysinfo()
|
|
local upsecs=mynix['uptime']
|
|
return secondsToClock(upsecs)
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- System Date Formatted
|
|
-------------------------------------
|
|
function model.getDate()
|
|
return os.date("%a %b %d %Y")
|
|
end
|
|
|
|
-------------------------------------
|
|
-- System Time Formatted
|
|
-------------------------------------
|
|
function model.getTime()
|
|
return os.date("%H:%M:%S %Z")
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Returns current epoch time
|
|
-------------------------------------
|
|
function getEpoch()
|
|
return os.time()
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns last three average loads
|
|
-------------------------------------
|
|
function model.getLoads()
|
|
local loads={}
|
|
local mynix=nixio.sysinfo()
|
|
loads=mynix['loads']
|
|
for n,x in ipairs(loads) do
|
|
loads[n]=round2(x,2)
|
|
end
|
|
return loads
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns memory details
|
|
-------------------------------------
|
|
function model.getFreeMemory()
|
|
local mem={}
|
|
local mynix=nixio.sysinfo()
|
|
mem['totalram']=mynix['totalram']/1024
|
|
mem['freeram']=mynix['freeram']/1024
|
|
mem['sharedram']=mynix['sharedram']/1024
|
|
mem['bufferram']=mynix['bufferram']/1024
|
|
return mem
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns FS Usage details
|
|
-------------------------------------
|
|
function model.getFSFree()
|
|
local fsf={}
|
|
local mynix=nixio.fs.statvfs("/")
|
|
fsf['rootfree']=mynix['bfree']*4
|
|
fsf['roottotal']=mynix['blocks']*4
|
|
mynix=nixio.fs.statvfs("/tmp")
|
|
fsf['tmpfree']=mynix['bfree']*4
|
|
fsf['tmptotal']=mynix['blocks']*4
|
|
mynix=nil
|
|
return fsf
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns OLSR info
|
|
-------------------------------------
|
|
function model.getOLSRInfo()
|
|
local info={}
|
|
tot=os.capture('/sbin/ip route list table 30|wc -l')
|
|
info['entries']=tot:chomp()
|
|
nodes=os.capture('/sbin/ip route list table 30|grep -E "/"|wc -l')
|
|
info['nodes']=nodes:chomp()
|
|
return info
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Interface IP Address
|
|
-- @param interface name of interface 'wifi' | 'lan' | 'wan'
|
|
-------------------------------------
|
|
function model.getInterfaceIPAddress(interface)
|
|
-- special case
|
|
if interface == "wan" then
|
|
return getWAN()
|
|
end
|
|
|
|
return aredn_uci.getUciConfSectionOption("network",interface,"ipaddr")
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Interface Netmask
|
|
-- @param interface name of interface 'wifi' | 'lan' | 'wan'
|
|
-------------------------------------
|
|
function model.getInterfaceNetmask(interface)
|
|
-- special case
|
|
-- if interface == "wan" then
|
|
-- return getWAN()
|
|
-- end
|
|
return aredn_uci.getUciConfSectionOption("network",interface,"netmask")
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Default Gateway
|
|
-------------------------------------
|
|
function model.getDefaultGW()
|
|
local gw=""
|
|
local rt=lip.route("8.8.8.8")
|
|
if rt ~= nil then
|
|
gw=tostring(rt.gw)
|
|
end
|
|
return gw
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Table of current DHCP leases
|
|
-------------------------------------
|
|
function model.getCurrentDHCPLeases()
|
|
local lines={}
|
|
local leases={}
|
|
local filename="/tmp/dhcp.leases"
|
|
if file_exists(filename) then
|
|
for line in io.lines(filename) do table.insert(lines,line) end
|
|
for n, l in pairs(lines) do
|
|
local lease={}
|
|
local data=l:splitWhiteSpace()
|
|
lease["mac"]=data[2]
|
|
lease["ip"]=data[3]
|
|
lease["host"]=data[4]
|
|
table.insert(leases, lease)
|
|
end
|
|
end
|
|
return leases
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Local Hosts
|
|
-------------------------------------
|
|
function model.getLocalHosts()
|
|
local localhosts = {}
|
|
myhosts=os.capture('/bin/grep "# myself" /var/run/hosts_olsr.stable|grep -v dtdlink')
|
|
local lines = myhosts:splitNewLine()
|
|
data = {}
|
|
for k,v in pairs(lines) do
|
|
data = v:splitWhiteSpace()
|
|
local ip = data[1]
|
|
local hostname = data[2]
|
|
if ip and hostname then
|
|
local entry = {}
|
|
entry['ip'] = ip
|
|
entry['hostname'] = hostname
|
|
if hostname:lower() == string.lower( model.getNodeName() ) then
|
|
entry['cnxtype'] = "RF"
|
|
else
|
|
entry['cnxtype'] = "LAN"
|
|
end
|
|
table.insert(localhosts, entry)
|
|
end
|
|
end
|
|
return localhosts
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns Mesh gateway setting
|
|
-------------------------------------
|
|
function model.getMeshGatewaySetting()
|
|
return uci.cursor():get("aredn", "@wan[0]", "olsrd_gw") or ""
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns LAN Mode (dmz_mode)
|
|
-------------------------------------
|
|
function model.getLANMode()
|
|
lm=os.capture("cat /etc/config.mesh/_setup|grep dmz_mode|cut -d'=' -f2|tr -d ' ' ")
|
|
lm=lm:chomp()
|
|
return lm
|
|
end
|
|
|
|
-------------------------------------
|
|
-- is LAN DHCP enabled
|
|
-------------------------------------
|
|
function model.isLANDHCPEnabled()
|
|
r=os.capture("cat /etc/config.mesh/_setup|grep lan_dhcp|cut -d'=' -f2|tr -d ' ' ")
|
|
r=r:chomp()
|
|
if r=="0" then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
-------------------------------------
|
|
-- is Mesh olsr gateway enabled
|
|
-------------------------------------
|
|
function model.isMeshGatewayEnabled()
|
|
local r = model.getMeshGatewaySetting()
|
|
if r=="0" then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- Get and set NVRAM values
|
|
-------------------------------------
|
|
function model.get_nvram(var)
|
|
return uci.cursor("/etc/local/uci"):get("hsmmmesh", "settings", var) or ""
|
|
end
|
|
|
|
function model.set_nvram(var, val)
|
|
local c = uci.cursor("/etc/local/uci")
|
|
c:set("hsmmmesh", "settings", var, val)
|
|
c:commit("hsmmmesh")
|
|
end
|
|
|
|
return model
|