]> granicus.if.org Git - pdns/commitdiff
move 'resolver.cc' to MOADNSParser, which allows us to rip out 'getAnswers' hideousit...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 18 Feb 2007 23:13:42 +0000 (23:13 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 18 Feb 2007 23:13:42 +0000 (23:13 +0000)
move assorted stuff to ComboAddress
teach DNSWriter about opcodes

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@962 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnspacket.cc
pdns/dnspacket.hh
pdns/dnsproxy.cc
pdns/dnswriter.cc
pdns/dnswriter.hh
pdns/resolver.cc

index fd61aea18c02d2f5d885895630c0af24ce45d39d..cee289bdf1fde531d638543c3be7999a46ebe948 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2001 - 2005  PowerDNS.COM BV
+    Copyright (C) 2001 - 2007  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as 
@@ -49,16 +49,6 @@ string DNSPacket::getString()
   return stringbuffer;
 }
 
-string DNSPacket::getLocal() const
-{
-  struct sockaddr_in6 sa;
-  int addrlen=sizeof(sa);
-
-  getsockname(d_socket, (struct sockaddr *)&sa, (socklen_t *)&addrlen);
-  return sockAddrToString((struct sockaddr_in*)&sa);
-}
-
-
 string DNSPacket::getRemote() const
 {
   return remote.toString();
@@ -130,7 +120,6 @@ int DNSPacket::expand(const unsigned char *begin, const unsigned char *end, stri
   // lowercase(qdomain); (why was this?)
   
   return p-begin;
-
 }
 
 /** copies the question into our class
@@ -203,7 +192,6 @@ void DNSPacket::setRD(bool b)
   d.rd=b;
 }
 
-
 void DNSPacket::setOpcode(uint16_t opcode)
 {
   d.opcode=opcode;
@@ -273,8 +261,6 @@ void DNSPacket::addAAAARecord(const DNSResourceRecord &rr)
      <<endl;
 }
 
-
-
 void DNSPacket::addAAAARecord(const string &name, unsigned char addr[16], uint32_t ttl,DNSResourceRecord::Place place)
 {
   string piece1;
@@ -296,7 +282,6 @@ void DNSPacket::addAAAARecord(const string &name, unsigned char addr[16], uint32
     d.ancount++;
 }
 
-
 void DNSPacket::addMXRecord(const DNSResourceRecord &rr)
 {
   addMXRecord(rr.qname, rr.content, rr.priority, rr.ttl);
@@ -1217,210 +1202,11 @@ void DNSPacket::setQuestion(int op, const string &qd, int newqtype)
 
 /** A DNS answer packets needs to include the original question. This function allows you to
     paste in a question */
-
 void DNSPacket::pasteQ(const char *question, int length)
 {
   stringbuffer.replace(12, length, question, length);  // bytes 12 & onward need to become *question
 }
 
-
-vector<DNSResourceRecord> DNSPacket::getAnswers()
-{
-  // XXX FIXME a lot of this code happily touches bytes beyond your packet! 
-
-  vector<DNSResourceRecord> rrs;
-  if(!(d.ancount|d.arcount|d.nscount))
-    return rrs;
-
-  const unsigned char *answerp=(const unsigned char *)stringbuffer.c_str()+d_qlen+12;
-  const unsigned char *end=(const unsigned char *)stringbuffer.c_str()+len;
-
-  int numanswers=ntohs(d.ancount) + ntohs(d.nscount) + ntohs(d.arcount);
-  int length;
-  uint16_t pos=0;
-  while(numanswers--) {
-    string name;  
-    int offset=0;
-    offset=expand(answerp,end,name);
-
-    DNSResourceRecord rr;
-    rr.qname=name;
-    rr.qtype=answerp[offset]*256+answerp[offset+1];
-    rr.ttl=answerp[offset+7]+256*(answerp[offset+6]+256*(answerp[offset+5]+256*answerp[offset+4]));
-    rr.content="";
-    length=256*(unsigned char)answerp[offset+8]+(unsigned char)answerp[offset+8+1];
-
-    const unsigned char *datapos=answerp+offset+10;
-
-    if(datapos+length  > end)
-      throw AhuException("Record extends beyond end of packet");
-
-    string part;
-    offset=0;
-
-    ostringstream o;
-    int ip;
-    int weight;
-    int port;
-
-    switch(rr.qtype.getCode()) {
-
-    case QType::SOA:
-      part=""; offset+=expand(datapos+offset,end,part); rr.content=part;      // mname
-      part=""; offset+=expand(datapos+offset,end,part); rr.content+=" "+part;  // hostmaster
-
-      // explicitly copy the SOA values out of the packet to avoid 
-      // SPARC alignment issues.
-      
-      rr.content+=" ";rr.content+=uitoa(getLong( datapos+offset    ));
-      rr.content+=" ";rr.content+=uitoa(getLong( datapos+offset+4  ));
-      rr.content+=" ";rr.content+=uitoa(getLong( datapos+offset+8  ));
-      rr.content+=" ";rr.content+=uitoa(getLong( datapos+offset+12 ));
-      rr.content+=" ";rr.content+=uitoa(getLong( datapos+offset+16 ));
-
-      break;
-
-    case QType::A:
-      ip = getLong(datapos);
-
-      o.clear();
-      o<<((ip>>24)&0xff)<<".";
-      o<<((ip>>16)&0xff)<<".";
-      o<<((ip>>8)&0xff)<<".";
-      o<<((ip>>0)&0xff);
-      
-      rr.content=o.str();
-      break;
-      
-    case QType::MX:
-      rr.priority=(datapos[0] << 8) + datapos[1];
-      expand(datapos+2,end,rr.content);
-
-      break;
-
-    case QType::TXT:
-      rr.content.assign((const char *)datapos+offset+1,(int)datapos[offset]);
-      break;
-
-    case QType::HINFO:  // this code is way way way overdue for a redesign
-      rr.content="\"";
-      rr.content.append((const char *)datapos+offset+1,(int)datapos[offset]);
-      rr.content+="\" \"";
-      rr.content.append((const char *)datapos+offset+(int)datapos[offset]+2,
-                       (int)datapos[offset+(int)datapos[offset]+1]);
-      rr.content+="\"";
-      break;
-
-
-    case QType::LOC:
-      rr.content=parseLOC(reinterpret_cast<const unsigned char *>(datapos+offset),length);
-      break;
-
-
-    case QType::SRV: // rfc 2052
-      // priority goes into mx-priority
-      rr.priority=(datapos[0] << 8) + datapos[1];
-      // rest glue together  
-      weight = (datapos[2] << 8) + datapos[3];
-      port = (datapos[4] << 8) + datapos[5];
-      expand(datapos+offset+6,end,part);
-      rr.content.assign(itoa(weight));
-      rr.content+=" "+itoa(port)+" "+part;
-      break;
-
-    case QType::NAPTR: // rfc 2915
-      {
-        const string quote="\"";
-        const string space=" ";
-
-        int order;
-        int pref;
-        string flags, services, regex, replacement, result;
-
-        order=(datapos[0] << 8) + datapos[1];
-
-        // "pref" should maybe be put into rr.priority, but that
-        // might have unintended side effects that I cannot
-        // evaluate at this time.
-        //
-        // Lorens Kockum 2004-10-12
-
-        pref=(datapos[2] << 8) + datapos[3];
-
-        // The following would be a good subject for a mini-
-        // function with boundary checking, which could be
-        // reused in a lot of places in this file (see FIXME
-        // at beginning of function).
-
-        offset = 4 ;
-        flags.assign((const char *)datapos+offset+1,(int)datapos[offset]);
-        offset+=flags.size()+1;
-        services.assign((const char *)datapos+offset+1,(int)datapos[offset]);
-        offset+=services.size()+1;
-        regex.assign((const char *)datapos+offset+1,(int)datapos[offset]);
-        offset+=regex.size()+1;
-
-        expand(datapos+offset,end,replacement);
-
-        if (!replacement.size()) replacement = "." ;
-
-        rr.content = itoa(order) \
-                     + " " + itoa(pref) \
-                     + " " + quote + flags + quote \
-                     + " " + quote + services + quote \
-                     + " " + quote + regex + quote \
-                     + " " + replacement;
-      }
-      break;
-
-    case QType::RP:
-      offset+=expand(datapos+offset,end,rr.content);
-      expand(datapos+offset,end,part);
-      rr.content+=" "+part;
-      break;
-
-
-    case QType::CNAME:
-    case QType::NS:
-    case QType::PTR:
-    case QType::MR:
-      expand(datapos+offset,end,rr.content);
-      break;
-
-    case QType::AAAA:
-      if(length!=16)
-       throw AhuException("Wrong length AAAA record returned from remote");
-      char tmp[128];
-#ifdef AF_INET6        
-      if(!Utility::inet_ntop(AF_INET6, (const char *)datapos, tmp, sizeof(tmp)-1))
-#endif
-       throw AhuException("Unable to translate record of type AAAA in resolver");
-
-      rr.content=tmp;
-      break;
-
-    default:
-      rr.qtype=rr.qtype.getCode()+1024;
-      rr.content.assign((const char *)datapos,length);
-      //      throw AhuException("Unknown type number "+itoa(rr.qtype.getCode())+" for: '"+rr.qname+"'");
-    }
-    if(pos<ntohs(d.ancount))
-      rr.d_place=DNSResourceRecord::ANSWER;
-    else if(pos<ntohs(d.ancount)+ntohs(d.nscount))
-      rr.d_place=DNSResourceRecord::AUTHORITY;
-    else
-      rr.d_place=DNSResourceRecord::ADDITIONAL;
-      
-    rrs.push_back(rr);    
-    pos++;
-    //    cout<<"Added '"<<rr.qname<<"' '"<<rr.content<<"' "<<rr.qtype.getName()<<endl;
-    //    cout<<"Advancing "<<length<<" bytes"<<endl;
-    answerp=datapos+length; 
-  }
-  return rrs;
-  
-}
-
 /** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
 DNSPacket *DNSPacket::replyPacket() const
 {
index d971d2a6a53f7d58481f31b2a66506e4d89a85eb..7dba11e6645e1bd92b24eaf965f04289bedc24d6 100644 (file)
@@ -85,48 +85,16 @@ public:
   inline int parse(const char *mesg, int len); //!< parse a raw UDP or TCP packet and suck the data inward
   string getString(); //!< for serialization - just passes the whole packet
 
-  //! the raw DNS header
-  struct dnsheader 
-  {
-    unsigned int id:16;  //!< id of this query/response
-#ifdef WORDS_BIGENDIAN     // ultrasparc
-    unsigned int qr:1;      //!< 1 if this is a query, 0 if response
-    unsigned int opcode:4;  //!< the opcode
-    unsigned int aa:1;   //!< packet contains authoritative data
-    unsigned int tc:1;   //!< packet is truncated
-    unsigned int rd:1;   //!< this packets wants us to recurse
-    unsigned int ra:1;     //!< ??
-    unsigned int unused:1; //!< 
-    unsigned int ad:1;     //!< authentic data
-    unsigned int cd:1;     //!< checking disabled by resolver
-    unsigned int rcode:4;  //!< ??
-#else
-    unsigned int rd:1;   //!< this packets wants us to recurse
-    unsigned int tc:1;   //!< packet is truncated
-    unsigned int aa:1;   //!< packet contains authoritative data
-    unsigned int opcode:4;  //!< the opcode
-    unsigned int qr:1;      //!< 1 if this is a query, 0 if response
-
-    /////////// 
-
-    unsigned int rcode:4;  //!< ??
-    unsigned int cd:1;     //!< checking disabled by resolver
-    unsigned int ad:1;     //!< authentic data
-    unsigned int unused:1; //!< 
-    unsigned int ra:1;     //!< recursion available
-#endif
-    ////////////////
-    
-    unsigned int qdcount:16;  //!< number of questions
-    unsigned int ancount:16;  //!< number of answers
-    unsigned int nscount:16;  //!< number of authoritative nameservers included in answer
-    unsigned int arcount:16;  //!< number of additional resource records
-  };
-
   // address & socket manipulation
   inline void setRemote(const ComboAddress*);
-  string getLocal() const;
   string getRemote() const;
+  string getLocal() const
+  {
+    ComboAddress ca;
+    socklen_t len=sizeof(ca);
+    getsockname(d_socket, (sockaddr*)&ca, &len);
+    return ca.toString();
+  }
   uint16_t getRemotePort() const;
 
   Utility::sock_t getSocket() const
@@ -154,7 +122,6 @@ public:
   void addRecord(const DNSResourceRecord &);  // adds to 'rrs'
 
   void setQuestion(int op, const string &qdomain, int qtype);  // wipes 'd', sets a random id, creates start of packet (label, type, class etc)
-  vector<DNSResourceRecord> getAnswers(); // this can be called only when a packet has been parsed
 
   DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer
   void wrapup(void);  // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer
index b2567bf69bcd0b24308bae96152712d7ea1a6d77..768ddb114b2bba71c1defbff60740baa419334ef 100644 (file)
@@ -167,7 +167,7 @@ void DNSProxy::mainloop(void)
       }
       (*d_resanswers)++;
       (*d_udpanswers)++;
-      DNSPacket::dnsheader d;
+      dnsheader d;
       memcpy(&d,buffer,sizeof(d));
       {
        Lock l(&d_lock);
index 1a2f41951b5bf8d476215b939158d43165eff6d2..d0d26a7ea99a3678c415d0be1326155a9a40c943 100644 (file)
@@ -2,7 +2,7 @@
 #include "misc.hh"
 #include "dnsparser.hh"
 
-DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass)
+DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass, uint8_t opcode)
   : d_pos(0), d_content(content), d_qname(qname), d_qtype(qtype), d_qclass(qclass)
 {
   d_content.clear();
@@ -11,6 +11,7 @@ DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname,
   memset(&dnsheader, 0, sizeof(dnsheader));
   dnsheader.id=0;
   dnsheader.qdcount=htons(1);
+  dnsheader.opcode=opcode;
   
   const uint8_t* ptr=(const uint8_t*)&dnsheader;
   uint32_t len=d_content.size();
@@ -50,7 +51,6 @@ dnsheader* DNSPacketWriter::getHeader()
   return (dnsheader*)&*d_content.begin();
 }
 
-
 void DNSPacketWriter::startRecord(const string& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, Place place)
 {
   if(!d_record.empty()) 
index 91443209cdc5385ca16e465db4422fe3ced7633d..ad6006a67f98e286892925393d623ccab609427c 100644 (file)
@@ -46,7 +46,7 @@ public:
   enum Place {ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; 
 
   //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass
-  DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass=1);
+  DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass=1, uint8_t opcode=0);
   
   /** Start a new DNS record within this packet for namq, qtype, ttl, class and in the requested place. Note that packets can only be written in natural order - 
       ANSWER, AUTHORITY, ADDITIONAL */
index 279aba004ed5ce1586c29aade7e4bf9d27a94b4b..f2286a5d55f16e122e70ec2fcc2db4b81c34ceb2 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002 - 2005 PowerDNS.COM BV
+    Copyright (C) 2002 - 2007 PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as 
 #include <cstring>
 #include <string>
 #include <vector>
-#include "dnspacket.hh"
+
 #include "dns.hh"
 #include "qtype.hh"
 #include "tcpreceiver.hh"
 #include "ahuexception.hh"
 #include "statbag.hh"
 #include "arguments.hh"
+#include "dnswriter.hh"
+#include "dnsparser.hh"
+#include <boost/shared_ptr.hpp>
+
+using namespace boost;
 
 void Resolver::makeUDPSocket()
 {
@@ -132,22 +137,13 @@ char* Resolver::sendReceive(const string &ip, uint16_t remotePort, const char *p
 
 int Resolver::notify(int sock, const string &domain, const string &ip, uint16_t id)
 {
-  DNSPacket p;
-  p.setQuestion(Opcode::Notify,domain,QType::SOA);
-  p.wrapup();
-  p.spoofID(id);
-
-  struct in_addr inp;
-  if(!Utility::inet_aton(ip.c_str(),&inp))
-    throw ResolverException("Unable to convert '"+ip+"' to an IP address");
-
-  struct sockaddr_in toaddr;
-  toaddr.sin_addr.s_addr=inp.s_addr;
-
-  toaddr.sin_port=htons(53);
-  toaddr.sin_family=AF_INET;
+  vector<uint8_t> packet;
+  DNSPacketWriter pw(packet, domain, QType::SOA, Opcode::Notify);
+  pw.getHeader()->id = id;
+  
+  ComboAddress dest(ip, 53);
 
-  if(sendto(sock, p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr))<0) {
+  if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&dest), dest.getSocklen())<0) {
     throw ResolverException("Unable to send notify to "+ip+": "+stringerror());
   }
   return true;
@@ -155,17 +151,13 @@ int Resolver::notify(int sock, const string &domain, const string &ip, uint16_t
 
 void Resolver::sendResolve(const string &ip, const char *domain, int type)
 {
-  DNSPacket p;
-
-  p.setQuestion(Opcode::Query,domain,type);
-  p.wrapup();
+  vector<uint8_t> packet;
+  DNSPacketWriter pw(packet, domain, type);
 
   d_domain=domain;
   d_type=type;
   d_inaxfr=false;
 
-  struct sockaddr_in toaddr;
-  struct in_addr inp;
   ServiceTuple st;
   st.port=53;
   try {
@@ -175,13 +167,9 @@ void Resolver::sendResolve(const string &ip, const char *domain, int type)
     throw ResolverException("Sending a dns question to '"+ip+"': "+ae.reason);
   }
 
-  Utility::inet_aton(st.host.c_str(),&inp);
-  toaddr.sin_addr.s_addr=inp.s_addr;
-
-  toaddr.sin_port=htons(st.port);
-  toaddr.sin_family=AF_INET;
+  ComboAddress remote(st.host, st.port);
 
-  if(sendto(d_sock, p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr))<0) {
+  if(sendto(d_sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) {
     throw ResolverException("Unable to ask query of "+st.host+":"+itoa(st.port)+": "+stringerror());
   }
 }
@@ -230,12 +218,7 @@ void Resolver::makeTCPSocket(const string &ip, uint16_t port)
   if(d_sock>=0)
     return;
 
-  struct in_addr inp;
-  Utility::inet_aton(ip.c_str(),&inp);
-  d_toaddr.sin4.sin_addr.s_addr=inp.s_addr;
-
-  d_toaddr.sin4.sin_port=htons(port);
-  d_toaddr.sin4.sin_family=AF_INET;
+  d_toaddr=ComboAddress(ip, port);
 
   d_sock=socket(AF_INET,SOCK_STREAM,0);
   if(d_sock<0)
@@ -243,22 +226,10 @@ void Resolver::makeTCPSocket(const string &ip, uint16_t port)
 
   // Use query-local-address as source IP for queries, if specified.
   string querylocaladdress(arg()["query-local-address"]);
-  if (querylocaladdress!="") {
-    struct sockaddr_in fromaddr;
-    struct hostent *h=0;
+  if (!querylocaladdress.empty()) {
+    ComboAddress fromaddr(querylocaladdress, 0);
 
-    h = gethostbyname(querylocaladdress.c_str());
-    if(!h) {
-      Utility::closesocket(d_sock);
-      d_sock=-1;
-      throw ResolverException("Unable to resolve query local address");
-    }
-
-    fromaddr.sin_family = AF_INET;
-    fromaddr.sin_addr.s_addr = *(int*)h->h_addr;
-    fromaddr.sin_port = 0;
-
-    if (bind(d_sock, (struct sockaddr *)&fromaddr, sizeof(fromaddr)) < 0) {
+    if (bind(d_sock, (struct sockaddr *)&fromaddr, fromaddr.getSocklen()) < 0) {
       Utility::closesocket(d_sock);
       d_sock=-1;
       throw ResolverException("Binding to query-local-address: "+stringerror());
@@ -316,7 +287,6 @@ void Resolver::makeTCPSocket(const string &ip, uint16_t port)
   // d_sock now connected
 }
 
-
 //! returns -1 for permanent error, 0 for timeout, 1 for success
 int Resolver::axfr(const string &ip, const char *domain)
 {
@@ -325,17 +295,16 @@ int Resolver::axfr(const string &ip, const char *domain)
   makeTCPSocket(ip);
 
   d_type=QType::AXFR;
-  DNSPacket p;
-  p.d_tcp = true;
-  p.setQuestion(Opcode::Query,domain,QType::AXFR);
-  p.wrapup();
+  
+  vector<uint8_t> packet;
+  DNSPacketWriter pw(packet, domain, QType::AXFR);
 
-  uint16_t replen=htons(p.len);
+  uint16_t replen=htons(packet.size());
   Utility::iovec iov[2];
   iov[0].iov_base=(char*)&replen;
   iov[0].iov_len=2;
-  iov[1].iov_base=(char*)p.getData();
-  iov[1].iov_len=p.len;
+  iov[1].iov_base=(char*)&packet[0];
+  iov[1].iov_len=packet.size();
 
   int ret=Utility::writev(d_sock,iov,2);
   if(ret<0)
@@ -415,34 +384,54 @@ int Resolver::axfrChunk(Resolver::res_t &res)
 
 Resolver::res_t Resolver::result()
 {
+  shared_ptr<MOADNSParser> mdp;
+  
   try {
-    DNSPacket p;
-    p.setRemote(&d_toaddr);
-    p.d_tcp = d_inaxfr; // fixes debian bug 330184
-    if(p.parse((char *)d_buf, d_len)<0)
-      throw ResolverException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
-    
-    if(p.d.rcode)
-      if(d_inaxfr)
-       throw ResolverException("Remote nameserver unable/unwilling to AXFR with us: RCODE="+itoa(p.d.rcode));
-      else
-       throw ResolverException("Remote nameserver reported error: RCODE="+itoa(p.d.rcode));
-    
+    mdp=shared_ptr<MOADNSParser>(new MOADNSParser((char*)d_buf, d_len));
+  }
+  catch(...) {
+    throw ResolverException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
+  }
+  if(mdp->d_header.rcode)
+    if(d_inaxfr)
+      throw ResolverException("Remote nameserver unable/unwilling to AXFR with us: RCODE="+itoa(mdp->d_header.rcode));
+    else
+      throw ResolverException("Remote nameserver reported error: RCODE="+itoa(mdp->d_header.rcode));
+  
     if(!d_inaxfr) {
-      if(ntohs(p.d.qdcount)!=1)
-       throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(ntohs(p.d.qdcount))+")");
+      if(mdp->d_header.qdcount!=1)
+       throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp->d_header.qdcount)+")");
       
-      if(p.qdomain!=d_domain)
-       throw ResolverException(string("resolver: received an answer to another question (")+p.qdomain+"!="+d_domain+")");
+      if(mdp->d_qname != d_domain+".")
+       throw ResolverException(string("resolver: received an answer to another question (")+mdp->d_qname+"!="+d_domain+".)");
     }
-    return p.getAnswers();
-  }
-  catch(AhuException &ae) { // translate
-    throw ResolverException(ae.reason);
-  }
+    
+    vector<DNSResourceRecord> ret; 
+    DNSResourceRecord rr;
+    for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {          
+      rr.qname = i->first.d_label;
+      rr.qtype = i->first.d_type;
+      rr.ttl = i->first.d_ttl;
+      rr.content = i->first.d_content->getZoneRepresentation();
+      if(rr.qtype.getCode() == QType::MX) {
+       vector<string> parts;
+       stringtok(parts, rr.content);
+       rr.priority = atoi(parts[0].c_str());
+       if(parts.size() > 1)
+         rr.content=parts[1];
+      } else if(rr.qtype.getCode() == QType::SRV) {
+       rr.priority = atoi(rr.content.c_str());
+       vector<pair<string::size_type, string::size_type> > fields;
+       vstringtok(fields, rr.content, " ");
+       if(fields.size()==4)
+         rr.content=string(rr.content.c_str() + fields[1].first, fields[3].second - fields[1].first);
+      }
+      ret.push_back(rr);
+    }
+    
+    return ret;
 }
 
-
 void Resolver::sendSoaSerialRequest(const string &ip, const string &domain)
 {
   sendResolve(ip,domain.c_str(),QType::SOA);