"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/test/dns-proto.cc" (8 Aug 2021, 18601 Bytes) of package /linux/misc/dns/c-ares-1.17.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "dns-proto.cc": 1.17.1_vs_1.17.2.

    1 
    2 // Include ares internal file for DNS protocol details
    3 #include "ares_setup.h"
    4 #include "ares.h"
    5 #include "ares_dns.h"
    6 #include "dns-proto.h"
    7 
    8 #include <stdio.h>
    9 #include <stdlib.h>
   10 
   11 #include <sstream>
   12 
   13 namespace ares {
   14 
   15 std::string HexDump(std::vector<byte> data) {
   16   std::stringstream ss;
   17   for (size_t ii = 0; ii < data.size();  ii++) {
   18     char buffer[2 + 1];
   19     sprintf(buffer, "%02x", data[ii]);
   20     ss << buffer;
   21   }
   22   return ss.str();
   23 }
   24 
   25 std::string HexDump(const byte *data, int len) {
   26   return HexDump(std::vector<byte>(data, data + len));
   27 }
   28 
   29 std::string HexDump(const char *data, int len) {
   30   return HexDump(reinterpret_cast<const byte*>(data), len);
   31 }
   32 
   33 std::string StatusToString(int status) {
   34   switch (status) {
   35   case ARES_SUCCESS: return "ARES_SUCCESS";
   36   case ARES_ENODATA: return "ARES_ENODATA";
   37   case ARES_EFORMERR: return "ARES_EFORMERR";
   38   case ARES_ESERVFAIL: return "ARES_ESERVFAIL";
   39   case ARES_ENOTFOUND: return "ARES_ENOTFOUND";
   40   case ARES_ENOTIMP: return "ARES_ENOTIMP";
   41   case ARES_EREFUSED: return "ARES_EREFUSED";
   42   case ARES_EBADQUERY: return "ARES_EBADQUERY";
   43   case ARES_EBADNAME: return "ARES_EBADNAME";
   44   case ARES_EBADFAMILY: return "ARES_EBADFAMILY";
   45   case ARES_EBADRESP: return "ARES_EBADRESP";
   46   case ARES_ECONNREFUSED: return "ARES_ECONNREFUSED";
   47   case ARES_ETIMEOUT: return "ARES_ETIMEOUT";
   48   case ARES_EOF: return "ARES_EOF";
   49   case ARES_EFILE: return "ARES_EFILE";
   50   case ARES_ENOMEM: return "ARES_ENOMEM";
   51   case ARES_EDESTRUCTION: return "ARES_EDESTRUCTION";
   52   case ARES_EBADSTR: return "ARES_EBADSTR";
   53   case ARES_EBADFLAGS: return "ARES_EBADFLAGS";
   54   case ARES_ENONAME: return "ARES_ENONAME";
   55   case ARES_EBADHINTS: return "ARES_EBADHINTS";
   56   case ARES_ENOTINITIALIZED: return "ARES_ENOTINITIALIZED";
   57   case ARES_ELOADIPHLPAPI: return "ARES_ELOADIPHLPAPI";
   58   case ARES_EADDRGETNETWORKPARAMS: return "ARES_EADDRGETNETWORKPARAMS";
   59   case ARES_ECANCELLED: return "ARES_ECANCELLED";
   60   default: return "UNKNOWN";
   61   }
   62 }
   63 
   64 std::string RcodeToString(int rcode) {
   65   switch (rcode) {
   66   case NOERROR: return "NOERROR";
   67   case FORMERR: return "FORMERR";
   68   case SERVFAIL: return "SERVFAIL";
   69   case NXDOMAIN: return "NXDOMAIN";
   70   case NOTIMP: return "NOTIMP";
   71   case REFUSED: return "REFUSED";
   72   case YXDOMAIN: return "YXDOMAIN";
   73   case YXRRSET: return "YXRRSET";
   74   case NXRRSET: return "NXRRSET";
   75   case NOTAUTH: return "NOTAUTH";
   76   case NOTZONE: return "NOTZONE";
   77   case TSIG_BADSIG: return "BADSIG";
   78   case TSIG_BADKEY: return "BADKEY";
   79   case TSIG_BADTIME: return "BADTIME";
   80   default: return "UNKNOWN";
   81   }
   82 }
   83 
   84 std::string RRTypeToString(int rrtype) {
   85   switch (rrtype) {
   86   case T_A: return "A";
   87   case T_NS: return "NS";
   88   case T_MD: return "MD";
   89   case T_MF: return "MF";
   90   case T_CNAME: return "CNAME";
   91   case T_SOA: return "SOA";
   92   case T_MB: return "MB";
   93   case T_MG: return "MG";
   94   case T_MR: return "MR";
   95   case T_NULL: return "NULL";
   96   case T_WKS: return "WKS";
   97   case T_PTR: return "PTR";
   98   case T_HINFO: return "HINFO";
   99   case T_MINFO: return "MINFO";
  100   case T_MX: return "MX";
  101   case T_TXT: return "TXT";
  102   case T_RP: return "RP";
  103   case T_AFSDB: return "AFSDB";
  104   case T_X25: return "X25";
  105   case T_ISDN: return "ISDN";
  106   case T_RT: return "RT";
  107   case T_NSAP: return "NSAP";
  108   case T_NSAP_PTR: return "NSAP_PTR";
  109   case T_SIG: return "SIG";
  110   case T_KEY: return "KEY";
  111   case T_PX: return "PX";
  112   case T_GPOS: return "GPOS";
  113   case T_AAAA: return "AAAA";
  114   case T_LOC: return "LOC";
  115   case T_NXT: return "NXT";
  116   case T_EID: return "EID";
  117   case T_NIMLOC: return "NIMLOC";
  118   case T_SRV: return "SRV";
  119   case T_ATMA: return "ATMA";
  120   case T_NAPTR: return "NAPTR";
  121   case T_KX: return "KX";
  122   case T_CERT: return "CERT";
  123   case T_A6: return "A6";
  124   case T_DNAME: return "DNAME";
  125   case T_SINK: return "SINK";
  126   case T_OPT: return "OPT";
  127   case T_APL: return "APL";
  128   case T_DS: return "DS";
  129   case T_SSHFP: return "SSHFP";
  130   case T_RRSIG: return "RRSIG";
  131   case T_NSEC: return "NSEC";
  132   case T_DNSKEY: return "DNSKEY";
  133   case T_TKEY: return "TKEY";
  134   case T_TSIG: return "TSIG";
  135   case T_IXFR: return "IXFR";
  136   case T_AXFR: return "AXFR";
  137   case T_MAILB: return "MAILB";
  138   case T_MAILA: return "MAILA";
  139   case T_ANY: return "ANY";
  140   case T_ZXFR: return "ZXFR";
  141   case T_MAX: return "MAX";
  142   default: return "UNKNOWN";
  143   }
  144 }
  145 
  146 std::string ClassToString(int qclass) {
  147   switch (qclass) {
  148   case C_IN: return "IN";
  149   case C_CHAOS: return "CHAOS";
  150   case C_HS: return "HESIOD";
  151   case C_NONE: return "NONE";
  152   case C_ANY: return "ANY";
  153   default: return "UNKNOWN";
  154   }
  155 }
  156 
  157 std::string AddressToString(const void* vaddr, int len) {
  158   const byte* addr = reinterpret_cast<const byte*>(vaddr);
  159   std::stringstream ss;
  160   if (len == 4) {
  161     char buffer[4*4 + 3 + 1];
  162     sprintf(buffer, "%u.%u.%u.%u",
  163             (unsigned char)addr[0],
  164             (unsigned char)addr[1],
  165             (unsigned char)addr[2],
  166             (unsigned char)addr[3]);
  167     ss << buffer;
  168   } else if (len == 16) {
  169     for (int ii = 0; ii < 16;  ii+=2) {
  170       if (ii > 0) ss << ':';
  171       char buffer[4 + 1];
  172       sprintf(buffer, "%02x%02x", (unsigned char)addr[ii], (unsigned char)addr[ii+1]);
  173       ss << buffer;
  174     }
  175   } else {
  176     ss << "!" << HexDump(addr, len) << "!";
  177   }
  178   return ss.str();
  179 }
  180 
  181 std::string PacketToString(const std::vector<byte>& packet) {
  182   const byte* data = packet.data();
  183   int len = packet.size();
  184   std::stringstream ss;
  185   if (len < NS_HFIXEDSZ) {
  186     ss << "(too short, len " << len << ")";
  187     return ss.str();
  188   }
  189   ss << ((DNS_HEADER_QR(data) == 0) ? "REQ " : "RSP ");
  190   switch (DNS_HEADER_OPCODE(data)) {
  191   case O_QUERY: ss << "QRY "; break;
  192   case O_IQUERY: ss << "IQRY "; break;
  193   case O_STATUS: ss << "STATUS "; break;
  194   case O_NOTIFY: ss << "NOTIFY "; break;
  195   case O_UPDATE: ss << "UPDATE "; break;
  196   default: ss << "UNKNOWN(" << DNS_HEADER_OPCODE(data) << ") "; break;
  197   }
  198   if (DNS_HEADER_AA(data)) ss << "AA ";
  199   if (DNS_HEADER_TC(data)) ss << "TC ";
  200   if (DNS_HEADER_RD(data)) ss << "RD ";
  201   if (DNS_HEADER_RA(data)) ss << "RA ";
  202   if (DNS_HEADER_Z(data)) ss << "Z ";
  203   if (DNS_HEADER_QR(data) == 1) ss << RcodeToString(DNS_HEADER_RCODE(data));
  204 
  205   int nquestions = DNS_HEADER_QDCOUNT(data);
  206   int nanswers = DNS_HEADER_ANCOUNT(data);
  207   int nauths = DNS_HEADER_NSCOUNT(data);
  208   int nadds = DNS_HEADER_ARCOUNT(data);
  209 
  210   const byte* pq = data + NS_HFIXEDSZ;
  211   len -= NS_HFIXEDSZ;
  212   for (int ii = 0; ii < nquestions; ii++) {
  213     ss << " Q:" << QuestionToString(packet, &pq, &len);
  214   }
  215   const byte* prr = pq;
  216   for (int ii = 0; ii < nanswers; ii++) {
  217     ss << " A:" << RRToString(packet, &prr, &len);
  218   }
  219   for (int ii = 0; ii < nauths; ii++) {
  220     ss << " AUTH:" << RRToString(packet, &prr, &len);
  221   }
  222   for (int ii = 0; ii < nadds; ii++) {
  223     ss << " ADD:" << RRToString(packet, &prr, &len);
  224   }
  225   return ss.str();
  226 }
  227 
  228 std::string QuestionToString(const std::vector<byte>& packet,
  229                              const byte** data, int* len) {
  230   std::stringstream ss;
  231   ss << "{";
  232   if (*len < NS_QFIXEDSZ) {
  233     ss << "(too short, len " << *len << ")";
  234     return ss.str();
  235   }
  236 
  237   char *name = nullptr;
  238   long enclen;
  239   int rc = ares_expand_name(*data, packet.data(), packet.size(), &name, &enclen);
  240   if (rc != ARES_SUCCESS) {
  241     ss << "(error from ares_expand_name)";
  242     return ss.str();
  243   }
  244   if (enclen > *len) {
  245     ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
  246     return ss.str();
  247   }
  248   *len -= enclen;
  249   *data += enclen;
  250   ss << "'" << name << "' ";
  251   ares_free_string(name);
  252   if (*len < NS_QFIXEDSZ) {
  253     ss << "(too short, len left " << *len << ")";
  254     return ss.str();
  255   }
  256   ss << ClassToString(DNS_QUESTION_CLASS(*data)) << " ";
  257   ss << RRTypeToString(DNS_QUESTION_TYPE(*data));
  258   *data += NS_QFIXEDSZ;
  259   *len -= NS_QFIXEDSZ;
  260   ss << "}";
  261   return ss.str();
  262 }
  263 
  264 std::string RRToString(const std::vector<byte>& packet,
  265                        const byte** data, int* len) {
  266   std::stringstream ss;
  267   ss << "{";
  268   if (*len < NS_RRFIXEDSZ) {
  269     ss << "too short, len " << *len << ")";
  270     return ss.str();
  271   }
  272 
  273   char *name = nullptr;
  274   long enclen;
  275   int rc = ares_expand_name(*data, packet.data(), packet.size(), &name, &enclen);
  276   if (rc != ARES_SUCCESS) {
  277     ss << "(error from ares_expand_name)";
  278     return ss.str();
  279   }
  280   if (enclen > *len) {
  281     ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
  282     return ss.str();
  283   }
  284   *len -= enclen;
  285   *data += enclen;
  286   ss << "'" << name << "' ";
  287   ares_free_string(name);
  288   name = nullptr;
  289 
  290   if (*len < NS_RRFIXEDSZ) {
  291     ss << "(too short, len left " << *len << ")";
  292     return ss.str();
  293   }
  294   int rrtype = DNS_RR_TYPE(*data);
  295   if (rrtype == T_OPT) {
  296     ss << "MAXUDP=" << DNS_RR_CLASS(*data) << " ";
  297     ss << RRTypeToString(rrtype) << " ";
  298     ss << "RCODE2=" << DNS_RR_TTL(*data);
  299   } else {
  300     ss << ClassToString(DNS_RR_CLASS(*data)) << " ";
  301     ss << RRTypeToString(rrtype) << " ";
  302     ss << "TTL=" << DNS_RR_TTL(*data);
  303   }
  304   int rdatalen = DNS_RR_LEN(*data);
  305 
  306   *data += NS_RRFIXEDSZ;
  307   *len -= NS_RRFIXEDSZ;
  308   if (*len < rdatalen) {
  309     ss << "(RR too long at " << rdatalen << ", len left " << *len << ")";
  310   } else {
  311     switch (rrtype) {
  312     case T_A:
  313     case T_AAAA:
  314       ss << " " << AddressToString(*data, rdatalen);
  315       break;
  316     case T_TXT: {
  317       const byte* p = *data;
  318       while (p < (*data + rdatalen)) {
  319         int len = *p++;
  320         if ((p + len) <= (*data + rdatalen)) {
  321           std::string txt(p, p + len);
  322           ss << " " << len << ":'" << txt << "'";
  323         } else {
  324           ss << "(string too long)";
  325         }
  326         p += len;
  327       }
  328       break;
  329     }
  330     case T_CNAME:
  331     case T_NS:
  332     case T_PTR: {
  333       int rc = ares_expand_name(*data, packet.data(), packet.size(), &name, &enclen);
  334       if (rc != ARES_SUCCESS) {
  335         ss << "(error from ares_expand_name)";
  336         break;
  337       }
  338       ss << " '" << name << "'";
  339       ares_free_string(name);
  340       break;
  341     }
  342     case T_MX:
  343       if (rdatalen > 2) {
  344         int rc = ares_expand_name(*data + 2, packet.data(), packet.size(), &name, &enclen);
  345         if (rc != ARES_SUCCESS) {
  346           ss << "(error from ares_expand_name)";
  347           break;
  348         }
  349         ss << " " << DNS__16BIT(*data) << " '" << name << "'";
  350         ares_free_string(name);
  351       } else {
  352         ss << "(RR too short)";
  353       }
  354       break;
  355     case T_SRV: {
  356       if (rdatalen > 6) {
  357         const byte* p = *data;
  358         unsigned long prio = DNS__16BIT(p);
  359         unsigned long weight = DNS__16BIT(p + 2);
  360         unsigned long port = DNS__16BIT(p + 4);
  361         p += 6;
  362         int rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
  363         if (rc != ARES_SUCCESS) {
  364           ss << "(error from ares_expand_name)";
  365           break;
  366         }
  367         ss << prio << " " << weight << " " << port << " '" << name << "'";
  368         ares_free_string(name);
  369       } else {
  370         ss << "(RR too short)";
  371       }
  372       break;
  373     }
  374     case T_SOA: {
  375       const byte* p = *data;
  376       int rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
  377       if (rc != ARES_SUCCESS) {
  378         ss << "(error from ares_expand_name)";
  379         break;
  380       }
  381       ss << " '" << name << "'";
  382       ares_free_string(name);
  383       p += enclen;
  384       rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
  385       if (rc != ARES_SUCCESS) {
  386         ss << "(error from ares_expand_name)";
  387         break;
  388       }
  389       ss << " '" << name << "'";
  390       ares_free_string(name);
  391       p += enclen;
  392       if ((p + 20) <= (*data + rdatalen)) {
  393         unsigned long serial = DNS__32BIT(p);
  394         unsigned long refresh = DNS__32BIT(p + 4);
  395         unsigned long retry = DNS__32BIT(p + 8);
  396         unsigned long expire = DNS__32BIT(p + 12);
  397         unsigned long minimum = DNS__32BIT(p + 16);
  398         ss << " " << serial << " " << refresh << " " << retry << " " << expire << " " << minimum;
  399       } else {
  400         ss << "(RR too short)";
  401       }
  402       break;
  403     }
  404     case T_NAPTR: {
  405       if (rdatalen > 7) {
  406         const byte* p = *data;
  407         unsigned long order = DNS__16BIT(p);
  408         unsigned long pref = DNS__16BIT(p + 2);
  409         p += 4;
  410         ss << order << " " << pref;
  411 
  412         int len = *p++;
  413         std::string flags(p, p + len);
  414         ss << " " << flags;
  415         p += len;
  416 
  417         len = *p++;
  418         std::string service(p, p + len);
  419         ss << " '" << service << "'";
  420         p += len;
  421 
  422         len = *p++;
  423         std::string regexp(p, p + len);
  424         ss << " '" << regexp << "'";
  425         p += len;
  426 
  427         int rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
  428         if (rc != ARES_SUCCESS) {
  429           ss << "(error from ares_expand_name)";
  430           break;
  431         }
  432         ss << " '" << name << "'";
  433         ares_free_string(name);
  434       } else {
  435         ss << "(RR too short)";
  436       }
  437       break;
  438     }
  439     default:
  440       ss << " " << HexDump(*data, rdatalen);
  441       break;
  442     }
  443   }
  444   *data += rdatalen;
  445   *len -= rdatalen;
  446 
  447   ss << "}";
  448   return ss.str();
  449 }
  450 
  451 void PushInt32(std::vector<byte>* data, int value) {
  452   data->push_back((value & 0xff000000) >> 24);
  453   data->push_back((value & 0x00ff0000) >> 16);
  454   data->push_back((value & 0x0000ff00) >> 8);
  455   data->push_back(value & 0x000000ff);
  456 }
  457 
  458 void PushInt16(std::vector<byte>* data, int value) {
  459   data->push_back((value & 0xff00) >> 8);
  460   data->push_back(value & 0x00ff);
  461 }
  462 
  463 std::vector<byte> EncodeString(const std::string& name) {
  464   std::vector<byte> data;
  465   std::stringstream ss(name);
  466   std::string label;
  467   // TODO: cope with escapes
  468   while (std::getline(ss, label, '.')) {
  469     data.push_back(label.length());
  470     data.insert(data.end(), label.begin(), label.end());
  471   }
  472   data.push_back(0);
  473   return data;
  474 }
  475 
  476 std::vector<byte> DNSQuestion::data() const {
  477   std::vector<byte> data;
  478   std::vector<byte> encname = EncodeString(name_);
  479   data.insert(data.end(), encname.begin(), encname.end());
  480   PushInt16(&data, rrtype_);
  481   PushInt16(&data, qclass_);
  482   return data;
  483 }
  484 
  485 std::vector<byte> DNSRR::data() const {
  486   std::vector<byte> data = DNSQuestion::data();
  487   PushInt32(&data, ttl_);
  488   return data;
  489 }
  490 
  491 std::vector<byte> DNSSingleNameRR::data() const {
  492   std::vector<byte> data = DNSRR::data();
  493   std::vector<byte> encname = EncodeString(other_);
  494   int len = encname.size();
  495   PushInt16(&data, len);
  496   data.insert(data.end(), encname.begin(), encname.end());
  497   return data;
  498 }
  499 
  500 std::vector<byte> DNSTxtRR::data() const {
  501   std::vector<byte> data = DNSRR::data();
  502   int len = 0;
  503   for (const std::string& txt : txt_) {
  504     len += (1 + txt.size());
  505   }
  506   PushInt16(&data, len);
  507   for (const std::string& txt : txt_) {
  508     data.push_back(txt.size());
  509     data.insert(data.end(), txt.begin(), txt.end());
  510   }
  511   return data;
  512 }
  513 
  514 std::vector<byte> DNSMxRR::data() const {
  515   std::vector<byte> data = DNSRR::data();
  516   std::vector<byte> encname = EncodeString(other_);
  517   int len = 2 + encname.size();
  518   PushInt16(&data, len);
  519   PushInt16(&data, pref_);
  520   data.insert(data.end(), encname.begin(), encname.end());
  521   return data;
  522 }
  523 
  524 std::vector<byte> DNSSrvRR::data() const {
  525   std::vector<byte> data = DNSRR::data();
  526   std::vector<byte> encname = EncodeString(target_);
  527   int len = 6 + encname.size();
  528   PushInt16(&data, len);
  529   PushInt16(&data, prio_);
  530   PushInt16(&data, weight_);
  531   PushInt16(&data, port_);
  532   data.insert(data.end(), encname.begin(), encname.end());
  533   return data;
  534 }
  535 
  536 std::vector<byte> DNSAddressRR::data() const {
  537   std::vector<byte> data = DNSRR::data();
  538   int len = addr_.size();
  539   PushInt16(&data, len);
  540   data.insert(data.end(), addr_.begin(), addr_.end());
  541   return data;
  542 }
  543 
  544 std::vector<byte> DNSSoaRR::data() const {
  545   std::vector<byte> data = DNSRR::data();
  546   std::vector<byte> encname1 = EncodeString(nsname_);
  547   std::vector<byte> encname2 = EncodeString(rname_);
  548   int len = encname1.size() + encname2.size() + 5*4;
  549   PushInt16(&data, len);
  550   data.insert(data.end(), encname1.begin(), encname1.end());
  551   data.insert(data.end(), encname2.begin(), encname2.end());
  552   PushInt32(&data, serial_);
  553   PushInt32(&data, refresh_);
  554   PushInt32(&data, retry_);
  555   PushInt32(&data, expire_);
  556   PushInt32(&data, minimum_);
  557   return data;
  558 }
  559 
  560 std::vector<byte> DNSOptRR::data() const {
  561   std::vector<byte> data = DNSRR::data();
  562   int len = 0;
  563   for (const DNSOption& opt : opts_) {
  564     len += (4 + opt.data_.size());
  565   }
  566   PushInt16(&data, len);
  567   for (const DNSOption& opt : opts_) {
  568     PushInt16(&data, opt.code_);
  569     PushInt16(&data, opt.data_.size());
  570     data.insert(data.end(), opt.data_.begin(), opt.data_.end());
  571   }
  572   return data;
  573 }
  574 
  575 std::vector<byte> DNSNaptrRR::data() const {
  576   std::vector<byte> data = DNSRR::data();
  577   std::vector<byte> encname = EncodeString(replacement_);
  578   int len = (4 + 1 + flags_.size() + 1 + service_.size() + 1 + regexp_.size() + encname.size());
  579   PushInt16(&data, len);
  580   PushInt16(&data, order_);
  581   PushInt16(&data, pref_);
  582   data.push_back(flags_.size());
  583   data.insert(data.end(), flags_.begin(), flags_.end());
  584   data.push_back(service_.size());
  585   data.insert(data.end(), service_.begin(), service_.end());
  586   data.push_back(regexp_.size());
  587   data.insert(data.end(), regexp_.begin(), regexp_.end());
  588   data.insert(data.end(), encname.begin(), encname.end());
  589   return data;
  590 }
  591 
  592 std::vector<byte> DNSPacket::data() const {
  593   std::vector<byte> data;
  594   PushInt16(&data, qid_);
  595   byte b = 0x00;
  596   if (response_) b |= 0x80;
  597   b |= ((opcode_ & 0x0f) << 3);
  598   if (aa_) b |= 0x04;
  599   if (tc_) b |= 0x02;
  600   if (rd_) b |= 0x01;
  601   data.push_back(b);
  602   b = 0x00;
  603   if (ra_) b |= 0x80;
  604   if (z_) b |= 0x40;
  605   if (ad_) b |= 0x20;
  606   if (cd_) b |= 0x10;
  607   b |= (rcode_ & 0x0f);
  608   data.push_back(b);
  609 
  610   int count = questions_.size();
  611   PushInt16(&data, count);
  612   count = answers_.size();
  613   PushInt16(&data, count);
  614   count = auths_.size();
  615   PushInt16(&data, count);
  616   count = adds_.size();
  617   PushInt16(&data, count);
  618 
  619   for (const std::unique_ptr<DNSQuestion>& question : questions_) {
  620     std::vector<byte> qdata = question->data();
  621     data.insert(data.end(), qdata.begin(), qdata.end());
  622   }
  623   for (const std::unique_ptr<DNSRR>& rr : answers_) {
  624     std::vector<byte> rrdata = rr->data();
  625     data.insert(data.end(), rrdata.begin(), rrdata.end());
  626   }
  627   for (const std::unique_ptr<DNSRR>& rr : auths_) {
  628     std::vector<byte> rrdata = rr->data();
  629     data.insert(data.end(), rrdata.begin(), rrdata.end());
  630   }
  631   for (const std::unique_ptr<DNSRR>& rr : adds_) {
  632     std::vector<byte> rrdata = rr->data();
  633     data.insert(data.end(), rrdata.begin(), rrdata.end());
  634   }
  635   return data;
  636 }
  637 
  638 }  // namespace ares