From ea4619dd2fca9f7414f04a7ffec6812e68a18b35 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Tue, 12 Mar 2019 16:54:29 +0100 Subject: [PATCH] Reworked local broadcast domain implementation --- include/AddressTree.h | 4 +- include/NetworkInterface.h | 1 + include/Ntop.h | 1 + include/Utils.h | 11 +++-- src/AddressTree.cpp | 3 +- src/Host.cpp | 21 +++++---- src/IpAddress.cpp | 10 ++-- src/LocalHost.cpp | 2 +- src/NetworkInterface.cpp | 96 +++++++++++++++++++++++--------------- src/Ntop.cpp | 30 ++++++------ 10 files changed, 108 insertions(+), 71 deletions(-) diff --git a/include/AddressTree.h b/include/AddressTree.h index d81f03863f..ce097e11dd 100644 --- a/include/AddressTree.h +++ b/include/AddressTree.h @@ -52,8 +52,8 @@ class AddressTree { inline patricia_tree_t* getTree(bool isV4) { return(isV4 ? ptree_v4 : ptree_v6); } bool addAddress(char *_net, const int16_t user_data = -1); - patricia_node_t *addAddress(const IpAddress * const ipa); - patricia_node_t *addAddress(const IpAddress * const ipa, int network_bits, bool compact_after_add); + patricia_node_t* addAddress(const IpAddress * const ipa); + patricia_node_t* addAddress(const IpAddress * const ipa, int network_bits, bool compact_after_add); bool addAddresses(char *net, const int16_t user_data = -1); void getAddresses(lua_State* vm); int16_t findAddress(int family, void *addr, u_int8_t *network_mask_bits = NULL); diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 066a614df1..550407e5c6 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -676,6 +676,7 @@ class NetworkInterface : public Checkpointable { void topMacsAdd(Mac *mac, u_int16_t protocol, u_int32_t bytes); inline bool isDynamicInterface() { return(is_dynamic_interface); }; inline void setDynamicInterface() { is_dynamic_interface = true; }; + bool isLocalBroadcastDomainHost(Host *h); inline void luaTopMacsProtos(lua_State *vm) { frequentMacs->luaTopMacsProtocols(vm); } inline MDNS* getMDNS() { return(mdns); } inline NetworkDiscovery* getNetworkDiscovery() { return(discovery); } diff --git a/include/Ntop.h b/include/Ntop.h index 76e0944415..9feb2fe704 100644 --- a/include/Ntop.h +++ b/include/Ntop.h @@ -431,6 +431,7 @@ class Ntop { void runHousekeepingTasks(); void runShutdownTasks(); inline bool isStarted() { return(is_started); } + inline AddressTree* getLoadInterfaceAddresses() { return(&local_interface_addresses); } bool isLocalInterfaceAddress(int family, void *addr) { return(local_interface_addresses.findAddress(family, addr) == -1 ? false : true); }; inline char* getLocalNetworkName(int16_t local_network_id) { return(address->get_local_network((u_int8_t)local_network_id)); diff --git a/include/Utils.h b/include/Utils.h index ae001ae073..6531c2e52b 100755 --- a/include/Utils.h +++ b/include/Utils.h @@ -68,10 +68,15 @@ class Utils { static char* urlDecode(const char *src, char *dst, u_int dst_len); static bool purifyHTTPparam(char * const param, bool strict, bool allowURL, bool allowDots); static char* stripHTML(const char * const str); - static bool postHTTPJsonData(char *username, char *password, char *url, char *json, int timeout, HTTPTranferStats *stats); - static bool postHTTPJsonData(char *username, char *password, char *url, char *json, int timeout, HTTPTranferStats *stats, char *return_data, int return_data_size, int *response_code); + static bool postHTTPJsonData(char *username, char *password, char *url, + char *json, int timeout, HTTPTranferStats *stats); + static bool postHTTPJsonData(char *username, char *password, char *url, + char *json, int timeout, + HTTPTranferStats *stats, char *return_data, + int return_data_size, int *response_code); static bool sendMail(char *from, char *to, char *message, char *smtp_server); - static bool postHTTPTextFile(lua_State* vm, char *username, char *password, char *url, char *path, int timeout, HTTPTranferStats *stats); + static bool postHTTPTextFile(lua_State* vm, char *username, char *password, + char *url, char *path, int timeout, HTTPTranferStats *stats); static bool httpGetPost(lua_State* vm, char *url, char *username, char *password, int timeout, bool return_content, bool use_cookie_authentication, HTTPTranferStats *stats, const char *form_data, diff --git a/src/AddressTree.cpp b/src/AddressTree.cpp index 836c4ae789..d12b1b1bb4 100644 --- a/src/AddressTree.cpp +++ b/src/AddressTree.cpp @@ -224,6 +224,7 @@ bool AddressTree::match(char *addr) { if(net_prefix) { int bits = atoi(net_prefix + 1); char tmp = *net_prefix; + *net_prefix = '\0', address.set(addr), *net_prefix = tmp; if(address.isIPv4()) @@ -232,7 +233,7 @@ bool AddressTree::match(char *addr) { return(Utils::ptree_match(ptree_v6, AF_INET6, (void*)&address.getIP()->ipType.ipv6, bits)); } else { address.set(addr); - return address.match(this); + return(address.match(this)); } } diff --git a/src/Host.cpp b/src/Host.cpp index 99dd207f22..1ce536681e 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -36,7 +36,9 @@ Host::Host(NetworkInterface *_iface, Mac *_mac, #ifdef BROADCAST_DEBUG char buf[32]; - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Setting %s [broadcast: %u]", ip.print(buf, sizeof(buf)), ip.isBroadcastAddress() ? 1 : 0); + + ntop->getTrace()->traceEvent(TRACE_NORMAL, "Setting %s [broadcast: %u]", + ip.print(buf, sizeof(buf)), ip.isBroadcastAddress() ? 1 : 0); #endif initialize(_mac, _vlanId, true); @@ -78,9 +80,11 @@ Host::~Host() { if(stats) delete stats; if(stats_shadow) delete stats_shadow; - /* Pool counters are updated both in and outside the datapath. - So decPoolNumHosts must stay in the destructor to preserve counters - consistency (no thread outside the datapath will change the last pool id) */ + /* + Pool counters are updated both in and outside the datapath. + So decPoolNumHosts must stay in the destructor to preserve counters + consistency (no thread outside the datapath will change the last pool id) + */ iface->decPoolNumHosts(get_host_pool(), true /* Host is deleted inline */); } @@ -160,15 +164,14 @@ void Host::initialize(Mac *_mac, u_int16_t _vlanId, bool init_all) { asn = 0, asname = NULL; as = NULL, country = NULL; blacklisted_host = false, reloadHostBlacklist(); - is_in_broadcast_domain = false; is_dhcp_host = false; num_alerts_detected = 0; trigger_host_alerts = false; PROFILING_SUB_SECTION_ENTER(iface, "Host::initialize: new AlertCounter", 17); - syn_flood_attacker_alert = new AlertCounter(ntop->getPrefs()->get_attacker_max_num_syn_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); - syn_flood_victim_alert = new AlertCounter(ntop->getPrefs()->get_victim_max_num_syn_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); + syn_flood_attacker_alert = new AlertCounter(ntop->getPrefs()->get_attacker_max_num_syn_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); + syn_flood_victim_alert = new AlertCounter(ntop->getPrefs()->get_victim_max_num_syn_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); flow_flood_attacker_alert = new AlertCounter(ntop->getPrefs()->get_attacker_max_num_flows_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); flow_flood_victim_alert = new AlertCounter(ntop->getPrefs()->get_victim_max_num_flows_per_sec(), CONST_MAX_THRESHOLD_CROSS_DURATION); PROFILING_SUB_SECTION_EXIT(iface, 17); @@ -193,6 +196,8 @@ void Host::initialize(Mac *_mac, u_int16_t _vlanId, bool init_all) { reloadHideFromTop(); reloadDhcpHost(); + + is_in_broadcast_domain = iface->isLocalBroadcastDomainHost(this); } /* *************************************** */ @@ -1345,7 +1350,7 @@ void Host::deleteHostData() { char* Host::get_mac_based_tskey(Mac *mac, char *buf, size_t bufsize) { char *k = mac->print(buf, bufsize); - /* NOTE: it is important to differentiate between v4 and v6 for macs */ + /* NOTE: it is important to differentiate between v4 and v6 for macs */ strncat(buf, get_ip()->isIPv4() ? "_v4" : "_v6", bufsize); return(k); diff --git a/src/IpAddress.cpp b/src/IpAddress.cpp index 8b1892e973..16d4d69d9a 100644 --- a/src/IpAddress.cpp +++ b/src/IpAddress.cpp @@ -293,19 +293,19 @@ json_object* IpAddress::getJSONObject() { /* ******************************************* */ /** - * @brief Check if the host matches the specified host tree - * + * @brief Check if the host matches the specified host tree. + * @param ptree The hosts allowed to be accessed. - * @return true if the host matches the ptre, false otherwise. + * @return true if the host matches the tree, false otherwise. */ bool IpAddress::match(AddressTree *tree) { if(tree == NULL) - return(true); + return(false); else { patricia_tree_t *ptree = tree->getTree((addr.ipVersion == 4) ? true : false); patricia_node_t *node; - if(ptree == NULL) return(true); + if(ptree == NULL) return(false); if(addr.ipVersion == 4) node = Utils::ptree_match(ptree, AF_INET, (void*)&addr.ipType.ipv4, 32); diff --git a/src/LocalHost.cpp b/src/LocalHost.cpp index 5fc69f77c6..a8ee6a8539 100644 --- a/src/LocalHost.cpp +++ b/src/LocalHost.cpp @@ -5,7 +5,7 @@ * * 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 -o * the Free Software Foundation; either version 3 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index e97dacdd6b..1e9928f2f1 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -283,7 +283,7 @@ void NetworkInterface::init() { next_idle_flow_purge = next_idle_host_purge = 0, running = false, customIftype = NULL, is_dynamic_interface = false, is_loopback = is_traffic_mirrored = false; - numVirtualInterfaces = 0, flowHashing = NULL, + numVirtualInterfaces = 0, flowHashing = NULL, pcap_datalink_type = 0, mtuWarningShown = false, purge_idle_flows_hosts = true, id = (u_int8_t)-1, last_remote_pps = 0, last_remote_bps = 0, @@ -297,16 +297,16 @@ void NetworkInterface::init() { pollLoopCreated = false, bridge_interface = false, mdns = NULL, discovery = NULL, ifDescription = NULL, flowHashingMode = flowhashing_none; - macs_hash = NULL, ases_hash = NULL, countries_hash = NULL, vlans_hash = NULL, + macs_hash = NULL, ases_hash = NULL, countries_hash = NULL, vlans_hash = NULL, arp_hash_matrix = NULL; - numSubInterfaces = 0; - memset(subInterfaces, 0, sizeof(subInterfaces)); - reload_custom_categories = reload_hosts_blacklist = false; - - broadcast_domains = new AddressTree(false); + numSubInterfaces = 0; + memset(subInterfaces, 0, sizeof(subInterfaces)); + reload_custom_categories = reload_hosts_blacklist = false; - ip_addresses = "", networkStats = NULL, + broadcast_domains = new AddressTree(false); + + ip_addresses = "", networkStats = NULL, pcap_datalink_type = 0, cpu_affinity = -1; hide_from_top = hide_from_top_shadow = NULL; @@ -335,23 +335,23 @@ void NetworkInterface::init() { dhcp_ranges = dhcp_ranges_shadow = NULL; - ts_ring = NULL; + ts_ring = NULL; - if(ntop->getPrefs()) { - if(TimeseriesRing::isRingEnabled(ntop->getPrefs())) - ts_ring = new TimeseriesRing(this); - } + if(ntop->getPrefs()) { + if(TimeseriesRing::isRingEnabled(ntop->getPrefs())) + ts_ring = new TimeseriesRing(this); + } #ifdef HAVE_EBPF - if(bridge_interface - || is_dynamic_interface - || is_traffic_mirrored - || isView()) - ; - else { - ebpfEvents = (eBPFevent**)calloc(sizeof(eBPFevent*), EBPF_QUEUE_LEN); - next_insert_idx = next_remove_idx = 0; - } + if(bridge_interface + || is_dynamic_interface + || is_traffic_mirrored + || isView()) + ; + else { + ebpfEvents = (eBPFevent**)calloc(sizeof(eBPFevent*), EBPF_QUEUE_LEN); + next_insert_idx = next_remove_idx = 0; + } #endif PROFILING_INIT(); @@ -375,8 +375,8 @@ void NetworkInterface::aggregatePartialFlow(Flow *flow) { if(aggregatedFlow == NULL) { if(!aggregated_flows_hash->hasEmptyRoom()) { /* There is no more room in the hash table */ - } else if(!ntop->getPrefs()->is_aggregated_flows_export_limit_enabled() - || aggregated_flows_hash->getNumEntries() < ntop->getPrefs()->get_max_num_aggregated_flows_per_export()) { + } else if((!ntop->getPrefs()->is_aggregated_flows_export_limit_enabled()) + || (aggregated_flows_hash->getNumEntries() < ntop->getPrefs()->get_max_num_aggregated_flows_per_export())) { #ifdef AGGREGATED_FLOW_DEBUG char buf[256]; ntop->getTrace()->traceEvent(TRACE_NORMAL, "AggregatedFlow not found [%s]. Creating it.", @@ -1573,23 +1573,30 @@ bool NetworkInterface::processPacket(u_int32_t bridge_iface_idx, src2dst_direction = false; } - if((icmp_type == ND_NEIGHBOR_ADVERT || icmp_type == ND_NEIGHBOR_SOLICIT) +#if 0 + if(((icmp_type == ND_NEIGHBOR_ADVERT) || (icmp_type == ND_NEIGHBOR_SOLICIT)) && l4_packet_len >= 24) { - /* Neighbor Solicitation and Neighbor Advertisement - have the Target Address at offset 8. - - https://tools.ietf.org/html/rfc2461#section-4.1 - */ + /* + Neighbor Solicitation and Neighbor Advertisement + have the Target Address at offset 8. + + https://tools.ietf.org/html/rfc2461#section-4.1 + */ Host * target_address_h; IpAddress target_address; + target_address.set((ndpi_in6_addr*)&l4[8]); + char buf[64]; + ntop->getTrace()->traceEvent(TRACE_WARNING, "->> %s", target_address.print(buf, sizeof(buf))); + if(target_address.isNonEmptyUnicastAddress() && (target_address_h = getHost(&target_address, vlan_id)) - && !target_address_h->isBroadcastDomainHost()) + && (!target_address_h->isBroadcastDomainHost())) target_address_h->setBroadcastDomainHost(); } - +#endif + flow->setICMP(src2dst_direction, icmp_type, icmp_code, l4); if(l4_proto == IPPROTO_ICMP) icmp_v4.incStats(icmp_type, icmp_code, is_sent_packet, NULL); @@ -2508,12 +2515,15 @@ decode_packet_eth: if((eth_type == ETHERTYPE_ARP) && (h->caplen >= (sizeof(arp_header)+sizeof(struct ndpi_ethhdr)))) { struct arp_header *arpp = (struct arp_header*)&packet[ip_offset]; u_int16_t arp_opcode = ntohs(arpp->ar_op); +#if 0 u_int32_t arp_spa; IpAddress arp_spa_ipa; Host *arp_spa_h; +#endif bool src2dst_element = false; ArpStatsMatrixElement* e; - + +#if 0 arp_spa = arpp->arp_spa; /* Sender protocol address */ arp_spa_ipa.set(arp_spa); @@ -2521,7 +2531,8 @@ decode_packet_eth: && (arp_spa_h = getHost(&arp_spa_ipa, vlan_id)) && !arp_spa_h->isBroadcastDomainHost()) arp_spa_h->setBroadcastDomainHost(); - +#endif + if(broadcast_domains) { #ifdef DEBUG char buf1[32], buf2[32], buf3[32]; @@ -6243,11 +6254,10 @@ void NetworkInterface::reloadHideFromTop(bool refreshHosts) { bool NetworkInterface::isHiddenFromTop(Host *host) { VlanAddressTree *vlan_addrtree = hide_from_top; + if(!vlan_addrtree) return false; - AddressTree *tree = vlan_addrtree->getAddressTree(host->getVlanId()); - - return host->get_ip()->findAddress(tree); + return(host->get_ip()->findAddress(vlan_addrtree->getAddressTree(host->getVlanId()))); } /* **************************************** */ @@ -7313,6 +7323,18 @@ bool NetworkInterface::isInDhcpRange(IpAddress *ip) { /* *************************************** */ +bool NetworkInterface::isLocalBroadcastDomainHost(Host *h) { + if(broadcast_domains == NULL) + return(false); + else { + IpAddress *i = h->get_ip(); + + return(i->match(broadcast_domains) || i->match(ntop->getLoadInterfaceAddresses())); + } +} + +/* *************************************** */ + #ifdef HAVE_EBPF bool NetworkInterface::enqueueeBPFEvent(eBPFevent *event) { diff --git a/src/Ntop.cpp b/src/Ntop.cpp index 6b1551b501..d75b0d8c49 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -682,23 +682,25 @@ void Ntop::loadLocalInterfaceAddress() { for(int ifIdx = 0; ifIdx < (int)pIPAddrTable->dwNumEntries; ifIdx++) { char name[256]; - + getIfName(pIPAddrTable->table[ifIdx].dwIndex, name, sizeof(name)); - + for(int id = 0; id < num_defined_interfaces; id++) { if((name[0] != '\0') && (strstr(iface[id]->get_name(), name) != NULL)) { - u_int32_t bits = Utils::numberOfSetBits((u_int32_t)pIPAddrTable->table[ifIdx].dwMask); - - IPAddr.S_un.S_addr = (u_long)(pIPAddrTable->table[ifIdx].dwAddr & pIPAddrTable->table[ifIdx].dwMask); - snprintf(buf, bufsize, "%s/%u", inet_ntoa(IPAddr), bits); - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Adding %s as IPv4 local network for %", buf, iface[id]->get_name()); - address->setLocalNetwork(buf); - - IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[ifIdx].dwAddr; - snprintf(buf, bufsize, "%s/32", inet_ntoa(IPAddr)); - local_interface_addresses.addAddress(buf); - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Adding %s as IPv4 interface address for %s", buf, iface[id]->get_name()); - iface[id]->addInterfaceAddress(buf); + u_int32_t bits = Utils::numberOfSetBits((u_int32_t)pIPAddrTable->table[ifIdx].dwMask); + + IPAddr.S_un.S_addr = (u_long)(pIPAddrTable->table[ifIdx].dwAddr & pIPAddrTable->table[ifIdx].dwMask); + snprintf(buf, bufsize, "%s/%u", inet_ntoa(IPAddr), bits); + ntop->getTrace()->traceEvent(TRACE_NORMAL, "Adding %s as IPv4 local network for %", + buf, iface[id]->get_name()); + address->setLocalNetwork(buf); + + IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[ifIdx].dwAddr; + snprintf(buf, bufsize, "%s/32", inet_ntoa(IPAddr)); + local_interface_addresses.addAddress(buf); + ntop->getTrace()->traceEvent(TRACE_NORMAL, "Adding %s as IPv4 interface address for %s", + buf, iface[id]->get_name()); + iface[id]->addInterfaceAddress(buf); } } }