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 
HexDump(std::vector<byte> data)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 
HexDump(const byte * data,int len)25 std::string HexDump(const byte *data, int len) {
26   return HexDump(std::vector<byte>(data, data + len));
27 }
28 
HexDump(const char * data,int len)29 std::string HexDump(const char *data, int len) {
30   return HexDump(reinterpret_cast<const byte*>(data), len);
31 }
32 
StatusToString(int status)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 
RcodeToString(int rcode)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 
RRTypeToString(int rrtype)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_URI: return "URI";
141   case T_MAX: return "MAX";
142   default: return "UNKNOWN";
143   }
144 }
145 
ClassToString(int qclass)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 
AddressToString(const void * vaddr,int len)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 
PacketToString(const std::vector<byte> & packet)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 
QuestionToString(const std::vector<byte> & packet,const byte ** data,int * len)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 
RRToString(const std::vector<byte> & packet,const byte ** data,int * len)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_URI: {
375       if (rdatalen > 4) {
376         const byte* p = *data;
377         unsigned long prio = DNS__16BIT(p);
378         unsigned long weight = DNS__16BIT(p + 2);
379         p += 4;
380         std::string uri(p, p + (rdatalen - 4));
381         ss << prio << " " << weight << " '" << uri << "'";
382       } else {
383         ss << "(RR too short)";
384       }
385       break;
386     }
387     case T_SOA: {
388       const byte* p = *data;
389       int rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
390       if (rc != ARES_SUCCESS) {
391         ss << "(error from ares_expand_name)";
392         break;
393       }
394       ss << " '" << name << "'";
395       ares_free_string(name);
396       p += enclen;
397       rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
398       if (rc != ARES_SUCCESS) {
399         ss << "(error from ares_expand_name)";
400         break;
401       }
402       ss << " '" << name << "'";
403       ares_free_string(name);
404       p += enclen;
405       if ((p + 20) <= (*data + rdatalen)) {
406         unsigned long serial = DNS__32BIT(p);
407         unsigned long refresh = DNS__32BIT(p + 4);
408         unsigned long retry = DNS__32BIT(p + 8);
409         unsigned long expire = DNS__32BIT(p + 12);
410         unsigned long minimum = DNS__32BIT(p + 16);
411         ss << " " << serial << " " << refresh << " " << retry << " " << expire << " " << minimum;
412       } else {
413         ss << "(RR too short)";
414       }
415       break;
416     }
417     case T_NAPTR: {
418       if (rdatalen > 7) {
419         const byte* p = *data;
420         unsigned long order = DNS__16BIT(p);
421         unsigned long pref = DNS__16BIT(p + 2);
422         p += 4;
423         ss << order << " " << pref;
424 
425         int len = *p++;
426         std::string flags(p, p + len);
427         ss << " " << flags;
428         p += len;
429 
430         len = *p++;
431         std::string service(p, p + len);
432         ss << " '" << service << "'";
433         p += len;
434 
435         len = *p++;
436         std::string regexp(p, p + len);
437         ss << " '" << regexp << "'";
438         p += len;
439 
440         int rc = ares_expand_name(p, packet.data(), packet.size(), &name, &enclen);
441         if (rc != ARES_SUCCESS) {
442           ss << "(error from ares_expand_name)";
443           break;
444         }
445         ss << " '" << name << "'";
446         ares_free_string(name);
447       } else {
448         ss << "(RR too short)";
449       }
450       break;
451     }
452     default:
453       ss << " " << HexDump(*data, rdatalen);
454       break;
455     }
456   }
457   *data += rdatalen;
458   *len -= rdatalen;
459 
460   ss << "}";
461   return ss.str();
462 }
463 
PushInt32(std::vector<byte> * data,int value)464 void PushInt32(std::vector<byte>* data, int value) {
465   data->push_back((value & 0xff000000) >> 24);
466   data->push_back((value & 0x00ff0000) >> 16);
467   data->push_back((value & 0x0000ff00) >> 8);
468   data->push_back(value & 0x000000ff);
469 }
470 
PushInt16(std::vector<byte> * data,int value)471 void PushInt16(std::vector<byte>* data, int value) {
472   data->push_back((value & 0xff00) >> 8);
473   data->push_back(value & 0x00ff);
474 }
475 
EncodeString(const std::string & name)476 std::vector<byte> EncodeString(const std::string& name) {
477   std::vector<byte> data;
478   std::stringstream ss(name);
479   std::string label;
480   // TODO: cope with escapes
481   while (std::getline(ss, label, '.')) {
482     data.push_back(label.length());
483     data.insert(data.end(), label.begin(), label.end());
484   }
485   data.push_back(0);
486   return data;
487 }
488 
data() const489 std::vector<byte> DNSQuestion::data() const {
490   std::vector<byte> data;
491   std::vector<byte> encname = EncodeString(name_);
492   data.insert(data.end(), encname.begin(), encname.end());
493   PushInt16(&data, rrtype_);
494   PushInt16(&data, qclass_);
495   return data;
496 }
497 
data() const498 std::vector<byte> DNSRR::data() const {
499   std::vector<byte> data = DNSQuestion::data();
500   PushInt32(&data, ttl_);
501   return data;
502 }
503 
data() const504 std::vector<byte> DNSSingleNameRR::data() const {
505   std::vector<byte> data = DNSRR::data();
506   std::vector<byte> encname = EncodeString(other_);
507   int len = encname.size();
508   PushInt16(&data, len);
509   data.insert(data.end(), encname.begin(), encname.end());
510   return data;
511 }
512 
data() const513 std::vector<byte> DNSTxtRR::data() const {
514   std::vector<byte> data = DNSRR::data();
515   int len = 0;
516   for (const std::string& txt : txt_) {
517     len += (1 + txt.size());
518   }
519   PushInt16(&data, len);
520   for (const std::string& txt : txt_) {
521     data.push_back(txt.size());
522     data.insert(data.end(), txt.begin(), txt.end());
523   }
524   return data;
525 }
526 
data() const527 std::vector<byte> DNSMxRR::data() const {
528   std::vector<byte> data = DNSRR::data();
529   std::vector<byte> encname = EncodeString(other_);
530   int len = 2 + encname.size();
531   PushInt16(&data, len);
532   PushInt16(&data, pref_);
533   data.insert(data.end(), encname.begin(), encname.end());
534   return data;
535 }
536 
data() const537 std::vector<byte> DNSSrvRR::data() const {
538   std::vector<byte> data = DNSRR::data();
539   std::vector<byte> encname = EncodeString(target_);
540   int len = 6 + encname.size();
541   PushInt16(&data, len);
542   PushInt16(&data, prio_);
543   PushInt16(&data, weight_);
544   PushInt16(&data, port_);
545   data.insert(data.end(), encname.begin(), encname.end());
546   return data;
547 }
548 
data() const549 std::vector<byte> DNSUriRR::data() const {
550   std::vector<byte> data = DNSRR::data();
551   int len = 4 + target_.size();
552   PushInt16(&data, len);
553   PushInt16(&data, prio_);
554   PushInt16(&data, weight_);
555   data.insert(data.end(), target_.begin(), target_.end());
556   return data;
557 }
558 
data() const559 std::vector<byte> DNSAddressRR::data() const {
560   std::vector<byte> data = DNSRR::data();
561   int len = addr_.size();
562   PushInt16(&data, len);
563   data.insert(data.end(), addr_.begin(), addr_.end());
564   return data;
565 }
566 
data() const567 std::vector<byte> DNSSoaRR::data() const {
568   std::vector<byte> data = DNSRR::data();
569   std::vector<byte> encname1 = EncodeString(nsname_);
570   std::vector<byte> encname2 = EncodeString(rname_);
571   int len = encname1.size() + encname2.size() + 5*4;
572   PushInt16(&data, len);
573   data.insert(data.end(), encname1.begin(), encname1.end());
574   data.insert(data.end(), encname2.begin(), encname2.end());
575   PushInt32(&data, serial_);
576   PushInt32(&data, refresh_);
577   PushInt32(&data, retry_);
578   PushInt32(&data, expire_);
579   PushInt32(&data, minimum_);
580   return data;
581 }
582 
data() const583 std::vector<byte> DNSOptRR::data() const {
584   std::vector<byte> data = DNSRR::data();
585   int len = 0;
586   for (const DNSOption& opt : opts_) {
587     len += (4 + opt.data_.size());
588   }
589   PushInt16(&data, len);
590   for (const DNSOption& opt : opts_) {
591     PushInt16(&data, opt.code_);
592     PushInt16(&data, opt.data_.size());
593     data.insert(data.end(), opt.data_.begin(), opt.data_.end());
594   }
595   return data;
596 }
597 
data() const598 std::vector<byte> DNSNaptrRR::data() const {
599   std::vector<byte> data = DNSRR::data();
600   std::vector<byte> encname = EncodeString(replacement_);
601   int len = (4 + 1 + flags_.size() + 1 + service_.size() + 1 + regexp_.size() + encname.size());
602   PushInt16(&data, len);
603   PushInt16(&data, order_);
604   PushInt16(&data, pref_);
605   data.push_back(flags_.size());
606   data.insert(data.end(), flags_.begin(), flags_.end());
607   data.push_back(service_.size());
608   data.insert(data.end(), service_.begin(), service_.end());
609   data.push_back(regexp_.size());
610   data.insert(data.end(), regexp_.begin(), regexp_.end());
611   data.insert(data.end(), encname.begin(), encname.end());
612   return data;
613 }
614 
data() const615 std::vector<byte> DNSPacket::data() const {
616   std::vector<byte> data;
617   PushInt16(&data, qid_);
618   byte b = 0x00;
619   if (response_) b |= 0x80;
620   b |= ((opcode_ & 0x0f) << 3);
621   if (aa_) b |= 0x04;
622   if (tc_) b |= 0x02;
623   if (rd_) b |= 0x01;
624   data.push_back(b);
625   b = 0x00;
626   if (ra_) b |= 0x80;
627   if (z_) b |= 0x40;
628   if (ad_) b |= 0x20;
629   if (cd_) b |= 0x10;
630   b |= (rcode_ & 0x0f);
631   data.push_back(b);
632 
633   int count = questions_.size();
634   PushInt16(&data, count);
635   count = answers_.size();
636   PushInt16(&data, count);
637   count = auths_.size();
638   PushInt16(&data, count);
639   count = adds_.size();
640   PushInt16(&data, count);
641 
642   for (const std::unique_ptr<DNSQuestion>& question : questions_) {
643     std::vector<byte> qdata = question->data();
644     data.insert(data.end(), qdata.begin(), qdata.end());
645   }
646   for (const std::unique_ptr<DNSRR>& rr : answers_) {
647     std::vector<byte> rrdata = rr->data();
648     data.insert(data.end(), rrdata.begin(), rrdata.end());
649   }
650   for (const std::unique_ptr<DNSRR>& rr : auths_) {
651     std::vector<byte> rrdata = rr->data();
652     data.insert(data.end(), rrdata.begin(), rrdata.end());
653   }
654   for (const std::unique_ptr<DNSRR>& rr : adds_) {
655     std::vector<byte> rrdata = rr->data();
656     data.insert(data.end(), rrdata.begin(), rrdata.end());
657   }
658   return data;
659 }
660 
661 }  // namespace ares
662