diff -ru pdns-recursor-4.1.4.orig/packetcache.hh pdns-recursor-4.1.4/packetcache.hh
--- pdns-recursor-4.1.4.orig/packetcache.hh	2018-08-31 13:29:25.000000000 +0200
+++ pdns-recursor-4.1.4/packetcache.hh	2018-10-09 15:44:57.646908242 +0200
@@ -28,13 +28,13 @@
 
 class PacketCache : public boost::noncopyable
 {
-protected:
-  static uint32_t canHashPacket(const std::string& packet, bool skipECS=true)
+public:
+  static uint32_t canHashPacket(const std::string& packet, uint16_t* ecsBegin, uint16_t* ecsEnd)
   {
     uint32_t ret = 0;
-    ret=burtle((const unsigned char*)packet.c_str() + 2, 10, ret); // rest of dnsheader, skip id
+    ret = burtle(reinterpret_cast<const unsigned char*>(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id
     size_t packetSize = packet.size();
-    size_t pos = 12;
+    size_t pos = sizeof(dnsheader);
     const char* end = packet.c_str() + packetSize;
     const char* p = packet.c_str() + pos;
 
@@ -43,36 +43,110 @@
       ret=burtle(&l, 1, ret);
     }                           // XXX the embedded 0 in the qname will break the subnet stripping
 
-    struct dnsheader* dh = (struct dnsheader*)packet.c_str();
+    const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.c_str());
     const char* skipBegin = p;
     const char* skipEnd = p;
+    if (ecsBegin != nullptr && ecsEnd != nullptr) {
+      *ecsBegin = 0;
+      *ecsEnd = 0;
+    }
     /* we need at least 1 (final empty label) + 2 (QTYPE) + 2 (QCLASS)
        + OPT root label (1), type (2), class (2) and ttl (4)
        + the OPT RR rdlen (2)
        = 16
     */
-    if(skipECS && ntohs(dh->arcount)==1 && (pos+16) < packetSize) {
+    if(ntohs(dh->arcount)==1 && (pos+16) < packetSize) {
       char* optionBegin = nullptr;
       size_t optionLen = 0;
       /* skip the final empty label (1), the qtype (2), qclass (2) */
       /* root label (1), type (2), class (2) and ttl (4) */
-      int res = getEDNSOption((char*) p + 14, end - (p + 14), EDNSOptionCode::ECS, &optionBegin, &optionLen);
+      int res = getEDNSOption(const_cast<char*>(reinterpret_cast<const char*>(p)) + 14, end - (p + 14), EDNSOptionCode::ECS, &optionBegin, &optionLen);
       if (res == 0) {
         skipBegin = optionBegin;
         skipEnd = optionBegin + optionLen;
+        if (ecsBegin != nullptr && ecsEnd != nullptr) {
+          *ecsBegin = optionBegin - packet.c_str();
+          *ecsEnd = *ecsBegin + optionLen;
+        }
       }
     }
     if (skipBegin > p) {
-      // cerr << "Hashing from " << (p-packet.c_str()) << " for " << skipBegin-p << "bytes, end is at "<< end-packet.c_str() << endl;
-      ret = burtle((const unsigned char*)p, skipBegin-p, ret);
+      ret = burtle(reinterpret_cast<const unsigned char*>(p), skipBegin-p, ret);
     }
     if (skipEnd < end) {
-      // cerr << "Hashing from " << (skipEnd-packet.c_str()) << " for " << end-skipEnd << "bytes, end is at " << end-packet.c_str() << endl;
-      ret = burtle((const unsigned char*) skipEnd, end-skipEnd, ret);
+      ret = burtle(reinterpret_cast<const unsigned char*>(skipEnd), end-skipEnd, ret);
     }
 
     return ret;
   }
+
+  static uint32_t canHashPacket(const std::string& packet)
+  {
+    uint32_t ret = 0;
+    ret = burtle(reinterpret_cast<const unsigned char*>(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id
+    size_t packetSize = packet.size();
+    size_t pos = sizeof(dnsheader);
+    const char* end = packet.c_str() + packetSize;
+    const char* p = packet.c_str() + pos;
+
+    for(; p < end && *p; ++p) { // XXX if you embed a 0 in your qname we'll stop lowercasing there
+      const unsigned char l = dns_tolower(*p); // label lengths can safely be lower cased
+      ret=burtle(&l, 1, ret);
+    }                           // XXX the embedded 0 in the qname will break the subnet stripping
+
+    if (p < end) {
+      ret = burtle(reinterpret_cast<const unsigned char*>(p), end-p, ret);
+    }
+
+    return ret;
+  }
+
+  static bool queryHeaderMatches(const std::string& cachedQuery, const std::string& query)
+  {
+    if (cachedQuery.size() != query.size()) {
+      return false;
+    }
+
+    return (cachedQuery.compare(/* skip the ID */ 2, sizeof(dnsheader) - 2, query, 2, sizeof(dnsheader) - 2) == 0);
+  }
+
+  static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname)
+  {
+    if (!queryHeaderMatches(cachedQuery, query)) {
+      return false;
+    }
+
+    size_t pos = sizeof(dnsheader) + qname.wirelength();
+
+    return (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) == 0);
+  }
+
+  static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname, uint16_t ecsBegin, uint16_t ecsEnd)
+  {
+    if (!queryHeaderMatches(cachedQuery, query)) {
+      return false;
+    }
+
+    size_t pos = sizeof(dnsheader) + qname.wirelength();
+
+    if (ecsBegin != 0 && ecsBegin >= pos && ecsEnd > ecsBegin) {
+      if (cachedQuery.compare(pos, ecsBegin - pos, query, pos, ecsBegin - pos) != 0) {
+        return false;
+      }
+
+      if (cachedQuery.compare(ecsEnd, cachedQuery.size() - ecsEnd, query, ecsEnd, query.size() - ecsEnd) != 0) {
+        return false;
+      }
+    }
+    else {
+      if (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) != 0) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
 };
 
 #endif /* PACKETCACHE_HH */
diff -ru pdns-recursor-4.1.4.orig/pdns_recursor.cc pdns-recursor-4.1.4/pdns_recursor.cc
--- pdns-recursor-4.1.4.orig/pdns_recursor.cc	2018-08-31 13:29:26.000000000 +0200
+++ pdns-recursor-4.1.4/pdns_recursor.cc	2018-10-09 15:47:13.765509822 +0200
@@ -219,6 +219,7 @@
   string d_requestorId;
   string d_deviceId;
 #endif
+  std::string d_query;
   EDNSSubnetOpts d_ednssubnet;
   bool d_ecsFound{false};
   bool d_ecsParsed{false};
@@ -226,12 +227,13 @@
   int d_socket;
   unsigned int d_tag{0};
   uint32_t d_qhash{0};
-  string d_query;
   shared_ptr<TCPConnection> d_tcpConnection;
   vector<pair<uint16_t, string> > d_ednsOpts;
   std::vector<std::string> d_policyTags;
   LuaContext::LuaObject d_data;
   uint32_t d_ttlCap{std::numeric_limits<uint32_t>::max()};
+  uint16_t d_ecsBegin{0};
+  uint16_t d_ecsEnd{0};
   bool d_variable{false};
 };
 
