]]
end
-- ################################################################################
function discover.devtype2icon(devtype)
local label = id2label[tonumber(devtype) or 0]
if(label == nil) then label = 'unknown' else label = label[1] end
return(discover.asset_icons[label])
end
-- ################################################################################
function discover.devtype2id(devtype)
for k,v in pairs(id2label) do
if(v[1] == devtype) then return k end
end
return(0) -- unknown
end
-- ################################################################################
function discover.devtype2string(devtype)
devtype = tonumber(devtype)
for k,v in pairs(id2label) do
if(k == devtype) then return v[2] end
end
return("") -- unknown
end
-- ################################################################################
local function getbaseURL(url)
local name = url:match( "([^/]+)$" )
if((name == "") or (name == nil)) then
return(url)
else
return(string.sub(url, 1, string.len(url)-string.len(name)-1))
end
end
-- ################################################################################
local function findDevice(ip, mac, manufacturer, _mdns, ssdp_str, ssdp_entries, names,
snmpName, snmpDescr, osx, symName)
local mdns = { }
local ssdp = { }
local str
local friendlyName = ""
if(snmpName ~= nil) then
ntop.setHashCache("ntopng.prefs.snmp_devices", ip, ntop.getPref("ntopng.prefs.default_snmp_community"))
end
if((ssdp_entries ~= nil) and (ssdp_entries.friendlyName ~= nil)) then
friendlyName = ssdp_entries["friendlyName"]
end
if((names == nil) or (names[ip] == nil)) then
hostname = ""
else
hostname = string.lower(names[ip])
end
if(symName == nil) then symName = "" else symName = string.lower(symName) end
if(_mdns ~= nil) then
if(discover.debug) then io.write(mac .. " /" .. manufacturer .. " / ".. _mdns.."\n") end
local mdns_items = string.split(_mdns, ";")
if(mdns_items == nil) then
mdns[_mdns] = 1
else
for _,v in pairs(mdns_items) do
mdns[v] = 1
end
end
end
if(ssdp_str ~= nil) then
if(discover.debug) then io.write(mac .. " /" .. manufacturer .. " / ".. ssdp_str.."\n") end
local ssdp_items = string.split(ssdp_str, ";")
if(ssdp_items == nil) then
ssdp[ssdp_str] = 1
else
for _,v in pairs(ssdp_items) do
ssdp[v] = 1
end
end
end
if(osx ~= nil) then
-- model=iMac11,3;osxvers=16
local elems = string.split(osx, ';')
if((elems == nil) and string.contains(osx, "model=")) then
elems = {}
table.insert(elems, osx)
end
if(elems ~= nil) then
local model = string.split(elems[1], '=')
local osxvers = nil
if(discover.apple_products[model[2]] ~= nil) then
model = discover.apple_products[model[2]]
if(model == nil) then model = "" end
else
model = model[2]
end
if(elems[2] ~= nil) then
local osxvers = string.split(elems[2], '=')
if(discover.apple_osx_versions[osxvers[2]] ~= nil) then
osxvers = discover.apple_osx_versions[osxvers[2]]
if(osxvers == nil) then osxvers = "" end
else
osxvers = osxvers[2]
end
end
osx = " "..model
if(osxvers ~= nil) then osx = osx .." "..osxvers end
end
end
if(mdns["_ssh._tcp.local"] ~= nil) then
local icon = 'workstation'
local ret
if(osx ~= nil) then
if(string.contains(osx, "MacBook")) then
icon = 'laptop'
end
end
ret = ''..discover.asset_icons[icon]..' ' .. discover.apple_icon
if(osx ~= nil) then ret = ret .. osx end
interface.setMacOperatingSystem(mac, 3) -- 3 = OSX
return icon, ret, nil
elseif(mdns["_nvstream_dbd._tcp.local"] ~= nil) then
interface.setMacOperatingSystem(mac, 2) -- 2 = windows
return 'workstation', discover.asset_icons['workstation']..' (Windows)', nil
elseif(mdns["_workstation._tcp.local"] ~= nil) then
interface.setMacOperatingSystem(mac, 1) -- 1 = Linux
return 'workstation', discover.asset_icons['workstation']..' (Linux)', nil
else
interface.setMacOperatingSystem(mac, 0) -- Unknown
end
if(string.contains(friendlyName, "TV")) then
return 'tv', discover.asset_icons['tv'], nil
end
if((ssdp["urn:upnp-org:serviceId:AVTransport"] ~= nil)
or (ssdp["urn:upnp-org:serviceId:RenderingControl"] ~= nil)
or (ssdp["urn:upnp-org:serviceId:MusicServices"] ~= nil)
or (mdns["_airplay._tcp.local"] ~= nil)
) then
return 'multimedia', discover.asset_icons['multimedia'], nil
end
if(ssdp["_airport._tcp.local"] ~= nil) then
return 'wifi', discover.asset_icons['wifi'], nil
end
if(ssdp_entries and ssdp_entries["modelDescription"]) then
local descr = string.lower(ssdp_entries["modelDescription"])
if(string.contains(descr, "camera")) then
return 'video', discover.asset_icons['video'], nil
elseif(string.contains(descr, "router")) then
return 'networking', discover.asset_icons['networking'], nil
end
end
if(discover.debug) then io.write("[manufacturer] "..manufacturer.."\n") end
if(string.contains(manufacturer, "Oki Electric") and (snmpName ~= nil)) then
return 'printer', discover.asset_icons['printer'].. ' ('..snmpName..')', snmpName
elseif(string.contains(manufacturer, "Lexmark")) then
return 'printer', discover.asset_icons['printer'], nil
elseif(string.contains(manufacturer, "Hikvision")) then
return 'video', discover.asset_icons['video'], nil
elseif(string.contains(manufacturer, "Synology")) then
return 'nas', discover.asset_icons['nas'], nil
elseif(string.contains(manufacturer, "Sonos")) then
return 'multimedia', discover.asset_icons['multimedia'], nil
elseif(string.contains(manufacturer, "Super Micro")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "Quanta Computer Inc")) then -- Often Dell DRACK
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "Fujitsu Technology Solutions")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "ASUSTek COMPUTER")) then
return 'workstation', discover.asset_icons['laptop'], nil
elseif(string.contains(manufacturer, "Raspberry")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "Juniper Networks")) then
return 'networking', discover.asset_icons['networking'], nil
elseif(string.contains(manufacturer, "Cisco")) then
return 'networking', discover.asset_icons['networking'], nil
elseif(string.contains(manufacturer, "3COM CORPORATION")) then
return 'networking', discover.asset_icons['networking'], nil
elseif(string.contains(manufacturer, "Gigaset")) then
return 'phone', discover.extra_asset_icons['phone'], nil
elseif(string.contains(manufacturer, "Palo Alto Networks")) then
return 'networking', discover.asset_icons['networking'], nil
elseif(string.contains(manufacturer, "Liteon Technology")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "Realtek")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, 'TP%-LINK')) then -- % is the escape char in Lua
return 'wifi', discover.asset_icons['wifi'], nil
elseif(string.contains(manufacturer, 'Broadband')) then -- % is the escape char in Lua
return 'networking', discover.asset_icons['networking'], nil
elseif(string.contains(manufacturer, 'Nest Labs')
or string.contains(manufacturer, 'Netatmo')) then
return 'iot', discover.asset_icons['iot'], nil
elseif(string.contains(manufacturer, "Samsung Electronics")
or string.contains(manufacturer, "SAMSUNG ELECTRO")
or string.contains(manufacturer, "HTC Corporation")
or string.contains(manufacturer, "HUAWEI")
or string.contains(manufacturer, "Xiaomi Communications")
or string.contains(manufacturer, "Mobile Communications") -- LG Electronics (Mobile Communications)
) then
interface.setMacOperatingSystem(mac, 5) -- 5 = Android
return 'phone', discover.asset_icons['phone'].. ' ' ..discover.android_icon, nil
elseif((string.contains(manufacturer, "Hewlett Packard")
or string.contains(manufacturer, "Hon Hai"))
and (snmpName ~= nil)) then
local _snmpName = string.lower(snmpName)
local _snmpDescr
--io.write("IP "..ip.." has descr (".. _snmpName ..")\n")
if(snmpDescr == nil) then
-- io.write("IP "..ip.." has empty descr (".. _snmpName ..")\n")
_snmpDescr = _snmpName
else
_snmpDescr = string.lower(snmpDescr)
end
if(string.contains(_snmpDescr, "jet") -- JetDirect, LaserJet, InkJet, DeskJet
or string.contains(_snmpDescr, "fax")) then
return 'printer', discover.asset_icons['printer']..' ('..snmpName..')', snmpName
elseif(string.contains(_snmpDescr, "curve")) then
return 'networking', discover.asset_icons['networking']..' ('..snmpName..')', snmpName
else
-- return 'unknown', snmpName, nil
end
elseif(string.contains(manufacturer, "VMware")
or string.contains(manufacturer, "QEMU")
or string.contains(manufacturer, "Xen")
or string.contains(manufacturer, "Parallel")
) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(manufacturer, "Xerox") and (snmpName ~= nil)) then
return 'printer', discover.asset_icons['printer']..' ('..snmpName..')', snmpName
elseif(string.contains(manufacturer, "Apple, Inc.")) then
if(string.contains(hostname, "iphone") or string.contains(symName, "iphone")) then
interface.setMacOperatingSystem(mac, 4) -- 4 = iOS
return 'phone', discover.asset_icons['phone']..' (' .. discover.apple_icon .. ' iPhone)', nil
elseif(string.contains(hostname, "ipad") or string.contains(symName, "ipad")) then
interface.setMacOperatingSystem(mac, 4) -- 4 = iOS
return 'tablet', discover.asset_icons['tablet']..' (' .. discover.apple_icon .. 'iPad)', nil
elseif(string.contains(hostname, "ipod") or string.contains(symName, "ipod")) then
interface.setMacOperatingSystem(mac, 4) -- 4 = iOS
return 'phone', discover.asset_icons['phone']..' (' .. discover.apple_icon .. 'iPod)', nil
else
local ret = ' '..discover.asset_icons['workstation']..' ' .. discover.apple_icon
local what = 'workstation'
if(((snmpName ~= nil) and string.contains(snmpName, "capsul"))
or string.contains(symName, "capsule") or string.contains(hostname, "capsule")) then
ret = ' '..discover.asset_icons['nas'], nil
what = 'nas'
elseif(string.contains(symName, "book") or string.contains(hostname, "book")) then
ret = ' '..discover.asset_icons['laptop']..' ' .. discover.apple_icon, nil
what = 'laptop'
elseif(string.contains(symName, "airport")) then
ret = ' '..discover.asset_icons['wifi']..' ' .. discover.apple_icon, nil
what = 'laptop'
end
if(snmpName ~= nil) then ret = ret .. " ["..snmpName.."]" end
interface.setMacOperatingSystem(mac, 3) -- 3 = OSX
return what, ret, snmpName
end
end
-- Amazon devices
if(string.contains(mac, "F0:4F:7C") and string.contains(hostname, "kindle-")) then
return 'tablet', discover.asset_icons['tablet']..' (Kindle)', "Kindle"
elseif(string.contains(mac, "40:B4:CD") -- and string.contains(hostname, "amazon-")
) then
return 'multimedia', discover.asset_icons['multimedia'], "Alexa" -- Alexa
end
-- io.write("==>"..mac .. " /" .. manufacturer .. " / ".. friendlyName.. "/"..discover.extra_asset_icons['lightbulb'] .."\n")
-- Philips Hue
if(string.contains(mac, "00:17:88") and string.contains(friendlyName, "hue")) then
return 'iot', discover.extra_asset_icons['lightbulb'], nil
end
-- Withings (Nokia Health)
if(string.contains(mac, "00:24:E4")) then
return 'iot', discover.extra_asset_icons['health'], nil
end
-- Logitech
if(string.contains(manufacturer, "Logitech")) then
if(string.contains(friendlyName, "Harmony")) then
return 'iot', discover.asset_icons['iot'], nil
else
return 'multimedia', discover.asset_icons['multimedia'], nil
end
end
if(names["gateway.local"] == ip) then
return 'networking', discover.asset_icons['networking'], nil
end
if(string.starts(hostname, "desktop-") or string.starts(symName, "desktop-")) then
interface.setMacOperatingSystem(mac, 2) -- 2 = windows
return 'workstation', discover.asset_icons['workstation']..' (Windows)', nil
elseif(string.contains(hostname, "thinkpad") or string.contains(symName, "thinkpad")) then
return 'laptop', discover.asset_icons['laptop'], nil
elseif(string.contains(hostname, "android") or string.contains(symName, "android")) then
interface.setMacOperatingSystem(mac, 5) -- 5 = Android
return 'phone', discover.asset_icons['phone']..' ' ..discover.android_icon, nil
elseif(string.contains(hostname, "%-NAS") or string.contains(symName, "%-NAS")) then
return 'nas', discover.asset_icons['nas'], nil
end
if(snmpName ~= nil) then
if(string.contains(snmpName, "router")
or string.contains(snmpName, "switch")
) then
return 'networking', discover.asset_icons['networking']..' ('..snmpName..')', snmpName
elseif(string.contains(snmpName, "air")) then
return 'wifi', discover.asset_icons['wifi']..' ('..snmpName..')', snmpName
else
return 'unknown', snmpName, nil
end
end
if(string.contains(manufacturer, "Ubiquity")) then
return 'networking', discover.asset_icons['networking'], nil
end
if((mdns["_printer._tcp.local"] ~= nil) or (mdns["_scanner._tcp.local"] ~= nil)) then
return 'printer', discover.asset_icons['printer'], nil
end
if((mdns["_edcp._udp.local"] ~= nil) or (mdns["_afpovertcp._tcp.local"] ~= nil) or (mdns["_smb._tcp.local"] ~= nil)) then
return 'nas', discover.asset_icons['nas'], nil
end
if(discover.debug) then
tprint(ssdp)
tprint(mdns)
end
-- Last resort is HTTP
http_rsp = ntop.httpGet("http://"..ip, "", "", 1)
if((http_rsp ~= nil) and (http_rsp.HTTP_HEADER ~= nil)) then
local server = http_rsp.HTTP_HEADER["server"]
if(server ~= nil) then
if(string.contains(server, "Ubuntu") or string.contains(server, "Debian") or string.contains(server, "Linux")) then
interface.setMacOperatingSystem(mac, 1) -- 1 = Linux
return 'workstation', discover.asset_icons['workstation']..' (Linux)', nil
elseif(string.contains(server, "Apache")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(server, "GoAhead")) then
return 'workstation', discover.asset_icons['workstation'], nil
elseif(string.contains(server, "Microsoft")) then
interface.setMacOperatingSystem(mac, 2) -- 2 = windows
return 'workstation', discover.asset_icons['workstation']..' (Windows)', nil
elseif(string.contains(server, "Virata%-EmWeb") or string.contains(server, "HP%-ChaiSOE") -- Usually LaserJet
or string.contains(server, "EWS%-NIC5") -- Xerox
or string.contains(server, "RomPager") -- Xerox
) then
return 'printer', discover.asset_icons['printer'], nil
else
return 'workstation', discover.asset_icons['workstation'], server -- default
end
end
--io.write(ip.."\n")
--tprint(http_rsp.HTTP_HEADER)
end
return 'unknown', "", nil
end
-- #############################################################################
local function analyzeSSDP(ssdp)
local rsp = {}
for url,host in pairs(ssdp) do
local hresp = ntop.httpGet(url, "", "", 3 --[[ seconds ]])
local manufacturer = ""
local modelDescription = ""
local modelName = ""
local icon = ""
local base_url = getbaseURL(url)
local services = { }
local friendlyName = ""
if(hresp ~= nil) then
local xml = require("xmlSimple").newParser()
local r = xml:ParseXmlText(hresp["CONTENT"])
if(r.root ~= nil) then
if(r.root.device ~= nil) then
if(r.root.device.friendlyName ~= nil) then
friendlyName = r.root.device.friendlyName:value()
end
if(r.root.device.modelName ~= nil) then
modelName = r.root.device.modelName:value()
end
if(r.root.device.modelDescription ~= nil) then
modelDescription = r.root.device.modelDescription:value()
end
end
end
if(r.root ~= nil) then
if(r.root.device ~= nil) then
if(r.root.device.manufacturer ~= nil) then
manufacturer = r.root.device.manufacturer:value()
end
if(r.root.device.serviceList ~= nil) then
local k,v
local serviceList = r.root.device.serviceList:children()
for k,v in pairs(serviceList) do
if(v.serviceId ~= nil) then
if(discover.debug) then io.write(v.serviceId:value().."\n") end
table.insert(services, v.serviceId:value())
end
end
end
if(r.root.device.iconList ~= nil) then
local k,v
local iconList = r.root.device.iconList:children()
local lastwidth = 999
for k,v in pairs(iconList) do
if((v.mimetype ~= nil) and (v.width ~= nil) and (v.url ~= nil)) then
local mime = v.mimetype:value()
local width = tonumber(v.width:value())
if(width <= lastwidth) then
if((mime == "image/jpeg") or (mime == "image/png") or (mime == "image/gif")) then
if(string.sub(v.url:value(), 1, 1) == "/") then
local slash = string.split(base_url, "/")
if(slash ~= nil) then
base_url = ""
for i,v in pairs(slash) do
-- io.write(i.." =>"..v.." ["..base_url.."]\n")
if(i < 4) then
if(i > 1) then base_url = base_url .. "/" end
base_url = base_url .. v
end
end
end
end
if((string.sub(base_url, -1) ~= "/")
and (string.sub(v.url:value(), 1, 1) ~= "/"))
then
base_url = base_url .. "/"
end
icon = ""
-- io.write(icon.."\n")
lastwidth = width -- Pick the smallest icon
end
end
end
end
end
end
end
if(discover.debug) then io.write(hresp["CONTENT"].."\n") end
end
if(rsp[host] ~= nil) then
rsp[host].url = rsp[host].url .. " "..friendlyName..""
for _,v in ipairs(services) do
table.insert(rsp[host].services, v)
end
else
rsp[host] = { ["icon"] = icon, ["manufacturer"] = manufacturer, ["url"] = ""..friendlyName.."",
["services"] = services, ["modelName"] = modelName,
["modelDescription"] = modelDescription, ["friendlyName"] = friendlyName }
end
if(discover.debug) then io.write(rsp[host].icon .. " / " ..rsp[host].manufacturer .. " / " ..rsp[host].url .. " / " .. "\n") end
end
return rsp
end
-- ################################################################################
local function discoverStatus(code, message)
return {code = code or '', message = message or ''}
end
-- #############################################################################
local function discoverARP()
if(discover.debug) then io.write("Starting ARP discovery...\n") end
local status = discoverStatus("OK")
local res = {}
local ghost_macs = {}
local ghost_found = false
local arp_mdns = interface.arpScanHosts()
if(arp_mdns == nil) then
status = discoverStatus("ERROR", i18n("discover.err_unable_to_arp_discovery"))
else
-- Add the known macs to the list
local known_macs = interface.getMacsInfo(nil, 999, 0, false, true, nil) or {}
for _,hmac in pairs(known_macs.macs) do
if((hmac["bytes.sent"] > 0) and (hmac["location"] == "lan")) then -- Skip silent/wan hosts
if(arp_mdns[hmac.mac] == nil) then
local ips = interface.findHostByMac(hmac.mac) or {}
if(discover.debug) then io.write("Missing MAC "..hmac.mac.."\n") end
for k,v in pairs(ips) do
arp_mdns[hmac.mac] = k
ghost_macs[hmac.mac] = k
ghost_found = true
end
end
end
end
end
return { status = status, ghost_macs = ghost_macs, ghost_found = ghost_found, arp_mdns = arp_mdns }
end
-- #############################################################################
function discovery2config(interface_name)
local cached = ntop.getCache(discover.getCachedDiscoveryKey(interface_name))
local disc = json.decode(cached)
if(disc and false) then
for _,dev in pairs(disc.devices) do
if(dev.device_type.."" ~= "unknown") then
--print(dev.mac .. " = " .. dev.device_type .. "\n")
end
end
end
return(cached)
end
-- #############################################################################
function discover.discover2table(interface_name, recache)
local snmp_community = ntop.getPref("ntopng.prefs.default_snmp_community")
if isEmptyString(snmp_community) then
snmp_community = "public"
end
interface.select(interface_name)
local cached = discovery2config(interface_name)
if recache ~= true then
if not isEmptyString(cached) then
return json.decode(cached) or {status = discoverStatus("ERROR", i18n("discover.error_unable_to_decode_json"))}
else
return {status = discoverStatus("NOCACHE", i18n("discover.error_no_discovery_cached"))}
end
end
-- ARP
local arp_d = discoverARP()
if arp_d["status"]["code"] ~= "OK" then
return {status = arp_d["status"]}
end
local arp_mdns = arp_d["arp_mdns"] or {}
local ghost_macs = arp_d["ghost_macs"]
local ghost_found = arp_d["ghost_found"]
-- SSDP, MDNS and SNMP
if(discover.debug) then io.write("Starting SSDP discovery...\n") end
local ssdp = interface.discoverHosts(3)
local osx_devices = {}
for mac,ip in pairsByValues(arp_mdns, asc) do
if((ip == "0.0.0.0") or (ip == "255.255.255.255")) then
-- This does not look like a good IP/MAC combination
elseif(string.find(mac, ":") ~= nil) then
local manufacturer = get_manufacturer_mac(mac)
-- This is an ARP entry
if(discover.debug) then io.write("Attempting to resolve "..ip.."\n") end
local sym = ntop.getResolvedName(ip) -- dummy resolution just to fill-up the cache
interface.mdnsQueueNameToResolve(ip)
interface.snmpGetBatch(ip, snmp_community, "1.3.6.1.2.1.1.5.0", 0)
if(string.contains(manufacturer, "HP")
or string.contains(manufacturer, "Hewlett Packard")
or string.contains(manufacturer, "Hon Hai")
) then
-- Query printer model
interface.snmpGetBatch(ip, snmp_community, "1.3.6.1.2.1.25.3.2.1.3.1", 0)
end
else
local ip_addr = mac
local mdns_services = ip
if(discover.debug) then io.write("[MDNS Services] '"..ip_addr .. "' = '" ..mdns_services.."'\n") end
if(string.contains(mdns_services, '_sftp')) then
osx_devices[ip_addr] = 1
end
ntop.resolveName(ip) -- Force address resolution
end
end
if(discover.debug) then io.write("Analyzing SSDP...\n") end
ssdp = analyzeSSDP(ssdp)
local show_services = false
if(discover.debug) then io.write("Collecting MDNS responses\n") end
local mdns = interface.mdnsReadQueuedResponses()
if(discover.debug) then
for ip,rsp in pairsByValues(mdns, asc) do
io.write("[MDNS Resolver] "..ip.." = "..rsp.."\n")
end
end
for ip,_ in pairs(osx_devices) do
if(discover.debug) then io.write("[MDNS OSX] Querying "..ip.. "\n") end
interface.mdnsQueueAnyQuery(ip, "_sftp-ssh._tcp.local")
end
if(discover.debug) then io.write("Collecting SNMP responses\n") end
local snmp = interface.snmpReadResponses()
-- Query sysDescr for the hosts that have replied
for ip,rsp in pairsByValues(snmp, asc) do
-- io.write("Requesting sysDescr for "..ip.."\n")
interface.snmpGetBatch(ip, snmp_community, "1.3.6.1.2.1.1.1.0", 0)
end
if(discover.debug) then io.write("Collecting MDNS OSX responses\n") end
osx_devices = interface.mdnsReadQueuedResponses()
if(discover.debug) then io.write("Collected MDNS OSX responses\n") end
if(discover.debug) then
for a,b in pairs(osx_devices) do
io.write("[MDNS OSX] "..a.." / ".. b.. "\n")
end
end
local snmpSysDescr = interface.snmpReadResponses()
if(discover.debug) then
for ip,rsp in pairsByValues(snmpSysDescr, asc) do
io.write("[SNMP Descr] "..ip.." OK\n")
end
end
if(discover.debug) then
for ip,rsp in pairsByValues(snmp, asc) do
io.write("[SNMP] "..ip.." = ["..rsp.."][")
if(snmpSysDescr[i] ~= nil) then io.write(snmpSysDescr[i]) end
io.write("]\n")
end
end
-- Time to pack the results in a table...
local status = discoverStatus("OK")
local res = {}
for mac, ip in pairsByValues(arp_mdns, asc) do
if((string.find(mac, ":") == nil)
or (ip == "0.0.0.0")
or (ip == "255.255.255.255")) then
goto continue
end
local entry = {ip = ip, mac = mac, ghost = false, information = {}}
local host = interface.getHostInfo(ip, 0) -- no VLAN
local sym, device_type, device_label
local manufacturer
local services = ""
local symIP = mdns[ip]
if(host ~= nil) then sym = host["name"] else sym = ntop.getResolvedName(ip) end
if not isEmptyString(sym) and sym ~= ip then
entry["sym"] = sym
end
if not isEmptyString(symIP) and symIP ~= ip then
entry["symIP"] = symIP
end
if not isEmptyString(arp_mdns[ip]) then
entry["information"] = table.merge(entry["information"], string.split(arp_mdns[ip], ";"))
end
if ssdp[ip] then
if ssdp[ip].icon then entry["icon"] = ssdp[ip].icon end
if ssdp[ip].modelName then entry["modelName"] = ssdp[ip].modelName end
if ssdp[ip].url then entry["url"] = ssdp[ip].url end
if ssdp[ip].manufacturer then entry["manufacturer"] = ssdp[ip].manufacturer end
if ssdp[ip].services then
entry["information"] = table.merge(entry["information"], ssdp[ip].services)
for i, name in ipairs(ssdp[ip].services) do services = services .. ";" .. name end
end
end
if(ghost_macs[mac] == true) then entry["ghost"] = true end
device_type, device_label, device_info = findDevice(ip, mac, entry["manufacturer"] or get_manufacturer_mac(mac),
arp_mdns[ip], services, ssdp[ip],
mdns, snmp[ip], snmpSysDescr[ip],
osx_devices[ip], sym)
if isEmptyString(device_label) then
local mac_info = interface.getMacInfo(mac)
entry["device_label_noicon"] = device_label
if mac_info ~= nil then
device_label = discover.devtype2icon(mac_info.devtype)
end
end
interface.setMacDeviceType(mac, discover.devtype2id(device_type), false) -- false means don't overwrite if already set to ~= unknown
entry["device_type"] = device_type
entry["device_label"] = device_label
if(device_info ~= nil) then
entry["device_info"] = device_info
end
if(discover.debug) then
io.write("======================\n")
tprint(entry)
io.write("======================\n")
end
res[#res + 1] = entry
::continue::
end
local response = {status = status, devices = res, ghost_found = ghost_found, discovery_timestamp = os.time()}
ntop.setCache(discover.getCachedDiscoveryKey(interface_name), json.encode(response))
return response
end
-- ################################################################################
return discover