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

PowerDNS / pdns / 17235120617

26 Aug 2025 10:17AM UTC coverage: 65.959% (-0.02%) from 65.977%
17235120617

Pull #16016

github

web-flow
Merge d1e0ec6fc into 9eeac00a7
Pull Request #16016: auth: random doc nits

42117 of 92446 branches covered (45.56%)

Branch coverage included in aggregate %.

128034 of 165518 relevant lines covered (77.35%)

5925196.8 hits per line

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

83.01
/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
#include <boost/container/static_vector.hpp>
27
#include "dnswriter.hh"
28
#include "misc.hh"
29
#include "dnsparser.hh"
30

31
#include <limits.h>
32

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

38

39
*/
40

41
template <typename Container>
42
GenericDNSPacketWriter<Container>::GenericDNSPacketWriter(Container& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode) :
43
  d_content(content), d_qname(qname)
3,543,080✔
44
{
9,714,235✔
45
  d_content.clear();
9,714,235✔
46
  dnsheader dnsheader;
9,714,235✔
47

48
  memset(&dnsheader, 0, sizeof(dnsheader));
9,714,235✔
49
  dnsheader.id=0;
9,714,235✔
50
  dnsheader.qdcount=htons(1);
9,714,235✔
51
  dnsheader.opcode=opcode;
9,714,235✔
52

53
  const uint8_t* ptr=(const uint8_t*)&dnsheader;
9,714,235✔
54
  d_content.reserve(sizeof(dnsheader) + qname.wirelength() + sizeof(qtype) + sizeof(qclass));
9,714,235✔
55
  d_content.resize(sizeof(dnsheader));
9,714,235✔
56
  uint8_t* dptr=(&*d_content.begin());
9,714,235✔
57

58
  memcpy(dptr, ptr, sizeof(dnsheader));
9,714,235✔
59
  d_namepositions.reserve(16);
9,714,235✔
60
  xfrName(qname, false);
9,714,235✔
61
  xfr16BitInt(qtype);
9,714,235✔
62
  xfr16BitInt(qclass);
9,714,235✔
63

64
  d_truncatemarker=d_content.size();
9,714,235✔
65
  d_sor = 0;
9,714,235✔
66
  d_rollbackmarker = 0;
9,714,235✔
67
}
9,714,235✔
68

69
template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
70
{
11,039,733✔
71
  return reinterpret_cast<dnsheader*>(&*d_content.begin());
11,039,733✔
72
}
11,039,733✔
73

74

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

81
  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
8,310,645✔
82
    static unsigned char marker[2]={0xc0, 0x0c};
1,853,628✔
83
    d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]);
1,853,628✔
84
  }
1,853,628✔
85
  else {
4,301,424,311✔
86
    xfrName(name, compress);
4,301,424,311✔
87
  }
4,301,424,311✔
88
  xfr16BitInt(qtype);
8,304,759✔
89
  xfr16BitInt(qclass);
8,304,759✔
90
  xfr32BitInt(ttl);
8,304,759✔
91
  xfr16BitInt(0); // this will be the record size
8,304,759✔
92
  d_recordplace = place;
8,304,759✔
93
  d_sor=d_content.size(); // this will remind us where to stuff the record size
8,304,759✔
94
}
8,304,759✔
95

96
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)
97
{
158,805✔
98
  uint32_t ttl=0;
158,805✔
99

100
  EDNS0Record stuff;
158,805✔
101

102
  stuff.version = version;
158,805✔
103
  stuff.extFlags = htons(ednsFlags);
158,805✔
104

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

117
  static_assert(sizeof(EDNS0Record) == sizeof(ttl), "sizeof(EDNS0Record) must match sizeof(ttl)");
158,805✔
118
  memcpy(&ttl, &stuff, sizeof(stuff));
158,805✔
119

120
  ttl=ntohl(ttl); // will be reversed later on
158,805✔
121

122
  startRecord(g_rootdnsname, QType::OPT, ttl, udpsize, DNSResourceRecord::ADDITIONAL, false);
158,805✔
123
  for(auto const &option : options) {
158,805✔
124
    xfr16BitInt(option.first);
1,782✔
125
    xfr16BitInt(option.second.length());
1,782✔
126
    xfrBlob(option.second);
1,782✔
127
  }
1,782✔
128
}
158,805✔
129

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

