diff --git a/include/Host.h b/include/Host.h
index 28b3defba9..8b6a944983 100644
--- a/include/Host.h
+++ b/include/Host.h
@@ -174,6 +174,7 @@ class Host : public GenericHost {
void serialize2redis();
bool deserialize(char *json_str, char *key);
bool addIfMatching(lua_State* vm, AddressTree * ptree, char *key);
+ bool addIfMatching(lua_State* vm, u_int8_t *mac);
void updateSynFlags(time_t when, u_int8_t flags, Flow *f, bool syn_sent);
void incNumFlows(bool as_client);
diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h
index c7f7117fe3..7a19d7e76e 100644
--- a/include/NetworkInterface.h
+++ b/include/NetworkInterface.h
@@ -305,6 +305,7 @@ class NetworkInterface {
Mac *dst_mac, IpAddress *_dst_ip, Host **dst);
Flow* findFlowByKey(u_int32_t key, AddressTree *allowed_hosts);
bool findHostsByName(lua_State* vm, AddressTree *allowed_hosts, char *key);
+ bool findHostsByMac(lua_State* vm, u_int8_t *mac);
bool dissectPacket(u_int8_t bridge_iface_idx,
u_int8_t *sender_mac, /* Non NULL only for NFQUEUE interfaces */
const struct pcap_pkthdr *h, const u_char *packet,
diff --git a/scripts/lua/discover.lua b/scripts/lua/discover.lua
index 78ed3f1752..ff43211981 100644
--- a/scripts/lua/discover.lua
+++ b/scripts/lua/discover.lua
@@ -144,6 +144,8 @@ local asset_icons = {
['wifi'] = '',
}
+local ghost_icon = ''
+
local function getbaseURL(url)
local name = url:match( "([^/]+)$" )
@@ -394,6 +396,8 @@ end
interface.select(ifname)
+
+
io.write("Starting ARP discovery...\n")
local arp_mdns = interface.arpScanHosts()
@@ -404,6 +408,27 @@ if(arp_mdns == nil) then
return
end
+local ghost_macs = {}
+local ghost_found = false
+
+-- Add the known macs to the list
+local known_macs = interface.getMacsInfo(nil, 999, 0, false, 0, tonumber(vlan), true, true, nil)
+
+for _,hmac in pairs(known_macs.macs) do
+ if(hmac["bytes.sent"] > 0) then -- Skip silent hosts
+ if(arp_mdns[hmac.mac] == nil) then
+ local ips = interface.findHostByMac(hmac.mac)
+ -- io.write("Missing MAC "..hmac.mac.."\n")
+
+ for k,v in pairs(ips) do
+ arp_mdns[hmac.mac] = k
+ ghost_macs[hmac.mac] = k
+ ghost_found = true
+ end
+ end
+ end
+end
+
io.write("Starting SSDP discovery...\n")
local ssdp = interface.discoverHosts(3)
@@ -490,6 +515,10 @@ for mac,ip in pairsByValues(arp_mdns, asc) do
print(""..ip.."")
if(ssdp[ip] and ssdp[ip].icon) then print(ssdp[ip].icon .. " ") end
+ if(ghost_macs[mac] ~= nil) then
+ print(' '..ghost_icon..'')
+ end
+
print("
")
if((sym ~= "") and (sym ~= ip)) then print(sym) end
@@ -555,4 +584,8 @@ end
print("\n")
+if(ghost_found) then
+ print('NOTE: The '..ghost_icon..' icon highlights ghost hosts (i.e. they do not belong to the interface IP address network).')
+end
+
dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")
diff --git a/src/Host.cpp b/src/Host.cpp
index 8f667cb030..d266bc90cf 100644
--- a/src/Host.cpp
+++ b/src/Host.cpp
@@ -1092,8 +1092,7 @@ bool Host::addIfMatching(lua_State* vm, AddressTree *ptree, char *key) {
keybuf_ptr = get_hostkey(keybuf, sizeof(keybuf));
if(strcasestr((ipbuf_ptr = Utils::formatMac(m ? m->get_mac() : NULL, ipbuf, sizeof(ipbuf))), key) /* Match by MAC */
- ||
- strcasestr((ipbuf_ptr = Utils::formatMac(sm ? sm->get_mac() : NULL, ipbuf, sizeof(ipbuf))), key) /* Match by MAC */
+ || strcasestr((ipbuf_ptr = Utils::formatMac(sm ? sm->get_mac() : NULL, ipbuf, sizeof(ipbuf))), key) /* Match by MAC */
|| strcasestr((ipbuf_ptr = keybuf_ptr), key) /* Match by hostkey */
|| strcasestr((ipbuf_ptr = get_visual_name(ipbuf, sizeof(ipbuf))), key)) { /* Match by name */
lua_push_str_table_entry(vm, keybuf_ptr, ipbuf_ptr);
@@ -1105,6 +1104,22 @@ bool Host::addIfMatching(lua_State* vm, AddressTree *ptree, char *key) {
/* *************************************** */
+bool Host::addIfMatching(lua_State* vm, u_int8_t *_mac) {
+ if((mac && mac->equal(0, _mac))
+ || (secondary_mac && secondary_mac->equal(0, _mac))) {
+ char keybuf[64], ipbuf[32];
+
+ lua_push_str_table_entry(vm,
+ get_string_key(ipbuf, sizeof(ipbuf)),
+ get_hostkey(keybuf, sizeof(keybuf)));
+ return(true);
+ }
+
+ return(false);
+}
+
+/* *************************************** */
+
bool Host::deserialize(char *json_str, char *key) {
json_object *o, *obj;
enum json_tokener_error jerr = json_tokener_success;
diff --git a/src/Lua.cpp b/src/Lua.cpp
index 3a501869b1..146d96b704 100644
--- a/src/Lua.cpp
+++ b/src/Lua.cpp
@@ -697,15 +697,15 @@ static int ntop_get_interface_macs_info(lua_State* vm) {
u_int16_t vlan_id = 0, pool_filter = (u_int16_t)-1;
bool a2zSortOrder = true, sourceMacsOnly = false, hostMacsOnly = false;
- if(lua_type(vm, 1) == LUA_TSTRING) sortColumn = (char*)lua_tostring(vm, 1);
- if(lua_type(vm, 2) == LUA_TNUMBER) maxHits = (u_int16_t)lua_tonumber(vm, 2);
- if(lua_type(vm, 3) == LUA_TNUMBER) toSkip = (u_int16_t)lua_tonumber(vm, 3);
+ if(lua_type(vm, 1) == LUA_TSTRING) sortColumn = (char*)lua_tostring(vm, 1);
+ if(lua_type(vm, 2) == LUA_TNUMBER) maxHits = (u_int16_t)lua_tonumber(vm, 2);
+ if(lua_type(vm, 3) == LUA_TNUMBER) toSkip = (u_int16_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TBOOLEAN) a2zSortOrder = lua_toboolean(vm, 4);
- if(lua_type(vm, 5) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 5);
+ if(lua_type(vm, 5) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 5);
if(lua_type(vm, 6) == LUA_TBOOLEAN) sourceMacsOnly = lua_toboolean(vm, 6);
if(lua_type(vm, 7) == LUA_TBOOLEAN) hostMacsOnly = lua_toboolean(vm, 7);
- if(lua_type(vm, 8) == LUA_TSTRING) manufacturer = lua_tostring(vm, 8);
- if(lua_type(vm, 9) == LUA_TNUMBER) pool_filter = (u_int16_t)lua_tonumber(vm, 9);
+ if(lua_type(vm, 8) == LUA_TSTRING) manufacturer = lua_tostring(vm, 8);
+ if(lua_type(vm, 9) == LUA_TNUMBER) pool_filter = (u_int16_t)lua_tonumber(vm, 9);
if(!ntop_interface ||
ntop_interface->getActiveMacList(vm,
@@ -2475,6 +2475,26 @@ static int ntop_get_interface_find_host(lua_State* vm) {
/* ****************************************** */
+static int ntop_get_interface_find_host_by_mac(lua_State* vm) {
+ NetworkInterface *ntop_interface = getCurrentInterface(vm);
+ char *mac;
+ u_int8_t _mac[6];
+
+ ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
+
+ if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING)) return(CONST_LUA_ERROR);
+ mac = (char*)lua_tostring(vm, 1);
+
+ if(!ntop_interface) return(CONST_LUA_ERROR);
+ Utils::parseMac(_mac, mac);
+
+ ntop_interface->findHostsByMac(vm, _mac);
+
+ return(CONST_LUA_OK);
+}
+
+/* ****************************************** */
+
static int ntop_update_host_traffic_policy(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
@@ -5818,6 +5838,7 @@ static const luaL_Reg ntop_interface_reg[] = {
{ "findNameFlows", ntop_get_interface_find_proc_name_flows },
{ "listHTTPhosts", ntop_list_http_hosts },
{ "findHost", ntop_get_interface_find_host },
+ { "findHostByMac", ntop_get_interface_find_host_by_mac },
{ "updateHostTrafficPolicy", ntop_update_host_traffic_policy },
{ "refreshHostsAlertsConfiguration", ntop_refresh_hosts_alerts_configuration },
{ "setSecondTraffic", ntop_set_second_traffic },
diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp
index 6e59997d3c..73ef163d92 100644
--- a/src/NetworkInterface.cpp
+++ b/src/NetworkInterface.cpp
@@ -4622,6 +4622,39 @@ static bool hosts_search_walker(GenericHashEntry *h, void *user_data) {
/* **************************************************** */
+struct search_mac_info {
+ lua_State *vm;
+ u_int8_t *mac;
+ u_int num_matches;
+};
+
+/* **************************************************** */
+
+static bool macs_search_walker(GenericHashEntry *h, void *user_data) {
+ Host *host = (Host*)h;
+ struct search_mac_info *info = (struct search_mac_info*)user_data;
+
+ if(host->addIfMatching(info->vm, info->mac))
+ info->num_matches++;
+
+ /* Stop after CONST_MAX_NUM_FIND_HITS matches */
+ return((info->num_matches > CONST_MAX_NUM_FIND_HITS) ? true /* stop */ : false /* keep walking */);
+}
+
+/* *************************************** */
+
+bool NetworkInterface::findHostsByMac(lua_State* vm, u_int8_t *mac) {
+ struct search_mac_info info;
+
+ info.vm = vm, info.mac = mac, info.num_matches = 0;
+
+ lua_newtable(vm);
+ walker(walker_hosts, macs_search_walker, (void*)&info);
+ return(info.num_matches > 0);
+}
+
+/* **************************************************** */
+
bool NetworkInterface::findHostsByName(lua_State* vm,
AddressTree *allowed_hosts,
char *key) {
@@ -5844,3 +5877,4 @@ void NetworkInterface::topMacsAdd(Mac *mac, ndpi_protocol *proto, u_int32_t byte
frequentMacs->addMacProtocol(mac->get_mac(), proto->app_protocol, bytes);
}
}
+
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 0eedaadd85..07c542fda4 100755
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -1824,12 +1824,13 @@ bool Utils::isSpecialMac(u_int8_t *mac) {
/* ****************************************************** */
void Utils::parseMac(u_int8_t *mac, const char *symMac) {
- int _mac[6];
+ int _mac[6] = { 0 };
+
sscanf(symMac, "%x:%x:%x:%x:%x:%x",
&_mac[0], &_mac[1], &_mac[2],
&_mac[3], &_mac[4], &_mac[5]);
-
- for (int i = 0; i < 6; i++) mac[i] = (u_int8_t)_mac[i];
+
+ for(int i = 0; i < 6; i++) mac[i] = (u_int8_t)_mac[i];
}
/* *********************************************** */
|