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

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

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

82.4
/pdns/dnswriter.cc
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
#include <boost/version.hpp>
26
#if BOOST_VERSION >= 105400
27
#include <boost/container/static_vector.hpp>
28
#endif
29
#include "dnswriter.hh"
30
#include "misc.hh"
31
#include "dnsparser.hh"
32

33
#include <limits.h>
34

35
/* d_content:                                      <---- d_stuff ---->
36
                                      v d_truncatemarker
37
   dnsheader | qname | qtype | qclass | {recordname| dnsrecordheader | record }
38
                                        ^ d_rollbackmarker           ^ d_sor
39

40

41
*/
42

43

44
template <typename Container> GenericDNSPacketWriter<Container>::GenericDNSPacketWriter(Container& content, const DNSName& qname, uint16_t  qtype, uint16_t qclass, uint8_t opcode)
45
  : d_content(content), d_qname(qname), d_canonic(false), d_lowerCase(false)
46
{
5,215,315✔
47
  d_content.clear();
5,215,315✔
48
  dnsheader dnsheader;
5,215,315✔
49

50
  memset(&dnsheader, 0, sizeof(dnsheader));
5,215,315✔
51
  dnsheader.id=0;
5,215,315✔
52
  dnsheader.qdcount=htons(1);
5,215,315✔
53
  dnsheader.opcode=opcode;
5,215,315✔
54

55
  const uint8_t* ptr=(const uint8_t*)&dnsheader;
5,215,315✔
56
  d_content.reserve(sizeof(dnsheader) + qname.wirelength() + sizeof(qtype) + sizeof(qclass));
5,215,315✔
57
  d_content.resize(sizeof(dnsheader));
5,215,315✔
58
  uint8_t* dptr=(&*d_content.begin());
5,215,315✔
59

60
  memcpy(dptr, ptr, sizeof(dnsheader));
5,215,315✔
61
  d_namepositions.reserve(16);
5,215,315✔
62
  xfrName(qname, false);
5,215,315✔
63
  xfr16BitInt(qtype);
5,215,315✔
64
  xfr16BitInt(qclass);
5,215,315✔
65

66
  d_truncatemarker=d_content.size();
5,215,315✔
67
  d_sor = 0;
5,215,315✔
68
  d_rollbackmarker = 0;
5,215,315✔
69
}
5,215,315✔
70

71
template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
72
{
9,187,580✔
73
  return reinterpret_cast<dnsheader*>(&*d_content.begin());
9,187,580✔
74
}
9,187,580✔
75

76

77
template <typename Container> void GenericDNSPacketWriter<Container>::startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, DNSResourceRecord::Place place, bool compress)
78
{
1,738,873✔
79
  d_compress = compress;
1,738,873✔
80
  commit();
1,738,873✔
81
  d_rollbackmarker=d_content.size();
1,738,873✔
82

83
  if(compress && !name.isRoot() && d_qname==name) {  // don't do the whole label compression thing if we *know* we can get away with "see question" - except when compressing the root
1,742,918✔
84
    static unsigned char marker[2]={0xc0, 0x0c};
1,603,377✔
85
    d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]);
1,603,377✔
86
  }
1,603,377✔
87
  else {
6,442,590,482✔
88
    xfrName(name, compress);
6,442,590,482✔
89
  }
6,442,590,482✔
90
  xfr16BitInt(qtype);
1,738,873✔
91
  xfr16BitInt(qclass);
1,738,873✔
92
  xfr32BitInt(ttl);
1,738,873✔
93
  xfr16BitInt(0); // this will be the record size
1,738,873✔
94
  d_recordplace = place;
1,738,873✔
95
  d_sor=d_content.size(); // this will remind us where to stuff the record size
1,738,873✔
96
}
1,738,873✔
97