@@ -1208,11 +1210,13 @@
         L<<Logger::Warning<<"Sending UDP reply to client "<<dc->d_remote.toStringWithPort()<<" failed with: "<<strerror(errno)<<endl;
 
       if(!SyncRes::s_nopacketcache && !variableAnswer && !sr.wasVariable() ) {
-        t_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass,
+        t_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, dc->d_query, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass,
                                             string((const char*)&*packet.begin(), packet.size()),
                                             g_now.tv_sec,
                                             pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl :
                                             min(minTTL,SyncRes::s_packetcachettl),
+                                            dc->d_ecsBegin,
+                                            dc->d_ecsEnd,
                                             &pbMessage);
       }
       //      else cerr<<"Not putting in packet cache: "<<sr.wasVariable()<<endl;
@@ -1664,6 +1668,8 @@
   EDNSSubnetOpts ednssubnet;
   bool ecsFound = false;
   bool ecsParsed = false;
+  uint16_t ecsBegin = 0;
+  uint16_t ecsEnd = 0;
   uint32_t ttlCap = std::numeric_limits<uint32_t>::max();
   bool variable = false;
   try {
@@ -1727,10 +1733,10 @@
        but it means that the hash would not be computed. If some script decides at a later time to mark back the answer
        as cacheable we would cache it with a wrong tag, so better safe than sorry. */
     if (qnameParsed) {
-      cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, qtype, qclass, g_now.tv_sec, &response, &age, &qhash, &pbMessage));
+      cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, qtype, qclass, g_now.tv_sec, &response, &age, &qhash, &ecsBegin, &ecsEnd, &pbMessage));
     }
     else {
-      cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, g_now.tv_sec, &response, &age, &qhash, &pbMessage));
+      cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, &qtype, &qclass, g_now.tv_sec, &response, &age, &qhash, &ecsBegin, &ecsEnd, &pbMessage));
     }
 
     if (cacheHit) {
@@ -1808,6 +1814,8 @@
   dc->d_data = data;
   dc->d_ecsFound = ecsFound;
   dc->d_ecsParsed = ecsParsed;
+  dc->d_ecsBegin = ecsBegin;
+  dc->d_ecsEnd = ecsEnd;
   dc->d_ednssubnet = ednssubnet;
   dc->d_ttlCap = ttlCap;
   dc->d_variable = variable;
diff -ru pdns-recursor-4.1.4.orig/recpacketcache.cc pdns-recursor-4.1.4/recpacketcache.cc
--- pdns-recursor-4.1.4.orig/recpacketcache.cc	2018-08-31 13:29:26.000000000 +0200
+++ pdns-recursor-4.1.4/recpacketcache.cc	2018-10-09 16:08:34.075525011 +0200
@@ -43,19 +43,29 @@
   return count;
 }
 
