From dfa01cc73685ef145579133cbf953e271e13faba Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sat, 29 Mar 2025 14:42:05 +0100 Subject: [PATCH] Improved MAC address handling when 0.0.0.0 is used so that in this case we take inte MAC address into account The flow details page now reports the correct MAC --- include/Flow.h | 7 ++--- scripts/lua/flow_details.lua | 15 +++++------ scripts/lua/mac_details.lua | 10 +++++--- scripts/lua/modules/flow_utils.lua | 12 +++------ src/Flow.cpp | 41 +++++++++++++++++++++--------- src/FlowHash.cpp | 40 ++++++++++++++++------------- src/HostHash.cpp | 15 ++++++++--- 7 files changed, 83 insertions(+), 57 deletions(-) diff --git a/include/Flow.h b/include/Flow.h index 60816281a0..c5f362751a 100644 --- a/include/Flow.h +++ b/include/Flow.h @@ -40,7 +40,6 @@ typedef struct { u_int16_t cli2srv_window, srv2cli_window; struct timeval synTime, synAckTime, ackTime; /* network Latency (3-way handshake) */ float clientRTT3WH, serverRTT3WH; /* Computed at 3WH (msec) */ - time_t last_network_issues; /* last time retr/ooo/lost has been observed */ struct { @@ -97,6 +96,7 @@ private: #ifdef NTOPNG_PRO FlowUDP *udp; #endif + u_int32_t flow_key; FlowCollectionInfo *collection; /* Data collected from nProbe */ @@ -419,7 +419,8 @@ private: void updateUDPHostServices(bool src2dst_direction); void updateServerName(Host *h); void allocateCollection(); - + void computeKey(); + public: Flow(NetworkInterface *_iface, int32_t iface_idx, u_int16_t _vlanId, @@ -967,7 +968,7 @@ public: static char *printTCPflags(u_int8_t flags, char *const buf, u_int buf_len); char *print(char *buf, u_int buf_len, bool full_report = true) const; - u_int32_t key(); + inline u_int32_t key() { return(flow_key); } static u_int32_t key(Host *cli, u_int16_t cli_port, Host *srv, u_int16_t srv_port, u_int16_t vlan_id, u_int16_t _observation_point_id, u_int16_t protocol); diff --git a/scripts/lua/flow_details.lua b/scripts/lua/flow_details.lua index ad60062e47..12c3051c09 100644 --- a/scripts/lua/flow_details.lua +++ b/scripts/lua/flow_details.lua @@ -826,14 +826,13 @@ else print(" \n") end - print( - "" .. i18n("client") .. " " .. i18n("server") .. - ": " .. formatPackets(flow["cli2srv.packets"]) .. " / " .. - bytesToSize(flow["cli2srv.bytes"]) .. " " .. - i18n("client") .. " " .. i18n("server") .. - ": " .. formatPackets(flow["srv2cli.packets"]) .. " / " .. - bytesToSize(flow["srv2cli.bytes"]) .. " \n") - + print("" .. i18n("client") .. " " .. i18n("server") .. + ": " .. formatPackets(flow["cli2srv.packets"]) .. " / " .. + bytesToSize(flow["cli2srv.bytes"]) .. " " .. + i18n("client") .. " " .. i18n("server") .. + ": " .. formatPackets(flow["srv2cli.packets"]) .. " / " .. + bytesToSize(flow["srv2cli.bytes"]) .. " \n") + print("") cli2srv = round((flow["cli2srv.bytes"] * 100) / flow["bytes"], 0) diff --git a/scripts/lua/mac_details.lua b/scripts/lua/mac_details.lua index 0e58a557a0..f7f4fcfdb1 100644 --- a/scripts/lua/mac_details.lua +++ b/scripts/lua/mac_details.lua @@ -102,7 +102,7 @@ end local mac_info = interface.getMacInfo(mac) --- tprint(mac_info) +-- tprint(mac_info.dhcp_fingerprint) local only_historical = (mac_info == nil) and (page == "historical") local serialize_by_mac = ntop.getPref(string.format("ntopng.prefs.ifid_" .. ifId .. ".serialize_local_broadcast_hosts_as_macs")) == "1" @@ -245,9 +245,11 @@ if((page == "overview") or (page == nil)) then print("\n") end - if(mac_info.fingerprint ~= "") then - print("DHCP Fingerprint "..'' - ..""..mac_info.fingerprint.."\n") + if((mac_info.dhcp_fingerprint ~= nil) and (mac_info.dhcp_fingerprint ~= "")) then + print("DHCP Fingerprint "..'' + ..""..mac_info.dhcp_fingerprint) + print_copy_button('dhcp_fingerprint', mac_info.dhcp_fingerprint) + print("\n") end if have_nedge then diff --git a/scripts/lua/modules/flow_utils.lua b/scripts/lua/modules/flow_utils.lua index 5206e14fdc..e715fdc5be 100644 --- a/scripts/lua/modules/flow_utils.lua +++ b/scripts/lua/modules/flow_utils.lua @@ -666,16 +666,10 @@ local function formatFlowHost(flow, cli_or_srv, historical_bounds, hyperlink_suf host_name = host_name .. format_utils.formatFullAddressCategory(host) - local mac - if (host == nil) then - mac = nil - else - mac = host["mac"] - end + local mac + mac = flow[cli_or_srv..".mac"] - return - hostinfo2detailshref(flow2hostinfo(flow, cli_or_srv), hyperlink_params, host_name, tooltip, true --[[ perform link existance checks --]] ), - mac + return hostinfo2detailshref(flow2hostinfo(flow, cli_or_srv), hyperlink_params, host_name, tooltip, true --[[ perform link existance checks --]] ), mac end function formatFlowPort(flow, cli_or_srv, port, historical_bounds) diff --git a/src/Flow.cpp b/src/Flow.cpp index caf8ee8509..cef3e31014 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -315,6 +315,7 @@ Flow::Flow(NetworkInterface *_iface, break; } + computeKey(); deferredInitialization(); } @@ -2740,7 +2741,8 @@ bool Flow::equal(const Mac *_src_pkt_mac, const Mac *_dst_pkt_mac, bool *src2srv_direction) const { const IpAddress *cli_ip = get_cli_ip_addr(), *srv_ip = get_srv_ip_addr(); const Mac *src_mac, *dst_mac; - + bool useMacAddressInFlowKey = ntop->getPrefs()->useMacAddressInFlowKey(); + #if 0 if(ntohs(_cli_port) == 17446) { char buf1[64],buf2[64],buf3[64],buf4[64]; @@ -2784,7 +2786,11 @@ bool Flow::equal(const Mac *_src_pkt_mac, const Mac *_dst_pkt_mac, return (false); /* Check if MAC address needs to be used in flow key */ - if(ntop->getPrefs()->useMacAddressInFlowKey()) { + if((cli_ip->key() == 0) && (srv_ip->key() == 0xFFFFFFFF)) { + useMacAddressInFlowKey = true; + } + + if(useMacAddressInFlowKey) { if(cli_host && src_mac) { Mac *cli_mac = cli_host->getMac(); @@ -2920,7 +2926,7 @@ void Flow::lua(lua_State *vm, AddressTree *ptree, u_char community_id[200]; char buf[64]; Mac *cli_mac = get_cli_host() ? get_cli_host()->getMac() : NULL; - + if(ptree) { if(src_ip) src_match = src_ip->match(ptree); if(dst_ip) dst_match = dst_ip->match(ptree); @@ -3372,7 +3378,7 @@ void Flow::clearRisks() { /* *************************************** */ -u_int32_t Flow::key() { +void Flow::computeKey() { u_int32_t k = cli_port + srv_port + vlanId + protocol + privateFlowId; #ifdef MAKE_OBSERVATION_POINT_KEY @@ -3383,7 +3389,16 @@ u_int32_t Flow::key() { if(get_srv_ip_addr()) k += get_srv_ip_addr()->key(); if(icmp_info) k += icmp_info->key(); - return (k); + if(get_cli_ip_addr() && get_srv_ip_addr()) { + if((get_cli_ip_addr()->key() == 0) && (get_srv_ip_addr()->key() == 0xFFFFFFFF)) { + /* Add the MAC address of the source host (dst_mac is not necessary as it's FF:FF:FF:FF:FF:FF) */ + Mac *cli_mac = get_cli_host()->getMac(); + + if(cli_mac != NULL) k += cli_mac->key(); + } + } + + flow_key = k; } /* *************************************** */ @@ -7383,8 +7398,7 @@ void Flow::lua_get_ip(lua_State *vm, bool client) const { mask_host ? 0 : h->key()); if(h->isProtocolServer()) - lua_push_bool_table_entry( - vm, client ? "cli.protocol_server" : "srv.protocol_server", true); + lua_push_bool_table_entry(vm, client ? "cli.protocol_server" : "srv.protocol_server", true); } else if(h_ip) { /* Host hasn't been instantiated but we still have the ip address (e.g, in * viewed interfaces) */ @@ -7410,11 +7424,14 @@ void Flow::lua_get_mac(lua_State *vm, bool client) const { Host *h = client ? get_cli_host() : get_srv_host(); if(h) { - lua_push_str_table_entry(vm, client ? "cli.mac" : "srv.mac", - Utils::formatMac(h->get_mac(), buf, sizeof(buf))); - lua_push_bool_table_entry( - vm, client ? "cli.serialize_by_mac" : "srv.serialize_by_mac", - h->serializeByMac()); + Mac *m = h->getMac(); + + if(m != NULL) { + lua_push_str_table_entry(vm, client ? "cli.mac" : "srv.mac", + m->print(buf, sizeof(buf))); + lua_push_bool_table_entry(vm, client ? "cli.serialize_by_mac" : "srv.serialize_by_mac", + h->serializeByMac()); + } } } diff --git a/src/FlowHash.cpp b/src/FlowHash.cpp index cd0dcabdee..a45514d38b 100644 --- a/src/FlowHash.cpp +++ b/src/FlowHash.cpp @@ -33,34 +33,40 @@ FlowHash::FlowHash(NetworkInterface *_iface, u_int _num_hashes, static u_int16_t max_num_loops = 0; -Flow *FlowHash::find(Mac *src_mac, Mac *dst_mac, IpAddress *src_ip, +Flow* FlowHash::find(Mac *src_mac, Mac *dst_mac, IpAddress *src_ip, IpAddress *dst_ip, u_int16_t src_port, u_int16_t dst_port, u_int16_t vlanId, u_int16_t observation_point_id, u_int32_t private_flow_id, u_int8_t protocol, const ICMPinfo *const icmp_info, bool *src2dst_direction, bool is_inline_call, Flow **unswapped_flow) { - u_int32_t hash = ((src_ip->key() + - dst_ip->key() + - (icmp_info ? icmp_info->key() : 0) + - private_flow_id + - src_port + - dst_port + - vlanId + - protocol) % - num_hashes); - Flow *head = (Flow *)table[hash]; + u_int32_t hash; + Flow *head; u_int16_t num_loops = 0; + hash = src_ip->key() + dst_ip->key() + + (icmp_info ? icmp_info->key() : 0) + + private_flow_id + + src_port + dst_port + vlanId + protocol; + + if((src_ip->key() == 0) && (dst_ip->key() == 0xFFFFFFFF)) { + /* Add the MAC address of the source host (dst_mac is not necessary as it's FF:FF:FF:FF:FF:FF) */ + if(src_mac != NULL) hash += src_mac->key(); + } + + hash %= num_hashes; + + head = (Flow *)table[hash]; + *unswapped_flow = NULL; #if 0 ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%s] %u:%u / %u:%u [icmp key: %u]" - "[priv flow id: %u][vlan: %u][protocol: %u]" - "[hash: %u][head: 0x%x]", - iface->get_name(), - src_ip->key(), ntohs(src_port), dst_ip->key(), ntohs(dst_port), - icmp_info ? icmp_info->key() : 0, - private_flow_id, vlanId, protocol, hash, head); + "[priv flow id: %u][vlan: %u][protocol: %u]" + "[hash: %u][head: 0x%x]", + iface->get_name(), + src_ip->key(), ntohs(src_port), dst_ip->key(), ntohs(dst_port), + icmp_info ? icmp_info->key() : 0, + private_flow_id, vlanId, protocol, hash, head); #endif if (!head) return (NULL); diff --git a/src/HostHash.cpp b/src/HostHash.cpp index 75b951533a..151857dc3e 100644 --- a/src/HostHash.cpp +++ b/src/HostHash.cpp @@ -33,13 +33,20 @@ HostHash::HostHash(NetworkInterface *_iface, u_int _num_hashes, /* ************************************ */ -Host *HostHash::get(u_int16_t vlanId, IpAddress *key, Mac *mac, +Host* HostHash::get(u_int16_t vlanId, IpAddress *key, Mac *mac, bool is_inline_call, u_int16_t observation_point_id) { - u_int32_t hash = (key->key() % num_hashes); + u_int32_t hash = key->key(); - /* Check if MAC address needs to be used in host key */ - if (ntop->getPrefs()->useMacAddressInFlowKey() == false) mac = NULL; + if((hash == 0 /* 0.0.0.0 */) && (mac != NULL)) + hash += mac->key(); + else { + /* Check if MAC address needs to be used in host key */ + if (ntop->getPrefs()->useMacAddressInFlowKey() == false) + mac = NULL; + } + hash %= num_hashes; + if (table[hash] == NULL) { return (NULL); } else {