98
template <typename Container> void GenericDNSPacketWriter<Container>::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version)
99
{
10,210✔
100
  uint32_t ttl=0;
10,210✔
101

102
  EDNS0Record stuff;
10,210✔
103

104
  stuff.version = version;
10,210✔
105
  stuff.extFlags = htons(ednsFlags);
10,210✔
106

107
  /* RFC 6891 section 4 on the Extended RCode wire format
108
   *    EXTENDED-RCODE
109
   *        Forms the upper 8 bits of extended 12-bit RCODE (together with the
110
   *        4 bits defined in [RFC1035].  Note that EXTENDED-RCODE value 0
111
   *        indicates that an unextended RCODE is in use (values 0 through 15).
112
   */
113
  // XXX Should be check for extRCode > 1<<12 ?
114
  stuff.extRCode = extRCode>>4;
10,210✔
115
  if (extRCode != 0) { // As this trumps the existing RCODE
10,210!
116
    getHeader()->rcode = extRCode;
2✔
117
  }
2✔
118

119
  static_assert(sizeof(EDNS0Record) == sizeof(ttl), "sizeof(EDNS0Record) must match sizeof(ttl)");
10,210✔
120
  memcpy(&ttl, &stuff, sizeof(stuff));
10,210✔
121

122
  ttl=ntohl(ttl); // will be reversed later on
10,210✔
123

124
  startRecord(g_rootdnsname, QType::OPT, ttl, udpsize, DNSResourceRecord::ADDITIONAL, false);
10,210✔
125
  for(auto const &option : options) {
10,210✔
126
    xfr16BitInt(option.first);
377✔
127
    xfr16BitInt(option.second.length());
377✔
128
    xfrBlob(option.second);
377✔
129
  }
377✔
130
}
10,210✔
131

132
template <typename Container> void GenericDNSPacketWriter<Container>::xfr48BitInt(uint64_t val)
133
{
96✔
134
  std::array<unsigned char, 6> bytes;
96✔
135
  uint16_t theLeft = htons((val >> 32)&0xffffU);
96✔
136
  uint32_t theRight = htonl(val & 0xffffffffU);
96✔
137
  memcpy(&bytes[0], (void*)&theLeft, sizeof(theLeft));
96✔
138
  memcpy(&bytes[2], (void*)&theRight, sizeof(theRight));
96✔
139

140
  d_content.insert(d_content.end(), bytes.begin(), bytes.end());
96✔
141
}
96✔
142

143
template <typename Container> void GenericDNSPacketWriter<Container>::xfrNodeOrLocatorID(const NodeOrLocatorID& val)
144
{
10✔
145
  d_content.insert(d_content.end(), val.content, val.content + sizeof(val.content));
10✔
146
}
10✔
147

148
template <typename Container> void GenericDNSPacketWriter<Container>::xfr32BitInt(uint32_t val)
149
{
3,190,429✔
150
  uint32_t rval=htonl(val);
3,190,429✔
151
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
3,190,429✔
152
  d_content.insert(d_content.end(), ptr, ptr+4);
3,190,429✔
153
}
3,190,429✔
154

155
template <typename Container> void GenericDNSPacketWriter<Container>::xfr16BitInt(uint16_t val)
156
{
15,628,692✔
157
  uint16_t rval=htons(val);
15,628,692✔
158
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
15,628,692✔
159
  d_content.insert(d_content.end(), ptr, ptr+2);
15,628,692✔
160
}
15,628,692✔
161

162
template <typename Container> void GenericDNSPacketWriter<Container>::xfr8BitInt(uint8_t val)
163
{
82,519✔
164
  d_content.push_back(val);
82,519✔
165
}
82,519✔
166

167

168
/* input:
169
 if lenField is true
170
  "" -> 0
171
  "blah" -> 4blah
172
  "blah" "blah" -> output 4blah4blah
173
  "verylongstringlongerthan256....characters" \xffverylongstring\x23characters (autosplit)
174
  "blah\"blah" -> 9blah"blah
175
  "blah\97" -> 5blahb
176

177
 if lenField is false
178
  "blah" -> blah
179
  "blah\"blah" -> blah"blah
180
  */
181
template <typename Container> void GenericDNSPacketWriter<Container>::xfrText(const string& text, bool, bool lenField)
182
{
776✔
183
  if(text.empty()) {
776!
184
    d_content.push_back(0);
×
185
    return;
×
186
  }
×
187
  vector<string> segments = segmentDNSText(text);
776✔
188
  for(const string& str :  segments) {
876✔
189
    if(lenField)
876!
190
      d_content.push_back(str.length());
846✔
191
    d_content.insert(d_content.end(), str.c_str(), str.c_str() + str.length());
876✔
192
  }
876✔
193
}
776✔
194