-static bool qrMatch(const DNSName& qname, uint16_t qtype, uint16_t qclass, const DNSName& rname, uint16_t rtype, uint16_t rclass)
+bool RecursorPacketCache::qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint16_t ecsBegin, uint16_t ecsEnd)
 {
-  // this ignores checking on the EDNS subnet flags! 
-  return qname==rname && rtype == qtype && rclass == qclass;
+   // this ignores checking on the EDNS subnet flags! 
+  if (qname != iter->d_name || iter->d_type != qtype || iter->d_class != qclass) {
+    return false;
+  }
+
+  if (iter->d_ecsBegin != ecsBegin || iter->d_ecsEnd != ecsEnd) {
+    return false;
+  }
+
+  return queryMatches(iter->d_query, queryPacket, qname, ecsBegin, ecsEnd);
 }
 
-bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage)
+bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage, uint16_t ecsBegin, uint16_t ecsEnd)
 {
-  for(auto iter = range.first ; iter != range.second ; ++ iter) {
+  for(auto iter = range.first ; iter != range.second ; ++iter) {
     // the possibility is VERY real that we get hits that are not right - birthday paradox
-    if(!qrMatch(qname, qtype, qclass, iter->d_name, iter->d_type, iter->d_class))
+    if (!qrMatch(iter, queryPacket, qname, qtype, qclass, ecsBegin, ecsEnd)) {
       continue;
-    if(now < iter->d_ttd) { // it is right, it is fresh!
+    }
+
+    if (now < iter->d_ttd) { // it is right, it is fresh!
       *age = static_cast<uint32_t>(now - iter->d_creation);
       *responsePacket = iter->d_packet;
       responsePacket->replace(0, 2, queryPacket.c_str(), 2);
@@ -93,19 +103,25 @@
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now,
                                             std::string* responsePacket, uint32_t* age, uint32_t* qhash)
 {
-  return getResponsePacket(tag, queryPacket, now, responsePacket, age, qhash, nullptr);
+  DNSName qname;
+  uint16_t qtype, qclass;
+  uint16_t ecsBegin;
+  uint16_t ecsEnd;
+  return getResponsePacket(tag, queryPacket, qname, &qtype, &qclass, now, responsePacket, age, qhash, &ecsBegin, &ecsEnd, nullptr);
 }
 
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
                                             std::string* responsePacket, uint32_t* age, uint32_t* qhash)
 {
-  return getResponsePacket(tag, queryPacket, qname, qtype, qclass, now, responsePacket, age, qhash, nullptr);
+  uint16_t ecsBegin;
+  uint16_t ecsEnd;
+  return getResponsePacket(tag, queryPacket, qname, qtype, qclass, now, responsePacket, age, qhash, &ecsBegin, &ecsEnd, nullptr);
 }
 
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
-                                            std::string* responsePacket, uint32_t* age, uint32_t* qhash, RecProtoBufMessage* protobufMessage)
+                                            std::string* responsePacket, uint32_t* age, uint32_t* qhash, uint16_t* ecsBegin, uint16_t* ecsEnd, RecProtoBufMessage* protobufMessage)
 {
-  *qhash = canHashPacket(queryPacket, true);
+  *qhash = canHashPacket(queryPacket, ecsBegin, ecsEnd);
   const auto& idx = d_packetCache.get<HashTag>();
   auto range = idx.equal_range(tie(tag,*qhash));
 
@@ -114,13 +130,13 @@
     return false;
   }
 
-  return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, protobufMessage);
+  return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, protobufMessage, *ecsBegin, *ecsEnd);
 }
 
-bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now,
-                                            std::string* responsePacket, uint32_t* age, uint32_t* qhash, RecProtoBufMessage* protobufMessage)
+bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now,
+                                            std::string* responsePacket, uint32_t* age, uint32_t* qhash, uint16_t* ecsBegin, uint16_t* ecsEnd, RecProtoBufMessage* protobufMessage)
 {
-  *qhash = canHashPacket(queryPacket, true);
+  *qhash = canHashPacket(queryPacket, ecsBegin, ecsEnd);
   const auto& idx = d_packetCache.get<HashTag>();
   auto range = idx.equal_range(tie(tag,*qhash));
 
@@ -129,30 +145,33 @@
     return false;
   }
 
-  uint16_t qtype, qclass;
-  DNSName qname(queryPacket.c_str(), queryPacket.length(), sizeof(dnsheader), false, &qtype, &qclass, 0);
+  qname = DNSName(queryPacket.c_str(), queryPacket.length(), sizeof(dnsheader), false, qtype, qclass, 0);
 
-  return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, protobufMessage);
+  return checkResponseMatches(range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, protobufMessage, *ecsBegin, *ecsEnd);
 }
 
 
-void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl)
+void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, const std::string& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, uint16_t ecsBegin, uint16_t ecsEnd)
 {
-  insertResponsePacket(tag, qhash, qname, qtype, qclass, responsePacket, now, ttl, nullptr);
+  insertResponsePacket(tag, qhash, query, qname, qtype, qclass, responsePacket, now, ttl, ecsBegin, ecsEnd, nullptr);
 }
 
