diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 0f92a20a99..a36f9ea65e 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -750,6 +750,7 @@ class NetworkInterface : public AlertableEntity { inline void decNumAlertsEngaged(ScriptPeriodicity p) { num_alerts_engaged[(u_int)p]--; } inline bool hasAlerts() { return(has_alerts); } inline void refreshHasAlerts() { has_alerts = alertsManager ? alertsManager->hasAlerts() : false; } + virtual bool reproducePcapOriginalSpeed() { return(false); } u_int32_t getNumEngagedAlerts(); }; diff --git a/include/PcapInterface.h b/include/PcapInterface.h index e6aa0712ff..9fab10ff33 100644 --- a/include/PcapInterface.h +++ b/include/PcapInterface.h @@ -49,8 +49,9 @@ class PcapInterface : public NetworkInterface { void startPacketPolling(); void shutdown(); bool set_packet_filter(char *filter); - inline bool read_from_pcap_dump() { return(read_pkts_from_pcap_dump); }; - inline void sendTermination() { if(pcap_handle) pcap_breakloop(pcap_handle); } + inline bool read_from_pcap_dump() { return(read_pkts_from_pcap_dump); }; + inline void sendTermination() { if(pcap_handle) pcap_breakloop(pcap_handle); }; + bool reproducePcapOriginalSpeed(); virtual void updateDirectionStats(); }; diff --git a/include/Prefs.h b/include/Prefs.h index 284249dd57..f96c4d3d61 100644 --- a/include/Prefs.h +++ b/include/Prefs.h @@ -42,7 +42,7 @@ class Prefs { char **deferred_interfaces_to_register, *cli; char *http_binding_address1, *http_binding_address2; char *https_binding_address1, *https_binding_address2; - bool enable_client_x509_auth; + bool enable_client_x509_auth, reproduce_at_original_speed; char *lan_interface; Ntop *ntop; bool enable_dns_resolution, sniff_dns_responses, @@ -377,7 +377,9 @@ class Prefs { inline bool isGlobalDnsForgingEnabled() { return(global_dns_forging_enabled); }; inline u_int8_t getNumTsSlots() { return(num_ts_slots); }; inline u_int8_t getNumTsSteps() { return(ts_num_steps); }; - + inline bool reproduceOriginalSpeed() { return(reproduce_at_original_speed); }; + inline void doReproduceOriginalSpeed() { reproduce_at_original_speed = true; }; + void validate(); }; diff --git a/src/Host.cpp b/src/Host.cpp index 35ca4c1016..4c60d29990 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -1264,7 +1264,8 @@ void Host::dissectDropbox(const char *payload, u_int16_t payload_len) { enum json_tokener_error jerr; char str[1500]; - if ((payload_len + 1) > sizeof(str)) return; /* Too long: this isn't a valid Dropbox packet */ + if ((payload_len + 1) > (u_int16_t)sizeof(str)) + return; /* Too long: this isn't a valid Dropbox packet */ strncpy(str, payload, payload_len); str[payload_len] = '\0'; diff --git a/src/PcapInterface.cpp b/src/PcapInterface.cpp index bbb240fd34..d7d0281b72 100644 --- a/src/PcapInterface.cpp +++ b/src/PcapInterface.cpp @@ -262,6 +262,37 @@ static void* packetPollLoop(void* ptr) { } if((rc = pcap_next_ex(pd, &hdr, &pkt)) > 0) { + if(iface->reproducePcapOriginalSpeed()) { + struct timeval now; + static struct timeval lastPktProcessed = { 0, 0 }, lastPcapTime; + + gettimeofday(&now, NULL); + + if(lastPktProcessed.tv_sec > 0) { + u_int32_t n, m = Utils::msTimevalDiff(&hdr->ts, &lastPcapTime); + + if(m < 100000) { /* Catch wrong timestamps */ + n = (u_int32_t)Utils::msTimevalDiff(&now, &lastPktProcessed); + + if(n < m) { + ntop->getTrace()->traceEvent(TRACE_INFO, + "Sleeping %.3f sec [delta %.3f sec]", + ((float)(m-n))/1000, ((float)m)/1000); + + usleep((m - n)*1000); + } + } + + /* Recompute after sleep */ + gettimeofday(&now, NULL); + } + + lastPcapTime = hdr->ts; + lastPktProcessed = now; + + hdr->ts = now; + } + if((pkt != NULL) && (hdr->caplen > 0)) { u_int16_t p; Host *srcHost = NULL, *dstHost = NULL; @@ -300,7 +331,6 @@ static void* packetPollLoop(void* ptr) { iface->purgeIdle(time(NULL)); } } /* while */ - } while(pcap_list != NULL); if(iface->read_from_pcap_dump()) { @@ -432,3 +462,10 @@ void PcapInterface::updateDirectionStats() { } #endif + +/* **************************************************** */ + +bool PcapInterface::reproducePcapOriginalSpeed() { + return(read_pkts_from_pcap_dump && ntop->getPrefs()->reproduceOriginalSpeed()); +} + diff --git a/src/Prefs.cpp b/src/Prefs.cpp index 3de7b668a1..409d504ba9 100755 --- a/src/Prefs.cpp +++ b/src/Prefs.cpp @@ -39,7 +39,7 @@ Prefs::Prefs(Ntop *_ntop) { data_dir = strdup(CONST_DEFAULT_DATA_DIR); enable_access_log = false, enable_sql_log = false, flow_aggregation_enabled = false; enable_flow_device_port_rrd_creation = false; - enable_ip_reassignment_alerts = false; + enable_ip_reassignment_alerts = false, reproduce_at_original_speed = false; enable_top_talkers = false, enable_idle_local_hosts_cache = false; enable_active_local_hosts_cache = false, enable_tiny_flows_export = true, enable_aggregated_flows_export_limit = false, @@ -310,6 +310,8 @@ void usage() { " | (default: %u)\n" "[--users-file|-u] | Users configuration file path\n" " | Default: %s\n" + "[--original-speed] | Reproduce (-i) the pcap file at original speed\n" + " | Default: %s\n" #ifndef WIN32 "[--pid|-G] | Pid file path\n" #endif @@ -747,6 +749,7 @@ static const struct option long_options[] = { { "callbacks-dir", required_argument, NULL, '3' }, { "prefs-dir", required_argument, NULL, '4' }, { "pcap-dir", required_argument, NULL, '5' }, + { "original-speed", no_argument, NULL, 208 }, { "online-check", no_argument, NULL, 209 }, { "print-ndpi-protocols", no_argument, NULL, 210 }, { "online-license-check", no_argument, NULL, 211 }, @@ -1348,6 +1351,10 @@ int Prefs::setOption(int optkey, char *optarg) { max_num_flows = max_val(atoi(optarg), 1024); break; + case 208: + reproduce_at_original_speed = true; + break; + case 209: service_license_check = true; break;