quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

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