• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

c-ares / c-ares / 12675075779

08 Jan 2025 04:43PM UTC coverage: 91.497% (-0.03%) from 91.526%
12675075779

push

github

web-flow
CI: GitHub actions ubuntu-latest now points to 24.04 causing some minor issues (#957)

Containerized tests now need to be run with sudo to gain access to
chroot(). Also, `gcov` in ubuntu 24.04 is broken with googletest so
revert back to 22.04 for coverage.

Finally, codespell is updated in 24.04 to detect more issues and there
were some typos that needed to be fixed.

Signed-off-by: Brad House (@bradh352)

22404 of 24486 relevant lines covered (91.5%)

11927.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.48
/test/dns-proto.cc
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)
11,756✔
44
{
45
  size_t len;
46

47
  if (dest == NULL)
11,756✔
48
    return;
×
49

50
  memset(dest, 0, dest_size);
11,756✔
51

52
  if (src == NULL)
11,756✔
53
    return;
×
54

55
  len = strlen(src);
11,756✔
56
  if (len >= dest_size)
11,756✔
57
    return;
×
58

59
  for (size_t i = 0; i<len; i++) {
172,674✔
60
    dest[i] = (char)tolower(src[i]);
160,918✔
61
  }
62
}
63

64

65
namespace ares {
66

67
std::string HexDump(std::vector<byte> data) {
1,632✔
68
  std::stringstream ss;
1,632✔
69
  for (size_t ii = 0; ii < data.size();  ii++) {
12,218✔
70
    char buffer[2 + 1];
71
    snprintf(buffer, sizeof(buffer), "%02x", data[ii]);
10,586✔
72
    ss << buffer;
10,586✔
73
  }
74
  return ss.str();
3,264✔
75
}
1,632✔
76

77
std::string HexDump(const byte *data, int len) {
1,632✔
78
  return HexDump(std::vector<byte>(data, data + len));
3,264✔
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) {
4,823✔
86
  switch (status) {
4,823✔
87
  case ARES_SUCCESS: return "ARES_SUCCESS";
1,456✔
88
  case ARES_ENODATA: return "ARES_ENODATA";
72✔
89
  case ARES_EFORMERR: return "ARES_EFORMERR";
8✔
90
  case ARES_ESERVFAIL: return "ARES_ESERVFAIL";
28✔
91
  case ARES_ENOTFOUND: return "ARES_ENOTFOUND";
8✔
92
  case ARES_ENOTIMP: return "ARES_ENOTIMP";
38✔
93
  case ARES_EREFUSED: return "ARES_EREFUSED";
24✔
94
  case ARES_EBADQUERY: return "ARES_EBADQUERY";
1✔
95
  case ARES_EBADNAME: return "ARES_EBADNAME";
4✔
96
  case ARES_EBADFAMILY: return "ARES_EBADFAMILY";
×
97
  case ARES_EBADRESP: return "ARES_EBADRESP";
8✔
98
  case ARES_ECONNREFUSED: return "ARES_ECONNREFUSED";
54✔
99
  case ARES_ETIMEOUT: return "ARES_ETIMEOUT";
2✔
100
  case ARES_EOF: return "ARES_EOF";
×
101
  case ARES_EFILE: return "ARES_EFILE";
×
102
  case ARES_ENOMEM: return "ARES_ENOMEM";
34✔
103
  case ARES_EDESTRUCTION: return "ARES_EDESTRUCTION";
24✔
104
  case ARES_EBADSTR: return "ARES_EBADSTR";
×
105
  case ARES_EBADFLAGS: return "ARES_EBADFLAGS";
2✔
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";
3,059✔
112
  default: return "UNKNOWN";
1✔
113
  }
114
}
115

116
std::string RcodeToString(int rcode) {
3,404✔
117
  switch (rcode) {
3,404✔
118
  case NOERROR: return "NOERROR";
2,626✔
119
  case FORMERR: return "FORMERR";
32✔
120
  case SERVFAIL: return "SERVFAIL";
258✔
121
  case NXDOMAIN: return "NXDOMAIN";
266✔
122
  case NOTIMP: return "NOTIMP";
130✔
123
  case REFUSED: return "REFUSED";
74✔
124
  case YXDOMAIN: return "YXDOMAIN";
10✔
125
  case YXRRSET: return "YXRRSET";
8✔
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) {
14,707✔
137
  switch (rrtype) {
14,707✔
138
  case T_A: return "A";
12,471✔
139
  case T_NS: return "NS";
×
140
  case T_MD: return "MD";
×
141
  case T_MF: return "MF";
×
142
  case T_CNAME: return "CNAME";
50✔
143
  case T_SOA: return "SOA";
16✔
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";
4✔
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";
530✔
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";
4✔
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";
1,632✔
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) {
9,541✔
199
  switch (qclass) {
9,541✔
200
  case C_IN: return "IN";
9,541✔
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) {
4,105✔
210
  const byte* addr = reinterpret_cast<const byte*>(vaddr);
4,105✔
211
  std::stringstream ss;
4,105✔
212
  if (len == 4) {
4,105✔
213
    char buffer[4*4 + 3 + 1];
214
    snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u",
3,858✔
215
             (unsigned char)addr[0],
3,858✔
216
             (unsigned char)addr[1],
3,858✔
217
             (unsigned char)addr[2],
3,858✔
218
             (unsigned char)addr[3]);
3,858✔
219
    ss << buffer;
3,858✔
220
  } else if (len == 16) {
247✔
221
    for (int ii = 0; ii < 16;  ii+=2) {
2,223✔
222
      if (ii > 0) ss << ':';
1,976✔
223
      char buffer[4 + 1];
224
      snprintf(buffer, sizeof(buffer), "%02x%02x", (unsigned char)addr[ii], (unsigned char)addr[ii+1]);
1,976✔
225
      ss << buffer;
1,976✔
226
    }
227
  } else {
228
    ss << "!" << HexDump(addr, len) << "!";
×
229
  }
230
  return ss.str();
8,210✔
231
}
4,105✔
232

233
std::string PacketToString(const std::vector<byte>& packet) {
6,985✔
234
  const byte* data = packet.data();
6,985✔
235
  int len = (int)packet.size();
6,985✔
236
  std::stringstream ss;
6,985✔
237
  if (len < NS_HFIXEDSZ) {
6,985✔
238
    ss << "(too short, len " << len << ")";
38✔
239
    return ss.str();
38✔
240
  }
241
  ss << ((DNS_HEADER_QR(data) == 0) ? "REQ " : "RSP ");
6,947✔
242
  switch (DNS_HEADER_OPCODE(data)) {
6,947✔
243
  case O_QUERY: ss << "QRY "; break;
6,947✔
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 ";
6,947✔
251
  if (DNS_HEADER_TC(data)) ss << "TC ";
6,947✔
252
  if (DNS_HEADER_RD(data)) ss << "RD ";
6,947✔
253
  if (DNS_HEADER_RA(data)) ss << "RA ";
6,947✔
254
  if (DNS_HEADER_Z(data)) ss << "Z ";
6,947✔
255
  if (DNS_HEADER_QR(data) == 1) ss << RcodeToString(DNS_HEADER_RCODE(data));
6,947✔
256

257
  int nquestions = DNS_HEADER_QDCOUNT(data);
6,947✔
258
  int nanswers = DNS_HEADER_ANCOUNT(data);
6,947✔
259
  int nauths = DNS_HEADER_NSCOUNT(data);
6,947✔
260
  int nadds = DNS_HEADER_ARCOUNT(data);
6,947✔
261

262
  const byte* pq = data + NS_HFIXEDSZ;
6,947✔
263
  len -= NS_HFIXEDSZ;
6,947✔
264
  for (int ii = 0; ii < nquestions; ii++) {
13,894✔
265
    ss << " Q:" << QuestionToString(packet, &pq, &len);
6,947✔
266
  }
267
  const byte* prr = pq;
6,947✔
268
  for (int ii = 0; ii < nanswers; ii++) {
9,515✔
269
    ss << " A:" << RRToString(packet, &prr, &len);
2,568✔
270
  }
271
  for (int ii = 0; ii < nauths; ii++) {
6,951✔
272
    ss << " AUTH:" << RRToString(packet, &prr, &len);
4✔
273
  }
274
  for (int ii = 0; ii < nadds; ii++) {
8,601✔
275
    ss << " ADD:" << RRToString(packet, &prr, &len);
1,654✔
276
  }
277
  return ss.str();
6,947✔
278
}
6,985✔
279

280
std::string QuestionToString(const std::vector<byte>& packet,
6,947✔
281
                             const byte** data, int* len) {
282
  std::stringstream ss;
6,947✔
283
  ss << "{";
6,947✔
284
  if (*len < NS_QFIXEDSZ) {
6,947✔
285
    ss << "(too short, len " << *len << ")";
×
286
    return ss.str();
×
287
  }
288

289
  char *name = nullptr;
6,947✔
290
  long enclen;
291
  int rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
6,947✔
292
  if (rc != ARES_SUCCESS) {
6,947✔
293
    ss << "(error from ares_expand_name)";
×
294
    return ss.str();
×
295
  }
296
  if (enclen > *len) {
6,947✔
297
    ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
×
298
    return ss.str();
×
299
  }
300
  *len -= (int)enclen;
6,947✔
301
  *data += enclen;
6,947✔
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));
6,947✔
307
  ares_free_string(name);
6,947✔
308

309
  ss << "'" << lowername << "' ";
6,947✔
310
  if (*len < NS_QFIXEDSZ) {
6,947✔
311
    ss << "(too short, len left " << *len << ")";
×
312
    return ss.str();
×
313
  }
314
  ss << ClassToString(DNS_QUESTION_CLASS(*data)) << " ";
6,947✔
315
  ss << RRTypeToString(DNS_QUESTION_TYPE(*data));
6,947✔
316
  *data += NS_QFIXEDSZ;
6,947✔
317
  *len -= NS_QFIXEDSZ;
6,947✔
318
  ss << "}";
6,947✔
319
  return ss.str();
6,947✔
320
}
6,947✔
321

322
std::string RRToString(const std::vector<byte>& packet,
4,226✔
323
                       const byte** data, int* len) {
324
  std::stringstream ss;
4,226✔
325
  ss << "{";
4,226✔
326
  if (*len < NS_RRFIXEDSZ) {
4,226✔
327
    ss << "too short, len " << *len << ")";
×
328
    return ss.str();
×
329
  }
330

331
  char *name = nullptr;
4,226✔
332
  long enclen;
333
  int rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
4,226✔
334
  if (rc != ARES_SUCCESS) {
4,226✔
335
    ss << "(error from ares_expand_name)";
×
336
    return ss.str();
×
337
  }
338
  if (enclen > *len) {
4,226✔
339
    ss << "(error, encoded name len " << enclen << "bigger than remaining data " << *len << " bytes)";
×
340
    return ss.str();
×
341
  }
342
  *len -= (int)enclen;
4,226✔
343
  *data += enclen;
4,226✔
344
  ss << "'" << name << "' ";
4,226✔
345
  ares_free_string(name);
4,226✔
346
  name = nullptr;
4,226✔
347

348
  if (*len < NS_RRFIXEDSZ) {
4,226✔
349
    ss << "(too short, len left " << *len << ")";
×
350
    return ss.str();
×
351
  }
352
  int rrtype = DNS_RR_TYPE(*data);
4,226✔
353
  if (rrtype == T_OPT) {
4,226✔
354
    ss << "MAXUDP=" << DNS_RR_CLASS(*data) << " ";
1,632✔
355
    ss << RRTypeToString(rrtype) << " ";
1,632✔
356
    ss << "RCODE2=" << DNS_RR_TTL(*data);
1,632✔
357
  } else {
358
    ss << ClassToString(DNS_RR_CLASS(*data)) << " ";
2,594✔
359
    ss << RRTypeToString(rrtype) << " ";
2,594✔
360
    ss << "TTL=" << DNS_RR_TTL(*data);
2,594✔
361
  }
362
  int rdatalen = DNS_RR_LEN(*data);
4,226✔
363

364
  *data += NS_RRFIXEDSZ;
4,226✔
365
  *len -= NS_RRFIXEDSZ;
4,226✔
366
  if (*len < rdatalen) {
4,226✔
367
    ss << "(RR too long at " << rdatalen << ", len left " << *len << ")";
×
368
  } else {
369
    switch (rrtype) {
4,226✔
370
    case T_A:
2,532✔
371
    case T_AAAA:
372
      ss << " " << AddressToString(*data, rdatalen);
2,532✔
373
      break;
2,532✔
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:
50✔
389
    case T_NS:
390
    case T_PTR: {
391
      rc = ares_expand_name(*data, packet.data(), (int)packet.size(), &name, &enclen);
50✔
392
      if (rc != ARES_SUCCESS) {
50✔
393
        ss << "(error from ares_expand_name)";
×
394
        break;
×
395
      }
396
      ss << " '" << name << "'";
50✔
397
      ares_free_string(name);
50✔
398
      break;
50✔
399
    }
400
    case T_MX:
2✔
401
      if (rdatalen > 2) {
2✔
402
        rc = ares_expand_name(*data + 2, packet.data(), (int)packet.size(), &name, &enclen);
2✔
403
        if (rc != ARES_SUCCESS) {
2✔
404
          ss << "(error from ares_expand_name)";
×
405
          break;
×
406
        }
407
        ss << " " << DNS__16BIT(*data) << " '" << name << "'";
2✔
408
        ares_free_string(name);
2✔
409
      } else {
410
        ss << "(RR too short)";
×
411
      }
412
      break;
2✔
413
    case T_SRV: {
2✔
414
      if (rdatalen > 6) {
2✔
415
        const byte* p = *data;
2✔
416
        unsigned long prio = DNS__16BIT(p);
2✔
417
        unsigned long weight = DNS__16BIT(p + 2);
2✔
418
        unsigned long port = DNS__16BIT(p + 4);
2✔
419
        p += 6;
2✔
420
        rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
2✔
421
        if (rc != ARES_SUCCESS) {
2✔
422
          ss << "(error from ares_expand_name)";
×
423
          break;
×
424
        }
425
        ss << prio << " " << weight << " " << port << " '" << name << "'";
2✔
426
        ares_free_string(name);
2✔
427
      } else {
428
        ss << "(RR too short)";
×
429
      }
430
      break;
2✔
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: {
8✔
446
      const byte* p = *data;
8✔
447
      rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
8✔
448
      if (rc != ARES_SUCCESS) {
8✔
449
        ss << "(error from ares_expand_name)";
×
450
        break;
×
451
      }
452
      ss << " '" << name << "'";
8✔
453
      ares_free_string(name);
8✔
454
      p += enclen;
8✔
455
      rc = ares_expand_name(p, packet.data(), (int)packet.size(), &name, &enclen);
8✔
456
      if (rc != ARES_SUCCESS) {
8✔
457
        ss << "(error from ares_expand_name)";
×
458
        break;
×
459
      }
460
      ss << " '" << name << "'";
8✔
461
      ares_free_string(name);
8✔
462
      p += enclen;
8✔
463
      if ((p + 20) <= (*data + rdatalen)) {
8✔
464
        unsigned long serial = DNS__32BIT(p);
8✔
465
        unsigned long refresh = DNS__32BIT(p + 4);
8✔
466
        unsigned long retry = DNS__32BIT(p + 8);
8✔
467
        unsigned long expire = DNS__32BIT(p + 12);
8✔
468
        unsigned long minimum = DNS__32BIT(p + 16);
8✔
469
        ss << " " << serial << " " << refresh << " " << retry << " " << expire << " " << minimum;
8✔
470
      } else {
471
        ss << "(RR too short)";
×
472
      }
473
      break;
8✔
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:
1,632✔
511
      ss << " " << HexDump(*data, rdatalen);
1,632✔
512
      break;
1,632✔
513
    }
514
  }
515
  *data += rdatalen;
4,226✔
516
  *len -= rdatalen;
4,226✔
517

518
  ss << "}";
4,226✔
519
  return ss.str();
4,226✔
520
}
4,226✔
521

522
void PushInt32(std::vector<byte>* data, int value) {
2,857✔
523
  data->push_back((byte)(((unsigned int)value & 0xff000000) >> 24));
2,857✔
524
  data->push_back((byte)(((unsigned int)value & 0x00ff0000) >> 16));
2,857✔
525
  data->push_back((byte)(((unsigned int)value & 0x0000ff00) >> 8));
2,857✔
526
  data->push_back((byte)(value & 0x000000ff));
2,857✔
527
}
2,857✔
528

529
void PushInt16(std::vector<byte>* data, int value) {
32,733✔
530
  data->push_back((byte)((value & 0xff00) >> 8));
32,733✔
531
  data->push_back((byte)value & 0x00ff);
32,733✔
532
}
32,733✔
533

534
std::vector<byte> EncodeString(const std::string &name) {
6,463✔
535
  std::vector<byte> data;
6,463✔
536
  std::stringstream ss(name);
6,463✔
537
  std::string label;
6,463✔
538
  // TODO: cope with escapes
539
  while (std::getline(ss, label, '.')) {
25,149✔
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)
18,692✔
543
      break;
6✔
544
    data.push_back((byte)label.length());
18,686✔
545
    data.insert(data.end(), label.begin(), label.end());
18,686✔
546
  }
547
  data.push_back(0);
6,463✔
548
  return data;
12,926✔
549
}
6,463✔
550

551
std::vector<byte> DNSQuestion::data(const char *request_name, const ares_dns_record_t *dnsrec) const {
6,240✔
552
  std::vector<byte> data;
6,240✔
553
  std::vector<byte> encname;
6,240✔
554
  if (request_name != nullptr && strcasecmp(request_name, name_.c_str()) == 0) {
6,240✔
555
    encname = EncodeString(request_name);
3,342✔
556
  } else {
557
    encname = EncodeString(name_);
2,898✔
558
  }
559
  data.insert(data.end(), encname.begin(), encname.end());
6,240✔
560
  PushInt16(&data, rrtype_);
6,240✔
561
  PushInt16(&data, qclass_);
6,240✔
562
  return data;
12,480✔
563
}
6,240✔
564

565
std::vector<byte> DNSRR::data(const ares_dns_record_t *dnsrec) const {
2,777✔
566
  std::vector<byte> data = DNSQuestion::data(dnsrec);
2,777✔
567
  PushInt32(&data, ttl_);
2,777✔
568
  return data;
2,777✔
569
}
×
570

571
std::vector<byte> DNSSingleNameRR::data(const ares_dns_record_t *dnsrec) const {
151✔
572
  std::vector<byte> data = DNSRR::data(dnsrec);
151✔
573
  std::vector<byte> encname = EncodeString(other_);
151✔
574
  int len = (int)encname.size();
151✔
575
  PushInt16(&data, len);
151✔
576
  data.insert(data.end(), encname.begin(), encname.end());
151✔
577
  return data;
302✔
578
}
151✔
579

580
std::vector<byte> DNSTxtRR::data(const ares_dns_record_t *dnsrec) const {
17✔
581
  std::vector<byte> data = DNSRR::data(dnsrec);
17✔
582
  int len = 0;
17✔
583
  for (const std::string& txt : txt_) {
40✔
584
    len += (1 + (int)txt.size());
23✔
585
  }
586
  PushInt16(&data, len);
17✔
587
  for (const std::string& txt : txt_) {
40✔
588
    data.push_back((byte)txt.size());
23✔
589
    data.insert(data.end(), txt.begin(), txt.end());
23✔
590
  }
591
  return data;
17✔
592
}
×
593

594
std::vector<byte> DNSMxRR::data(const ares_dns_record_t *dnsrec) const {
17✔
595
  std::vector<byte> data = DNSRR::data(dnsrec);
17✔
596
  std::vector<byte> encname = EncodeString(other_);
17✔
597
  int len = 2 + (int)encname.size();
17✔
598
  PushInt16(&data, len);
17✔
599
  PushInt16(&data, pref_);
17✔
600
  data.insert(data.end(), encname.begin(), encname.end());
17✔
601
  return data;
34✔
602
}
17✔
603

604
std::vector<byte> DNSSrvRR::data(const ares_dns_record_t *dnsrec) const {
15✔
605
  std::vector<byte> data = DNSRR::data(dnsrec);
15✔
606
  std::vector<byte> encname = EncodeString(target_);
15✔
607
  int len = 6 + (int)encname.size();
15✔
608
  PushInt16(&data, len);
15✔
609
  PushInt16(&data, prio_);
15✔
610
  PushInt16(&data, weight_);
15✔
611
  PushInt16(&data, port_);
15✔
612
  data.insert(data.end(), encname.begin(), encname.end());
15✔
613
  return data;
30✔
614
}
15✔
615

616
std::vector<byte> DNSUriRR::data(const ares_dns_record_t *dnsrec) const {
14✔
617
  std::vector<byte> data = DNSRR::data(dnsrec);
14✔
618
  int len = 4 + (int)target_.size();
14✔
619
  PushInt16(&data, len);
14✔
620
  PushInt16(&data, prio_);
14✔
621
  PushInt16(&data, weight_);
14✔
622
  data.insert(data.end(), target_.begin(), target_.end());
14✔
623
  return data;
14✔
624
}
×
625

626
std::vector<byte> DNSAddressRR::data(const ares_dns_record_t *dnsrec) const {
2,506✔
627
  std::vector<byte> data = DNSRR::data(dnsrec);
2,506✔
628
  int len = (int)addr_.size();
2,506✔
629
  PushInt16(&data, len);
2,506✔
630
  data.insert(data.end(), addr_.begin(), addr_.end());
2,506✔
631
  return data;
2,506✔
632
}
×
633

634
std::vector<byte> DNSSoaRR::data(const ares_dns_record_t *dnsrec) const {
16✔
635
  std::vector<byte> data = DNSRR::data(dnsrec);
16✔
636
  std::vector<byte> encname1 = EncodeString(nsname_);
16✔
637
  std::vector<byte> encname2 = EncodeString(rname_);
16✔
638
  int len = (int)encname1.size() + (int)encname2.size() + 5*4;
16✔
639
  PushInt16(&data, len);
16✔
640
  data.insert(data.end(), encname1.begin(), encname1.end());
16✔
641
  data.insert(data.end(), encname2.begin(), encname2.end());
16✔
642
  PushInt32(&data, serial_);
16✔
643
  PushInt32(&data, refresh_);
16✔
644
  PushInt32(&data, retry_);
16✔
645
  PushInt32(&data, expire_);
16✔
646
  PushInt32(&data, minimum_);
16✔
647
  return data;
32✔
648
}
16✔
649

650
const ares_dns_rr_t *fetch_rr_opt(const ares_dns_record_t *rec)
43✔
651
{
652
  size_t i;
653
  for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
43✔
654
    const ares_dns_rr_t *rr =
655
      ares_dns_record_rr_get_const(rec, ARES_SECTION_ADDITIONAL, i);
42✔
656

657
    if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
42✔
658
      return rr;
42✔
659
    }
660
  }
661
  return NULL;
1✔
662
}
663

664
std::vector<byte> DNSOptRR::data(const ares_dns_record_t *dnsrec) const {
33✔
665
  std::vector<byte>    data = DNSRR::data(dnsrec);
33✔
666
  int len                   = 0;
33✔
667
  std::vector<byte>    cookie;
33✔
668
  const ares_dns_rr_t *rr  = fetch_rr_opt(dnsrec);
33✔
669
  size_t               passed_cookie_len = 0;
33✔
670
  const unsigned char *passed_cookie = NULL;
33✔
671

672
  ares_dns_rr_get_opt_byid(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE,
33✔
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_ &&
37✔
678
      (passed_cookie_len <= 8 ||
8✔
679
       passed_cookie_len - 8 != server_cookie_.size() ||
4✔
680
       memcmp(passed_cookie + 8, server_cookie_.data(), server_cookie_.size()) != 0
4✔
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) {
33✔
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()) {
26✔
693
      cookie.insert(cookie.end(), client_cookie_.begin(), client_cookie_.end());
2✔
694
    } else {
695
      cookie.insert(cookie.end(), passed_cookie, passed_cookie+8);
24✔
696
    }
697
    cookie.insert(cookie.end(), server_cookie_.begin(), server_cookie_.end());
26✔
698
  }
699

700
  if (cookie.size()) {
33✔
701
    len += 4 + (int)cookie.size();
26✔
702
  }
703
  for (const DNSOption& opt : opts_) {
33✔
704
    len += (4 + (int)opt.data_.size());
×
705
  }
706

707
  PushInt16(&data, len);
33✔
708
  for (const DNSOption& opt : opts_) {
33✔
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()) {
33✔
715
    PushInt16(&data, ARES_OPT_PARAM_COOKIE);
26✔
716
    PushInt16(&data, (int)cookie.size());
26✔
717
    data.insert(data.end(), cookie.begin(), cookie.end());
26✔
718
  }
719

720
  return data;
33✔
721
}
33✔
722

723
std::vector<byte> DNSNaptrRR::data(const ares_dns_record_t *dnsrec) const {
7✔
724
  std::vector<byte> data = DNSRR::data(dnsrec);
7✔
725
  std::vector<byte> encname = EncodeString(replacement_);
7✔
726
  int len = (4 + 1 + (int)flags_.size() + 1 + (int)service_.size() + 1 + (int)regexp_.size() + (int)encname.size());
7✔
727
  PushInt16(&data, len);
7✔
728
  PushInt16(&data, order_);
7✔
729
  PushInt16(&data, pref_);
7✔
730
  data.push_back((byte)flags_.size());
7✔
731
  data.insert(data.end(), flags_.begin(), flags_.end());
7✔
732
  data.push_back((byte)service_.size());
7✔
733
  data.insert(data.end(), service_.begin(), service_.end());
7✔
734
  data.push_back((byte)regexp_.size());
7✔
735
  data.insert(data.end(), regexp_.begin(), regexp_.end());
7✔
736
  data.insert(data.end(), encname.begin(), encname.end());
7✔
737
  return data;
14✔
738
}
7✔
739

740
std::vector<byte> DNSPacket::data(const char *request_name, const ares_dns_record_t *dnsrec) const {
3,464✔
741
  std::vector<byte> data;
3,464✔
742
  PushInt16(&data, qid_);
3,464✔
743
  byte b = 0x00;
3,464✔
744
  if (response_) b |= 0x80;
3,464✔
745
  b |= ((opcode_ & 0x0f) << 3);
3,464✔
746
  if (aa_) b |= 0x04;
3,464✔
747
  if (tc_) b |= 0x02;
3,464✔
748
  if (rd_) b |= 0x01;
3,464✔
749
  data.push_back(b);
3,464✔
750
  b = 0x00;
3,464✔
751
  if (ra_) b |= 0x80;
3,464✔
752
  if (z_) b |= 0x40;
3,464✔
753
  if (ad_) b |= 0x20;
3,464✔
754
  if (cd_) b |= 0x10;
3,464✔
755
  b |= (rcode_ & 0x0f);
3,464✔
756
  data.push_back(b);
3,464✔
757

758
  int count = (int)questions_.size();
3,464✔
759
  PushInt16(&data, count);
3,464✔
760
  count = (int)answers_.size();
3,464✔
761
  PushInt16(&data, count);
3,464✔
762
  count = (int)auths_.size();
3,464✔
763
  PushInt16(&data, count);
3,464✔
764
  count = (int)adds_.size();
3,464✔
765
  PushInt16(&data, count);
3,464✔
766

767
  for (const std::unique_ptr<DNSQuestion>& question : questions_) {
6,927✔
768
    std::vector<byte> qdata = question->data(request_name, dnsrec);
3,463✔
769
    if (qdata.size() == 0) {
3,463✔
770
      data.clear();
×
771
      return data;
×
772
    }
773
    data.insert(data.end(), qdata.begin(), qdata.end());
3,463✔
774
  }
3,463✔
775
  for (const std::unique_ptr<DNSRR>& rr : answers_) {
6,113✔
776
    std::vector<byte> rrdata = rr->data(dnsrec);
2,649✔
777
    if (rrdata.size() == 0) {
2,649✔
778
      data.clear();
×
779
      return data;
×
780
    }
781
    data.insert(data.end(), rrdata.begin(), rrdata.end());
2,649✔
782
  }
2,649✔
783
  for (const std::unique_ptr<DNSRR>& rr : auths_) {
3,508✔
784
    std::vector<byte> rrdata = rr->data(dnsrec);
44✔
785
    if (rrdata.size() == 0) {
44✔
786
      data.clear();
×
787
      return data;
×
788
    }
789
    data.insert(data.end(), rrdata.begin(), rrdata.end());
44✔
790
  }
44✔
791
  for (const std::unique_ptr<DNSRR>& rr : adds_) {
3,548✔
792
    std::vector<byte> rrdata = rr->data(dnsrec);
84✔
793
    if (rrdata.size() == 0) {
84✔
794
      data.clear();
×
795
      return data;
×
796
    }
797
    data.insert(data.end(), rrdata.begin(), rrdata.end());
84✔
798
  }
84✔
799
  return data;
3,464✔
800
}
×
801

802
}  // namespace ares
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc