Browse Source

[trac505] DNAME handling and CNAME synthesis

Michal 'vorner' Vaner 14 years ago
parent
commit
fb4ca10d60
1 changed files with 43 additions and 9 deletions
  1. 43 9
      src/bin/auth/query.cc

+ 43 - 9
src/bin/auth/query.cc

@@ -144,10 +144,47 @@ Query::process() const {
     while (keep_doing) {
         keep_doing = false;
         std::auto_ptr<RRsetList> target(qtype_is_any ? new RRsetList : NULL);
-        Zone::FindResult db_result =
-            result.zone->find(qname_, qtype_, target.get());
+        /*
+         * We use the rrset, not db_result.rrset because we might replace
+         * it while synthetizing the CNAME out of DNAME. The db_result is
+         * imutable, so we have a different variable.
+         */
+        Zone::FindResult db_result(result.zone->find(qname_, qtype_,
+            target.get()));
+        ConstRRsetPtr rrset(db_result.rrset);
 
         switch (db_result.code) {
+            case Zone::DNAME: {
+                // First, put the dname into the answer
+                response_.addRRset(Message::SECTION_ANSWER,
+                    boost::const_pointer_cast<RRset>(rrset));
+                /*
+                 * We synthetize CNAME out of it, replace the rrset and let
+                 * the CNAME case handle it (including future chaining).
+                 * Therefore, we just fall trough to it.
+                 */
+                /*
+                 * Empty DNAME should never get in, as it is impossible to
+                 * create one in master file.
+                 */
+                assert(rrset->getRdataCount() > 0);
+                // Get the data of DNAME
+                const rdata::generic::DNAME& dname(
+                    dynamic_cast<const rdata::generic::DNAME&>(
+                    rrset->getRdataIterator()->getCurrent()));
+                // The new CNAME we are creating (it will be unsigned even
+                // with DNSSEC, the DNAME is signed and it can be validated
+                // by that)
+                RRsetPtr cname(new RRset(qname_, rrset->getClass(),
+                    RRType::CNAME(), rrset->getTTL()));
+                // Construct the new target by replacing the end
+                cname->addRdata(rdata::generic::CNAME(qname_.split(0,
+                    qname_.getLabelCount() -
+                    rrset->getName().getLabelCount()).concatenate(
+                    dname.getDname())));
+                rrset = cname;
+                // No break; here, fall trough.
+            }
             case Zone::CNAME:
                 /*
                  * We don't do chaining yet. Therefore handling a CNAME is
@@ -167,9 +204,9 @@ Query::process() const {
                     }
                 } else {
                     response_.addRRset(Message::SECTION_ANSWER,
-                        boost::const_pointer_cast<RRset>(db_result.rrset));
+                        boost::const_pointer_cast<RRset>(rrset));
                     // Handle additional for answer section
-                    getAdditional(*result.zone, *db_result.rrset);
+                    getAdditional(*result.zone, *rrset);
                 }
                 // If apex NS records haven't been provided in the answer
                 // section, insert apex NS records into the authority section
@@ -186,8 +223,8 @@ Query::process() const {
                 response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
                 response_.setRcode(Rcode::NOERROR());
                 response_.addRRset(Message::SECTION_AUTHORITY,
-                    boost::const_pointer_cast<RRset>(db_result.rrset));
-                getAdditional(*result.zone, *db_result.rrset);
+                    boost::const_pointer_cast<RRset>(rrset));
+                getAdditional(*result.zone, *rrset);
                 break;
             case Zone::NXDOMAIN:
                 // Just empty answer with SOA in authority section
@@ -199,9 +236,6 @@ Query::process() const {
                 response_.setRcode(Rcode::NOERROR());
                 putSOA(*result.zone);
                 break;
-            case Zone::DNAME:
-                // TODO : replace qname, continue lookup
-                break;
         }
     }
 }