1 /* MIT License
2 *
3 * Copyright (c) The c-ares project and its contributors
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26
27 // Include ares internal file for DNS protocol details
28 #include "ares_setup.h"
29 #include "ares.h"
30 #include "ares_dns.h"
31 #include "dns-proto.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include <sstream>
37 #include <algorithm>
38
39 #if defined(_WIN32) && !defined(strcasecmp)
40 # define strcasecmp(a,b) stricmp(a,b)
41 #endif
42
arestest_strtolower(char * dest,const char * src,size_t dest_size)43 void arestest_strtolower(char *dest, const char *src, size_t dest_size)
44 {
45 size_t len;
46
47 if (dest == NULL)
48 return;
49
50 memset(dest, 0, dest_size);
51
52 if (src == NULL)
53 return;
54
55 len = strlen(src);
56 if (len >= dest_size)
57 return;
58
59 for (size_t i = 0; i<len; i++) {
60 dest[i] = (char)tolower(src[i]);
61 }
62 }
63
64
65 namespace ares {
66
HexDump(std::vector<byte> data)67 std::string HexDump(std::vector<byte> data) {
68 std::stringstream ss;
69 for (size_t ii = 0; ii < data.size(); ii++) {
70 char buffer[2 + 1];
71 snprintf(buffer, sizeof(buffer), "%02x", data[ii]);
72 ss << buffer;
73 }
74 return ss.str();
75 }
76
HexDump(const byte * data,int len)77 std::string HexDump(const byte *data, int len) {
78 return HexDump(std::vector<byte>(data, data + len));
79 }
80
HexDump(const char * data,int len)81 std::string HexDump(const char *data, int len) {
82 return HexDump(reinterpret_cast<const byte*>(data), len);
83 }
84
StatusToString(int status)85 std::string StatusToString(int status) {
86 switch (status) {
87 case ARES_SUCCESS: return "ARES_SUCCESS";
88 case ARES_ENODATA: return "ARES_ENODATA";
89 case ARES_EFORMERR: return "ARES_EFORMERR";
90 case ARES_ESERVFAIL: return "ARES_ESERVFAIL";
91 case ARES_ENOTFOUND: return "ARES_ENOTFOUND";
92 case ARES_ENOTIMP: return "ARES_ENOTIMP";
93 case ARES_EREFUSED: return "ARES_EREFUSED";
94 case ARES_EBADQUERY: return "ARES_EBADQUERY";
95 case ARES_EBADNAME: return "ARES_EBADNAME";
96 case ARES_EBADFAMILY: return "ARES_EBADFAMILY";
97 case ARES_EBADRESP: return "ARES_EBADRESP";
98 case ARES_ECONNREFUSED: return "ARES_ECONNREFUSED";
99 case ARES_ETIMEOUT: return "ARES_ETIMEOUT";
100 case ARES_EOF: return "ARES_EOF";
101 case ARES_EFILE: return "ARES_EFILE";
102 case ARES_ENOMEM: return "ARES_ENOMEM";
103 case ARES_EDESTRUCTION: return "ARES_EDESTRUCTION";
104 case ARES_EBADSTR: return "ARES_EBADSTR";
105 case ARES_EBADFLAGS: return "ARES_EBADFLAGS";
106 case ARES_ENONAME: return "ARES_ENONAME";
107 case ARES_EBADHINTS: return "ARES_EBADHINTS";
108 case ARES_ENOTINITIALIZED: return "ARES_ENOTINITIALIZED";
109 case ARES_ELOADIPHLPAPI: return "ARES_ELOADIPHLPAPI";
110 case ARES_EADDRGETNETWORKPARAMS: return "ARES_EADDRGETNETWORKPARAMS";
111 case ARES_ECANCELLED: return "ARES_ECANCELLED";
112 default: return "UNKNOWN";
113 }
114 }
115
RcodeToString(int rcode)116 std::string RcodeToString(int rcode) {
117 switch (rcode) {
118 case NOERROR: return "NOERROR";
119 case FORMERR: return "FORMERR";
120 case SERVFAIL: return "SERVFAIL";
121 case NXDOMAIN: return "NXDOMAIN";
122 case NOTIMP: return "NOTIMP";
123 case REFUSED: return "REFUSED";
124 case YXDOMAIN: return "YXDOMAIN";
125 case YXRRSET: return "YXRRSET";
126 case NXRRSET: return "NXRRSET";
127 case NOTAUTH: return "NOTAUTH";
128 case NOTZONE: return "NOTZONE";
129 case TSIG_BADSIG: return "BADSIG";
130 case TSIG_BADKEY: return "BADKEY";
131 case TSIG_BADTIME: return "BADTIME";
132 default: return "UNKNOWN";
133 }
134 }
135
RRTypeToString(int rrtype)136 std::string RRTypeToString(int rrtype) {
137 switch (rrtype) {
138 case T_A: return "A";
139 case T_NS: return "NS";
140 case T_MD: return "MD";
141 case T_MF: return "MF";
142 case T_CNAME: return "CNAME";
143 case T_SOA: return "SOA";
144 case T_MB: return "MB";
145 case T_MG: return "MG";
146 case T_MR: return "MR";
147 case T_NULL: return "NULL";
148 case T_WKS: return "WKS";
149 case T_PTR: return "PTR";
150 case T_HINFO: return "HINFO";
151 case T_MINFO: return "MINFO";
152 case T_MX: return "MX";
153 case T_TXT: return "TXT";
154 case T_RP: return "RP";
155 case T_AFSDB: return "AFSDB";
156 case T_X25: return "X25";
157 case T_ISDN: return "ISDN";
158 case T_RT: return "RT";
159 case T_NSAP: return "NSAP";
160 case T_NSAP_PTR: return "NSAP_PTR";
161 case T_SIG: return "SIG";
162 case T_KEY: return "KEY";
163 case T_PX: return "PX";
164 case T_GPOS: return "GPOS";
165 case T_AAAA: return "AAAA";
166 case T_LOC: return "LOC";
167 case T_NXT: return "NXT";
168 case T_EID: return "EID";
169 case T_NIMLOC: return "NIMLOC";
170 case T_SRV: return "SRV";
171 case T_ATMA: return "ATMA";
172 case T_NAPTR: return "NAPTR";
173 case T_KX: return "KX";
174 case T_CERT: return "CERT";
175 case T_A6: return "A6";
176 case T_DNAME: return "DNAME";
177 case T_SINK: return "SINK";
178 case T_OPT: return "OPT";
179 case T_APL: return "APL";
180 case T_DS: return "DS";
181 case T_SSHFP: return "SSHFP";
182 case T_RRSIG: return "RRSIG";
183 case T_NSEC: return "NSEC";
184 case T_DNSKEY: return "DNSKEY";
185 case T_TKEY: return "TKEY";
186 case T_TSIG: return "TSIG";
187 case T_IXFR: return "IXFR";
188 case T_AXFR: return "AXFR";
189 case T_MAILB: return "MAILB";
190 case T_MAILA: return "MAILA";
191 case T_ANY: return "ANY";
192 case T_URI: return "URI";
193 case T_MAX: return "MAX";
194 default: return "UNKNOWN";
195 }
196 }
197
ClassToString(int qclass)198 std::string ClassToString(int qclass) {
199 switch (qclass) {
200 case C_IN: return "IN";
201 case C_CHAOS: return "CHAOS";
202 case C_HS: return "HESIOD";
203 case C_NONE: return "NONE";
204 case C_ANY: return "ANY";
205 default: return "UNKNOWN";
206 }
207 }
208
AddressToString(const void * vaddr,int len)209 std::string AddressToString(const void* vaddr, int len) {
210 const byte* addr = reinterpret_cast<const byte*>(vaddr);
211 std::stringstream ss;
212 if (len == 4) {
213 char buffer[4*4 + 3 + 1];
214 snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u",
215 (unsigned char)addr[0],
216 (unsigned char)addr[1],
217 (unsigned char)addr[2],
218 (unsigned char)addr[3]);
219 ss << buffer;
220 } else if (len == 16) {
221 for (int ii = 0; ii < 16; ii+=2) {
222 if (ii > 0) ss << ':';
223 char buffer[4 + 1];
224 snprintf(buffer, sizeof(buffer), "%02x%02x", (unsigned char)addr[ii], (unsigned char)addr[ii+1]);
225 ss << buffer;
226 }
227 } else {
228 ss << "!" << HexDump(addr, len) << "!";
229 }
230 return ss.str();
231 }
232
PacketToString(const std::vector<byte> & packet)233 std::string PacketToString(const std::vector<byte>& packet) {
234 const byte* data = packet.data();
235 int len = (int)packet.size();
236 std::stringstream ss;
237 if (len < NS_HFIXEDSZ) {
238 ss << "(too short, len " << len << ")";
239 return ss.str();
240 }
241 ss << ((DNS_HEADER_QR(data) == 0) ? "REQ " : "RSP ");
242 switch (DNS_HEADER_OPCODE(data)) {
243 case O_QUERY: ss << "QRY "; break;
244 case O_IQUERY: ss << "IQRY "; break;
245 case O_STATUS: ss << "STATUS "; break;
246 case O_NOTIFY: ss << "NOTIFY "; break;
247 case O_UPDATE: ss << "UPDATE "; break;
248 default: ss << "UNKNOWN(" << DNS_HEADER_OPCODE(data) << ") "; break;
249 }
250 if (DNS_HEADER_AA(data)) ss << "AA ";
251 if (DNS_HEADER_TC(data)) ss << "TC ";
252 if (DNS_HEADER_RD(data)) ss << "RD ";
253 if (DNS_HEADER_RA(data)) ss << "RA ";
254 if (DNS_HEADER_Z(data)) ss << "Z ";
255 if (DNS_HEADER_QR(data) == 1) ss << RcodeToString(DNS_HEADER_RCODE(data));
256
257 int nquestions = DNS_HEADER_QDCOUNT(data);
258 int nanswers = DNS_HEADER_ANCOUNT(data);
259 int nauths = DNS_HEADER_NSCOUNT(data);
260 int nadds = DNS_HEADER_ARCOUNT(data);
261
262 const byte* pq = data + NS_HFIXEDSZ;
263 len -= NS_HFIXEDSZ;
264 for (int ii = 0; ii < nquestions; ii++) {
265 ss << " Q:" << QuestionToString(packet, &pq, &len);
266 }
267 const byte* prr = pq;
268 for (int ii = 0; ii < nanswers; ii++) {
269 ss << " A:" << RRToString(packet, &prr, &len);
270 }
271 for (int ii = 0; ii < nauths; ii++) {
272 ss << " AUTH:" << RRToString(packet, &prr, &len);
273 }
274 for (int ii = 0; ii < nadds; ii++) {
275 ss << " ADD:" << RRToString(packet, &prr, &len);
276 }
277 return ss.str();
278 }
279
QuestionToString(const std::vector<byte> & packet,const byte ** data,int * len)280 std::string QuestionToString(const std::vector<byte>& packet,
281 const byte** data, int* len) {
282 std::stringstream ss;
283 ss << "{";
284 if (*len < NS_QFIXEDSZ) {
285 ss << "(too short, len " << *len << ")";
286 return ss.str();
287 }
288
289 char *name = nullptr;
290 long enclen;
291 int rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
292 if (rc != ARES_SUCCESS) {
293 ss << "(error from ares_expand_name)";
294 return ss.str();
295 }
296 if (enclen > *len) {
297 ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
298 return ss.str();
299 }
300 *len -= (int)enclen;
301 *data += enclen;
302
303 // DNS 0x20 may mix case, output as all lower for checks as the mixed case
304 // is really more of an internal thing
305 char lowername[256];
306 arestest_strtolower(lowername, name, sizeof(lowername));
307 ares_free_string(name);
308
309 ss << "'" << lowername << "' ";
310 if (*len < NS_QFIXEDSZ) {
311 ss << "(too short, len left " << *len << ")";
312 return ss.str();
313 }
314 ss << ClassToString(DNS_QUESTION_CLASS(*data)) << " ";
315 ss << RRTypeToString(DNS_QUESTION_TYPE(*data));
316 *data += NS_QFIXEDSZ;
317 *len -= NS_QFIXEDSZ;
318 ss << "}";
319 return ss.str();
320 }
321
RRToString(const std::vector<byte> & packet,const byte ** data,int * len)322 std::string RRToString(const std::vector<byte>& packet,
323 const byte** data, int* len) {
324 std::stringstream ss;
325 ss << "{";
326 if (*len < NS_RRFIXEDSZ) {
327 ss << "too short, len " << *len << ")";
328 return ss.str();
329 }
330
331 char *name = nullptr;
332 long enclen;
333 int rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
334 if (rc != ARES_SUCCESS) {
335 ss << "(error from ares_expand_name)";
336 return ss.str();
337 }
338 if (enclen > *len) {
339 ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
340 return ss.str();
341 }
342 *len -= (int)enclen;
343 *data += enclen;
344 ss << "'" << name << "' ";
345 ares_free_string(name);
346 name = nullptr;
347
348 if (*len < NS_RRFIXEDSZ) {
349 ss << "(too short, len left " << *len << ")";
350 return ss.str();
351 }
352 int rrtype = DNS_RR_TYPE(*data);
353 if (rrtype == T_OPT) {
354 ss << "MAXUDP=" << DNS_RR_CLASS(*data) << " ";
355 ss << RRTypeToString(rrtype) << " ";
356 ss << "RCODE2=" << DNS_RR_TTL(*data);
357 } else {
358 ss << ClassToString(DNS_RR_CLASS(*data)) << " ";
359 ss << RRTypeToString(rrtype) << " ";
360 ss << "TTL=" << DNS_RR_TTL(*data);
361 }
362 int rdatalen = DNS_RR_LEN(*data);
363
364 *data += NS_RRFIXEDSZ;
365 *len -= NS_RRFIXEDSZ;
366 if (*len < rdatalen) {
367 ss << "(RR too long at " << rdatalen << ", len left " << *len << ")";
368 } else {
369 switch (rrtype) {
370 case T_A:
371 case T_AAAA:
372 ss << " " << AddressToString(*data, rdatalen);
373 break;
374 case T_TXT: {
375 const byte* p = *data;
376 while (p < (*data + rdatalen)) {
377 int tlen = *p++;
378 if ((p + tlen) <= (*data + rdatalen)) {
379 std::string txt(p, p + tlen);
380 ss << " " << tlen << ":'" << txt << "'";
381 } else {
382 ss << "(string too long)";
383 }
384 p += tlen;
385 }
386 break;
387 }
388 case T_CNAME:
389 case T_NS:
390 case T_PTR: {
391 rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
392 if (rc != ARES_SUCCESS) {
393 ss << "(error from ares_expand_name)";
394 break;
395 }
396 ss << " '" << name << "'";
397 ares_free_string(name);
398 break;
399 }
400 case T_MX:
401 if (rdatalen > 2) {
402 rc = ares_expand_name(*data + 2, packet.data(), (int)packet.size(), &name, &enclen);
403 if (rc != ARES_SUCCESS) {
404 ss << "(error from ares_expand_name)";
405 break;
406 }
407 ss << " " << DNS__16BIT(*data) << " '" << name << "'";
408 ares_free_string(name);
409 } else {
410 ss << "(RR too short)";
411 }
412 break;
413 case T_SRV: {
414 if (rdatalen > 6) {
415 const byte* p = *data;
416 unsigned long prio = DNS__16BIT(p);
417 unsigned long weight = DNS__16BIT(p + 2);
418 unsigned long port = DNS__16BIT(p + 4);
419 p += 6;
420 rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
421 if (rc != ARES_SUCCESS) {
422 ss << "(error from ares_expand_name)";
423 break;
424 }
425 ss << prio << " " << weight << " " << port << " '" << name << "'";
426 ares_free_string(name);
427 } else {
428 ss << "(RR too short)";
429 }
430 break;
431 }
432 case T_URI: {
433 if (rdatalen > 4) {
434 const byte* p = *data;
435 unsigned long prio = DNS__16BIT(p);
436 unsigned long weight = DNS__16BIT(p + 2);
437 p += 4;
438 std::string uri(p, p + (rdatalen - 4));
439 ss << prio << " " << weight << " '" << uri << "'";
440 } else {
441 ss << "(RR too short)";
442 }
443 break;
444 }
445 case T_SOA: {
446 const byte* p = *data;
447 rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
448 if (rc != ARES_SUCCESS) {
449 ss << "(error from ares_expand_name)";
450 break;
451 }
452 ss << " '" << name << "'";
453 ares_free_string(name);
454 p += enclen;
455 rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
456 if (rc != ARES_SUCCESS) {
457 ss << "(error from ares_expand_name)";
458 break;
459 }
460 ss << " '" << name << "'";
461 ares_free_string(name);
462 p += enclen;
463 if ((p + 20) <= (*data + rdatalen)) {
464 unsigned long serial = DNS__32BIT(p);
465 unsigned long refresh = DNS__32BIT(p + 4);
466 unsigned long retry = DNS__32BIT(p + 8);
467 unsigned long expire = DNS__32BIT(p + 12);
468 unsigned long minimum = DNS__32BIT(p + 16);
469 ss << " " << serial << " " << refresh << " " << retry << " " << expire << " " << minimum;
470 } else {
471 ss << "(RR too short)";
472 }
473 break;
474 }
475 case T_NAPTR: {
476 if (rdatalen > 7) {
477 const byte* p = *data;
478 unsigned long order = DNS__16BIT(p);
479 unsigned long pref = DNS__16BIT(p + 2);
480 p += 4;
481 ss << order << " " << pref;
482
483 int nlen = *p++;
484 std::string flags(p, p + nlen);
485 ss << " " << flags;
486 p += nlen;
487
488 nlen = *p++;
489 std::string service(p, p + nlen);
490 ss << " '" << service << "'";
491 p += nlen;
492
493 nlen = *p++;
494 std::string regexp(p, p + nlen);
495 ss << " '" << regexp << "'";
496 p += nlen;
497
498 rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
499 if (rc != ARES_SUCCESS) {
500 ss << "(error from ares_expand_name)";
501 break;
502 }
503 ss << " '" << name << "'";
504 ares_free_string(name);
505 } else {
506 ss << "(RR too short)";
507 }
508 break;
509 }
510 default:
511 ss << " " << HexDump(*data, rdatalen);
512 break;
513 }
514 }
515 *data += rdatalen;
516 *len -= rdatalen;
517
518 ss << "}";
519 return ss.str();
520 }
521
PushInt32(std::vector<byte> * data,int value)522 void PushInt32(std::vector<byte>* data, int value) {
523 data->push_back((byte)(((unsigned int)value & 0xff000000) >> 24));
524 data->push_back((byte)(((unsigned int)value & 0x00ff0000) >> 16));
525 data->push_back((byte)(((unsigned int)value & 0x0000ff00) >> 8));
526 data->push_back((byte)(value & 0x000000ff));
527 }
528
PushInt16(std::vector<byte> * data,int value)529 void PushInt16(std::vector<byte>* data, int value) {
530 data->push_back((byte)((value & 0xff00) >> 8));
531 data->push_back((byte)value & 0x00ff);
532 }
533
EncodeString(const std::string & name)534 std::vector<byte> EncodeString(const std::string &name) {
535 std::vector<byte> data;
536 std::stringstream ss(name);
537 std::string label;
538 // TODO: cope with escapes
539 while (std::getline(ss, label, '.')) {
540 /* Label length of 0 indicates the end, and we always push an end
541 * terminator, so don't do it twice */
542 if (label.length() == 0)
543 break;
544 data.push_back((byte)label.length());
545 data.insert(data.end(), label.begin(), label.end());
546 }
547 data.push_back(0);
548 return data;
549 }
550
data(const char * request_name,const ares_dns_record_t * dnsrec) const551 std::vector<byte> DNSQuestion::data(const char *request_name, const ares_dns_record_t *dnsrec) const {
552 std::vector<byte> data;
553 std::vector<byte> encname;
554 if (request_name != nullptr && strcasecmp(request_name, name_.c_str()) == 0) {
555 encname = EncodeString(request_name);
556 } else {
557 encname = EncodeString(name_);
558 }
559 data.insert(data.end(), encname.begin(), encname.end());
560 PushInt16(&data, rrtype_);
561 PushInt16(&data, qclass_);
562 return data;
563 }
564
data(const ares_dns_record_t * dnsrec) const565 std::vector<byte> DNSRR::data(const ares_dns_record_t *dnsrec) const {
566 std::vector<byte> data = DNSQuestion::data(dnsrec);
567 PushInt32(&data, ttl_);
568 return data;
569 }
570
data(const ares_dns_record_t * dnsrec) const571 std::vector<byte> DNSSingleNameRR::data(const ares_dns_record_t *dnsrec) const {
572 std::vector<byte> data = DNSRR::data(dnsrec);
573 std::vector<byte> encname = EncodeString(other_);
574 int len = (int)encname.size();
575 PushInt16(&data, len);
576 data.insert(data.end(), encname.begin(), encname.end());
577 return data;
578 }
579
data(const ares_dns_record_t * dnsrec) const580 std::vector<byte> DNSTxtRR::data(const ares_dns_record_t *dnsrec) const {
581 std::vector<byte> data = DNSRR::data(dnsrec);
582 int len = 0;
583 for (const std::string& txt : txt_) {
584 len += (1 + (int)txt.size());
585 }
586 PushInt16(&data, len);
587 for (const std::string& txt : txt_) {
588 data.push_back((byte)txt.size());
589 data.insert(data.end(), txt.begin(), txt.end());
590 }
591 return data;
592 }
593
data(const ares_dns_record_t * dnsrec) const594 std::vector<byte> DNSMxRR::data(const ares_dns_record_t *dnsrec) const {
595 std::vector<byte> data = DNSRR::data(dnsrec);
596 std::vector<byte> encname = EncodeString(other_);
597 int len = 2 + (int)encname.size();
598 PushInt16(&data, len);
599 PushInt16(&data, pref_);
600 data.insert(data.end(), encname.begin(), encname.end());
601 return data;
602 }
603
data(const ares_dns_record_t * dnsrec) const604 std::vector<byte> DNSSrvRR::data(const ares_dns_record_t *dnsrec) const {
605 std::vector<byte> data = DNSRR::data(dnsrec);
606 std::vector<byte> encname = EncodeString(target_);
607 int len = 6 + (int)encname.size();
608 PushInt16(&data, len);
609 PushInt16(&data, prio_);
610 PushInt16(&data, weight_);
611 PushInt16(&data, port_);
612 data.insert(data.end(), encname.begin(), encname.end());
613 return data;
614 }
615
data(const ares_dns_record_t * dnsrec) const616 std::vector<byte> DNSUriRR::data(const ares_dns_record_t *dnsrec) const {
617 std::vector<byte> data = DNSRR::data(dnsrec);
618 int len = 4 + (int)target_.size();
619 PushInt16(&data, len);
620 PushInt16(&data, prio_);
621 PushInt16(&data, weight_);
622 data.insert(data.end(), target_.begin(), target_.end());
623 return data;
624 }
625
data(const ares_dns_record_t * dnsrec) const626 std::vector<byte> DNSAddressRR::data(const ares_dns_record_t *dnsrec) const {
627 std::vector<byte> data = DNSRR::data(dnsrec);
628 int len = (int)addr_.size();
629 PushInt16(&data, len);
630 data.insert(data.end(), addr_.begin(), addr_.end());
631 return data;
632 }
633
data(const ares_dns_record_t * dnsrec) const634 std::vector<byte> DNSSoaRR::data(const ares_dns_record_t *dnsrec) const {
635 std::vector<byte> data = DNSRR::data(dnsrec);
636 std::vector<byte> encname1 = EncodeString(nsname_);
637 std::vector<byte> encname2 = EncodeString(rname_);
638 int len = (int)encname1.size() + (int)encname2.size() + 5*4;
639 PushInt16(&data, len);
640 data.insert(data.end(), encname1.begin(), encname1.end());
641 data.insert(data.end(), encname2.begin(), encname2.end());
642 PushInt32(&data, serial_);
643 PushInt32(&data, refresh_);
644 PushInt32(&data, retry_);
645 PushInt32(&data, expire_);
646 PushInt32(&data, minimum_);
647 return data;
648 }
649
fetch_rr_opt(const ares_dns_record_t * rec)650 const ares_dns_rr_t *fetch_rr_opt(const ares_dns_record_t *rec)
651 {
652 size_t i;
653 for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
654 const ares_dns_rr_t *rr =
655 ares_dns_record_rr_get_const(rec, ARES_SECTION_ADDITIONAL, i);
656
657 if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
658 return rr;
659 }
660 }
661 return NULL;
662 }
663
data(const ares_dns_record_t * dnsrec) const664 std::vector<byte> DNSOptRR::data(const ares_dns_record_t *dnsrec) const {
665 std::vector<byte> data = DNSRR::data(dnsrec);
666 int len = 0;
667 std::vector<byte> cookie;
668 const ares_dns_rr_t *rr = fetch_rr_opt(dnsrec);
669 size_t passed_cookie_len = 0;
670 const unsigned char *passed_cookie = NULL;
671
672 ares_dns_rr_get_opt_byid(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE,
673 &passed_cookie, &passed_cookie_len);
674
675 /* Error out if we expected a server cookie but didn't get one, or if the
676 * passed in server cookie doesn't match our expected value */
677 if (expect_server_cookie_ &&
678 (passed_cookie_len <= 8 ||
679 passed_cookie_len - 8 != server_cookie_.size() ||
680 memcmp(passed_cookie + 8, server_cookie_.data(), server_cookie_.size()) != 0
681 )
682 ) {
683 data.clear();
684 return data;
685 }
686
687 /* See if we should be applying a server cookie */
688 if (server_cookie_.size() && passed_cookie_len >= 8) {
689 /* If client cookie was provided to test framework, we are overwriting
690 * the one received from the client. This is likely to test failure
691 * scenarios */
692 if (client_cookie_.size()) {
693 cookie.insert(cookie.end(), client_cookie_.begin(), client_cookie_.end());
694 } else {
695 cookie.insert(cookie.end(), passed_cookie, passed_cookie+8);
696 }
697 cookie.insert(cookie.end(), server_cookie_.begin(), server_cookie_.end());
698 }
699
700 if (cookie.size()) {
701 len += 4 + (int)cookie.size();
702 }
703 for (const DNSOption& opt : opts_) {
704 len += (4 + (int)opt.data_.size());
705 }
706
707 PushInt16(&data, len);
708 for (const DNSOption& opt : opts_) {
709 PushInt16(&data, opt.code_);
710 PushInt16(&data, (int)opt.data_.size());
711 data.insert(data.end(), opt.data_.begin(), opt.data_.end());
712 }
713
714 if (cookie.size()) {
715 PushInt16(&data, ARES_OPT_PARAM_COOKIE);
716 PushInt16(&data, (int)cookie.size());
717 data.insert(data.end(), cookie.begin(), cookie.end());
718 }
719
720 return data;
721 }
722
data(const ares_dns_record_t * dnsrec) const723 std::vector<byte> DNSNaptrRR::data(const ares_dns_record_t *dnsrec) const {
724 std::vector<byte> data = DNSRR::data(dnsrec);
725 std::vector<byte> encname = EncodeString(replacement_);
726 int len = (4 + 1 + (int)flags_.size() + 1 + (int)service_.size() + 1 + (int)regexp_.size() + (int)encname.size());
727 PushInt16(&data, len);
728 PushInt16(&data, order_);
729 PushInt16(&data, pref_);
730 data.push_back((byte)flags_.size());
731 data.insert(data.end(), flags_.begin(), flags_.end());
732 data.push_back((byte)service_.size());
733 data.insert(data.end(), service_.begin(), service_.end());
734 data.push_back((byte)regexp_.size());
735 data.insert(data.end(), regexp_.begin(), regexp_.end());
736 data.insert(data.end(), encname.begin(), encname.end());
737 return data;
738 }
739
data(const char * request_name,const ares_dns_record_t * dnsrec) const740 std::vector<byte> DNSPacket::data(const char *request_name, const ares_dns_record_t *dnsrec) const {
741 std::vector<byte> data;
742 PushInt16(&data, qid_);
743 byte b = 0x00;
744 if (response_) b |= 0x80;
745 b |= ((opcode_ & 0x0f) << 3);
746 if (aa_) b |= 0x04;
747 if (tc_) b |= 0x02;
748 if (rd_) b |= 0x01;
749 data.push_back(b);
750 b = 0x00;
751 if (ra_) b |= 0x80;
752 if (z_) b |= 0x40;
753 if (ad_) b |= 0x20;
754 if (cd_) b |= 0x10;
755 b |= (rcode_ & 0x0f);
756 data.push_back(b);
757
758 int count = (int)questions_.size();
759 PushInt16(&data, count);
760 count = (int)answers_.size();
761 PushInt16(&data, count);
762 count = (int)auths_.size();
763 PushInt16(&data, count);
764 count = (int)adds_.size();
765 PushInt16(&data, count);
766
767 for (const std::unique_ptr<DNSQuestion>& question : questions_) {
768 std::vector<byte> qdata = question->data(request_name, dnsrec);
769 if (qdata.size() == 0) {
770 data.clear();
771 return data;
772 }
773 data.insert(data.end(), qdata.begin(), qdata.end());
774 }
775 for (const std::unique_ptr<DNSRR>& rr : answers_) {
776 std::vector<byte> rrdata = rr->data(dnsrec);
777 if (rrdata.size() == 0) {
778 data.clear();
779 return data;
780 }
781 data.insert(data.end(), rrdata.begin(), rrdata.end());
782 }
783 for (const std::unique_ptr<DNSRR>& rr : auths_) {
784 std::vector<byte> rrdata = rr->data(dnsrec);
785 if (rrdata.size() == 0) {
786 data.clear();
787 return data;
788 }
789 data.insert(data.end(), rrdata.begin(), rrdata.end());
790 }
791 for (const std::unique_ptr<DNSRR>& rr : adds_) {
792 std::vector<byte> rrdata = rr->data(dnsrec);
793 if (rrdata.size() == 0) {
794 data.clear();
795 return data;
796 }
797 data.insert(data.end(), rrdata.begin(), rrdata.end());
798 }
799 return data;
800 }
801
802 } // namespace ares
803