3 // Include ares internal file for DNS protocol details
14 std::string
HexDump(std::vector
<byte
> data
) {
16 for (size_t ii
= 0; ii
< data
.size(); ii
++) {
18 sprintf(buffer
, "%02x", data
[ii
]);
24 std::string
HexDump(const byte
*data
, int len
) {
25 return HexDump(std::vector
<byte
>(data
, data
+ len
));
28 std::string
HexDump(const char *data
, int len
) {
29 return HexDump(reinterpret_cast<const byte
*>(data
), len
);
32 std::string
StatusToString(int status
) {
34 case ARES_SUCCESS
: return "ARES_SUCCESS";
35 case ARES_ENODATA
: return "ARES_ENODATA";
36 case ARES_EFORMERR
: return "ARES_EFORMERR";
37 case ARES_ESERVFAIL
: return "ARES_ESERVFAIL";
38 case ARES_ENOTFOUND
: return "ARES_ENOTFOUND";
39 case ARES_ENOTIMP
: return "ARES_ENOTIMP";
40 case ARES_EREFUSED
: return "ARES_EREFUSED";
41 case ARES_EBADQUERY
: return "ARES_EBADQUERY";
42 case ARES_EBADNAME
: return "ARES_EBADNAME";
43 case ARES_EBADFAMILY
: return "ARES_EBADFAMILY";
44 case ARES_EBADRESP
: return "ARES_EBADRESP";
45 case ARES_ECONNREFUSED
: return "ARES_ECONNREFUSED";
46 case ARES_ETIMEOUT
: return "ARES_ETIMEOUT";
47 case ARES_EOF
: return "ARES_EOF";
48 case ARES_EFILE
: return "ARES_EFILE";
49 case ARES_ENOMEM
: return "ARES_ENOMEM";
50 case ARES_EDESTRUCTION
: return "ARES_EDESTRUCTION";
51 case ARES_EBADSTR
: return "ARES_EBADSTR";
52 case ARES_EBADFLAGS
: return "ARES_EBADFLAGS";
53 case ARES_ENONAME
: return "ARES_ENONAME";
54 case ARES_EBADHINTS
: return "ARES_EBADHINTS";
55 case ARES_ENOTINITIALIZED
: return "ARES_ENOTINITIALIZED";
56 case ARES_ELOADIPHLPAPI
: return "ARES_ELOADIPHLPAPI";
57 case ARES_EADDRGETNETWORKPARAMS
: return "ARES_EADDRGETNETWORKPARAMS";
58 case ARES_ECANCELLED
: return "ARES_ECANCELLED";
59 default: return "UNKNOWN";
63 std::string
RcodeToString(int rcode
) {
65 case ns_r_noerror
: return "NOERROR";
66 case ns_r_formerr
: return "FORMERR";
67 case ns_r_servfail
: return "SERVFAIL";
68 case ns_r_nxdomain
: return "NXDOMAIN";
69 case ns_r_notimpl
: return "NOTIMPL";
70 case ns_r_refused
: return "REFUSED";
71 case ns_r_yxdomain
: return "YXDOMAIN";
72 case ns_r_yxrrset
: return "YXRRSET";
73 case ns_r_nxrrset
: return "NXRRSET";
74 case ns_r_notauth
: return "NOTAUTH";
75 case ns_r_notzone
: return "NOTZONE";
76 case ns_r_badsig
: return "BADSIG";
77 case ns_r_badkey
: return "BADKEY";
78 case ns_r_badtime
: return "BADTIME";
79 default: return "UNKNOWN";
83 std::string
RRTypeToString(int rrtype
) {
85 case ns_t_a
: return "A";
86 case ns_t_ns
: return "NS";
87 case ns_t_md
: return "MD";
88 case ns_t_mf
: return "MF";
89 case ns_t_cname
: return "CNAME";
90 case ns_t_soa
: return "SOA";
91 case ns_t_mb
: return "MB";
92 case ns_t_mg
: return "MG";
93 case ns_t_mr
: return "MR";
94 case ns_t_null
: return "NULL";
95 case ns_t_wks
: return "WKS";
96 case ns_t_ptr
: return "PTR";
97 case ns_t_hinfo
: return "HINFO";
98 case ns_t_minfo
: return "MINFO";
99 case ns_t_mx
: return "MX";
100 case ns_t_txt
: return "TXT";
101 case ns_t_rp
: return "RP";
102 case ns_t_afsdb
: return "AFSDB";
103 case ns_t_x25
: return "X25";
104 case ns_t_isdn
: return "ISDN";
105 case ns_t_rt
: return "RT";
106 case ns_t_nsap
: return "NSAP";
107 case ns_t_nsap_ptr
: return "NSAP_PTR";
108 case ns_t_sig
: return "SIG";
109 case ns_t_key
: return "KEY";
110 case ns_t_px
: return "PX";
111 case ns_t_gpos
: return "GPOS";
112 case ns_t_aaaa
: return "AAAA";
113 case ns_t_loc
: return "LOC";
114 case ns_t_nxt
: return "NXT";
115 case ns_t_eid
: return "EID";
116 case ns_t_nimloc
: return "NIMLOC";
117 case ns_t_srv
: return "SRV";
118 case ns_t_atma
: return "ATMA";
119 case ns_t_naptr
: return "NAPTR";
120 case ns_t_kx
: return "KX";
121 case ns_t_cert
: return "CERT";
122 case ns_t_a6
: return "A6";
123 case ns_t_dname
: return "DNAME";
124 case ns_t_sink
: return "SINK";
125 case ns_t_opt
: return "OPT";
126 case ns_t_apl
: return "APL";
127 case ns_t_ds
: return "DS";
128 case ns_t_sshfp
: return "SSHFP";
129 case ns_t_rrsig
: return "RRSIG";
130 case ns_t_nsec
: return "NSEC";
131 case ns_t_dnskey
: return "DNSKEY";
132 case ns_t_tkey
: return "TKEY";
133 case ns_t_tsig
: return "TSIG";
134 case ns_t_ixfr
: return "IXFR";
135 case ns_t_axfr
: return "AXFR";
136 case ns_t_mailb
: return "MAILB";
137 case ns_t_maila
: return "MAILA";
138 case ns_t_any
: return "ANY";
139 case ns_t_zxfr
: return "ZXFR";
140 case ns_t_max
: return "MAX";
141 default: return "UNKNOWN";
145 std::string
ClassToString(int qclass
) {
147 case ns_c_in
: return "IN";
148 case ns_c_chaos
: return "CHAOS";
149 case ns_c_hs
: return "HESIOD";
150 case ns_c_none
: return "NONE";
151 case ns_c_any
: return "ANY";
152 default: return "UNKNOWN";
156 std::string
AddressToString(const void* vaddr
, int len
) {
157 const byte
* addr
= reinterpret_cast<const byte
*>(vaddr
);
158 std::stringstream ss
;
160 char buffer
[4*4 + 3 + 1];
161 sprintf(buffer
, "%u.%u.%u.%u",
162 (unsigned char)addr
[0],
163 (unsigned char)addr
[1],
164 (unsigned char)addr
[2],
165 (unsigned char)addr
[3]);
167 } else if (len
== 16) {
168 for (int ii
= 0; ii
< 16; ii
+=2) {
169 if (ii
> 0) ss
<< ':';
171 sprintf(buffer
, "%02x%02x", (unsigned char)addr
[ii
], (unsigned char)addr
[ii
+1]);
175 ss
<< "!" << HexDump(addr
, len
) << "!";
180 std::string
PacketToString(const std::vector
<byte
>& packet
) {
181 const byte
* data
= packet
.data();
182 int len
= packet
.size();
183 std::stringstream ss
;
184 if (len
< NS_HFIXEDSZ
) {
185 ss
<< "(too short, len " << len
<< ")";
188 ss
<< ((DNS_HEADER_QR(data
) == 0) ? "REQ " : "RSP ");
189 switch (DNS_HEADER_OPCODE(data
)) {
190 case ns_o_query
: ss
<< "QRY "; break;
191 case ns_o_iquery
: ss
<< "IQRY "; break;
192 case ns_o_status
: ss
<< "STATUS "; break;
193 case ns_o_notify
: ss
<< "NOTIFY "; break;
194 case ns_o_update
: ss
<< "UPDATE "; break;
195 default: ss
<< "UNKNOWN(" << DNS_HEADER_OPCODE(data
) << ") "; break;
197 if (DNS_HEADER_AA(data
)) ss
<< "AA ";
198 if (DNS_HEADER_TC(data
)) ss
<< "TC ";
199 if (DNS_HEADER_RD(data
)) ss
<< "RD ";
200 if (DNS_HEADER_RA(data
)) ss
<< "RA ";
201 if (DNS_HEADER_Z(data
)) ss
<< "Z ";
202 if (DNS_HEADER_QR(data
) == 1) ss
<< RcodeToString(DNS_HEADER_RCODE(data
));
204 int nquestions
= DNS_HEADER_QDCOUNT(data
);
205 int nanswers
= DNS_HEADER_ANCOUNT(data
);
206 int nauths
= DNS_HEADER_NSCOUNT(data
);
207 int nadds
= DNS_HEADER_ARCOUNT(data
);
209 const byte
* pq
= data
+ NS_HFIXEDSZ
;
211 for (int ii
= 0; ii
< nquestions
; ii
++) {
212 ss
<< " Q:" << QuestionToString(packet
, &pq
, &len
);
214 const byte
* prr
= pq
;
215 for (int ii
= 0; ii
< nanswers
; ii
++) {
216 ss
<< " A:" << RRToString(packet
, &prr
, &len
);
218 for (int ii
= 0; ii
< nauths
; ii
++) {
219 ss
<< " AUTH:" << RRToString(packet
, &prr
, &len
);
221 for (int ii
= 0; ii
< nadds
; ii
++) {
222 ss
<< " ADD:" << RRToString(packet
, &prr
, &len
);
227 std::string
QuestionToString(const std::vector
<byte
>& packet
,
228 const byte
** data
, int* len
) {
229 std::stringstream ss
;
231 if (*len
< NS_QFIXEDSZ
) {
232 ss
<< "(too short, len " << *len
<< ")";
236 char *name
= nullptr;
238 int rc
= ares_expand_name(*data
, packet
.data(), packet
.size(), &name
, &enclen
);
239 if (rc
!= ARES_SUCCESS
) {
240 ss
<< "(error from ares_expand_name)";
244 ss
<< "(error, encoded name len " << enclen
<< "bigger than remaining data " << *len
<< " bytes)";
249 ss
<< "'" << name
<< "' ";
251 if (*len
< NS_QFIXEDSZ
) {
252 ss
<< "(too short, len left " << *len
<< ")";
255 ss
<< ClassToString(DNS_QUESTION_CLASS(*data
)) << " ";
256 ss
<< RRTypeToString(DNS_QUESTION_TYPE(*data
));
257 *data
+= NS_QFIXEDSZ
;
263 std::string
RRToString(const std::vector
<byte
>& packet
,
264 const byte
** data
, int* len
) {
265 std::stringstream ss
;
267 if (*len
< NS_RRFIXEDSZ
) {
268 ss
<< "too short, len " << *len
<< ")";
272 char *name
= nullptr;
274 int rc
= ares_expand_name(*data
, packet
.data(), packet
.size(), &name
, &enclen
);
275 if (rc
!= ARES_SUCCESS
) {
276 ss
<< "(error from ares_expand_name)";
280 ss
<< "(error, encoded name len " << enclen
<< "bigger than remaining data " << *len
<< " bytes)";
285 ss
<< "'" << name
<< "' ";
289 if (*len
< NS_RRFIXEDSZ
) {
290 ss
<< "(too short, len left " << *len
<< ")";
293 int rrtype
= DNS_RR_TYPE(*data
);
294 if (rrtype
== ns_t_opt
) {
295 ss
<< "MAXUDP=" << DNS_RR_CLASS(*data
) << " ";
296 ss
<< RRTypeToString(rrtype
) << " ";
297 ss
<< "RCODE2=" << DNS_RR_TTL(*data
);
299 ss
<< ClassToString(DNS_RR_CLASS(*data
)) << " ";
300 ss
<< RRTypeToString(rrtype
) << " ";
301 ss
<< "TTL=" << DNS_RR_TTL(*data
);
303 int rdatalen
= DNS_RR_LEN(*data
);
305 *data
+= NS_RRFIXEDSZ
;
306 *len
-= NS_RRFIXEDSZ
;
307 if (*len
< rdatalen
) {
308 ss
<< "(RR too long at " << rdatalen
<< ", len left " << *len
<< ")";
313 ss
<< " " << AddressToString(*data
, rdatalen
);
316 const byte
* p
= *data
;
317 while (p
< (*data
+ rdatalen
)) {
319 if ((p
+ len
) <= (*data
+ rdatalen
)) {
320 std::string
txt(p
, p
+ len
);
321 ss
<< " " << len
<< ":'" << txt
<< "'";
323 ss
<< "(string too long)";
332 int rc
= ares_expand_name(*data
, packet
.data(), packet
.size(), &name
, &enclen
);
333 if (rc
!= ARES_SUCCESS
) {
334 ss
<< "(error from ares_expand_name)";
337 ss
<< " '" << name
<< "'";
343 int rc
= ares_expand_name(*data
+ 2, packet
.data(), packet
.size(), &name
, &enclen
);
344 if (rc
!= ARES_SUCCESS
) {
345 ss
<< "(error from ares_expand_name)";
348 ss
<< " " << DNS__16BIT(*data
) << " '" << name
<< "'";
351 ss
<< "(RR too short)";
356 const byte
* p
= *data
;
357 unsigned long prio
= DNS__16BIT(p
);
358 unsigned long weight
= DNS__16BIT(p
+ 2);
359 unsigned long port
= DNS__16BIT(p
+ 4);
361 int rc
= ares_expand_name(p
, packet
.data(), packet
.size(), &name
, &enclen
);
362 if (rc
!= ARES_SUCCESS
) {
363 ss
<< "(error from ares_expand_name)";
366 ss
<< prio
<< " " << weight
<< " " << port
<< " '" << name
<< "'";
369 ss
<< "(RR too short)";
374 const byte
* p
= *data
;
375 int rc
= ares_expand_name(p
, packet
.data(), packet
.size(), &name
, &enclen
);
376 if (rc
!= ARES_SUCCESS
) {
377 ss
<< "(error from ares_expand_name)";
380 ss
<< " '" << name
<< "'";
383 rc
= ares_expand_name(p
, packet
.data(), packet
.size(), &name
, &enclen
);
384 if (rc
!= ARES_SUCCESS
) {
385 ss
<< "(error from ares_expand_name)";
388 ss
<< " '" << name
<< "'";
391 if ((p
+ 20) <= (*data
+ rdatalen
)) {
392 unsigned long serial
= DNS__32BIT(p
);
393 unsigned long refresh
= DNS__32BIT(p
+ 4);
394 unsigned long retry
= DNS__32BIT(p
+ 8);
395 unsigned long expire
= DNS__32BIT(p
+ 12);
396 unsigned long minimum
= DNS__32BIT(p
+ 16);
397 ss
<< " " << serial
<< " " << refresh
<< " " << retry
<< " " << expire
<< " " << minimum
;
399 ss
<< "(RR too short)";
405 const byte
* p
= *data
;
406 unsigned long order
= DNS__16BIT(p
);
407 unsigned long pref
= DNS__16BIT(p
+ 2);
409 ss
<< order
<< " " << pref
;
412 std::string
flags(p
, p
+ len
);
417 std::string
service(p
, p
+ len
);
418 ss
<< " '" << service
<< "'";
422 std::string
regexp(p
, p
+ len
);
423 ss
<< " '" << regexp
<< "'";
426 int rc
= ares_expand_name(p
, packet
.data(), packet
.size(), &name
, &enclen
);
427 if (rc
!= ARES_SUCCESS
) {
428 ss
<< "(error from ares_expand_name)";
431 ss
<< " '" << name
<< "'";
434 ss
<< "(RR too short)";
439 ss
<< " " << HexDump(*data
, rdatalen
);
450 void PushInt32(std::vector
<byte
>* data
, int value
) {
451 data
->push_back((value
& 0xff000000) >> 24);
452 data
->push_back((value
& 0x00ff0000) >> 16);
453 data
->push_back((value
& 0x0000ff00) >> 8);
454 data
->push_back(value
& 0x000000ff);
457 void PushInt16(std::vector
<byte
>* data
, int value
) {
458 data
->push_back((value
& 0xff00) >> 8);
459 data
->push_back(value
& 0x00ff);
462 std::vector
<byte
> EncodeString(const std::string
& name
) {
463 std::vector
<byte
> data
;
464 std::stringstream
ss(name
);
466 // TODO: cope with escapes
467 while (std::getline(ss
, label
, '.')) {
468 data
.push_back(label
.length());
469 data
.insert(data
.end(), label
.begin(), label
.end());
475 std::vector
<byte
> DNSQuestion::data() const {
476 std::vector
<byte
> data
;
477 std::vector
<byte
> encname
= EncodeString(name_
);
478 data
.insert(data
.end(), encname
.begin(), encname
.end());
479 PushInt16(&data
, rrtype_
);
480 PushInt16(&data
, qclass_
);
484 std::vector
<byte
> DNSRR::data() const {
485 std::vector
<byte
> data
= DNSQuestion::data();
486 PushInt32(&data
, ttl_
);
490 std::vector
<byte
> DNSSingleNameRR::data() const {
491 std::vector
<byte
> data
= DNSRR::data();
492 std::vector
<byte
> encname
= EncodeString(other_
);
493 int len
= encname
.size();
494 PushInt16(&data
, len
);
495 data
.insert(data
.end(), encname
.begin(), encname
.end());
499 std::vector
<byte
> DNSTxtRR::data() const {
500 std::vector
<byte
> data
= DNSRR::data();
502 for (const std::string
& txt
: txt_
) {
503 len
+= (1 + txt
.size());
505 PushInt16(&data
, len
);
506 for (const std::string
& txt
: txt_
) {
507 data
.push_back(txt
.size());
508 data
.insert(data
.end(), txt
.begin(), txt
.end());
513 std::vector
<byte
> DNSMxRR::data() const {
514 std::vector
<byte
> data
= DNSRR::data();
515 std::vector
<byte
> encname
= EncodeString(other_
);
516 int len
= 2 + encname
.size();
517 PushInt16(&data
, len
);
518 PushInt16(&data
, pref_
);
519 data
.insert(data
.end(), encname
.begin(), encname
.end());
523 std::vector
<byte
> DNSSrvRR::data() const {
524 std::vector
<byte
> data
= DNSRR::data();
525 std::vector
<byte
> encname
= EncodeString(target_
);
526 int len
= 6 + encname
.size();
527 PushInt16(&data
, len
);
528 PushInt16(&data
, prio_
);
529 PushInt16(&data
, weight_
);
530 PushInt16(&data
, port_
);
531 data
.insert(data
.end(), encname
.begin(), encname
.end());
535 std::vector
<byte
> DNSAddressRR::data() const {
536 std::vector
<byte
> data
= DNSRR::data();
537 int len
= addr_
.size();
538 PushInt16(&data
, len
);
539 data
.insert(data
.end(), addr_
.begin(), addr_
.end());
543 std::vector
<byte
> DNSSoaRR::data() const {
544 std::vector
<byte
> data
= DNSRR::data();
545 std::vector
<byte
> encname1
= EncodeString(nsname_
);
546 std::vector
<byte
> encname2
= EncodeString(rname_
);
547 int len
= encname1
.size() + encname2
.size() + 5*4;
548 PushInt16(&data
, len
);
549 data
.insert(data
.end(), encname1
.begin(), encname1
.end());
550 data
.insert(data
.end(), encname2
.begin(), encname2
.end());
551 PushInt32(&data
, serial_
);
552 PushInt32(&data
, refresh_
);
553 PushInt32(&data
, retry_
);
554 PushInt32(&data
, expire_
);
555 PushInt32(&data
, minimum_
);
559 std::vector
<byte
> DNSOptRR::data() const {
560 std::vector
<byte
> data
= DNSRR::data();
562 for (const DNSOption
& opt
: opts_
) {
563 len
+= (4 + opt
.data_
.size());
565 PushInt16(&data
, len
);
566 for (const DNSOption
& opt
: opts_
) {
567 PushInt16(&data
, opt
.code_
);
568 PushInt16(&data
, opt
.data_
.size());
569 data
.insert(data
.end(), opt
.data_
.begin(), opt
.data_
.end());
574 std::vector
<byte
> DNSNaptrRR::data() const {
575 std::vector
<byte
> data
= DNSRR::data();
576 std::vector
<byte
> encname
= EncodeString(replacement_
);
577 int len
= (4 + 1 + flags_
.size() + 1 + service_
.size() + 1 + regexp_
.size() + encname
.size());
578 PushInt16(&data
, len
);
579 PushInt16(&data
, order_
);
580 PushInt16(&data
, pref_
);
581 data
.push_back(flags_
.size());
582 data
.insert(data
.end(), flags_
.begin(), flags_
.end());
583 data
.push_back(service_
.size());
584 data
.insert(data
.end(), service_
.begin(), service_
.end());
585 data
.push_back(regexp_
.size());
586 data
.insert(data
.end(), regexp_
.begin(), regexp_
.end());
587 data
.insert(data
.end(), encname
.begin(), encname
.end());
591 std::vector
<byte
> DNSPacket::data() const {
592 std::vector
<byte
> data
;
593 PushInt16(&data
, qid_
);
595 if (response_
) b
|= 0x80;
596 b
|= ((opcode_
& 0x0f) << 3);
606 b
|= (rcode_
& 0x0f);
609 int count
= questions_
.size();
610 PushInt16(&data
, count
);
611 count
= answers_
.size();
612 PushInt16(&data
, count
);
613 count
= auths_
.size();
614 PushInt16(&data
, count
);
615 count
= adds_
.size();
616 PushInt16(&data
, count
);
618 for (const std::unique_ptr
<DNSQuestion
>& question
: questions_
) {
619 std::vector
<byte
> qdata
= question
->data();
620 data
.insert(data
.end(), qdata
.begin(), qdata
.end());
622 for (const std::unique_ptr
<DNSRR
>& rr
: answers_
) {
623 std::vector
<byte
> rrdata
= rr
->data();
624 data
.insert(data
.end(), rrdata
.begin(), rrdata
.end());
626 for (const std::unique_ptr
<DNSRR
>& rr
: auths_
) {
627 std::vector
<byte
> rrdata
= rr
->data();
628 data
.insert(data
.end(), rrdata
.begin(), rrdata
.end());
630 for (const std::unique_ptr
<DNSRR
>& rr
: adds_
) {
631 std::vector
<byte
> rrdata
= rr
->data();
632 data
.insert(data
.end(), rrdata
.begin(), rrdata
.end());