dns-proto.cc (24441B)
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 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 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 77 std::string HexDump(const byte *data, int len) { 78 return HexDump(std::vector<byte>(data, data + len)); 79 } 80 81 std::string HexDump(const char *data, int len) { 82 return HexDump(reinterpret_cast<const byte*>(data), len); 83 } 84 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 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 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 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 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 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 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 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 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 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 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 551 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 565 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 571 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 580 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 594 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 604 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 616 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 626 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 634 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 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 664 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 723 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 740 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