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

PowerDNS / pdns / 12321902803

13 Dec 2024 07:34PM UTC coverage: 66.359% (+1.6%) from 64.78%
12321902803

Pull #14970

github

web-flow
Merge e3a7df61c into 3dfd8e317
Pull Request #14970: boost > std optional

26084 of 54744 branches covered (47.65%)

Branch coverage included in aggregate %.

14 of 15 new or added lines in 2 files covered. (93.33%)

1863 existing lines in 52 files now uncovered.

85857 of 113946 relevant lines covered (75.35%)

4412729.59 hits per line

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

73.85
/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,626,773✔
47
  d_content.clear();
5,626,773✔
48
  dnsheader dnsheader;
5,626,773✔
49

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

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

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

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

71
template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
72
{
1,565,959✔
73
  return reinterpret_cast<dnsheader*>(&*d_content.begin());
1,565,959✔
74
}
1,565,959✔
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
{
6,456,703✔
79
  d_compress = compress;
6,456,703✔
80
  commit();
6,456,703✔
81
  d_rollbackmarker=d_content.size();
6,456,703✔
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
6,457,783!
84
    static unsigned char marker[2]={0xc0, 0x0c};
602,605✔
85
    d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]);
602,605✔
86
  }
602,605✔
87
  else {
2,153,338,825✔
88
    xfrName(name, compress);
2,153,338,825✔
89
  }
2,153,338,825✔
90
  xfr16BitInt(qtype);
6,456,703✔
91
  xfr16BitInt(qclass);
6,456,703✔
92
  xfr32BitInt(ttl);
6,456,703✔
93
  xfr16BitInt(0); // this will be the record size
6,456,703✔
94
  d_recordplace = place;
6,456,703✔
95
  d_sor=d_content.size(); // this will remind us where to stuff the record size
