]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnsreplay.cc
Merge pull request #7945 from pieterlexis/syncres-CNAME-cache-cleanup
[thirdparty/pdns.git] / pdns / dnsreplay.cc
index a95a233f344de47f425b4c139ffdad83a73478e0..aa0f4e1c595e9ae8fbe2b2751a5fe44cf6b2ea9e 100644 (file)
@@ -444,7 +444,7 @@ try
        measureResultAndClean(iter);
       }
     }
-    catch(MOADNSException &e)
+    catch(const MOADNSException &mde)
     {
       s_wednserrors++;
     }
@@ -558,7 +558,7 @@ static void generateOptRR(const std::string& optRData, string& res)
   EDNS0Record edns0;
   edns0.extRCode = 0;
   edns0.version = 0;
-  edns0.Z = 0;
+  edns0.extFlags = 0;
   
   dh.d_type = htons(QType::OPT);
   dh.d_class = htons(1280);
@@ -569,7 +569,7 @@ static void generateOptRR(const std::string& optRData, string& res)
   res.append(optRData.c_str(), optRData.length());
 }
 
-static void addECSOption(char* packet, const size_t& packetSize, uint16_t* len, const ComboAddress& remote, int stamp)
+static void addECSOption(char* packet, const size_t packetSize, uint16_t* len, const ComboAddress& remote, int stamp)
 {
   string EDNSRR;
   struct dnsheader* dh = (struct dnsheader*) packet;
@@ -590,7 +590,7 @@ static void addECSOption(char* packet, const size_t& packetSize, uint16_t* len,
 
   uint16_t arcount = ntohs(dh->arcount);
   /* does it fit in the existing buffer? */
-  if (packetSize - *len > EDNSRR.size()) {
+  if (packetSize > *len && (packetSize - *len) > EDNSRR.size()) {
     arcount++;
     dh->arcount = htons(arcount);
     memcpy(packet + *len, EDNSRR.c_str(), EDNSRR.size());
@@ -603,9 +603,16 @@ static uint16_t g_pcapDnsPort;
 
 static bool sendPacketFromPR(PcapPacketReader& pr, const ComboAddress& remote, int stamp)
 {
-  dnsheader* dh=(dnsheader*)pr.d_payload;
   bool sent=false;
-  if((ntohs(pr.d_udp->uh_dport)!=g_pcapDnsPort && ntohs(pr.d_udp->uh_sport)!=g_pcapDnsPort) || dh->rd != g_rdSelector || (unsigned int)pr.d_len <= sizeof(dnsheader))
+  if (pr.d_len <= sizeof(dnsheader)) {
+    return sent;
+  }
+  if (pr.d_len > std::numeric_limits<uint16_t>::max()) {
+    /* too large for an DNS UDP query, something is not right */
+    return false;
+  }
+  dnsheader* dh=const_cast<dnsheader*>(reinterpret_cast<const dnsheader*>(pr.d_payload));
+  if((ntohs(pr.d_udp->uh_dport)!=g_pcapDnsPort && ntohs(pr.d_udp->uh_sport)!=g_pcapDnsPort) || dh->rd != g_rdSelector)
     return sent;
 
   QuestionData qd;
@@ -619,8 +626,16 @@ static bool sendPacketFromPR(PcapPacketReader& pr, const ComboAddress& remote, i
       //      dh->rd=1; // useful to replay traffic to auths to a recursor
       uint16_t dlen = pr.d_len;
 
-      if (stamp >= 0) addECSOption((char*)pr.d_payload, 1500, &dlen, pr.getSource(), stamp);
-      pr.d_len=dlen;
+      if (stamp >= 0) {
+        static_assert(sizeof(pr.d_buffer) >= 1500, "The size of the underlying buffer should be at least 1500 bytes");
+        if (dlen > 1500) {
+          /* the existing packet is larger than the maximum size we are willing to send, and it won't get better by adding ECS */
+          return false;
+        }
+        addECSOption((char*)pr.d_payload, 1500, &dlen, pr.getSource(), stamp);
+        pr.d_len=dlen;
+      }
+
       s_socket->sendTo((const char*)pr.d_payload, dlen, remote);
       sent=true;
       dh->id=tmp;
@@ -669,10 +684,10 @@ static bool sendPacketFromPR(PcapPacketReader& pr, const ComboAddress& remote, i
       }
     }
   }
-  catch(MOADNSException &e)
+  catch(const MOADNSException &mde)
   {
     if(!g_quiet)
-      cerr<<"Error parsing packet: "<<e.what()<<endl;
+      cerr<<"Error parsing packet: "<<mde.what()<<endl;
     s_idmanager.releaseID(qd.d_assignedID);  // not added to qids for cleanup
     s_origdnserrors++;
   }