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

PowerDNS / pdns / 15920880335

26 Jun 2025 03:30PM UTC coverage: 61.923% (-3.7%) from 65.652%
15920880335

push

github

web-flow
Merge pull request #15669 from miodvallat/serial_keyer

Increase zone serial number after zone key operations

38311 of 91850 branches covered (41.71%)

Branch coverage included in aggregate %.

27 of 29 new or added lines in 1 file covered. (93.1%)

6308 existing lines in 78 files now uncovered.

120482 of 164587 relevant lines covered (73.2%)

5965233.22 hits per line

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

81.86
/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
template <typename Container>
44
GenericDNSPacketWriter<Container>::GenericDNSPacketWriter(Container& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode) :
45
  d_content(content), d_qname(qname)
3,550,692✔
46
{
9,466,447✔
47
  d_content.clear();
9,466,447✔
48
  dnsheader dnsheader;
9,466,447✔
49

50
  memset(&dnsheader, 0, sizeof(dnsheader));
9,466,447✔
51
  dnsheader.id=0;
9,466,447✔
52
  dnsheader.qdcount=htons(1);
9,466,447✔
53
  dnsheader.opcode=opcode;
9,466,447✔
54

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

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

66
  d_truncatemarker=d_content.size();
9,466,447✔
67
  d_sor = 0;
9,466,447✔
68
  d_rollbackmarker = 0;
9,466,447✔
69
}
9,466,447✔
70

71
template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
72
{
10,768,952✔
73
  return reinterpret_cast<dnsheader*>(&*d_content.begin());
10,768,952✔
74
}
10,768,952✔
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
{
7,985,730✔
79
  d_compress = compress;
7,985,730✔
80
  commit();
7,985,730✔
81
  d_rollbackmarker=d_content.size();
7,985,730✔
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
7,989,404✔
84
    static unsigned char marker[2]={0xc0, 0x0c};
1,823,752✔
85
    d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]);
1,823,752✔
86
  }
1,823,752✔
87
  else {
4,301,132,946✔
88
    xfrName(name, compress);
4,301,132,946✔
89
  }
4,301,132,946✔
90
  xfr16BitInt(qtype);
7,985,730✔
91
  xfr16BitInt(qclass);
7,985,730✔
92
  xfr32BitInt(ttl);
7,985,730✔
93
  xfr16BitInt(0); // this will be the record size
7,985,730✔
94
  d_recordplace = place;
7,985,730✔
95
  d_sor=d_content.size(); // this will remind us where to stuff the record size
7,985,730✔
96
}
7,985,730✔
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
{
135,798✔
100
  uint32_t ttl=0;
135,798✔
101

102
  EDNS0Record stuff;
135,798✔
103

104
  stuff.version = version;
135,798✔
105
  stuff.extFlags = htons(ednsFlags);
135,798✔
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;
135,798✔
115
  if (extRCode != 0) { // As this trumps the existing RCODE
135,798✔
116
    getHeader()->rcode = extRCode;
3✔
117
  }
3✔
118

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

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

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

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

140
  d_content.insert(d_content.end(), bytes.begin(), bytes.end());
938✔
141
}
938✔
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
{
17,710,797✔
150
  uint32_t rval=htonl(val);
17,710,797✔
151
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
17,710,797✔
152
  d_content.insert(d_content.end(), ptr, ptr+4);
17,710,797✔
153
}
17,710,797✔
154

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

162
template <typename Container> void GenericDNSPacketWriter<Container>::xfr8BitInt(uint8_t val)
163
{
8,203,210✔
164
  d_content.push_back(val);
8,203,210✔
165
}
8,203,210✔
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
{
53,412✔
183
  if(text.empty()) {
53,412!
184
    d_content.push_back(0);
×
185
    return;
×
186
  }
×
187
  vector<string> segments = segmentDNSText(text);
53,412✔
188
  for(const string& str :  segments) {
60,700✔
189
    if(lenField)
60,700!
190
      d_content.push_back(str.length());
60,670✔
191
    d_content.insert(d_content.end(), str.c_str(), str.c_str() + str.length());
60,700✔
192
  }
60,700✔
193
}
53,412✔
194

195
template <typename Container> void GenericDNSPacketWriter<Container>::xfrUnquotedText(const string& text, bool lenField)
196
{
8,691✔
197
  if(text.empty()) {
8,691!
198
    d_content.push_back(0);
×
199
    return;
×
200
  }
×
201
  if(lenField)
8,691!
202
    d_content.push_back(text.length());
8,691✔
203
  d_content.insert(d_content.end(), text.c_str(), text.c_str() + text.length());
8,691✔
204
}
8,691✔
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
{
2,813,685✔
211
  // iterate over the written labels, see if we find a match
212
  const auto& raw = name.getStorage();
2,813,685✔
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;
2,813,685✔
219
  *matchLen=0;
2,813,685✔
220
  boost::container::static_vector<uint16_t, 34> nvect;
2,813,685✔
221
  boost::container::static_vector<uint16_t, 34> pvect;
2,813,685✔
222

223
  try {
2,813,685✔
224
    for(auto riter= raw.cbegin(); riter < raw.cend(); ) {
11,236,856!
225
      if(!*riter)
11,236,853✔
226
        break;
2,813,706✔
227
      nvect.push_back(riter - raw.cbegin());
8,423,147✔
228
      riter+=*riter+1;
8,423,147✔
229
    }
8,423,147✔
230
  }
2,813,685✔
231
  catch(std::bad_alloc& ba) {
2,813,685✔
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) {
2,813,705✔
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)
2,813,705✔
246
    cout<<"Have "<<d_namepositions.size()<<" to ponder"<<endl;
×
247
  int counter=1;
2,813,705✔
248
  for(auto p : d_namepositions) {
77,707,591✔
249
    if(l_verbose) {
77,668,931✔
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();
77,668,931✔
257
    try {
77,668,931✔
258
      for(auto iter = d_content.cbegin() + p; iter < d_content.cend();) {
315,165,588!
259
        uint8_t c=*iter;
315,165,579✔
260
        if(l_verbose)
315,165,579✔
261
          cout<<"Found label length: "<<(int)c<<endl;
×
262
        if(c & 0xc0) {
315,165,579✔
263
          uint16_t npos = 0x100*(c & (~0xc0)) + *++iter;
38,489,829✔
264
          iter = d_content.begin() + npos;
38,489,829✔
265
          if(l_verbose)
38,489,829✔
266
            cout<<"Is compressed label to newpos "<<npos<<", going there"<<endl;
×
267
          // check against going forward here
268
          continue;
38,489,829✔
269
        }
38,489,829✔
270
        if(!c)
276,675,750✔
271
          break;
77,668,928✔
272
        auto offset = iter - d_content.cbegin();
199,006,822✔
273
        if (offset >= maxCompressionOffset) break; // compression pointers cannot point here
199,006,822!
274
        pvect.push_back(offset);
199,006,821✔
275
        iter+=*iter+1;
199,006,821✔
276
      }
199,006,821✔
277
    }
77,668,931✔
278
    catch(std::bad_alloc& ba) {
77,668,931✔
279
      if(l_verbose)
6✔
280
        cout<<"Domain "<<name<<" too large to compress"<<endl;
×
281
      continue;
6✔
282
    }
6✔
283
    if(l_verbose) {
77,668,908✔
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();
77,668,908✔
290
    unsigned int cmatchlen=1;
77,668,908✔
291
    for(; niter != nvect.crend() && piter != pvect.crend(); ++niter, ++piter) {
232,633,157!
292
      // niter is an offset in raw, pvect an offset in packet
293
      uint8_t nlen = raw[*niter], plen=d_content[*piter];
197,987,117✔
294
      if(l_verbose)
197,987,117✔
295
        cout<<"nlnen="<<(int)nlen<<", plen="<<(int)plen<<endl;
×
296
      if(nlen != plen)
197,987,117✔
297
        break;
12,773,324✔
298
      if(strncasecmp(raw.c_str()+*niter+1, (const char*)&d_content[*piter]+1, nlen)) {
185,213,793✔
299
        if(l_verbose)
29,283,303✔
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;
29,283,303✔
302
      }
29,283,303✔
303
      cmatchlen+=nlen+1;
155,930,490✔
304
      if(cmatchlen == raw.length()) { // have matched all of it, can't improve
155,930,490✔
305
        if(l_verbose)
966,254✔
306
          cout<<"Stopping search, matched whole name"<<endl;
×
307
        *matchLen = cmatchlen;
966,254✔
308
        return *piter;
966,254✔
309
      }
966,254✔
310
    }
155,930,490✔
311
    if(piter != pvect.crbegin() && *matchLen < cmatchlen) {
76,702,654✔
312
      *matchLen = cmatchlen;
1,964,583✔
313
      bestpos=*--piter;
1,964,583✔
314
    }
1,964,583✔
315
  }
76,702,654✔
316
  return bestpos;
1,847,434✔
317
}
2,813,705✔
318
// this is the absolute hottest function in the pdns recursor
319
template <typename Container> void GenericDNSPacketWriter<Container>::xfrName(const DNSName& name, bool compress)
320
{
18,293,225✔
321
  if(l_verbose)
18,293,225✔
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
18,293,900✔
324
    compress=false;
3,809,872✔
325

326
  if(name.empty() || name.isRoot()) { // for speed
18,293,226✔
327
    d_content.push_back(0);
7,877,049✔
328
    return;
7,877,049✔
329
  }
7,877,049✔
330

331
  uint16_t li=0;
10,416,176✔
332
  uint16_t matchlen=0;
10,416,176✔
333
  if(d_compress && compress && (li=lookupName(name, &matchlen)) && li < maxCompressionOffset) {
10,416,176!
334
    const auto& dns=name.getStorage();
2,028,568✔
335
    if(l_verbose)
2,028,568✔
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();
2,028,568✔
340
    if(pos < maxCompressionOffset && matchlen != dns.size()) {
2,028,568!
341
      if(l_verbose)
1,062,306✔
342
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for compressed case"<<endl;
×
343
      d_namepositions.push_back(pos);
1,062,306✔
344
    }
1,062,306✔
345

346
    if(l_verbose)
2,028,568✔
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);
2,028,568✔
349
    uint16_t offset=li;
2,028,568✔
350
    offset|=0xc000;
2,028,568✔
351

352
    d_content.push_back((char)(offset >> 8));
2,028,568✔
353
    d_content.push_back((char)(offset & 0xff));
2,028,568✔
354
  }
2,028,568✔
355
  else {
8,387,608✔
356
    unsigned int pos=d_content.size();
8,387,608✔
357
    if(l_verbose)
8,387,608✔
358
      cout<<"Found nothing, we are at pos "<<pos<<", inserting whole name"<<endl;
×
359
    if(pos < maxCompressionOffset) {
8,387,618✔
360
      if(l_verbose)
8,330,874✔
361
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for uncompressed case"<<endl;
×
362
      d_namepositions.push_back(pos);
8,330,874✔
363
    }
8,330,874✔
364

365
    std::unique_ptr<DNSName> lc;
8,387,608✔
366
    if(d_lowerCase)
8,387,608!
367
      lc = make_unique<DNSName>(name.makeLowerCase());
1,058,128✔
368

369
    const DNSName::string_t& raw = (lc ? *lc : name).getStorage();
8,387,608!
370
    if(l_verbose)
8,387,608✔
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());
8,387,608✔
373
  }
8,387,608✔
374
}
10,416,176✔
375

