• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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