138
  d_content.insert(d_content.end(), bytes.begin(), bytes.end());
938✔
139
}
938✔
140

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

146
template <typename Container> void GenericDNSPacketWriter<Container>::xfr32BitInt(uint32_t val)
147
{
18,393,394✔
148
  uint32_t rval=htonl(val);
18,393,394✔
149
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
18,393,394✔
150
  d_content.insert(d_content.end(), ptr, ptr+4);
18,393,394✔
151
}
18,393,394✔
152

153
template <typename Container> void GenericDNSPacketWriter<Container>::xfr16BitInt(uint16_t val)
154
{
49,932,904✔
155
  uint16_t rval=htons(val);
49,932,904✔
156
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
49,932,904✔
157
  d_content.insert(d_content.end(), ptr, ptr+2);
49,932,904✔
158
}
49,932,904✔
159

160
template <typename Container> void GenericDNSPacketWriter<Container>::xfr8BitInt(uint8_t val)
161
{
8,560,263✔
162
  d_content.push_back(val);
8,560,263✔
163
}
8,560,263✔
164

165

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

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

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

204

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

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

221
  try {
2,935,346✔
222
    for(auto riter= raw.cbegin(); riter < raw.cend(); ) {
11,701,012!
223
      if(!*riter)
11,701,004✔
224
        break;
2,935,364✔
225
      nvect.push_back(riter - raw.cbegin());
8,765,640✔
226
      riter+=*riter+1;
8,765,640✔
227
    }
8,765,640✔
228
  }
2,935,346✔
229
  catch(std::bad_alloc& ba) {
2,935,346✔
230
    if(l_verbose)
3✔
231
      cout<<"Domain "<<name<<" too large to compress"<<endl;
×
232
    return 0;
3✔
233
  }
3✔
234

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

243
  if(l_verbose)
2,935,364✔
244
    cout<<"Have "<<d_namepositions.size()<<" to ponder"<<endl;
×
245
  int counter=1;
2,935,364✔
246
  for(auto p : d_namepositions) {
78,113,417✔
247
    if(l_verbose) {
78,080,836✔
248
      cout<<"Pos: "<<p<<", "<<d_content.size()<<endl;
×
249
      DNSName pname((const char*)&d_content[0], d_content.size(), p, true); // only for debugging
×
250
      cout<<"Looking at '"<<pname<<"' in packet at position "<<p<<"/"<<d_content.size()<<", option "<<counter<<"/"<<d_namepositions.size()<<endl;
×
251
      ++counter;
×
252
    }
×
253
    // memcmp here makes things _slower_
254
    pvect.clear();
78,080,836✔
255
    try {
78,080,836✔
256
      for(auto iter = d_content.cbegin() + p; iter < d_content.cend();) {
316,907,277!
257
        uint8_t c=*iter;
316,907,265✔
258
        if(l_verbose)
316,907,265✔
259
          cout<<"Found label length: "<<(int)c<<endl;
×
260
        if(c & 0xc0) {
316,907,265✔
261
          uint16_t npos = 0x100*(c & (~0xc0)) + *++iter;
38,680,812✔
262
          iter = d_content.begin() + npos;
38,680,812✔
263
          if(l_verbose)
38,680,812✔
264
            cout<<"Is compressed label to newpos "<<npos<<", going there"<<endl;
×
265
          // check against going forward here
266
          continue;
38,680,812✔
267
        }
38,680,812✔
268
        if(!c)
278,226,453✔
269
          break;
78,080,848✔
270
        auto offset = iter - d_content.cbegin();
200,145,605✔
271
        if (offset >= maxCompressionOffset) break; // compression pointers cannot point here
200,145,605!
272
        pvect.push_back(offset);
200,145,604✔
273
        iter+=*iter+1;
200,145,604✔
274
      }
200,145,604✔
275
    }
78,080,836✔
276
    catch(std::bad_alloc& ba) {
78,080,836✔
277
      if(l_verbose)
6✔
278
        cout<<"Domain "<<name<<" too large to compress"<<endl;
×
279
      continue;
6✔
280
    }
6✔
281
    if(l_verbose) {
78,080,832✔
282
      cout<<"Packet vector: "<<endl;
×
283
      for(const auto n : pvect)
×
284
        cout << n<<" ";
×
285
      cout<<endl;
×
286
    }
×
287
    auto niter=nvect.crbegin(), piter=pvect.crbegin();
78,080,832✔
288
    unsigned int cmatchlen=1;
78,080,832✔
289
    for(; niter != nvect.crend() && piter != pvect.crend(); ++niter, ++piter) {
233,797,125!
290
      // niter is an offset in raw, pvect an offset in packet
291
      uint8_t nlen = raw[*niter], plen=d_content[*piter];
199,014,539✔
292
      if(l_verbose)
199,014,539✔
293
        cout<<"nlnen="<<(int)nlen<<", plen="<<(int)plen<<endl;
×
294
      if(nlen != plen)
199,014,539✔
295
        break;
12,895,051✔
296
      if(strncasecmp(raw.c_str()+*niter+1, (const char*)&d_content[*piter]+1, nlen)) {
186,119,488✔
297
        if(l_verbose)
29,409,708✔
298
          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;
×
299
        break;
29,409,708✔
300
      }
29,409,708✔
301
      cmatchlen+=nlen+1;
156,709,780✔
302
      if(cmatchlen == raw.length()) { // have matched all of it, can't improve
156,709,780✔
303
        if(l_verbose)
993,514✔
304
          cout<<"Stopping search, matched whole name"<<endl;
×
305
        *matchLen = cmatchlen;
993,514✔
306
        return *piter;
993,514✔
307
      }
993,514✔
308
    }
156,709,780✔
309
    if(piter != pvect.crbegin() && *matchLen < cmatchlen) {
77,087,318✔
310
      *matchLen = cmatchlen;
2,034,006✔
311
      bestpos=*--piter;
2,034,006✔
312
    }
2,034,006✔
313
  }
77,087,318✔
314
  return bestpos;
1,941,852✔
315
}
2,935,364✔
316
// this is the absolute hottest function in the pdns recursor
317
template <typename Container> void GenericDNSPacketWriter<Container>::xfrName(const DNSName& name, bool compress)
318
{
19,014,709✔
319
  if(l_verbose)
19,014,709✔
320
    cout<<"Wants to write "<<name<<", compress="<<compress<<", canonic="<<d_canonic<<", LC="<<d_lowerCase<<endl;
×
321
  if(d_canonic || d_lowerCase)   // d_lowerCase implies canonic
19,015,709✔
322
    compress=false;
4,095,280✔
323

324
  if(name.empty() || name.isRoot()) { // for speed
19,014,713✔
325
    d_content.push_back(0);
8,330,200✔
326
    return;
8,330,200✔
327
  }
8,330,200✔
328

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

337
    unsigned int pos=d_content.size();
2,110,427✔
338
    if(pos < maxCompressionOffset && matchlen != dns.size()) {
2,110,427!
339
      if(l_verbose)
1,116,911✔
340
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for compressed case"<<endl;
×
341
      d_namepositions.push_back(pos);
1,116,911✔
342
    }
1,116,911✔
343

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

350
    d_content.push_back((char)(offset >> 8));
2,110,427✔
351
    d_content.push_back((char)(offset & 0xff));
2,110,427✔
352
  }
2,110,427✔
353
  else {
8,574,082✔
354
    unsigned int pos=d_content.size();
8,574,082✔
355
    if(l_verbose)
8,574,082✔
356
      cout<<"Found nothing, we are at pos "<<pos<<", inserting whole name"<<endl;
×
357
    if(pos < maxCompressionOffset) {
8,575,746✔
358
      if(l_verbose)
8,532,292✔
359
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for uncompressed case"<<endl;
×
360
      d_namepositions.push_back(pos);
8,532,292✔
361
    }
8,532,292✔
362

363
    std::unique_ptr<DNSName> lc;
8,574,082✔
364
    if(d_lowerCase)
8,574,082!
365
      lc = make_unique<DNSName>(name.makeLowerCase());
1,172,200✔
366

367
    const DNSName::string_t& raw = (lc ? *lc : name).getStorage();
8,574,082!
368
    if(l_verbose)
8,574,082✔
369
      cout<<"Writing out the whole thing "<<makeHexDump(string(raw.c_str(),  raw.c_str() + raw.length()))<<endl;
×
370
    d_content.insert(d_content.end(), raw.c_str(), raw.c_str() + raw.size());
8,574,082✔
371
  }
8,574,082✔
372
}
10,684,509✔
373

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

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

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

390
template <typename Container> void GenericDNSPacketWriter<Container>::xfrHexBlob(const string& blob, bool /* keepReading */)
391
{
28,589✔
392
  xfrBlob(blob);
28,589✔
393
}
28,589✔
394

395
template <typename Container> void GenericDNSPacketWriter<Container>::xfrSvcParamKeyVals(const std::set<SvcParam> &kvs)
396
{
7,766✔
397
  for (auto const &param : kvs) {
12,593!
398
    // Key first!
399
    xfr16BitInt(param.getKey());
12,593✔
400

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

452
// call __before commit__
453
template <typename Container> void GenericDNSPacketWriter<Container>::getRecordPayload(string& records)
454
{
4,448,078✔
455
  records.assign(d_content.begin() + d_sor, d_content.end());
4,448,078✔
456
}
4,448,078✔
457

458
// call __before commit__
459
template <typename Container> void GenericDNSPacketWriter<Container>::getWireFormatContent(string& record)
460
{
16,917✔
461
  record.assign(d_content.begin() + d_rollbackmarker, d_content.end());
16,917✔
462
}
16,917✔
463

464
template <typename Container> uint32_t GenericDNSPacketWriter<Container>::size() const
465
{
2,090,041✔
466
  return d_content.size();
2,090,041✔
467
}
2,090,041✔
468

469
template <typename Container> void GenericDNSPacketWriter<Container>::rollback()
470
{
718✔
471
  d_content.resize(d_rollbackmarker);
718✔
472
  d_sor = 0;
718✔
473
}
718✔
474

475
template <typename Container> void GenericDNSPacketWriter<Container>::truncate()
476
{
718✔
477
  d_content.resize(d_truncatemarker);
718✔
478
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
718✔
479
  dh->ancount = dh->nscount = dh->arcount = 0;
718✔
480
}
718✔
481

482
template <typename Container> void GenericDNSPacketWriter<Container>::commit()
483
{
10,208,497✔
484
  if(!d_sor)
10,208,497✔
485
    return;
6,367,164✔
486
  uint16_t rlen = d_content.size() - d_sor;
3,841,333✔
487
  d_content[d_sor-2]=rlen >> 8;
3,841,333✔
488
  d_content[d_sor-1]=rlen & 0xff;
3,841,333✔
489
  d_sor=0;
3,841,333✔
490
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
3,841,333✔
491
  switch(d_recordplace) {
3,841,333✔
492
  case DNSResourceRecord::QUESTION:
×
493
    dh->qdcount = htons(ntohs(dh->qdcount) + 1);
×
494
    break;
×
495
  case DNSResourceRecord::ANSWER:
3,371,222✔
496
    dh->ancount = htons(ntohs(dh->ancount) + 1);
3,371,222✔
497
    break;
3,371,222✔
498
  case DNSResourceRecord::AUTHORITY:
246,161✔
499
    dh->nscount = htons(ntohs(dh->nscount) + 1);
246,161✔
500
    break;
246,161✔
501
  case DNSResourceRecord::ADDITIONAL:
229,111✔
502
    dh->arcount = htons(ntohs(dh->arcount) + 1);
229,111✔
503
    break;
229,111✔
504
  }
3,841,333✔
505

506
}
3,841,333✔
507

508
template <typename Container> size_t GenericDNSPacketWriter<Container>::getSizeWithOpts(const optvect_t& options) const
509
{
14✔
510
  size_t result = size() + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE + DNS_RDLENGTH_SIZE;
14✔
511

512
  for(auto const &option : options) {
14!
513
    result += 4;
×
514
    result += option.second.size();
×
515
  }
×
516

517
  return result;
14✔
518
}
14✔
519

520
template class GenericDNSPacketWriter<std::vector<uint8_t>>;
521
#include "noinitvector.hh"
522
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