From a7ab2c6a46aee24b2fc1cf95e64d68a12cd7816d Mon Sep 17 00:00:00 2001 From: Steve AB7PA <69524416+ab7pa@users.noreply.github.com> Date: Sat, 10 Jul 2021 10:39:25 -0700 Subject: [PATCH] api: revise localhost function (#128) * api: revise localhost function Revise getLocalHosts() so it doesn't report unwanted hosts. getLocalCnxType() is no longer needed. * include new iplookup function too * incorporate Eric r1de values for getCurrentNeighbors * use alternative for mac2host() * get actual wlan interface for arp query * tested on dualband radio Tested on dualband radios with active clients on both Mesh RF and Wifi AP. * add more error checking * fix iplookup match It is possible to have 2-digit "mid" prefixes. Fixes match to account for 2 possible digits. * tighten up code * add extra info values for Eric r1de --- files/usr/lib/lua/aredn/info.lua | 64 ++++++------------ files/usr/lib/lua/aredn/olsr.lua | 109 ++++++++++++++++++------------ files/usr/lib/lua/aredn/utils.lua | 13 ++++ 3 files changed, 98 insertions(+), 88 deletions(-) diff --git a/files/usr/lib/lua/aredn/info.lua b/files/usr/lib/lua/aredn/info.lua index 308f7322..c294ed22 100755 --- a/files/usr/lib/lua/aredn/info.lua +++ b/files/usr/lib/lua/aredn/info.lua @@ -513,53 +513,31 @@ function model.getCurrentDHCPLeases() return leases end -------------------------------------- --- Returns Local Host Connection Type -------------------------------------- -function model.getLocalCnxType(hostname) - if string.match(hostname,"localhost") then - return "Loopback" - elseif string.match(hostname,"dtdlink") then - return "DTD" - elseif hostname:lower() == string.lower( model.getNodeName() ) then - return "RF" - else - return "LAN" - end -end - ------------------------------------- -- Returns Local Hosts ------------------------------------- function model.getLocalHosts() - local hosts, line - if nixio.fs.access("/etc/hosts") then - for line in io.lines("/etc/hosts") do - local data = line:match("^([^#;]+)[#;]*(.*)$") -- line is not a comment - if data then - local hostname, entries - local ip, entries = data:match("^%s*([%[%]%x%.%:]+)%s+(%S.-%S)%s*$") - - if ip then - local entry = { - ["ip"] = ip, - ["hostnames"] = { }, - ["cnxtype"] = "" - } - local index = 0 - for hostname in entries:gmatch("%S+") do - hostname = string.gsub(hostname,".local.mesh$","") - entry["cnxtype"] = model.getLocalCnxType(hostname) - entry["hostnames"][index] = hostname - index = index + 1 - end - hosts = hosts or { } - hosts[#hosts+1] = entry - end - end - end - end - return hosts + local localhosts = {} + myhosts=os.capture('/bin/grep "# myself" /var/run/hosts_olsr|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 ------------------------------------- diff --git a/files/usr/lib/lua/aredn/olsr.lua b/files/usr/lib/lua/aredn/olsr.lua index eca66735..f0925970 100755 --- a/files/usr/lib/lua/aredn/olsr.lua +++ b/files/usr/lib/lua/aredn/olsr.lua @@ -68,58 +68,77 @@ function model.getCurrentNeighbors(RFinfo) local info={} local links=model.getOLSRLinks() -- Get info for all current neighbors for k,v in pairs(links) do - local host - local linkip=v['remoteIP'] + local host=nslookup(v['remoteIP']) + if host then + local mainip=iplookup(host) + if mainip then + info[mainip]={} - info[linkip]={} - info[linkip]['olsrInterface']=v['olsrInterface'] - info[linkip]['linkType']= model.getOLSRInterfaceType(v['olsrInterface']) -- RF or DTD or TUN - info[linkip]['linkQuality']=v['linkQuality'] - info[linkip]['neighborLinkQuality']=v['neighborLinkQuality'] + if host~=nil then + host = string.gsub(host,"mid%d+.", "") + host = string.gsub(host,"dtdlink%.", "") + host = string.gsub(host,".local.mesh$","") + info[mainip]['hostname']=host + else + info[mainip]['hostname']=mainip + end - local linkhost=nslookup(linkip) -- TOTO: stop using nslookup? use /var/run/olsr_hosts - if linkhost~=nil then - host = string.gsub(linkhost,"mid%d+.", "") - host = string.gsub(host,"dtdlink%.", "") - host = string.gsub(host,".local.mesh$","") - info[linkip]['hostname']=host - else - info[linkip]['hostname']=linkip - end + info[mainip]['olsrInterface']=v['olsrInterface'] + info[mainip]['linkType']= model.getOLSRInterfaceType(v['olsrInterface']) -- RF or DTD or TUN + info[mainip]['linkQuality']=v['linkQuality'] + info[mainip]['neighborLinkQuality']=v['neighborLinkQuality'] - if info[linkip]['linkType'] == "RF" and RFinfo then -- get additional info for RF link - require("iwinfo") - info[linkip]["rfip"] = linkip - local radio = ai.getMeshRadioDevice() - local bandwidth = tonumber(ai.getChannelBW(radio)) - local wlan=get_ifname('wifi') - local RFneighbors=iwinfo['nl80211'].assoclist(wlan) - local mac2node=mac2host() - for i, mac_host in pairs(mac2node) do - local mac=string.match(mac_host, "^(.-)\-") - mac=mac:upper() - local node=string.match(mac_host, "\-(.*)") -- add error checking here? - if node == "" then node=linkhost end - if linkhost == node or linkip == node then - for stn in pairs(RFneighbors) do - stnInfo=iwinfo['nl80211'].assoclist(wlan)[mac] - if stnInfo ~= nil then - info[linkip]["signal"]=tonumber(stnInfo.signal) - info[linkip]["noise"]=tonumber(stnInfo.noise) - info[linkip]["tx_rate"]=adjust_rate(stnInfo.tx_rate/1000,bandwidth) - info[linkip]["rx_rate"]=adjust_rate(stnInfo.rx_rate/1000,bandwidth) - info[linkip]["expected_throughput"]=adjust_rate(stnInfo.expected_throughput/1000,bandwidth) + -- additional info about each link + info[mainip]['validityTime']=v['validityTime'] + info[mainip]['symmetryTime']=v['symmetryTime'] + info[mainip]['asymmetryTime']=v['asymmetryTime'] + info[mainip]['vtime']=v['vtime'] + info[mainip]['currentLinkStatus']=v['currentLinkStatus'] + info[mainip]['previousLinkStatus']=v['previousLinkStatus'] + info[mainip]['hysteresis']=v['hysteresis'] + info[mainip]['pending']=v['pending'] + info[mainip]['lostLinkTime']=v['lostLinkTime'] + info[mainip]['helloTime']=v['helloTime'] + info[mainip]['lastHelloTime']=v['lastHelloTime'] + info[mainip]['seqnoValid']=v['seqnoValid'] + info[mainip]['seqno']=v['seqno'] + info[mainip]['lossHelloInterval']=v['lossHelloInterval'] + info[mainip]['lossTime']=v['lossTime'] + info[mainip]['lossMultiplier']=v['lossMultiplier'] + info[mainip]['linkCost']=v['linkCost'] + + if info[mainip]['linkType'] == "RF" and RFinfo then + require("iwinfo") + local radio = ai.getMeshRadioDevice() + local bandwidth = tonumber(ai.getChannelBW(radio)) + local RFinterface=get_ifname('wifi') + local arptable=capture("/bin/cat /proc/net/arp |grep "..RFinterface) + local lines=arptable:splitNewLine() + table.remove(lines, #lines) -- remove blank last line + for k1,v1 in pairs(lines) do + local field=v1:splitWhiteSpace() + local arpip=field[1] + local mac=field[4] + mac=mac:upper() + if mac and arpip == mainip then + stnInfo=iwinfo['nl80211'].assoclist(RFinterface)[mac] + if stnInfo~=nil then + info[mainip]["signal"]=tonumber(stnInfo.signal) + info[mainip]["noise"]=tonumber(stnInfo.noise) + if stnInfo.tx_rate then + info[mainip]["tx_rate"]=adjust_rate(stnInfo.tx_rate/1000,bandwidth) + end + if stnInfo.rx_rate then + info[mainip]["rx_rate"]=adjust_rate(stnInfo.rx_rate/1000,bandwidth) + end + if stnInfo.expected_throughput then + info[mainip]["expected_throughput"]=adjust_rate(stnInfo.expected_throughput/1000,bandwidth) + end + end end end end end - else -- Get RF IP for non-RF nodes to display services keyed to RF IP - local allhosts=ai.all_hosts() - for k,v in pairs(allhosts) do - if linkhost == v['name'] or host == v['name'] then - info[linkip]["rfip"]=v['ip'] - end - end end end return info diff --git a/files/usr/lib/lua/aredn/utils.lua b/files/usr/lib/lua/aredn/utils.lua index 1b512e45..1f851e78 100755 --- a/files/usr/lib/lua/aredn/utils.lua +++ b/files/usr/lib/lua/aredn/utils.lua @@ -257,6 +257,19 @@ function nslookup(ip) end end +------------------------------------- +-- Returns first IP of given host +------------------------------------- +function iplookup(host) + if host:find("dtd.*%.") or host:find("mid%d+%.") then + host=host:match("%.(.*)") + end + local nso=capture("nslookup "..host) + local ip=nso:match("Address 1: (.*)%c") + return ip +end + + ------------------------------------- -- Returns traceroute -------------------------------------