-void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, const RecProtoBufMessage* protobufMessage)
+void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, const std::string& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, uint16_t ecsBegin, uint16_t ecsEnd, const RecProtoBufMessage* protobufMessage)
 {
   auto& idx = d_packetCache.get<HashTag>();
   auto range = idx.equal_range(tie(tag,qhash));
   auto iter = range.first;
 
   for( ; iter != range.second ; ++iter)  {
-    if(iter->d_type != qtype || iter->d_class != qclass || iter->d_name != qname)
+    if (iter->d_type != qtype || iter->d_class != qclass || iter->d_name != qname) {
       continue;
+    }
 
     moveCacheItemToBack(d_packetCache, iter);
     iter->d_packet = responsePacket;
+    iter->d_query = query;
+    iter->d_ecsBegin = ecsBegin;
+    iter->d_ecsEnd = ecsEnd;
     iter->d_ttd = now + ttl;
     iter->d_creation = now;
 #ifdef HAVE_PROTOBUF
@@ -165,10 +184,10 @@
   }
   
   if(iter == range.second) { // nothing to refresh
-    struct Entry e;
-    e.d_packet = responsePacket;
-    e.d_name = qname;
+    struct Entry e(qname, responsePacket, query);
     e.d_qhash = qhash;
+    e.d_ecsBegin = ecsBegin;
+    e.d_ecsEnd = ecsEnd;
     e.d_type = qtype;
     e.d_class = qclass;
     e.d_ttd = now+ttl;
diff -ru pdns-recursor-4.1.4.orig/recpacketcache.hh pdns-recursor-4.1.4/recpacketcache.hh
--- pdns-recursor-4.1.4.orig/recpacketcache.hh	2018-08-31 13:29:26.000000000 +0200
+++ pdns-recursor-4.1.4/recpacketcache.hh	2018-10-09 15:55:25.123754381 +0200
@@ -57,9 +57,10 @@
   bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
   bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash, RecProtoBufMessage* protobufMessage);
   bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
-  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash, RecProtoBufMessage* protobufMessage);
-  void insertResponsePacket(unsigned int tag, uint32_t qhash, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl);
-  void insertResponsePacket(unsigned int tag, uint32_t qhash, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, const RecProtoBufMessage* protobufMessage);
+  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash, uint16_t* ecsBegin, uint16_t* ecsEnd, RecProtoBufMessage* protobufMessage);
+  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash, uint16_t* ecsBegin, uint16_t* ecsEnd, RecProtoBufMessage* protobufMessage);
+  void insertResponsePacket(unsigned int tag, uint32_t qhash, const std::string& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, uint16_t ecsBegin, uint16_t ecsEnd);
+  void insertResponsePacket(unsigned int tag, uint32_t qhash, const std::string& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& responsePacket, time_t now, uint32_t ttl, uint16_t ecsBegin, uint16_t ecsEnd, const RecProtoBufMessage* protobufMessage);
   void doPruneTo(unsigned int maxSize=250000);
   uint64_t doDump(int fd);
   int doWipePacketCache(const DNSName& name, uint16_t qtype=0xffff, bool subtree=false);
@@ -74,17 +75,23 @@
   struct NameTag {};
   struct Entry 
   {
-    mutable time_t d_ttd;
-    mutable time_t d_creation; // so we can 'age' our packets
+    Entry(const DNSName& qname, const std::string& packet, const std::string& query): d_name(qname), d_packet(packet), d_query(query)
+    {
+    }
     DNSName d_name;
-    uint16_t d_type;
-    uint16_t d_class;
     mutable std::string d_packet; // "I know what I am doing"
+    mutable std::string d_query;
 #ifdef HAVE_PROTOBUF
     mutable RecProtoBufMessage d_protobufMessage;
 #endif
+    mutable time_t d_ttd;
+    mutable time_t d_creation; // so we can 'age' our packets
     uint32_t d_qhash;
     uint32_t d_tag;
+    uint16_t d_type;
+    uint16_t d_class;
+    mutable uint16_t d_ecsBegin;
+    mutable uint16_t d_ecsEnd;
     inline bool operator<(const struct Entry& rhs) const;
     
     time_t getTTD() const
@@ -104,7 +111,8 @@
   
   packetCache_t d_packetCache;
 
-  bool checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage);
+  static bool qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint16_t ecsBegin, uint16_t ecsEnd);
+  bool checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage, uint16_t ecsBegin, uint16_t ecsEnd);
 
 public:
   void preRemoval(const Entry& entry)
diff -ru pdns-recursor-4.1.4.orig/test-recpacketcache_cc.cc pdns-recursor-4.1.4/test-recpacketcache_cc.cc
--- pdns-recursor-4.1.4.orig/test-recpacketcache_cc.cc	2018-08-31 13:29:26.000000000 +0200
+++ pdns-recursor-4.1.4/test-recpacketcache_cc.cc	2018-10-09 15:58:40.458387552 +0200
@@ -41,16 +41,17 @@
   pw.commit();
   string rpacket((const char*)&packet[0], packet.size());
 
