From 8678b27fcb5123a0895c86c03521157b9de0619d Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Fri, 29 Mar 2019 16:02:57 +0100 Subject: [PATCH 01/11] Postpones set of detection completed --- src/Flow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Flow.cpp b/src/Flow.cpp index 9814392a8470..6b134c4a690e 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -561,8 +561,6 @@ void Flow::processDetectedProtocol() { void Flow::guessProtocol() { if(detection_completed) return; /* Nothing to do */ - else - detection_completed = true; /* We give up */ /* This code should no longer be necessary as the nDPI API changed */ if((protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)) { @@ -586,6 +584,8 @@ void Flow::guessProtocol() { l7_protocol_guessed = true; } + + detection_completed = true; /* We give up */ } /* *************************************** */ From 6a8c57d0425beafdffb97ea00f40800b5925b0cf Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Fri, 29 Mar 2019 16:23:00 +0100 Subject: [PATCH 02/11] Removes FlowChecker dependencies --- include/Ntop.h | 2 -- include/ntop_includes.h | 1 - src/Flow.cpp | 5 ----- src/Ntop.cpp | 6 ------ 4 files changed, 14 deletions(-) diff --git a/include/Ntop.h b/include/Ntop.h index b9bee35deef8..0dc57899131f 100644 --- a/include/Ntop.h +++ b/include/Ntop.h @@ -77,7 +77,6 @@ class Ntop { #ifndef WIN32 NagiosManager *nagios_manager; #endif - FlowChecker *flow_checker; #endif void loadLocalInterfaceAddress(); @@ -117,7 +116,6 @@ class Ntop { inline void rotateLogs(bool mode) { getTrace()->rotate_logs(mode); }; #ifdef NTOPNG_PRO void registerNagios(void); - inline FlowChecker *getFlowChecker() { return(flow_checker); }; #endif /** diff --git a/include/ntop_includes.h b/include/ntop_includes.h index 6cdb0045a30f..e37e4b860d85 100644 --- a/include/ntop_includes.h +++ b/include/ntop_includes.h @@ -299,7 +299,6 @@ using namespace std; #ifndef WIN32 #include "NagiosManager.h" #endif -#include "FlowChecker.h" #include "FrequentStringItems.h" #include "FrequentNumericItems.h" #include "FrequentTrafficItems.h" diff --git a/src/Flow.cpp b/src/Flow.cpp index 6b134c4a690e..4ee1da99be0f 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -545,11 +545,6 @@ void Flow::processDetectedProtocol() { break; } /* switch */ -#ifdef NTOPNG_PRO - if((ndpiDetectedProtocol.app_protocol == NDPI_PROTOCOL_UNKNOWN) && (!l7_protocol_guessed)) - ntop->getFlowChecker()->flowCheck(this); -#endif - if(protocol_processed /* For DNS we delay the memory free so that we can let nDPI analyze all the packets of the flow */ && (l7proto != NDPI_PROTOCOL_DNS)) diff --git a/src/Ntop.cpp b/src/Ntop.cpp index ffbdd7d057b2..ebed7b50d9c7 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -142,12 +142,7 @@ Ntop::Ntop(char *appName) { #ifndef WIN32 nagios_manager = NULL; #endif - flow_checker = new FlowChecker(); - if((pro == NULL) - || (flow_checker == NULL)) { - throw "Not enough memory"; - } #else pro = NULL; #endif @@ -235,7 +230,6 @@ Ntop::~Ntop() { #ifndef WIN32 if(nagios_manager) delete nagios_manager; #endif - if(flow_checker) delete flow_checker; #endif #ifdef HAVE_NINDEX From 97986853bb1670d7aa8a40bb7a9ebd5393d11d29 Mon Sep 17 00:00:00 2001 From: Alfredo Cardigliano Date: Fri, 29 Mar 2019 16:42:09 +0100 Subject: [PATCH 03/11] printing license signature --- src/Prefs.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Prefs.cpp b/src/Prefs.cpp index 96e9e6e2a8ec..09d7c6cf68f1 100755 --- a/src/Prefs.cpp +++ b/src/Prefs.cpp @@ -1319,8 +1319,21 @@ int Prefs::setOption(int optkey, char *optarg) { else printf("Maintenance:\t%s\n", ntop->getPro()->get_maintenance_expiration(buf, sizeof(buf))); + if(ntop->getPro()->get_encoded_license()[0] != '\0') { + char *enc_license = ntop->getPro()->get_encoded_license(); + int i, len = strlen(enc_license); + for (i = 0; i < len; i += 69) { + char buff[70]; + int clen = min((size_t) 69, strlen(&enc_license[i])); + memcpy(buff, &enc_license[i], clen); + buff[clen] = '\0'; + if (i == 0) printf("License:\t%s\n", buff); + else printf(" \t%s\n", buff); + } + } + if(ntop->getPro()->get_license()[0] != '\0') - printf("License:\t%s\n", ntop->getPro()->get_license()); + printf("License Hash:\t%s\n", ntop->getPro()->get_license()); #endif exit(0); break; From 1153c0029a7104c428e3479d2e43a4d3ca7dda1b Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 29 Mar 2019 18:55:13 +0100 Subject: [PATCH 04/11] Disable eBPF initialization for non-root users --- src/Ntop.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Ntop.cpp b/src/Ntop.cpp index ebed7b50d9c7..e9af32bf17f3 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -161,12 +161,15 @@ Ntop::Ntop(char *appName) { #endif #ifdef HAVE_EBPF - ebpf = init_ebpf_flow(this, ebpfHandler, &rc, 0xFFFF); - - if(!ebpf) - ntop->getTrace()->traceEvent(TRACE_ERROR, - "Unable to initialize libebpfflow: %s", - ebpf_print_error(rc)); + if(getuid() == 0) { + ebpf = init_ebpf_flow(this, ebpfHandler, &rc, 0xFFFF); + + if(!ebpf) + ntop->getTrace()->traceEvent(TRACE_ERROR, + "Unable to initialize libebpfflow: %s", + ebpf_print_error(rc)); + } else + ebpf = NULL; #endif } From 1848cc21302aa1745630a99134185fdf474858d0 Mon Sep 17 00:00:00 2001 From: Alfredo Cardigliano Date: Fri, 29 Mar 2019 19:21:18 +0100 Subject: [PATCH 05/11] linking liblicense --- configure.seed | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.seed b/configure.seed index 2f9b683786f4..2d8de707610d 100644 --- a/configure.seed +++ b/configure.seed @@ -269,7 +269,9 @@ DUMMY=`cd ./pro; make build` PRO_INCS="${PRO_INCS} -I${PWD}/pro -I${PWD}/pro/utils -I${PWD}/pro/third-party/libb64-1.2.1/include" if test -r "../license/systemId.c"; then : + LICENSELIBS="-L`pwd`/../license -llicense" AC_DEFINE_UNQUOTED(NTOPNG_PRO_HAVE_LICENSE, 1, [ntopng has license]) + PRO_LIBS="${PRO_LIBS} ${LICENSELIBS}" fi else AC_MSG_RESULT(not found) From 09be92ba3ddac8214e456cd61298b03b029d7f9b Mon Sep 17 00:00:00 2001 From: Alfredo Cardigliano Date: Fri, 29 Mar 2019 19:24:47 +0100 Subject: [PATCH 06/11] Binaries are no longer stripped --- packages/ntopng.spec.in | 2 +- packages/ubuntu/debian.ntopng/rules.in | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ntopng.spec.in b/packages/ntopng.spec.in index 405021c001ab..7a04a9ea9bdc 100644 --- a/packages/ntopng.spec.in +++ b/packages/ntopng.spec.in @@ -44,7 +44,7 @@ mkdir -p $RPM_BUILD_ROOT/etc/sudoers.d/ mkdir -p $RPM_BUILD_ROOT/etc/init.d %endif cp $HOME/ntopng/ntopng $RPM_BUILD_ROOT/usr/bin -strip $RPM_BUILD_ROOT/usr/bin/ntopng +# strip $RPM_BUILD_ROOT/usr/bin/ntopng cp $HOME/ntopng/ntopng.8 $RPM_BUILD_ROOT/usr/share/man/man8/ cp -Lr $HOME/ntopng/httpdocs $HOME/ntopng/scripts $RPM_BUILD_ROOT/usr/share/ntopng # L to dereference symlinks mv $RPM_BUILD_ROOT/usr/share/ntopng/httpdocs/misc/ntopng-utils-manage-config $RPM_BUILD_ROOT/usr/bin diff --git a/packages/ubuntu/debian.ntopng/rules.in b/packages/ubuntu/debian.ntopng/rules.in index bef5d3df1355..4867c99d5a33 100755 --- a/packages/ubuntu/debian.ntopng/rules.in +++ b/packages/ubuntu/debian.ntopng/rules.in @@ -43,7 +43,7 @@ binary-arch: build install dh_installdebconf dh_installman # Do not strip binary so we can leave debug symbols - dh_strip +# dh_strip dh_compress # dh_fixperms dh_installdeb @@ -60,7 +60,7 @@ binary-arch: build install fi rm -rf ./debian/@APP@/etc/ntopng/nedge.conf rm -rf ./debian/@APP@/usr/share/ntopng/httpdocs/geoip/*.dat - strip ./debian/@APP@/usr/bin/@APP@ +# strip ./debian/@APP@/usr/bin/@APP@ -find ./debian/@APP@ -name .svn -exec /bin/rm -rf {} ';' -find ./debian/@APP@ -name '*~' -exec /bin/rm -rf {} ';' -find ./debian/@APP@ -name '*#' -exec /bin/rm -rf {} ';' From 23c5d92b105d2680c0a26171bf2571035c92e246 Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Fri, 29 Mar 2019 20:02:54 +0100 Subject: [PATCH 07/11] Proper validation of base64-encoded license keys --- scripts/lua/modules/http_lint.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/lua/modules/http_lint.lua b/scripts/lua/modules/http_lint.lua index 5a5010e22f13..094739d407d3 100644 --- a/scripts/lua/modules/http_lint.lua +++ b/scripts/lua/modules/http_lint.lua @@ -182,6 +182,10 @@ local function validateUsername(p) return validateSingleWord(p) end +local function licenseCleanup(p) + return p -- don't touch passwords (checks against valid fs paths already performed) +end + local function passwordCleanup(p) return p -- don't touch passwords (checks against valid fs paths already performed) end @@ -197,6 +201,11 @@ local function whereCleanup(p) return(p:gsub('%W> Date: Mon, 1 Apr 2019 10:59:14 +0200 Subject: [PATCH 08/11] Broadcast domains detection algorithm stops at /16 --- src/NetworkInterface.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index ddb822e76f24..8e00c6b3a4d9 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -2562,7 +2562,7 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, u_int32_t cur_mask; u_int8_t cur_cidr; - for(cur_mask = 0xFFFFFFF0, cur_cidr = 28; cur_mask >= 0xFF000000; cur_mask <<= 1, cur_cidr--) { + for(cur_mask = 0xFFFFFFF0, cur_cidr = 28; cur_mask > 0x00000000; cur_mask <<= 1, cur_cidr--) { if((diff & cur_mask) == 0) { /* diff < cur_mask */ net &= cur_mask; @@ -2571,19 +2571,24 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, net = src & cur_mask; } - cur_bcast_domain.set(htonl(net)); + if(cur_mask >= 0xFFFF0000) { /* At most a /16 */ + cur_bcast_domain.set(htonl(net)); - if(!bcast_domains->isLocalBroadcastDomain(&cur_bcast_domain, cur_cidr, true /* Inline call */)) { - bcast_domains->inlineAddAddress(&cur_bcast_domain, cur_cidr); + if(!bcast_domains->isLocalBroadcastDomain(&cur_bcast_domain, cur_cidr, true /* Inline call */)) { + bcast_domains->inlineAddAddress(&cur_bcast_domain, cur_cidr); #ifdef BROADCAST_DOMAINS_DEBUG - char buf1[32], buf2[32], buf3[32]; - ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s <-> %s [%s - %u]", - Utils::intoaV4(src, buf1, sizeof(buf1)), - Utils::intoaV4(dst, buf2, sizeof(buf2)), - Utils::intoaV4(net, buf3, sizeof(buf3)), - cur_cidr); + char buf1[32], buf2[32], buf3[32]; + ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s <-> %s [%s - %u]", + Utils::intoaV4(src, buf1, sizeof(buf1)), + Utils::intoaV4(dst, buf2, sizeof(buf2)), + Utils::intoaV4(net, buf3, sizeof(buf3)), + cur_cidr); #endif + } + } else { + /* Suspicious broadcast domain (too large) + TODO: generate an alert */ } break; From e814d321cecc232db289063fcb71bcfc72763467 Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Mon, 1 Apr 2019 11:01:20 +0200 Subject: [PATCH 09/11] Code cleanup --- src/NetworkInterface.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 8e00c6b3a4d9..5aac6d222eb2 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -2569,7 +2569,7 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, if((src & cur_mask) != (dst & cur_mask)) { cur_mask <<= 1, cur_cidr -= 1; net = src & cur_mask; - } + } if(cur_mask >= 0xFFFF0000) { /* At most a /16 */ cur_bcast_domain.set(htonl(net)); @@ -2599,17 +2599,6 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, e = getArpHashMatrixElement(srcMac->get_mac(), dstMac->get_mac(), &src2dst_element); -#if 0 - char buf1[32], buf2[32]; - Utils::formatMac(srcMac->get_mac(), buf1, sizeof(buf1)); - Utils::formatMac(dstMac->get_mac(), buf2, sizeof(buf2)); - - if(!strcmp(buf1, "B4:75:0E:92:89:17") || !strcmp(buf2, "B4:75:0E:92:89:17")) { - ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%s][%s][0x%x][src2dst: %u]", - buf1, buf2, arp_opcode, src2dst_element ? 1 : 0); - } -#endif - if(arp_opcode == 0x1 /* ARP request */) { arp_requests++; srcMac->incSentArpRequests(); From 5e5ad77cec642eff73715b2480b06a42ec3d5dff Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Mon, 1 Apr 2019 14:20:57 +0200 Subject: [PATCH 10/11] Implements broadcast domain too large alerts --- include/AddressTree.h | 2 +- include/FrequentTrafficItems.h | 2 +- include/Host.h | 2 +- include/HostPools.h | 2 +- include/Mac.h | 2 +- include/NetworkInterface.h | 3 +- include/Utils.h | 2 +- include/VlanAddressTree.h | 2 +- include/ntop_defines.h | 9 +-- scripts/callbacks/system/housekeeping.lua | 1 + scripts/locales/en.lua | 2 + scripts/lua/modules/alert_consts.lua | 1 + scripts/lua/modules/alert_utils.lua | 37 ++++++++++++ src/AddressTree.cpp | 2 +- src/FrequentTrafficItems.cpp | 2 +- src/HostPools.cpp | 2 +- src/NetworkInterface.cpp | 74 +++++++++++++---------- src/Utils.cpp | 2 +- src/VlanAddressTree.cpp | 2 +- 19 files changed, 102 insertions(+), 49 deletions(-) diff --git a/include/AddressTree.h b/include/AddressTree.h index 66d14463e6a6..45a061d34f35 100644 --- a/include/AddressTree.h +++ b/include/AddressTree.h @@ -57,7 +57,7 @@ class AddressTree { bool addAddresses(char *net, const int16_t user_data = -1); void getAddresses(lua_State* vm) const; int16_t findAddress(int family, void *addr, u_int8_t *network_mask_bits = NULL); - int16_t findMac(u_int8_t addr[]); + int16_t findMac(const u_int8_t addr[]); bool match(char *addr); bool match(const IpAddress * const ipa, int network_bits) const; void dump(); diff --git a/include/FrequentTrafficItems.h b/include/FrequentTrafficItems.h index c129d2917ba6..92273378988c 100644 --- a/include/FrequentTrafficItems.h +++ b/include/FrequentTrafficItems.h @@ -74,7 +74,7 @@ class FrequentTrafficItems { void addPoolProtocol(u_int16_t pool_id, u_int16_t proto_id, u_int32_t value); void luaTopPoolsProtocols(lua_State *vm); - void addMacProtocol(u_int8_t mac[6], u_int16_t proto_id, u_int32_t value); + void addMacProtocol(const u_int8_t mac[6], u_int16_t proto_id, u_int32_t value); void luaTopMacsProtocols(lua_State *vm); }; diff --git a/include/Host.h b/include/Host.h index 65c11d406953..22edcf143219 100644 --- a/include/Host.h +++ b/include/Host.h @@ -152,7 +152,7 @@ class Host : public GenericHashEntry { void set_mac(u_int8_t *m); inline bool isBlacklisted() { return(blacklisted_host); }; void reloadHostBlacklist(); - inline u_int8_t* get_mac() { return(mac ? mac->get_mac() : NULL); } + inline const u_int8_t* const get_mac() const { return(mac ? mac->get_mac() : NULL);} inline Mac* getMac() const { return(mac); } char * getResolvedName(char * const buf, ssize_t buf_len); char * getMDNSName(char * const buf, ssize_t buf_len); diff --git a/include/HostPools.h b/include/HostPools.h index eab8b1e3c5ca..add1f845be20 100644 --- a/include/HostPools.h +++ b/include/HostPools.h @@ -85,7 +85,7 @@ class HostPools { u_int16_t getPool(Mac *m); bool findIpPool(IpAddress *ip, u_int16_t vlan_id, u_int16_t *found_pool, patricia_node_t **found_node); - bool findMacPool(u_int8_t *mac, u_int16_t *found_pool); + bool findMacPool(const u_int8_t * const mac, u_int16_t *found_pool); bool findMacPool(Mac *mac, u_int16_t *found_pool); void lua(lua_State *vm); diff --git a/include/Mac.h b/include/Mac.h index 3502b01ac63d..54e763988ba1 100644 --- a/include/Mac.h +++ b/include/Mac.h @@ -85,7 +85,7 @@ class Mac : public GenericHashEntry { MacLocation locate(); inline u_int32_t key() { return(Utils::macHash(mac)); } - inline u_int8_t* get_mac() { return(mac); } + inline const u_int8_t* const get_mac() const { return(mac); } inline const char * const get_manufacturer() { return manuf ? manuf : NULL; } bool isNull() const; diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 1982835fad4e..72cf5af1cdcc 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -255,6 +255,7 @@ class NetworkInterface : public Checkpointable { void topItemsCommit(const struct timeval *when); void checkMacIPAssociation(bool triggerEvent, u_char *_mac, u_int32_t ipv4); + bool checkBroadcastDomainTooLarge(u_int32_t bcast_mask, u_int16_t vlan_id, const Mac * const src_mac, const Mac * const dst_mac, u_int32_t spa, u_int32_t tpa) const; void pollQueuedeBPFEvents(); void reloadCustomCategories(); @@ -522,7 +523,7 @@ class NetworkInterface : public Checkpointable { void runHousekeepingTasks(); void runShutdownTasks(); - ArpStatsMatrixElement* getArpHashMatrixElement(u_int8_t _src_mac[6], u_int8_t _dst_mac[6], bool * const src2dst); + ArpStatsMatrixElement* getArpHashMatrixElement(const u_int8_t _src_mac[6], const u_int8_t _dst_mac[6], bool * const src2dst); Vlan* getVlan(u_int16_t vlanId, bool createIfNotPresent); AutonomousSystem *getAS(IpAddress *ipa, bool createIfNotPresent); Country* getCountry(const char *country_name, bool createIfNotPresent); diff --git a/include/Utils.h b/include/Utils.h index e4a108ebf875..f4e917ae12d3 100755 --- a/include/Utils.h +++ b/include/Utils.h @@ -107,7 +107,7 @@ class Utils { static const char* flowStatus2str(FlowStatus s, AlertType *aType, AlertLevel *aLevel); static char* formatMac(const u_int8_t * const mac, char *buf, u_int buf_len); static void parseMac(u_int8_t *mac, const char *symMac); - static u_int32_t macHash(u_int8_t *mac); + static u_int32_t macHash(const u_int8_t * const mac); static bool isSpecialMac(u_int8_t *mac); static int numberOfSetBits(u_int32_t i); static void initRedis(Redis **r, const char *redis_host, const char *redis_password, diff --git a/include/VlanAddressTree.h b/include/VlanAddressTree.h index 00aa809d00db..75c632c8a02a 100644 --- a/include/VlanAddressTree.h +++ b/include/VlanAddressTree.h @@ -36,7 +36,7 @@ class VlanAddressTree { bool addAddresses(u_int16_t vlan_id, char *net, const int16_t user_data = -1); int16_t findAddress(u_int16_t vlan_id, int family, void *addr, u_int8_t *network_mask_bits = NULL); - int16_t findMac(u_int16_t vlan_id, u_int8_t addr[]); + int16_t findMac(u_int16_t vlan_id, const u_int8_t addr[]); inline AddressTree *getAddressTree(u_int16_t vlan_id) { return tree[vlan_id]; }; }; diff --git a/include/ntop_defines.h b/include/ntop_defines.h index c987d97e4810..c4929264743e 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -498,10 +498,11 @@ #define CONST_INFLUXDB_FILE_QUEUE "ntopng.influx_file_queue" #define CONST_INFLUXDB_FLUSH_TIME 10 /* sec */ #define CONST_INFLUXDB_MAX_DUMP_SIZE 4194304 /* 4 MB */ -#define CONST_ALERT_MSG_QUEUE "ntopng.alert_queue" -#define CONST_ALERT_MAC_IP_QUEUE "ntopng.alert_mac_ip_queue" -#define CONST_ALERT_NFQ_FLUSHED "ntopng.alert_nfq_flushed_queue" -#define CONST_ALERT_HOST_REMOTE_TO_REMOTE "ntopng.alert_host_remote_to_remote" +#define CONST_ALERT_MSG_QUEUE "ntopng.alert_queue" +#define CONST_ALERT_MAC_IP_QUEUE "ntopng.alert_mac_ip_queue" +#define CONST_ALERT_NFQ_FLUSHED "ntopng.alert_nfq_flushed_queue" +#define CONST_ALERT_HOST_REMOTE_TO_REMOTE "ntopng.alert_host_remote_to_remote" +#define CONST_ALERT_BCAST_DOMAIN_TOO_LARGE_QUEUE "ntopng.alert_bcast_domain_too_large" #define CONST_REMOTE_TO_REMOTE_MAX_QUEUE 32 #define CONST_SQL_QUEUE "ntopng.sql_queue" #define CONST_SQL_BATCH_SIZE 32 diff --git a/scripts/callbacks/system/housekeeping.lua b/scripts/callbacks/system/housekeeping.lua index 7565806c7530..607fd5401c59 100644 --- a/scripts/callbacks/system/housekeeping.lua +++ b/scripts/callbacks/system/housekeeping.lua @@ -22,6 +22,7 @@ if ntop.isnEdge() then check_nfq_flushed_queue_alerts() end check_host_remote_to_remote_alerts() +check_broadcast_domain_too_large_alerts() check_process_alerts() callback_utils.uploadTSdata() lists_utils.checkReloadLists() diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index 1020b8e8eaac..80422da279e9 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -224,6 +224,7 @@ local lang = { ["influxdb_write_error"] = "There was an error while sending timeseries data to \"%{influxdb}\": %{err}", ["interface_entity"] = "interface %{entity_value}", ["mac_ip_association_change"] = "IP %{ip} changed association from %{old_mac} to %{new_mac}", + ["broadcast_domain_too_large"] = "ARP traffic from %{src_mac}/%{spa} to %{dst_mac}/%{tpa} detected. It is unlikely to see ARP traffic between those IPs as they are seemingly belonging to different broadcast domains. Check for hosts and networks configurations.", ["network_entity"] = "network %{entity_value}", ["nfq_flushed"] = "Interface %{name} packets queue flushed. Queue %{pct}%% full with %{tot} packets and %{dropped} drops.", ["ntopng_anomalous_termination"] = "Started after anomalous termination (bug report)", @@ -259,6 +260,7 @@ local lang = { ["host_pool_connection"] = "Host Pool Connection", ["host_pool_disconnection"] = "Host Pool Disconnection", ["icmp_anomaly"] = "ICMP Anomaly", + ["broadcast_domain_too_large"] = "Broadcast domain", ["inactivity"] = "Inactivity", ["influxdb_export_failure"] = "InfluxDB Export Failure", ["info"] = "Info", diff --git a/scripts/lua/modules/alert_consts.lua b/scripts/lua/modules/alert_consts.lua index 2fb76151ccac..be324aacd1a2 100644 --- a/scripts/lua/modules/alert_consts.lua +++ b/scripts/lua/modules/alert_consts.lua @@ -54,6 +54,7 @@ alert_consts.alert_type_keys = { { " " .. i18n("alerts_dashboard.list_download_failed"), 31, "list_download_failed" }, { " " .. i18n("alerts_dashboard.dns_anomaly"), 32, "dns_anomaly" }, { " " .. i18n("alerts_dashboard.icmp_anomaly"), 33, "icmp_anomaly" }, + { " " .. i18n("alerts_dashboard.broadcast_domain_too_large"), 34, "broadcast_domain_too_large" }, } -- Keep in sync with ntop_typedefs.h:AlertEntity diff --git a/scripts/lua/modules/alert_utils.lua b/scripts/lua/modules/alert_utils.lua index 05ae061a6017..9dfd2eb8bf09 100644 --- a/scripts/lua/modules/alert_utils.lua +++ b/scripts/lua/modules/alert_utils.lua @@ -2670,6 +2670,10 @@ local function getMacUrl(mac) return ntop.getHttpPrefix() .. "/lua/mac_details.lua?host=" .. mac end +local function getHostUrl(host, vlan_id) + return ntop.getHttpPrefix() .. "/lua/host_details.lua?" .. hostinfo2url({host = host, vlan = vlan_id}) +end + local function getSavedDeviceNameKey(mac) return "ntopng.cache.devnames." .. mac end @@ -2708,6 +2712,39 @@ function check_mac_ip_association_alerts() end end +-- Global function +function check_broadcast_domain_too_large_alerts() + while(true) do + local message = ntop.lpopCache("ntopng.alert_bcast_domain_too_large") + local elems + + if((message == nil) or (message == "")) then + break + end + + elems = json.decode(message) + + if elems ~= nil then + local entity = alertEntity("interface") + local entity_value = "iface_"..elems.ifid + + --io.write(elems.ip.." ==> "..message.."[".. elems.ifname .."]\n") + interface.select(elems.ifname) + interface.storeAlert(entity, entity_value, + alertType("broadcast_domain_too_large"), + alertSeverity("warning"), + i18n("alert_messages.broadcast_domain_too_large", + {src_mac = elems.src_mac, + src_mac_url = getMacUrl(elems.src_mac), + dst_mac = elems.dst_mac, + dst_mac_url = getMacUrl(elems.dst_mac), + spa = elems.spa, + spa_url = getHostUrl(elems.spa, elems.vlan_id), + tpa = elems.tpa, + tpa_url = getHostUrl(elems.tpa, elems.vlan_id)})) + end + end +end -- Global function function check_nfq_flushed_queue_alerts() diff --git a/src/AddressTree.cpp b/src/AddressTree.cpp index dd55f29610b5..f2c909126aba 100644 --- a/src/AddressTree.cpp +++ b/src/AddressTree.cpp @@ -284,7 +284,7 @@ int16_t AddressTree::findAddress(int family, void *addr, u_int8_t *network_mask_ /* ******************************************* */ -int16_t AddressTree::findMac(u_int8_t addr[]) { +int16_t AddressTree::findMac(const u_int8_t addr[]) { MacKey_t *s = NULL; HASH_FIND(hh, macs, addr, 6, s); diff --git a/src/FrequentTrafficItems.cpp b/src/FrequentTrafficItems.cpp index 637c35b908a3..47fb89ecf952 100644 --- a/src/FrequentTrafficItems.cpp +++ b/src/FrequentTrafficItems.cpp @@ -114,7 +114,7 @@ void FrequentTrafficItems::luaTopPoolsProtocols(lua_State *vm) { /* ******************************************************** */ -void FrequentTrafficItems::addMacProtocol(u_int8_t mac[6], u_int16_t proto_id, u_int32_t value) { +void FrequentTrafficItems::addMacProtocol(const u_int8_t mac[6], u_int16_t proto_id, u_int32_t value) { FrequentTrafficKey_t key; memset(&key, 0, sizeof(key)); diff --git a/src/HostPools.cpp b/src/HostPools.cpp index db7afa361503..cba9477c95a1 100644 --- a/src/HostPools.cpp +++ b/src/HostPools.cpp @@ -803,7 +803,7 @@ void HostPools::reloadPools() { /* *************************************** */ -bool HostPools::findMacPool(u_int8_t *mac, u_int16_t *found_pool) { +bool HostPools::findMacPool(const u_int8_t * const mac, u_int16_t *found_pool) { VlanAddressTree *cur_tree; /* must use this as tree can be swapped */ int16_t ret; diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 5aac6d222eb2..f9ad5d41f359 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -2526,24 +2526,9 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, 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); - - if(arp_spa_ipa.isNonEmptyUnicastAddress() - && (arp_spa_h = getHost(&arp_spa_ipa, vlan_id)) - && !arp_spa_h->isBroadcastDomainHost()) - arp_spa_h->setBroadcastDomainHost(); -#endif - u_int32_t src = ntohl(arpp->arp_spa); u_int32_t dst = ntohl(arpp->arp_tpa); u_int32_t net = src & dst; @@ -2571,30 +2556,25 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, net = src & cur_mask; } - if(cur_mask >= 0xFFFF0000) { /* At most a /16 */ - cur_bcast_domain.set(htonl(net)); + cur_bcast_domain.set(htonl(net)); - if(!bcast_domains->isLocalBroadcastDomain(&cur_bcast_domain, cur_cidr, true /* Inline call */)) { - bcast_domains->inlineAddAddress(&cur_bcast_domain, cur_cidr); + if(!checkBroadcastDomainTooLarge(net, vlan_id, srcMac, dstMac, src, dst) + && !bcast_domains->isLocalBroadcastDomain(&cur_bcast_domain, cur_cidr, true /* Inline call */)) { + bcast_domains->inlineAddAddress(&cur_bcast_domain, cur_cidr); #ifdef BROADCAST_DOMAINS_DEBUG - char buf1[32], buf2[32], buf3[32]; - ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s <-> %s [%s - %u]", - Utils::intoaV4(src, buf1, sizeof(buf1)), - Utils::intoaV4(dst, buf2, sizeof(buf2)), - Utils::intoaV4(net, buf3, sizeof(buf3)), - cur_cidr); + char buf1[32], buf2[32], buf3[32]; + ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s <-> %s [%s - %u]", + Utils::intoaV4(src, buf1, sizeof(buf1)), + Utils::intoaV4(dst, buf2, sizeof(buf2)), + Utils::intoaV4(net, buf3, sizeof(buf3)), + cur_cidr); #endif - } - } else { - /* Suspicious broadcast domain (too large) - TODO: generate an alert */ } break; } } - } e = getArpHashMatrixElement(srcMac->get_mac(), dstMac->get_mac(), &src2dst_element); @@ -5596,8 +5576,8 @@ Mac* NetworkInterface::getMac(u_int8_t _mac[6], bool createIfNotPresent) { /* **************************************************** */ -ArpStatsMatrixElement* NetworkInterface::getArpHashMatrixElement(u_int8_t _src_mac[6], - u_int8_t _dst_mac[6], +ArpStatsMatrixElement* NetworkInterface::getArpHashMatrixElement(const u_int8_t _src_mac[6], + const u_int8_t _dst_mac[6], bool * const src2dst){ ArpStatsMatrixElement *ret = NULL; @@ -6911,6 +6891,36 @@ void NetworkInterface::checkMacIPAssociation(bool triggerEvent, u_char *_mac, u_ /* *************************************** */ +bool NetworkInterface::checkBroadcastDomainTooLarge(u_int32_t bcast_mask, u_int16_t vlan_id, const Mac * const src_mac, const Mac * const dst_mac, u_int32_t spa, u_int32_t tpa) const { + if(bcast_mask < 0xFFFF0000) { + if(!ntop->getPrefs()->are_alerts_disabled()) { + json_object *jobject; + char buf[32]; + + if((jobject = json_object_new_object()) != NULL) { + json_object_object_add(jobject, "ifname", json_object_new_string(get_name())); + json_object_object_add(jobject, "ifid", json_object_new_int(id)); + json_object_object_add(jobject, "vlan_id", json_object_new_int(vlan_id)); + json_object_object_add(jobject, "src_mac", json_object_new_string(Utils::formatMac(src_mac->get_mac(), buf, sizeof(buf)))); + json_object_object_add(jobject, "dst_mac", json_object_new_string(Utils::formatMac(dst_mac->get_mac(), buf, sizeof(buf)))); + json_object_object_add(jobject, "spa", json_object_new_string(Utils::intoaV4(spa, buf, sizeof(buf)))); + json_object_object_add(jobject, "tpa", json_object_new_string(Utils::intoaV4(tpa, buf, sizeof(buf)))); + + ntop->getRedis()->rpush(CONST_ALERT_BCAST_DOMAIN_TOO_LARGE_QUEUE, (char *)json_object_to_json_string(jobject), 0 /* No trim */); + + /* Free Memory */ + json_object_put(jobject); + } + } + + return true; /* At most a /16 broadcast domain is acceptable */ + } + + return false; +} + +/* *************************************** */ + /* Put here all the code that is executed when the NIC initialization is succesful diff --git a/src/Utils.cpp b/src/Utils.cpp index bc793eee3d40..5f34f8b3daf5 100755 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -2439,7 +2439,7 @@ void Utils::xor_encdec(u_char *data, int data_len, u_char *key) { /* ****************************************************** */ -u_int32_t Utils::macHash(u_int8_t *mac) { +u_int32_t Utils::macHash(const u_int8_t * const mac) { if(mac == NULL) return(0); else { diff --git a/src/VlanAddressTree.cpp b/src/VlanAddressTree.cpp index b6f762452eba..1151650a6c98 100644 --- a/src/VlanAddressTree.cpp +++ b/src/VlanAddressTree.cpp @@ -65,7 +65,7 @@ int16_t VlanAddressTree::findAddress(u_int16_t vlan_id, int family, void *addr, /* **************************************** */ -int16_t VlanAddressTree::findMac(u_int16_t vlan_id, u_int8_t addr[]) { +int16_t VlanAddressTree::findMac(u_int16_t vlan_id, const u_int8_t addr[]) { if(! tree[vlan_id]) return -1; return tree[vlan_id]->findMac(addr); } From 4fb8cd243399dc587d277e90d16dd1a4d1200c2e Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Mon, 1 Apr 2019 14:30:05 +0200 Subject: [PATCH 11/11] Minor fix --- src/NetworkInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index f9ad5d41f359..5d31cec09dad 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -2558,7 +2558,7 @@ bool NetworkInterface::dissectPacket(u_int32_t bridge_iface_idx, cur_bcast_domain.set(htonl(net)); - if(!checkBroadcastDomainTooLarge(net, vlan_id, srcMac, dstMac, src, dst) + if(!checkBroadcastDomainTooLarge(cur_mask, vlan_id, srcMac, dstMac, src, dst) && !bcast_domains->isLocalBroadcastDomain(&cur_bcast_domain, cur_cidr, true /* Inline call */)) { bcast_domains->inlineAddAddress(&cur_bcast_domain, cur_cidr);