Browse Source

[trac493] Process the NXDOMAIN response in the MessageEntry

Ocean Wang 14 years ago
parent
commit
cc7a7fb930
2 changed files with 96 additions and 10 deletions
  1. 74 7
      src/lib/cache/message_entry.cc
  2. 22 3
      src/lib/cache/message_entry.h

+ 74 - 7
src/lib/cache/message_entry.cc

@@ -18,6 +18,7 @@
 
 #include <limits>
 #include <dns/message.h>
+#include <dns/rcode.h>
 #include <nsas/nsas_entry.h>
 #include "message_entry.h"
 #include "rrset_cache.h"
@@ -50,7 +51,8 @@ MessageEntry::getRRsetEntries(vector<RRsetEntryPtr>& rrset_entry_vec,
     uint16_t entry_count = answer_count_ + authority_count_ + additional_count_;
     rrset_entry_vec.reserve(rrset_entry_vec.size() + entry_count);
     for (int index = 0; index < entry_count; ++index) {
-        RRsetEntryPtr rrset_entry = rrset_cache_->lookup(rrsets_[index].name_,
+        boost::shared_ptr<RRsetCache> rrset_cache = rrsets_[index].cache_; 
+        RRsetEntryPtr rrset_entry = rrset_cache->lookup(rrsets_[index].name_,
                                                         rrsets_[index].type_);
         if (time_now < rrset_entry->getExpireTime()) {
             rrset_entry_vec.push_back(rrset_entry);
@@ -212,7 +214,7 @@ MessageEntry::parseSection(const isc::dns::Message& msg,
         RRsetPtr rrset_ptr = *iter;
         RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, section);
         RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
-        rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType()));
+        rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), rrset_cache_));
 
         uint32_t rrset_ttl = rrset_entry->getTTL();
         if (smaller_ttl > rrset_ttl) {
@@ -226,6 +228,48 @@ MessageEntry::parseSection(const isc::dns::Message& msg,
 }
 
 void
+MessageEntry::parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
+        uint32_t& soa_ttl,
+        uint16_t& rrset_count,
+        bool& found_soa)
+{
+    RRsetIterator iter;
+    for(iter = msg.beginSection(Message::SECTION_AUTHORITY);
+            iter != msg.endSection(Message::SECTION_AUTHORITY);
+            ++iter){
+        RRsetPtr rrset_ptr = *iter;
+        if (rrset_ptr->getType() == RRType::SOA()){
+            found_soa = true;
+            break;
+        }
+    }
+    if(!found_soa){
+        return;
+    }
+
+    // We found the SOA record, so we can cache the message and RRsets in the cache
+    uint16_t count = 0;
+    for(iter = msg.beginSection(Message::SECTION_AUTHORITY);
+            iter != msg.endSection(Message::SECTION_AUTHORITY);
+            ++iter){
+        RRsetPtr rrset_ptr = *iter;
+        RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, Message::SECTION_AUTHORITY);
+        if (rrset_ptr->getType() == RRType::SOA()){
+            soa_ttl = rrset_ptr->getTTL().getValue();
+            RRsetEntryPtr rrset_entry = negative_soa_cache_->update(*rrset_ptr, level);
+            rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), negative_soa_cache_));
+        } else {
+            RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
+            rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), rrset_cache_));
+        }
+
+        ++count;
+    }
+
+    rrset_count = count;
+}
+
+void
 MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
     //TODO better way to cache the header flags?
     headerflag_aa_ = msg.getHeaderFlag(Message::HEADERFLAG_AA);
@@ -239,12 +283,35 @@ MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
     query_type_ = (*iter)->getType().getCode();
     query_class_ = (*iter)->getClass().getCode();
 
-    uint32_t min_ttl = MAX_UINT32;
-    parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
-    parseSection(msg, Message::SECTION_AUTHORITY, min_ttl, authority_count_);
-    parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
+    if (!isNegativeResponse(msg)){
+        uint32_t min_ttl = MAX_UINT32;
+        parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
+        parseSection(msg, Message::SECTION_AUTHORITY, min_ttl, authority_count_);
+        parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
+        expire_time_ = time(NULL) + min_ttl;
+    } else {
+        uint32_t min_ttl = MAX_UINT32;
+        uint32_t soa_ttl = MAX_UINT32;
+        bool found_soa = false;
+        uint16_t rrset_count = 0;
+        parseNegativeResponseAuthoritySection(msg, soa_ttl, rrset_count, found_soa);
+        // For negative response, if no soa RRset is found, dont cache it
+        if(!found_soa) {
+            return;
+        }
+        authority_count_ = rrset_count;
+        parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
+        parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
 
-    expire_time_ = time(NULL) + min_ttl;
+        expire_time_ = time(NULL) + soa_ttl;
+    }
+
+}
+
+bool
+MessageEntry::isNegativeResponse(const isc::dns::Message& msg)
+{
+    return msg.getRcode() == Rcode::NXDOMAIN();
 }
 
 } // namespace cache

+ 22 - 3
src/lib/cache/message_entry.h

@@ -40,13 +40,16 @@ struct RRsetRef{
     /// \brief Constructor
     ///
     /// \param name The Name for the RRset
-    /// \param type the RRType for the RRrset
-    RRsetRef(const isc::dns::Name& name, const isc::dns::RRType& type):
-            name_(name), type_(type)
+    /// \param type The RRType for the RRrset
+    /// \param cache Which cache the RRset is stored in
+    RRsetRef(const isc::dns::Name& name, const isc::dns::RRType& type,
+            boost::shared_ptr<RRsetCache> cache):
+            name_(name), type_(type), cache_(cache)
     {}
 
     isc::dns::Name name_; // Name of rrset.
     isc::dns::RRType type_; // Type of rrset.
+    boost::shared_ptr<RRsetCache> cache_; //Which cache the RRset is stored
 };
 
 /// \brief Message Entry
@@ -115,6 +118,18 @@ protected:
                       uint32_t& smaller_ttl,
                       uint16_t& rrset_count);
 
+    /// \brief Parse the RRsets in the authority section of
+    ///        negative response. The SOA RRset need to be located and
+    ///        stored in a seperate cache
+    /// \param msg The message to parse the RRsets from
+    /// \param soa_ttl Get the ttl of soa rrset in the authority section
+    /// \param rrset_count the rrset count of the authority section
+    /// \param found_soa whether the soa RRset is found in the authority section
+    void parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
+            uint32_t& soa_ttl,
+            uint16_t& rrset_count,
+            bool& found_soa);
+
     /// \brief Get RRset Trustworthiness
     ///        The algorithm refers to RFC2181 section 5.4.1
     ///        Only the rrset can be updated by the rrsets
@@ -155,6 +170,10 @@ protected:
     //@}
 
 private:
+    /// \brief Check whetehr the message is a negative response(NXDOMAIN or NOERROR_NODATA)
+    ///
+    bool isNegativeResponse(const isc::dns::Message& msg);
+
     std::string entry_name_; // The name for this entry(name + type)
     HashKey* hash_key_ptr_;  // the key for messag entry in hash table.