6,456,703✔
96
}
6,456,703✔
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
{
121,444✔
100
  uint32_t ttl=0;
121,444✔
101

102
  EDNS0Record stuff;
121,444✔
103

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

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

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

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

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

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

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

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

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

223
  try {
2,569,016✔
224
    for(auto riter= raw.cbegin(); riter < raw.cend(); ) {
10,256,200!
225
      if(!*riter)
10,256,195!
226
        break;
2,569,012✔
227
      nvect.push_back(riter - raw.cbegin());
7,687,183✔
228
      riter+=*riter+1;
7,687,183✔
229
    }
7,687,183✔
230
  }
2,569,016✔
231
  catch(std::bad_alloc& ba) {
2,569,016✔
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,569,012✔
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,569,012✔
246
    cout<<"Have "<<d_namepositions.size()<<" to ponder"<<endl;
×
247
  int counter=1;
2,569,012✔
248
  for(auto p : d_namepositions) {
77,583,659!
249
    if(l_verbose) {
77,562,167✔
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,562,167✔
257
    try {
77,562,167✔
258
      for(auto iter = d_content.cbegin() + p; iter < d_content.cend();) {
314,628,000!
259
        uint8_t c=*iter;
314,627,993✔
260
        if(l_verbose)
314,627,993✔
261
          cout<<"Found label length: "<<(int)c<<endl;
×
262
        if(c & 0xc0) {
314,627,993!
263
          uint16_t npos = 0x100*(c & (~0xc0)) + *++iter;
38,442,536✔
264
          iter = d_content.begin() + npos;
38,442,536✔
265
          if(l_verbose)
38,442,536✔
266
            cout<<"Is compressed label to newpos "<<npos<<", going there"<<endl;
×
267
          // check against going forward here
268
          continue;
38,442,536✔
269
        }
38,442,536✔
270
        if(!c)
276,185,457!
271
          break;
77,562,202✔
272
        auto offset = iter - d_content.cbegin();
198,623,255✔
273
        if (offset >= maxCompressionOffset) break; // compression pointers cannot point here
198,623,255!
274
        pvect.push_back(offset);
198,623,254✔
275
        iter+=*iter+1;
198,623,254✔
276
      }
198,623,254✔
277
    }
77,562,167✔
278
    catch(std::bad_alloc& ba) {
77,562,167✔
279
      if(l_verbose)
6✔
280
        cout<<"Domain "<<name<<" too large to compress"<<endl;
×
281
      continue;
6✔
282
    }
6✔
283
    if(l_verbose) {
77,562,206✔
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,562,206✔
290
    unsigned int cmatchlen=1;
77,562,206✔
291
    for(; niter != nvect.crend() && piter != pvect.crend(); ++niter, ++piter) {
232,329,229!
292
      // niter is an offset in raw, pvect an offset in packet
293
      uint8_t nlen = raw[*niter], plen=d_content[*piter];
197,708,104✔
294
      if(l_verbose)
197,708,104✔
295
        cout<<"nlnen="<<(int)nlen<<", plen="<<(int)plen<<endl;
×
296
      if(nlen != plen)
197,708,104!
297
        break;
12,628,140✔
298
      if(strncasecmp(raw.c_str()+*niter+1, (const char*)&d_content[*piter]+1, nlen)) {
185,079,964!
299
        if(l_verbose)
29,376,104✔
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,376,104✔
302
      }
29,376,104✔
303
      cmatchlen+=nlen+1;
155,703,860✔
304
      if(cmatchlen == raw.length()) { // have matched all of it, can't improve
155,703,860!
305
        if(l_verbose)
936,840✔
306
          cout<<"Stopping search, matched whole name"<<endl;
×
307
        *matchLen = cmatchlen;
936,840✔
308
        return *piter;
936,840✔
309
      }
936,840✔
310
    }
155,703,860✔
311
    if(piter != pvect.crbegin() && *matchLen < cmatchlen) {
76,625,366!
312
      *matchLen = cmatchlen;
1,908,481✔
313
      bestpos=*--piter;
1,908,481✔
314
    }
1,908,481✔
315
  }
76,625,366✔
316
  return bestpos;
1,632,217✔
317
}
2,569,012✔
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
{
14,057,935✔
321
  if(l_verbose)
14,057,935✔
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
14,058,347!
324
    compress=false;
3,754,805✔
325

326
  if(name.empty() || name.isRoot()) { // for speed
14,057,935!
327
    d_content.push_back(0);
7,540,173✔
328
    return;
7,540,173✔
329
  }
7,540,173✔
330

331
  uint16_t li=0;
6,517,762✔
332
  uint16_t matchlen=0;
6,517,762✔
333
  if(d_compress && compress && (li=lookupName(name, &matchlen)) && li < maxCompressionOffset) {
6,517,762!
334
    const auto& dns=name.getStorage();
1,964,325✔
335
    if(l_verbose)
1,964,325✔
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();
1,964,325✔
340
    if(pos < maxCompressionOffset && matchlen != dns.size()) {
1,964,325!
341
      if(l_verbose)
1,027,482✔
342
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for compressed case"<<endl;
×
343
      d_namepositions.push_back(pos);
1,027,482✔
344
    }
1,027,482✔
345

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

352
    d_content.push_back((char)(offset >> 8));
1,964,325✔
353
    d_content.push_back((char)(offset & 0xff));
1,964,325✔
354
  }
1,964,325✔
355
  else {
4,553,437✔
356
    unsigned int pos=d_content.size();
4,553,437✔
357
    if(l_verbose)
4,553,437✔
358
      cout<<"Found nothing, we are at pos "<<pos<<", inserting whole name"<<endl;
×
359
    if(pos < maxCompressionOffset) {
4,553,548!
360
      if(l_verbose)
4,541,748✔
361
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for uncompressed case"<<endl;
×
362
      d_namepositions.push_back(pos);
4,541,748✔
363
    }
4,541,748✔
364

365
    std::unique_ptr<DNSName> lc;
4,553,437✔
366
    if(d_lowerCase)
4,553,437!
367
      lc = make_unique<DNSName>(name.makeLowerCase());
1,044,789✔
368

369
    const DNSName::string_t& raw = (lc ? *lc : name).getStorage();
4,553,437!
370
    if(l_verbose)
4,553,437✔
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());
4,553,437✔
373
  }
4,553,437✔
374
}
6,517,762✔
375

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

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

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

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

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

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

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

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

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

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

478
template <typename Container> void GenericDNSPacketWriter<Container>::commit()
479
{
7,096,499✔
480
  if(!d_sor)
7,096,499✔
481
    return;
4,616,818✔
482
  uint16_t rlen = d_content.size() - d_sor;
2,479,681✔
483
  d_content[d_sor-2]=rlen >> 8;
2,479,681✔
484
  d_content[d_sor-1]=rlen & 0xff;
2,479,681✔
485
  d_sor=0;
2,479,681✔
486
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
2,479,681✔
487
  switch(d_recordplace) {
2,479,681!
488
  case DNSResourceRecord::QUESTION:
×
489
    dh->qdcount = htons(ntohs(dh->qdcount) + 1);
×
490
    break;
×
491
  case DNSResourceRecord::ANSWER:
2,119,855✔
492
    dh->ancount = htons(ntohs(dh->ancount) + 1);
2,119,855✔
493
    break;
2,119,855✔
494
  case DNSResourceRecord::AUTHORITY:
180,841!
495
    dh->nscount = htons(ntohs(dh->nscount) + 1);
180,841✔
496
    break;
180,841✔
497
  case DNSResourceRecord::ADDITIONAL:
179,412✔
498
    dh->arcount = htons(ntohs(dh->arcount) + 1);
179,412✔
499
    break;
179,412✔
500
  }
2,479,681✔
501

502
}
2,479,681✔
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