195
template <typename Container> void GenericDNSPacketWriter<Container>::xfrUnquotedText(const string& text, bool lenField)
196
{
121✔
197
  if(text.empty()) {
121!
198
    d_content.push_back(0);
×
199
    return;
×
200
  }
×
201
  if(lenField)
121!
202
    d_content.push_back(text.length());
121✔
203
  d_content.insert(d_content.end(), text.c_str(), text.c_str() + text.length());
121✔
204
}
121✔
205

206

207
static constexpr bool l_verbose=false;
208
static constexpr uint16_t maxCompressionOffset=16384;
209
template <typename Container> uint16_t GenericDNSPacketWriter<Container>::lookupName(const DNSName& name, uint16_t* matchLen)
210
{
6,611✔
211
  // iterate over the written labels, see if we find a match
212
  const auto& raw = name.getStorage();
6,611✔
213

214
  /* name might be a.root-servers.net, we need to be able to benefit from finding:
215
     b.root-servers.net, or even:
216
     b\xc0\x0c
217
  */
218
  unsigned int bestpos=0;
6,611✔
219
  *matchLen=0;
6,611✔
220
  boost::container::static_vector<uint16_t, 34> nvect;
6,611✔
221
  boost::container::static_vector<uint16_t, 34> pvect;
6,611✔
222

223
  try {
6,611✔
224
    for(auto riter= raw.cbegin(); riter < raw.cend(); ) {
31,338!
225
      if(!*riter)
31,335✔
226
        break;
6,609✔
227
      nvect.push_back(riter - raw.cbegin());
24,726✔
228
      riter+=*riter+1;
24,726✔
229
    }
24,726✔
230
  }
6,611✔
231
  catch(std::bad_alloc& ba) {
6,611✔
232
    if(l_verbose)
3✔
233
      cout<<"Domain "<<name<<" too large to compress"<<endl;
×
234
    return 0;
3✔
235
  }
3✔
236

237
  if(l_verbose) {
6,609✔
238
    cout<<"Input vector for lookup "<<name<<": ";
×
239
    for(const auto n : nvect)
×
240
      cout << n<<" ";
×
241
    cout<<endl;
×
242
    cout<<makeHexDump(string(raw.c_str(), raw.c_str()+raw.size()))<<endl;
×
243
  }
×
244

245
  if(l_verbose)
6,609✔
246
    cout<<"Have "<<d_namepositions.size()<<" to ponder"<<endl;
×
247
  int counter=1;
6,609✔
248
  for(auto p : d_namepositions) {
15,289✔
249
    if(l_verbose) {
14,826✔
250
      cout<<"Pos: "<<p<<", "<<d_content.size()<<endl;
×
251
      DNSName pname((const char*)&d_content[0], d_content.size(), p, true); // only for debugging
×
252
      cout<<"Looking at '"<<pname<<"' in packet at position "<<p<<"/"<<d_content.size()<<", option "<<counter<<"/"<<d_namepositions.size()<<endl;
×
253
      ++counter;
×
254
    }
×
255
    // memcmp here makes things _slower_
256
    pvect.clear();
14,826✔
257
    try {
14,826✔
258
      for(auto iter = d_content.cbegin() + p; iter < d_content.cend();) {
76,898!
259
        uint8_t c=*iter;
76,892✔
260
        if(l_verbose)
76,892✔
261
          cout<<"Found label length: "<<(int)c<<endl;
×
262
        if(c & 0xc0) {
76,892✔
263
          uint16_t npos = 0x100*(c & (~0xc0)) + *++iter;
6,767✔
264
          iter = d_content.begin() + npos;
6,767✔
265
          if(l_verbose)
6,767✔
266
            cout<<"Is compressed label to newpos "<<npos<<", going there"<<endl;
×
267
          // check against going forward here
268
          continue;
6,767✔
269
        }
6,767✔
270
        if(!c)
70,125✔
271
          break;
14,821✔
272
        auto offset = iter - d_content.cbegin();
55,304✔
273
        if (offset >= maxCompressionOffset) break; // compression pointers cannot point here
55,304!
274
        pvect.push_back(offset);
55,303✔
275
        iter+=*iter+1;
55,303✔
276
      }
55,303✔
277
    }
14,826✔
278
    catch(std::bad_alloc& ba) {
14,826✔
279
      if(l_verbose)
6✔
280
        cout<<"Domain "<<name<<" too large to compress"<<endl;
×
281
      continue;
6✔
282
    }
6✔
283
    if(l_verbose) {
14,822✔
284
      cout<<"Packet vector: "<<endl;
×
285
      for(const auto n : pvect)
×
286
        cout << n<<" ";
×
287
      cout<<endl;
×
288
    }
×
289
    auto niter=nvect.crbegin(), piter=pvect.crbegin();
14,822✔
290
    unsigned int cmatchlen=1;
14,822✔
291
    for(; niter != nvect.crend() && piter != pvect.crend(); ++niter, ++piter) {
36,470!
292
      // niter is an offset in raw, pvect an offset in packet
293
      uint8_t nlen = raw[*niter], plen=d_content[*piter];
35,668✔
294
      if(l_verbose)
35,668✔
295
        cout<<"nlnen="<<(int)nlen<<", plen="<<(int)plen<<endl;
×
296
      if(nlen != plen)
35,668✔
297
        break;
5,888✔
298
      if(strncasecmp(raw.c_str()+*niter+1, (const char*)&d_content[*piter]+1, nlen)) {
29,780✔
299
        if(l_verbose)
4,911✔
300
          cout<<"Mismatch: "<<string(raw.c_str()+*niter+1, raw.c_str()+*niter+nlen+1)<< " != "<<string((const char*)&d_content[*piter]+1, (const char*)&d_content[*piter]+nlen+1)<<endl;
×
301
        break;
4,911✔
302
      }
4,911✔
303
      cmatchlen+=nlen+1;
24,869✔
304
      if(cmatchlen == raw.length()) { // have matched all of it, can't improve
24,869✔
305
        if(l_verbose)
3,229✔
306
          cout<<"Stopping search, matched whole name"<<endl;
×
307
        *matchLen = cmatchlen;
3,229✔
308
        return *piter;
3,229✔
309
      }
3,229✔
310
    }
24,869✔
311
    if(piter != pvect.crbegin() && *matchLen < cmatchlen) {
11,593✔
312
      *matchLen = cmatchlen;
4,983✔
313
      bestpos=*--piter;
4,983✔
314
    }
4,983✔
315
  }
11,593✔
316
  return bestpos;
3,382✔
317
}
6,609✔
318
// this is the absolute hottest function in the pdns recursor
319
template <typename Container> void GenericDNSPacketWriter<Container>::xfrName(const DNSName& name, bool compress, bool)
320
{
5,454,537✔
321
  if(l_verbose)
5,454,537✔
322
    cout<<"Wants to write "<<name<<", compress="<<compress<<", canonic="<<d_canonic<<", LC="<<d_lowerCase<<endl;
×
323
  if(d_canonic || d_lowerCase)   // d_lowerCase implies canonic
5,454,537✔
324
    compress=false;
202,748✔
325

326
  if(name.empty() || name.isRoot()) { // for speed
5,454,537✔
327
    d_content.push_back(0);
273,327✔
328
    return;
273,327✔
329
  }
273,327✔
330

331
  uint16_t li=0;
5,181,210✔
332
  uint16_t matchlen=0;
5,181,210✔
333
  if(d_compress && compress && (li=lookupName(name, &matchlen)) && li < maxCompressionOffset) {
5,181,210!
334
    const auto& dns=name.getStorage();
5,373✔
335
    if(l_verbose)
5,373✔
336
      cout<<"Found a substring of "<<matchlen<<" bytes from the back, offset: "<<li<<", dnslen: "<<dns.size()<<endl;
×
337
    // found a substring, if www.powerdns.com matched powerdns.com, we get back matchlen = 13
338

339
    unsigned int pos=d_content.size();
5,373✔
340
    if(pos < maxCompressionOffset && matchlen != dns.size()) {
5,373!
341
      if(l_verbose)
2,144✔
342
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for compressed case"<<endl;
×
343
      d_namepositions.push_back(pos);
2,144✔
344
    }
2,144✔
345

346
    if(l_verbose)
5,373✔
347
      cout<<"Going to write unique part: '"<<makeHexDump(string(dns.c_str(), dns.c_str() + dns.size() - matchlen)) <<"'"<<endl;
×
348
    d_content.insert(d_content.end(), (const unsigned char*)dns.c_str(), (const unsigned char*)dns.c_str() + dns.size() - matchlen);
5,373✔
349
    uint16_t offset=li;
5,373✔
350
    offset|=0xc000;
5,373✔
351

352
    d_content.push_back((char)(offset >> 8));
5,373✔
353
    d_content.push_back((char)(offset & 0xff));
5,373✔
354
  }
5,373✔
355
  else {
5,175,837✔
356
    unsigned int pos=d_content.size();
5,175,837✔
357
    if(l_verbose)
5,175,837✔
358
      cout<<"Found nothing, we are at pos "<<pos<<", inserting whole name"<<endl;
×
359
    if(pos < maxCompressionOffset) {
5,175,842✔
360
      if(l_verbose)
5,149,849✔
361
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for uncompressed case"<<endl;
×
362
      d_namepositions.push_back(pos);
5,149,849✔
363
    }
5,149,849✔
364

365
    std::unique_ptr<DNSName> lc;
5,175,837✔
366
    if(d_lowerCase)
5,175,837!
367
      lc = make_unique<DNSName>(name.makeLowerCase());
77,455✔
368

369
    const DNSName::string_t& raw = (lc ? *lc : name).getStorage();
5,175,837!
370
    if(l_verbose)
5,175,837✔
371
      cout<<"Writing out the whole thing "<<makeHexDump(string(raw.c_str(),  raw.c_str() + raw.length()))<<endl;
×
372
    d_content.insert(d_content.end(), raw.c_str(), raw.c_str() + raw.size());
5,175,837✔
373
  }
5,175,837✔
374
}
5,181,210✔
375

376
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const string& blob, int  )
377
{
253,776✔
378
  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
253,776✔
379
  d_content.insert(d_content.end(), ptr, ptr+blob.size());
253,776✔
380
}
253,776✔
381

382
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const std::vector<uint8_t>& blob)
383
{
30✔
384
  d_content.insert(d_content.end(), blob.begin(), blob.end());
30✔
385
}
30✔
386

387
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlobNoSpaces(const string& blob, int  )
388
{
59✔
389
  xfrBlob(blob);
59✔
390
}
59✔
391

392
template <typename Container> void GenericDNSPacketWriter<Container>::xfrHexBlob(const string& blob, bool /* keepReading */)
393
{
4,325✔
394
  xfrBlob(blob);
4,325✔
395
}
4,325✔
396

397
template <typename Container> void GenericDNSPacketWriter<Container>::xfrSvcParamKeyVals(const std::set<SvcParam> &kvs)
398
{
127✔
399
  for (auto const &param : kvs) {
305!
400
    // Key first!
401
    xfr16BitInt(param.getKey());
305✔
402

403
    switch (param.getKey())
305✔
404
    {
305✔
405
    case SvcParam::mandatory:
50!
406
      xfr16BitInt(2 * param.getMandatory().size());
50✔
407
      for (auto const &m: param.getMandatory()) {
54!
408
        xfr16BitInt(m);
54✔
409
      }
54✔
410
      break;
50✔
411
    case SvcParam::alpn:
66!
412
    {
66✔
413
      uint16_t totalSize = param.getALPN().size(); // All 1 octet size headers for each value
66✔
414
      for (auto const &a : param.getALPN()) {
100!
415
        totalSize += a.length();
100✔
416
      }
100✔
417
      xfr16BitInt(totalSize);
66✔
418
      for (auto const &a : param.getALPN()) {
100!
419
        xfrUnquotedText(a, true); // will add the 1-byte length field
100✔
420
      }
100✔
421
      break;
66✔
422
    }
×
423
    case SvcParam::no_default_alpn:
22!
424
      xfr16BitInt(0); // no size :)
22✔
425
      break;
22✔
426
    case SvcParam::port:
42!
427
      xfr16BitInt(2); // size
42✔
428
      xfr16BitInt(param.getPort());
42✔
429
      break;
42✔
430
    case SvcParam::ipv4hint:
42!
431
      xfr16BitInt(param.getIPHints().size() * 4); // size
42✔
432
      for (const auto& a: param.getIPHints()) {
46!
433
        xfrCAWithoutPort(param.getKey(), a);
46✔
434
      }
46✔
435
      break;
42✔
436
    case SvcParam::ipv6hint:
37!
437
      xfr16BitInt(param.getIPHints().size() * 16); // size
37✔
438
      for (const auto& a: param.getIPHints()) {
45!
439
        xfrCAWithoutPort(param.getKey(), a);
45✔
440
      }
45✔
441
      break;
37✔
442
    case SvcParam::ech:
11!
443
      xfr16BitInt(param.getECH().size()); // size
11✔
444
      xfrBlobNoSpaces(param.getECH());
11✔
445
      break;
11✔
446
    default:
35!
447
      xfr16BitInt(param.getValue().size());
35✔
448
      xfrBlob(param.getValue());
35✔
449
      break;
35✔
450
    }
305✔
451
  }
305✔
452
}
127✔
453

