]> granicus.if.org Git - pdns/commitdiff
when receiving a QR=0 "response", try to match it to an outstanding query so we can...
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 23 May 2013 10:58:29 +0000 (12:58 +0200)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 23 May 2013 10:58:29 +0000 (12:58 +0200)
pdns/pdns_recursor.cc

index f250a21213bef3dad0bf4d560c70497dbdb93d68..a3339921b144946185476947f114df21d1b33bbb 100644 (file)
@@ -1447,63 +1447,65 @@ void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
   dnsheader dh;
   memcpy(&dh, data, sizeof(dh));
   
-  if(dh.qr) {
-    PacketID pident;
-    pident.remote=fromaddr;
-    pident.id=dh.id;
-    pident.fd=fd;
-    if(!dh.qdcount) { // UPC, Nominum, very old BIND on FormErr, NSD
-      pident.domain.clear();
-      pident.type = 0;
-    }
-    else {
-      try {
-        pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
-      }
-      catch(std::exception& e) {
-        g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
-        L<<Logger::Warning<<"Error in packet from "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
-        return;
-      }
-    }
-    string packet;
-    packet.assign(data, len);
+  PacketID pident;
+  pident.remote=fromaddr;
+  pident.id=dh.id;
+  pident.fd=fd;
 
-    MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
-    if(iter != MT->d_waiters.end()) {
-      doResends(iter, pident, packet);
+  if(!dh.qr) {
+    L<<Logger::Warning<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort()  <<endl;
+  }
+
+  if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
+     !dh.qr) {      // one weird server
+    pident.domain.clear();
+    pident.type = 0;
+  }
+  else {
+    try {
+      pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
+    }
+    catch(std::exception& e) {
+      g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
+      L<<Logger::Warning<<"Error in packet from "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
+      return;
     }
+  }
+  string packet;
+  packet.assign(data, len);
 
-  retryWithName:
+  MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
+  if(iter != MT->d_waiters.end()) {
+    doResends(iter, pident, packet);
+  }
 
-    if(!MT->sendEvent(pident, &packet)) {
-      // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
-      for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
-        if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote &&  mthread->key.type == pident.type &&
-           pdns_iequals(pident.domain, mthread->key.domain)) {
-          mthread->key.nearMisses++;
-        }
+retryWithName:
 
-        // be a bit paranoid here since we're weakening our matching
-        if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type && 
-           pident.id  == mthread->key.id && mthread->key.remote == pident.remote) {
-          // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
-          pident.domain = mthread->key.domain;
-          pident.type = mthread->key.type;
-          goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
-        }
+  if(!MT->sendEvent(pident, &packet)) {
+    // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
+    for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
+      if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote &&  mthread->key.type == pident.type &&
+         pdns_iequals(pident.domain, mthread->key.domain)) {
+        mthread->key.nearMisses++;
       }
-      g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
-      if(g_logCommonErrors) {
-        L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
+
+      // be a bit paranoid here since we're weakening our matching
+      if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type && 
+         pident.id  == mthread->key.id && mthread->key.remote == pident.remote) {
+        // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
+        pident.domain = mthread->key.domain;
+        pident.type = mthread->key.type;
+        goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
       }
     }
-    else if(fd >= 0) {
-      t_udpclientsocks->returnSocket(fd);
+    g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
+    if(g_logCommonErrors) {
+      L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
     }
   }
-  else
-    L<<Logger::Warning<<"Ignoring question on outgoing socket from "<< fromaddr.toStringWithPort()  <<endl;
+  else if(fd >= 0) {
+    t_udpclientsocks->returnSocket(fd);
+  }
 }
 
 FDMultiplexer* getMultiplexer()