diff --git a/CHANGES b/CHANGES index 3b3d487ff5..2474f3c5ac 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,10 @@ +2.6-300 | 2019-05-15 09:00:57 -0700 + + * Fixes to DNS lookup, including ref-counting bugs, preventing starvation + of the DNS_Mgr in the I/O loop, dead code removal, and a fix that + prevents the timeout of already resolved DNS lookups (Jon Siwek, Corelight) + 2.6-292 | 2019-05-14 19:01:05 -0700 * Fix maybe-uninitialized compiler warning (Jon Siwek, Corelight) diff --git a/VERSION b/VERSION index 5978f27f47..91de3cddd1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6-292 +2.6-300 diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 1e4d65bf8a..2e1f46de31 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -289,10 +289,13 @@ ListVal* DNS_Mapping::Addrs() TableVal* DNS_Mapping::AddrsSet() { ListVal* l = Addrs(); - if ( l ) - return l->ConvertToSet(); - else + + if ( ! l ) return empty_addr_set(); + + auto rval = l->ConvertToSet(); + Unref(l); + return rval; } StringVal* DNS_Mapping::Host() @@ -389,6 +392,7 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode) successful = 0; failed = 0; nb_dns = nullptr; + next_timestamp = -1.0; } DNS_Mgr::~DNS_Mgr() @@ -1249,8 +1253,17 @@ void DNS_Mgr::GetFds(iosource::FD_Set* read, iosource::FD_Set* write, double DNS_Mgr::NextTimestamp(double* network_time) { - // This is kind of cheating ... - return asyncs_timeouts.size() ? timer_mgr->Time() : -1.0; + if ( asyncs_timeouts.empty() ) + // No pending requests. + return -1.0; + + if ( next_timestamp < 0 ) + // Store the timestamp to help prevent starvation by some other + // IOSource always trying to use the same timestamp + // (assuming network_time does actually increase). + next_timestamp = timer_mgr->Time(); + + return next_timestamp; } void DNS_Mgr::CheckAsyncAddrRequest(const IPAddr& addr, bool timeout) @@ -1356,7 +1369,7 @@ void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout) void DNS_Mgr::Flush() { - DoProcess(false); + DoProcess(); HostMap::iterator it; for ( it = host_mappings.begin(); it != host_mappings.end(); ++it ) @@ -1378,10 +1391,11 @@ void DNS_Mgr::Flush() void DNS_Mgr::Process() { - DoProcess(false); + DoProcess(); + next_timestamp = -1.0; } -void DNS_Mgr::DoProcess(bool flush) +void DNS_Mgr::DoProcess() { if ( ! nb_dns ) return; @@ -1390,23 +1404,23 @@ void DNS_Mgr::DoProcess(bool flush) { AsyncRequest* req = asyncs_timeouts.top(); - if ( req->time + DNS_TIMEOUT > current_time() || flush ) + if ( req->time + DNS_TIMEOUT > current_time() ) break; - if ( req->IsAddrReq() ) - CheckAsyncAddrRequest(req->host, true); - else if ( req->is_txt ) - CheckAsyncTextRequest(req->name.c_str(), true); - else - CheckAsyncHostRequest(req->name.c_str(), true); + if ( ! req->processed ) + { + if ( req->IsAddrReq() ) + CheckAsyncAddrRequest(req->host, true); + else if ( req->is_txt ) + CheckAsyncTextRequest(req->name.c_str(), true); + else + CheckAsyncHostRequest(req->name.c_str(), true); + } asyncs_timeouts.pop(); delete req; } - if ( asyncs_addrs.size() == 0 && asyncs_names.size() == 0 && asyncs_texts.size() == 0 ) - return; - if ( AnswerAvailable(0) <= 0 ) return; diff --git a/src/DNS_Mgr.h b/src/DNS_Mgr.h index f6f62bd1ec..39f728c812 100644 --- a/src/DNS_Mgr.h +++ b/src/DNS_Mgr.h @@ -132,7 +132,7 @@ protected: void CheckAsyncTextRequest(const char* host, bool timeout); // Process outstanding requests. - void DoProcess(bool flush); + void DoProcess(); // IOSource interface. void GetFds(iosource::FD_Set* read, iosource::FD_Set* write, @@ -172,12 +172,13 @@ protected: struct AsyncRequest { double time; + bool is_txt; + bool processed; IPAddr host; string name; - bool is_txt; CallbackList callbacks; - AsyncRequest() : time(0.0), is_txt(false) { } + AsyncRequest() : time(0.0), is_txt(false), processed(false) { } bool IsAddrReq() const { return name.length() == 0; } @@ -190,6 +191,7 @@ protected: delete *i; } callbacks.clear(); + processed = true; } void Resolved(TableVal* addrs) @@ -201,6 +203,7 @@ protected: delete *i; } callbacks.clear(); + processed = true; } void Timeout() @@ -212,6 +215,7 @@ protected: delete *i; } callbacks.clear(); + processed = true; } }; @@ -228,7 +232,14 @@ protected: typedef list QueuedList; QueuedList asyncs_queued; - typedef priority_queue TimeoutQueue; + struct AsyncRequestCompare { + bool operator()(const AsyncRequest* a, const AsyncRequest* b) + { + return a->time > b->time; + } + }; + + typedef priority_queue, AsyncRequestCompare> TimeoutQueue; TimeoutQueue asyncs_timeouts; int asyncs_pending; @@ -236,6 +247,7 @@ protected: unsigned long num_requests; unsigned long successful; unsigned long failed; + double next_timestamp; }; extern DNS_Mgr* dns_mgr;