#include <dns/buffer.h> #include <dns/name.h> #include <dns/rrset.h> #include <dns/message.h> #include <cc/data.h> #include "data_source.h" namespace isc { namespace dns { DSResult DataSrc::runQuery(Query q) { DSResult result; Name container("."); Message& m = q.message(); while (!q.tasks().empty()) { RRsetList data, sigs; bool found = false; QueryTaskPtr task = q.tasks().front(); q.tasks().pop(); const DataSrc* ds = findClosestEnclosure(task->qname, container, found); if (ds == NULL) { result = ZONE_NOT_FOUND; } else if (q.wantDnssec()) { result = ds->findRRset(task->qname, task->qclass, task->qtype, data, sigs); // XXX validity check: // for now, there must only be exactly one RRset in data // and no more than one RRset in sigs. the rrtype of data // must match the sigtype of sigs, if any } else { result = ds->findRRset(task->qname, task->qclass, task->qtype, data); } switch (result) { case SUCCESS: // XXX: what if 'data' contains more than one RRset? m.addRRset(task->section, data[0]); if (q.wantDnssec() && sigs.size() == 1) { m.addRRset(Section(task->section), sigs[0]); } if (q.status() == QUERY_FINISHING) { q.setStatus(QUERY_DONE); return (SUCCESS); } // if there are no more work items, add the authority section if (q.tasks().empty() && q.status() == QUERY_INCOMPLETE) { QueryTask *qt = new QueryTask(container, task->qclass, RRType::NS(), Section::AUTHORITY()); q.tasks().push(QueryTaskPtr(qt)); q.setStatus(QUERY_FINISHING); } continue; case CNAME: m.addRRset(task->section, data[0]); if (q.wantDnssec() && sigs.size() == 1) { m.addRRset(Section(task->section), sigs[0]); } // if (data[0].getType() == RRType::CNAME()) { // // take apart the CNAME rdata and re-query HERE // } continue; case NAME_NOT_FOUND: q.setStatus(QUERY_NODATA); if (q.wantDnssec()) { result = ds->findRRset(container, task->qclass, RRType::SOA(), data, sigs); } else { result = ds->findRRset(container, task->qclass, RRType::SOA(), data); } if (result != SUCCESS) { m.setRcode(Rcode::SERVFAIL()); return (ERROR); } m.setRcode(Rcode::NXDOMAIN()); m.addRRset(Section::AUTHORITY(), data[0]); if (q.wantDnssec() && sigs.size() == 1) { m.addRRset(Section::AUTHORITY(), sigs[0]); } break; case TYPE_NOT_FOUND: m.setRcode(Rcode::NOERROR()); q.setStatus(QUERY_NODATA); return (result); case ZONE_NOT_FOUND: m.setRcode(Rcode::REFUSED()); q.setStatus(QUERY_NODATA); return (result); default: m.setRcode(Rcode::SERVFAIL()); q.setStatus(QUERY_NODATA); return (result); } } return (result); }; } }