-  rpc.insertResponsePacket(tag, qhash, qname, QType::A, QClass::IN, rpacket, time(0), ttd);
+  rpc.insertResponsePacket(tag, qhash, qpacket, qname, QType::A, QClass::IN, rpacket, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
   rpc.doPruneTo(0);
   BOOST_CHECK_EQUAL(rpc.size(), 0);
-  rpc.insertResponsePacket(tag, qhash, qname, QType::A, QClass::IN, rpacket, time(0), ttd);
+  rpc.insertResponsePacket(tag, qhash, qpacket, qname, QType::A, QClass::IN, rpacket, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
   rpc.doWipePacketCache(qname);
   BOOST_CHECK_EQUAL(rpc.size(), 0);
 
-  rpc.insertResponsePacket(tag, qhash, qname, QType::A, QClass::IN, rpacket, time(0), ttd);
+  rpc.insertResponsePacket(tag, qhash, qpacket, qname, QType::A, QClass::IN, rpacket, time(0), ttd, 0, 0);
+  BOOST_CHECK_EQUAL(rpc.size(), 1);
   uint32_t qhash2 = 0;
   bool found = rpc.getResponsePacket(tag, qpacket, time(nullptr), &fpacket, &age, &qhash2);
   BOOST_CHECK_EQUAL(found, true);
@@ -132,11 +133,11 @@
   BOOST_CHECK(r1packet != r2packet);
 
   /* inserting a response for tag1 */
-  rpc.insertResponsePacket(tag1, qhash, qname, QType::A, QClass::IN, r1packet, time(0), ttd);
+  rpc.insertResponsePacket(tag1, qhash, qpacket, qname, QType::A, QClass::IN, r1packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
 
   /* inserting a different response for tag2, should not override the first one */
-  rpc.insertResponsePacket(tag2, qhash, qname, QType::A, QClass::IN, r2packet, time(0), ttd);
+  rpc.insertResponsePacket(tag2, qhash, qpacket, qname, QType::A, QClass::IN, r2packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 2);
 
   /* remove all responses from the cache */
@@ -144,10 +145,10 @@
   BOOST_CHECK_EQUAL(rpc.size(), 0);
 
   /* reinsert both */
-  rpc.insertResponsePacket(tag1, qhash, qname, QType::A, QClass::IN, r1packet, time(0), ttd);
+  rpc.insertResponsePacket(tag1, qhash, qpacket, qname, QType::A, QClass::IN, r1packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
 
-  rpc.insertResponsePacket(tag2, qhash, qname, QType::A, QClass::IN, r2packet, time(0), ttd);
+  rpc.insertResponsePacket(tag2, qhash, qpacket, qname, QType::A, QClass::IN, r2packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 2);
 
   /* remove the responses by qname, should remove both */
@@ -155,7 +156,7 @@
   BOOST_CHECK_EQUAL(rpc.size(), 0);
 
   /* insert the response for tag1 */
-  rpc.insertResponsePacket(tag1, qhash, qname, QType::A, QClass::IN, r1packet, time(0), ttd);
+  rpc.insertResponsePacket(tag1, qhash, qpacket, qname, QType::A, QClass::IN, r1packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
 
   /* we can retrieve it */
@@ -174,7 +175,7 @@
   BOOST_CHECK_EQUAL(temphash, qhash);
 
   /* adding a response for the second tag */
-  rpc.insertResponsePacket(tag2, qhash, qname, QType::A, QClass::IN, r2packet, time(0), ttd);
+  rpc.insertResponsePacket(tag2, qhash, qpacket, qname, QType::A, QClass::IN, r2packet, time(0), ttd, 0, 0);
   BOOST_CHECK_EQUAL(rpc.size(), 2);
 
   /* We still get the correct response for the first tag */
