X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcoremods%2Fcore_dns.cpp;h=da468af5fae273a4ace9e1c48f266d45aa5552a7;hb=a876f2c58e2f6f2602ed27da09a6e9c40008a80c;hp=829351f04dceec1cc07ee37786ced76aaf1b9a85;hpb=bd1471bc08be28bc2554d35fdaeb078338b14266;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp index 829351f04..da468af5f 100644 --- a/src/coremods/core_dns.cpp +++ b/src/coremods/core_dns.cpp @@ -27,6 +27,13 @@ #pragma comment(lib, "Iphlpapi.lib") #endif +namespace DNS +{ + /** Maximum value of a dns request id, 16 bits wide, 0xFFFF. + */ + const unsigned int MAX_REQUEST_ID = 0xFFFF; +} + using namespace DNS; /** A full packet sent or recieved to/from the nameserver @@ -367,7 +374,18 @@ class MyManager : public Manager, public Timer, public EventHandler */ void AddCache(Query& r) { - const ResourceRecord& rr = r.answers[0]; + // Determine the lowest TTL value and use that as the TTL of the cache entry + unsigned int cachettl = UINT_MAX; + for (std::vector::const_iterator i = r.answers.begin(); i != r.answers.end(); ++i) + { + const ResourceRecord& rr = *i; + if (rr.ttl < cachettl) + cachettl = rr.ttl; + } + + ResourceRecord& rr = r.answers.front(); + // Set TTL to what we've determined to be the lowest + rr.ttl = cachettl; ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "cache: added cache for " + rr.name + " -> " + rr.rdata + " ttl: " + ConvToStr(rr.ttl)); this->cache[r.question] = r; } @@ -457,11 +475,15 @@ class MyManager : public Manager, public Timer, public EventHandler if (SocketEngine::SendTo(this, buffer, len, 0, &this->myserver.sa, this->myserver.sa_size()) != len) throw Exception("DNS: Unable to send query"); + + // Add timer for timeout + ServerInstance->Timers.AddTimer(req); } void RemoveRequest(DNS::Request* req) { - this->requests[req->id] = NULL; + if (requests[req->id] == req) + requests[req->id] = NULL; } std::string GetErrorStr(Error e) @@ -475,6 +497,7 @@ class MyManager : public Manager, public Timer, public EventHandler case ERROR_NOT_AN_ANSWER: case ERROR_NONSTANDARD_QUERY: case ERROR_FORMAT_ERROR: + case ERROR_MALFORMED: return "Malformed answer"; case ERROR_SERVER_FAILURE: case ERROR_NOT_IMPLEMENTED: @@ -517,17 +540,19 @@ class MyManager : public Manager, public Timer, public EventHandler } Packet recv_packet; + bool valid = false; try { recv_packet.Fill(buffer, length); + valid = true; } catch (Exception& ex) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, ex.GetReason()); - return; } + // recv_packet.id must be filled in here DNS::Request* request = this->requests[recv_packet.id]; if (request == NULL) { @@ -542,14 +567,20 @@ class MyManager : public Manager, public Timer, public EventHandler return; } - if (recv_packet.flags & QUERYFLAGS_OPCODE) + if (!valid) + { + ServerInstance->stats.DnsBad++; + recv_packet.error = ERROR_MALFORMED; + request->OnError(&recv_packet); + } + else if (recv_packet.flags & QUERYFLAGS_OPCODE) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Received a nonstandard query"); ServerInstance->stats.DnsBad++; recv_packet.error = ERROR_NONSTANDARD_QUERY; request->OnError(&recv_packet); } - else if (recv_packet.flags & QUERYFLAGS_RCODE) + else if (!(recv_packet.flags & QUERYFLAGS_QR) || (recv_packet.flags & QUERYFLAGS_RCODE)) { Error error = ERROR_UNKNOWN; @@ -717,7 +748,7 @@ class ModuleDNS : public Module if (DNSServer == "nameserver") { resolv >> DNSServer; - if (DNSServer.find_first_not_of("0123456789.") == std::string::npos) + if (DNSServer.find_first_not_of("0123456789.") == std::string::npos || DNSServer.find_first_not_of("0123456789ABCDEFabcdef:") == std::string::npos) { ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, " set to '%s' as first resolver in /etc/resolv.conf.",DNSServer.c_str()); return;