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