454
// call __before commit__
455
template <typename Container> void GenericDNSPacketWriter<Container>::getRecordPayload(string& records)
456
{
126,706✔
457
  records.assign(d_content.begin() + d_sor, d_content.end());
126,706✔
458
}
126,706✔
459

460
template <typename Container> uint32_t GenericDNSPacketWriter<Container>::size() const
461
{
7,129✔
462
  return d_content.size();
7,129✔
463
}
7,129✔
464

465
template <typename Container> void GenericDNSPacketWriter<Container>::rollback()
466
{
3✔
467
  d_content.resize(d_rollbackmarker);
3✔
468
  d_sor = 0;
3✔
469
}
3✔
470

471
template <typename Container> void GenericDNSPacketWriter<Container>::truncate()
472
{
3✔
473
  d_content.resize(d_truncatemarker);
3✔
474
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
3✔
475
  dh->ancount = dh->nscount = dh->arcount = 0;
3✔
476
}
3✔
477

478
template <typename Container> void GenericDNSPacketWriter<Container>::commit()
479
{
3,343,900✔
480
  if(!d_sor)
3,343,900✔
481
    return;
1,730,384✔
482
  uint16_t rlen = d_content.size() - d_sor;
1,613,516✔
483
  d_content[d_sor-2]=rlen >> 8;
1,613,516✔
484
  d_content[d_sor-1]=rlen & 0xff;
1,613,516✔
485
  d_sor=0;
1,613,516✔
486
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
1,613,516✔
487
  switch(d_recordplace) {
1,613,516✔
488
  case DNSResourceRecord::QUESTION:
×
489
    dh->qdcount = htons(ntohs(dh->qdcount) + 1);
×
490
    break;
×
491
  case DNSResourceRecord::ANSWER:
1,603,695✔
492
    dh->ancount = htons(ntohs(dh->ancount) + 1);
1,603,695✔
493
    break;
1,603,695✔
494
  case DNSResourceRecord::AUTHORITY:
1,120✔
495
    dh->nscount = htons(ntohs(dh->nscount) + 1);
1,120✔
496
    break;
1,120✔
497
  case DNSResourceRecord::ADDITIONAL:
10,526✔
498
    dh->arcount = htons(ntohs(dh->arcount) + 1);
10,526✔
499
    break;
10,526✔
500
  }
1,613,516✔
501

502
}
1,613,516✔
503

504
template <typename Container> size_t GenericDNSPacketWriter<Container>::getSizeWithOpts(const optvect_t& options) const
505
{
14✔
506
  size_t result = size() + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE + DNS_RDLENGTH_SIZE;
14✔
507

508
  for(auto const &option : options) {
14!
509
    result += 4;
×
510
    result += option.second.size();
×
511
  }
×
512

513
  return result;
14✔
514
}
14✔
515

516
template class GenericDNSPacketWriter<std::vector<uint8_t>>;
517
#include "noinitvector.hh"
518
template class GenericDNSPacketWriter<PacketBuffer>;
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