376
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const string& blob, int  )
377
{
5,154,493✔
378
  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
5,154,493✔
379
  d_content.insert(d_content.end(), ptr, ptr+blob.size());
5,154,493✔
380
}
5,154,493✔
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
{
350✔
389
  xfrBlob(blob);
350✔
390
}
350✔
391

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

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

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

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

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

466
template <typename Container> uint32_t GenericDNSPacketWriter<Container>::size() const
467
{
2,021,857✔
468
  return d_content.size();
2,021,857✔
469
}
2,021,857✔
470

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

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

484
template <typename Container> void GenericDNSPacketWriter<Container>::commit()
485
{
9,841,822✔
486
  if(!d_sor)
9,841,822✔
487
    return;
6,089,308✔
488
  uint16_t rlen = d_content.size() - d_sor;
3,752,514✔
489
  d_content[d_sor-2]=rlen >> 8;
3,752,514✔
490
  d_content[d_sor-1]=rlen & 0xff;
3,752,514✔
491
  d_sor=0;
3,752,514✔
492
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
3,752,514✔
493
  switch(d_recordplace) {
3,752,514✔
494
  case DNSResourceRecord::QUESTION:
×
495
    dh->qdcount = htons(ntohs(dh->qdcount) + 1);
×
496
    break;
×
497
  case DNSResourceRecord::ANSWER:
3,347,019✔
498
    dh->ancount = htons(ntohs(dh->ancount) + 1);
3,347,019✔
499
    break;
3,347,019✔
500
  case DNSResourceRecord::AUTHORITY:
205,177✔
501
    dh->nscount = htons(ntohs(dh->nscount) + 1);
205,177✔
502
    break;
205,177✔
503
  case DNSResourceRecord::ADDITIONAL:
203,247✔
504
    dh->arcount = htons(ntohs(dh->arcount) + 1);
203,247✔
505
    break;
203,247✔
506
  }
3,752,514✔
507

508
}
3,752,514✔
509

510
template <typename Container> size_t GenericDNSPacketWriter<Container>::getSizeWithOpts(const optvect_t& options) const
UNCOV
511
{
×
UNCOV
512
  size_t result = size() + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE + DNS_RDLENGTH_SIZE;
×
513

UNCOV
514
  for(auto const &option : options) {
×
515
    result += 4;
×
516
    result += option.second.size();
×
517
  }
×
518

UNCOV
519
  return result;
×
UNCOV
520
}
×
521

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