message_entry.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // $Id$
  15. #include <config.h>
  16. #include <limits>
  17. #include <dns/message.h>
  18. #include <nsas/nsas_entry.h>
  19. #include "message_entry.h"
  20. #include "message_utility.h"
  21. #include "rrset_cache.h"
  22. using namespace isc::dns;
  23. using namespace std;
  24. namespace isc {
  25. namespace cache {
  26. static uint32_t MAX_UINT32 = numeric_limits<uint32_t>::max();
  27. MessageEntry::MessageEntry(const isc::dns::Message& msg,
  28. boost::shared_ptr<RRsetCache> rrset_cache,
  29. boost::shared_ptr<RRsetCache> negative_soa_cache):
  30. rrset_cache_(rrset_cache),
  31. negative_soa_cache_(negative_soa_cache),
  32. headerflag_aa_(false),
  33. headerflag_tc_(false)
  34. {
  35. initMessageEntry(msg);
  36. entry_name_ = genCacheEntryName(query_name_, query_type_);
  37. hash_key_ptr_ = new HashKey(entry_name_, RRClass(query_class_));
  38. }
  39. bool
  40. MessageEntry::getRRsetEntries(vector<RRsetEntryPtr>& rrset_entry_vec,
  41. const time_t time_now)
  42. {
  43. uint16_t entry_count = answer_count_ + authority_count_ + additional_count_;
  44. rrset_entry_vec.reserve(rrset_entry_vec.size() + entry_count);
  45. for (int index = 0; index < entry_count; ++index) {
  46. boost::shared_ptr<RRsetCache> rrset_cache = rrsets_[index].cache_;
  47. RRsetEntryPtr rrset_entry = rrset_cache->lookup(rrsets_[index].name_,
  48. rrsets_[index].type_);
  49. if (time_now < rrset_entry->getExpireTime()) {
  50. rrset_entry_vec.push_back(rrset_entry);
  51. } else {
  52. return (false);
  53. }
  54. }
  55. return (true);
  56. }
  57. void
  58. MessageEntry::addRRset(isc::dns::Message& message,
  59. const vector<RRsetEntryPtr>& rrset_entry_vec,
  60. const isc::dns::Message::Section& section,
  61. bool dnssec_need)
  62. {
  63. uint16_t start_index = 0;
  64. uint16_t end_index = answer_count_;
  65. assert(section != Message::SECTION_QUESTION);
  66. if (section == Message::SECTION_AUTHORITY) {
  67. start_index = answer_count_;
  68. end_index = answer_count_ + authority_count_;
  69. } else if (section == Message::SECTION_ADDITIONAL) {
  70. start_index = answer_count_ + authority_count_;
  71. end_index = start_index + additional_count_;
  72. }
  73. for (uint16_t index = start_index; index < end_index; ++index) {
  74. message.addRRset(section, rrset_entry_vec[index]->getRRset(), dnssec_need);
  75. }
  76. }
  77. bool
  78. MessageEntry::genMessage(const time_t& time_now,
  79. isc::dns::Message& msg)
  80. {
  81. if (time_now >= expire_time_) {
  82. // The message entry has expired.
  83. return (false);
  84. } else {
  85. // Before do any generation, we should check if some rrset
  86. // has expired, if it is, return false.
  87. vector<RRsetEntryPtr> rrset_entry_vec;
  88. if (false == getRRsetEntries(rrset_entry_vec, time_now)) {
  89. return (false);
  90. }
  91. // Begin message generation. We don't need to add question
  92. // section, since it has been included in the message.
  93. // Set cached header flags.
  94. msg.setHeaderFlag(Message::HEADERFLAG_AA, headerflag_aa_);
  95. msg.setHeaderFlag(Message::HEADERFLAG_TC, headerflag_tc_);
  96. bool dnssec_need = msg.getEDNS().get();
  97. addRRset(msg, rrset_entry_vec, Message::SECTION_ANSWER, dnssec_need);
  98. addRRset(msg, rrset_entry_vec, Message::SECTION_AUTHORITY, dnssec_need);
  99. addRRset(msg, rrset_entry_vec, Message::SECTION_ADDITIONAL, dnssec_need);
  100. return (true);
  101. }
  102. }
  103. RRsetTrustLevel
  104. MessageEntry::getRRsetTrustLevel(const Message& message,
  105. const isc::dns::RRsetPtr& rrset,
  106. const isc::dns::Message::Section& section)
  107. {
  108. bool aa = message.getHeaderFlag(Message::HEADERFLAG_AA);
  109. switch(section) {
  110. case Message::SECTION_ANSWER: {
  111. if (aa) {
  112. RRsetIterator rrset_iter = message.beginSection(section);
  113. // Make sure we are inspecting the right RRset
  114. while((*rrset_iter)->getName() != rrset->getName() &&
  115. (*rrset_iter)->getType() != rrset->getType() &&
  116. rrset_iter != message.endSection(section)) {
  117. ++rrset_iter;
  118. }
  119. assert(rrset_iter != message.endSection(section));
  120. // According RFC2181 section 5.4.1, only the record
  121. // describing that ailas is necessarily authoritative.
  122. // If there is one or more CNAME records in answer section.
  123. // CNAME records is assumed as the first rrset.
  124. if ((*rrset_iter)->getType() == RRType::CNAME()) {
  125. // TODO: real equals for RRsets?
  126. if ((*rrset_iter).get() == rrset.get()) {
  127. return (RRSET_TRUST_ANSWER_AA);
  128. } else {
  129. return (RRSET_TRUST_ANSWER_NONAA);
  130. }
  131. }
  132. // Here, if the first rrset is DNAME, then assume the
  133. // second rrset is synchronized CNAME record, except
  134. // these two records, any other records in answer section
  135. // should be treated as non-authoritative.
  136. // TODO, this part logic should be revisited later,
  137. // since it's not mentioned by RFC2181.
  138. if ((*rrset_iter)->getType() == RRType::DNAME()) {
  139. // TODO: real equals for RRsets?
  140. if ((*rrset_iter).get() == rrset.get() ||
  141. ((++rrset_iter) != message.endSection(section) &&
  142. (*rrset_iter).get() == rrset.get())) {
  143. return (RRSET_TRUST_ANSWER_AA);
  144. } else {
  145. return (RRSET_TRUST_ANSWER_NONAA);
  146. }
  147. }
  148. return (RRSET_TRUST_ANSWER_AA);
  149. } else {
  150. return (RRSET_TRUST_ANSWER_NONAA);
  151. }
  152. break;
  153. }
  154. case Message::SECTION_AUTHORITY: {
  155. if (aa) {
  156. return (RRSET_TRUST_AUTHORITY_AA);
  157. } else {
  158. return (RRSET_TRUST_AUTHORITY_NONAA);
  159. }
  160. break;
  161. }
  162. case Message::SECTION_ADDITIONAL: {
  163. if (aa) {
  164. return (RRSET_TRUST_ADDITIONAL_AA);
  165. } else {
  166. return (RRSET_TRUST_ADDITIONAL_NONAA);
  167. }
  168. break;
  169. }
  170. default:
  171. return (RRSET_TRUST_DEFAULT);
  172. }
  173. }
  174. void
  175. MessageEntry::parseSection(const isc::dns::Message& msg,
  176. const Message::Section& section,
  177. uint32_t& smaller_ttl,
  178. uint16_t& rrset_count)
  179. {
  180. RRsetIterator iter;
  181. int count = 0;
  182. for (iter = msg.beginSection(section);
  183. iter != msg.endSection(section);
  184. ++iter) {
  185. // Add the rrset entry to rrset_cache or update the existed
  186. // rrset entry if the new one is more authoritative.
  187. //TODO set proper rrset trust level.
  188. RRsetPtr rrset_ptr = *iter;
  189. RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, section);
  190. RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
  191. rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), rrset_cache_));
  192. uint32_t rrset_ttl = rrset_entry->getTTL();
  193. if (smaller_ttl > rrset_ttl) {
  194. smaller_ttl = rrset_ttl;
  195. }
  196. count++;
  197. }
  198. rrset_count = count;
  199. }
  200. void
  201. MessageEntry::parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
  202. uint32_t& min_ttl,
  203. uint16_t& rrset_count)
  204. {
  205. // We found the SOA record, so we can cache the message and RRsets in the cache
  206. uint16_t count = 0;
  207. for (RRsetIterator iter = msg.beginSection(Message::SECTION_AUTHORITY);
  208. iter != msg.endSection(Message::SECTION_AUTHORITY);
  209. ++iter) {
  210. RRsetPtr rrset_ptr = *iter;
  211. RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr,
  212. Message::SECTION_AUTHORITY);
  213. boost::shared_ptr<RRsetCache> rrset_cache_ptr = rrset_cache_;
  214. if (rrset_ptr->getType() == RRType::SOA()) {
  215. rrset_cache_ptr = negative_soa_cache_;
  216. }
  217. RRsetEntryPtr rrset_entry = rrset_cache_ptr->update(*rrset_ptr, level);
  218. rrsets_.push_back(RRsetRef(rrset_ptr->getName(),
  219. rrset_ptr->getType(),
  220. rrset_cache_ptr));
  221. uint32_t rrset_ttl = rrset_entry->getTTL();
  222. if (min_ttl > rrset_ttl) {
  223. min_ttl = rrset_ttl;
  224. }
  225. ++count;
  226. }
  227. rrset_count = count;
  228. }
  229. void
  230. MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
  231. //TODO better way to cache the header flags?
  232. headerflag_aa_ = msg.getHeaderFlag(Message::HEADERFLAG_AA);
  233. headerflag_tc_ = msg.getHeaderFlag(Message::HEADERFLAG_TC);
  234. // We only cache the first question in question section.
  235. // TODO, do we need to support muptiple questions?
  236. query_count_ = 1;
  237. QuestionIterator iter = msg.beginQuestion();
  238. query_name_ = (*iter)->getName().toText();
  239. query_type_ = (*iter)->getType().getCode();
  240. query_class_ = (*iter)->getClass().getCode();
  241. uint32_t min_ttl = MAX_UINT32;
  242. parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
  243. if (!MessageUtility::isNegativeResponse(msg)){
  244. parseSection(msg, Message::SECTION_AUTHORITY, min_ttl, authority_count_);
  245. } else {
  246. parseNegativeResponseAuthoritySection(msg, min_ttl, authority_count_);
  247. }
  248. parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
  249. expire_time_ = time(NULL) + min_ttl;
  250. }
  251. } // namespace cache
  252. } // namespace isc