Coverage Report

Created: 2025-06-13 06:27

/src/pdns/pdns/dnsdistdist/dnswriter.cc
Line
Count
Source (jump to first uncovered line)
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
0
  d_content(content), d_qname(qname)
46
0
{
47
0
  d_content.clear();
48
0
  dnsheader dnsheader;
49
50
0
  memset(&dnsheader, 0, sizeof(dnsheader));
51
0
  dnsheader.id=0;
52
0
  dnsheader.qdcount=htons(1);
53
0
  dnsheader.opcode=opcode;
54
55
0
  const uint8_t* ptr=(const uint8_t*)&dnsheader;
56
0
  d_content.reserve(sizeof(dnsheader) + qname.wirelength() + sizeof(qtype) + sizeof(qclass));
57
0
  d_content.resize(sizeof(dnsheader));
58
0
  uint8_t* dptr=(&*d_content.begin());
59
60
0
  memcpy(dptr, ptr, sizeof(dnsheader));
61
0
  d_namepositions.reserve(16);
62
0
  xfrName(qname, false);
63
0
  xfr16BitInt(qtype);
64
0
  xfr16BitInt(qclass);
65
66
0
  d_truncatemarker=d_content.size();
67
0
  d_sor = 0;
68
0
  d_rollbackmarker = 0;
69
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::GenericDNSPacketWriter(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, DNSName const&, unsigned short, unsigned short, unsigned char)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::GenericDNSPacketWriter(std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > >&, DNSName const&, unsigned short, unsigned short, unsigned char)
70
71
template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
72
0
{
73
0
  return reinterpret_cast<dnsheader*>(&*d_content.begin());
74
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::getHeader()
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::getHeader()
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
0
{
79
0
  d_compress = compress;
80
0
  commit();
81
0
  d_rollbackmarker=d_content.size();
82
83
0
  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
84
0
    static unsigned char marker[2]={0xc0, 0x0c};
85
0
    d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]);
86
0
  }
87
0
  else {
88
0
    xfrName(name, compress);
89
0
  }
90
0
  xfr16BitInt(qtype);
91
0
  xfr16BitInt(qclass);
92
0
  xfr32BitInt(ttl);
93
0
  xfr16BitInt(0); // this will be the record size
94
0
  d_recordplace = place;
95
0
  d_sor=d_content.size(); // this will remind us where to stuff the record size
96
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::startRecord(DNSName const&, unsigned short, unsigned int, unsigned short, DNSResourceRecord::Place, bool)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::startRecord(DNSName const&, unsigned short, unsigned int, unsigned short, DNSResourceRecord::Place, bool)
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
0
{
100
0
  uint32_t ttl=0;
101
102
0
  EDNS0Record stuff;
103
104
0
  stuff.version = version;
105
0
  stuff.extFlags = htons(ednsFlags);
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
0
  stuff.extRCode = extRCode>>4;
115
0
  if (extRCode != 0) { // As this trumps the existing RCODE
116
0
    getHeader()->rcode = extRCode;
117
0
  }
118
119
0
  static_assert(sizeof(EDNS0Record) == sizeof(ttl), "sizeof(EDNS0Record) must match sizeof(ttl)");
120
0
  memcpy(&ttl, &stuff, sizeof(stuff));
121
122
0
  ttl=ntohl(ttl); // will be reversed later on
123
124
0
  startRecord(g_rootdnsname, QType::OPT, ttl, udpsize, DNSResourceRecord::ADDITIONAL, false);
125
0
  for(auto const &option : options) {
126
0
    xfr16BitInt(option.first);
127
0
    xfr16BitInt(option.second.length());
128
0
    xfrBlob(option.second);
129
0
  }
130
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::addOpt(unsigned short, unsigned short, unsigned short, std::__1::vector<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, unsigned char)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::addOpt(unsigned short, unsigned short, unsigned short, std::__1::vector<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, unsigned char)
131
132
template <typename Container> void GenericDNSPacketWriter<Container>::xfr48BitInt(uint64_t val)
133
0
{
134
0
  std::array<unsigned char, 6> bytes;
135
0
  uint16_t theLeft = htons((val >> 32)&0xffffU);
136
0
  uint32_t theRight = htonl(val & 0xffffffffU);
137
0
  memcpy(&bytes[0], (void*)&theLeft, sizeof(theLeft));
138
0
  memcpy(&bytes[2], (void*)&theRight, sizeof(theRight));
139
140
0
  d_content.insert(d_content.end(), bytes.begin(), bytes.end());
141
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfr48BitInt(unsigned long)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfr48BitInt(unsigned long)
142
143
template <typename Container> void GenericDNSPacketWriter<Container>::xfrNodeOrLocatorID(const NodeOrLocatorID& val)
144
0
{
145
0
  d_content.insert(d_content.end(), val.content, val.content + sizeof(val.content));
146
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrNodeOrLocatorID(NodeOrLocatorID const&)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrNodeOrLocatorID(NodeOrLocatorID const&)
147
148
template <typename Container> void GenericDNSPacketWriter<Container>::xfr32BitInt(uint32_t val)
149
0
{
150
0
  uint32_t rval=htonl(val);
151
0
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
152
0
  d_content.insert(d_content.end(), ptr, ptr+4);
153
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfr32BitInt(unsigned int)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfr32BitInt(unsigned int)
154
155
template <typename Container> void GenericDNSPacketWriter<Container>::xfr16BitInt(uint16_t val)
156
0
{
157
0
  uint16_t rval=htons(val);
158
0
  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
159
0
  d_content.insert(d_content.end(), ptr, ptr+2);
160
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfr16BitInt(unsigned short)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfr16BitInt(unsigned short)
161
162
template <typename Container> void GenericDNSPacketWriter<Container>::xfr8BitInt(uint8_t val)
163
0
{
164
0
  d_content.push_back(val);
165
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfr8BitInt(unsigned char)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfr8BitInt(unsigned char)
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
0
{
183
0
  if(text.empty()) {
184
0
    d_content.push_back(0);
185
0
    return;
186
0
  }
187
0
  vector<string> segments = segmentDNSText(text);
188
0
  for(const string& str :  segments) {
189
0
    if(lenField)
190
0
      d_content.push_back(str.length());
191
0
    d_content.insert(d_content.end(), str.c_str(), str.c_str() + str.length());
192
0
  }
193
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrText(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrText(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool)
194
195
template <typename Container> void GenericDNSPacketWriter<Container>::xfrUnquotedText(const string& text, bool lenField)
196
0
{
197
0
  if(text.empty()) {
198
0
    d_content.push_back(0);
199
0
    return;
200
0
  }
201
0
  if(lenField)
202
0
    d_content.push_back(text.length());
203
0
  d_content.insert(d_content.end(), text.c_str(), text.c_str() + text.length());
204
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrUnquotedText(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrUnquotedText(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
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
0
{
211
  // iterate over the written labels, see if we find a match
212
0
  const auto& raw = name.getStorage();
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
0
  unsigned int bestpos=0;
219
0
  *matchLen=0;
220
0
  boost::container::static_vector<uint16_t, 34> nvect;
221
0
  boost::container::static_vector<uint16_t, 34> pvect;
222
223
0
  try {
224
0
    for(auto riter= raw.cbegin(); riter < raw.cend(); ) {
225
0
      if(!*riter)
226
0
        break;
227
0
      nvect.push_back(riter - raw.cbegin());
228
0
      riter+=*riter+1;
229
0
    }
230
0
  }
231
0
  catch(std::bad_alloc& ba) {
232
0
    if(l_verbose)
233
0
      cout<<"Domain "<<name<<" too large to compress"<<endl;
234
0
    return 0;
235
0
  }
236
237
0
  if(l_verbose) {
238
0
    cout<<"Input vector for lookup "<<name<<": ";
239
0
    for(const auto n : nvect)
240
0
      cout << n<<" ";
241
0
    cout<<endl;
242
0
    cout<<makeHexDump(string(raw.c_str(), raw.c_str()+raw.size()))<<endl;
243
0
  }
244
245
0
  if(l_verbose)
246
0
    cout<<"Have "<<d_namepositions.size()<<" to ponder"<<endl;
247
0
  int counter=1;
248
0
  for(auto p : d_namepositions) {
249
0
    if(l_verbose) {
250
0
      cout<<"Pos: "<<p<<", "<<d_content.size()<<endl;
251
0
      DNSName pname((const char*)&d_content[0], d_content.size(), p, true); // only for debugging
252
0
      cout<<"Looking at '"<<pname<<"' in packet at position "<<p<<"/"<<d_content.size()<<", option "<<counter<<"/"<<d_namepositions.size()<<endl;
253
0
      ++counter;
254
0
    }
255
    // memcmp here makes things _slower_
256
0
    pvect.clear();
257
0
    try {
258
0
      for(auto iter = d_content.cbegin() + p; iter < d_content.cend();) {
259
0
        uint8_t c=*iter;
260
0
        if(l_verbose)
261
0
          cout<<"Found label length: "<<(int)c<<endl;
262
0
        if(c & 0xc0) {
263
0
          uint16_t npos = 0x100*(c & (~0xc0)) + *++iter;
264
0
          iter = d_content.begin() + npos;
265
0
          if(l_verbose)
266
0
            cout<<"Is compressed label to newpos "<<npos<<", going there"<<endl;
267
          // check against going forward here
268
0
          continue;
269
0
        }
270
0
        if(!c)
271
0
          break;
272
0
        auto offset = iter - d_content.cbegin();
273
0
        if (offset >= maxCompressionOffset) break; // compression pointers cannot point here
274
0
        pvect.push_back(offset);
275
0
        iter+=*iter+1;
276
0
      }
277
0
    }
278
0
    catch(std::bad_alloc& ba) {
279
0
      if(l_verbose)
280
0
        cout<<"Domain "<<name<<" too large to compress"<<endl;
281
0
      continue;
282
0
    }
283
0
    if(l_verbose) {
284
0
      cout<<"Packet vector: "<<endl;
285
0
      for(const auto n : pvect)
286
0
        cout << n<<" ";
287
0
      cout<<endl;
288
0
    }
289
0
    auto niter=nvect.crbegin(), piter=pvect.crbegin();
290
0
    unsigned int cmatchlen=1;
291
0
    for(; niter != nvect.crend() && piter != pvect.crend(); ++niter, ++piter) {
292
      // niter is an offset in raw, pvect an offset in packet
293
0
      uint8_t nlen = raw[*niter], plen=d_content[*piter];
294
0
      if(l_verbose)
295
0
        cout<<"nlnen="<<(int)nlen<<", plen="<<(int)plen<<endl;
296
0
      if(nlen != plen)
297
0
        break;
298
0
      if(strncasecmp(raw.c_str()+*niter+1, (const char*)&d_content[*piter]+1, nlen)) {
299
0
        if(l_verbose)
300
0
          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
0
        break;
302
0
      }
303
0
      cmatchlen+=nlen+1;
304
0
      if(cmatchlen == raw.length()) { // have matched all of it, can't improve
305
0
        if(l_verbose)
306
0
          cout<<"Stopping search, matched whole name"<<endl;
307
0
        *matchLen = cmatchlen;
308
0
        return *piter;
309
0
      }
310
0
    }
311
0
    if(piter != pvect.crbegin() && *matchLen < cmatchlen) {
312
0
      *matchLen = cmatchlen;
313
0
      bestpos=*--piter;
314
0
    }
315
0
  }
316
0
  return bestpos;
317
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::lookupName(DNSName const&, unsigned short*)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::lookupName(DNSName const&, unsigned short*)
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
0
{
321
0
  if(l_verbose)
322
0
    cout<<"Wants to write "<<name<<", compress="<<compress<<", canonic="<<d_canonic<<", LC="<<d_lowerCase<<endl;
323
0
  if(d_canonic || d_lowerCase)   // d_lowerCase implies canonic
324
0
    compress=false;
325
326
0
  if(name.empty() || name.isRoot()) { // for speed
327
0
    d_content.push_back(0);
328
0
    return;
329
0
  }
330
331
0
  uint16_t li=0;
332
0
  uint16_t matchlen=0;
333
0
  if(d_compress && compress && (li=lookupName(name, &matchlen)) && li < maxCompressionOffset) {
334
0
    const auto& dns=name.getStorage();
335
0
    if(l_verbose)
336
0
      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
0
    unsigned int pos=d_content.size();
340
0
    if(pos < maxCompressionOffset && matchlen != dns.size()) {
341
0
      if(l_verbose)
342
0
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for compressed case"<<endl;
343
0
      d_namepositions.push_back(pos);
344
0
    }
345
346
0
    if(l_verbose)
347
0
      cout<<"Going to write unique part: '"<<makeHexDump(string(dns.c_str(), dns.c_str() + dns.size() - matchlen)) <<"'"<<endl;
348
0
    d_content.insert(d_content.end(), (const unsigned char*)dns.c_str(), (const unsigned char*)dns.c_str() + dns.size() - matchlen);
349
0
    uint16_t offset=li;
350
0
    offset|=0xc000;
351
352
0
    d_content.push_back((char)(offset >> 8));
353
0
    d_content.push_back((char)(offset & 0xff));
354
0
  }
355
0
  else {
356
0
    unsigned int pos=d_content.size();
357
0
    if(l_verbose)
358
0
      cout<<"Found nothing, we are at pos "<<pos<<", inserting whole name"<<endl;
359
0
    if(pos < maxCompressionOffset) {
360
0
      if(l_verbose)
361
0
        cout<<"Inserting pos "<<pos<<" for "<<name<<" for uncompressed case"<<endl;
362
0
      d_namepositions.push_back(pos);
363
0
    }
364
365
0
    std::unique_ptr<DNSName> lc;
366
0
    if(d_lowerCase)
367
0
      lc = make_unique<DNSName>(name.makeLowerCase());
368
369
0
    const DNSName::string_t& raw = (lc ? *lc : name).getStorage();
370
0
    if(l_verbose)
371
0
      cout<<"Writing out the whole thing "<<makeHexDump(string(raw.c_str(),  raw.c_str() + raw.length()))<<endl;
372
0
    d_content.insert(d_content.end(), raw.c_str(), raw.c_str() + raw.size());
373
0
  }
374
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrName(DNSName const&, bool)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrName(DNSName const&, bool)
375
376
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const string& blob, int  )
377
0
{
378
0
  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
379
0
  d_content.insert(d_content.end(), ptr, ptr+blob.size());
380
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrBlob(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrBlob(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
381
382
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const std::vector<uint8_t>& blob)
383
0
{
384
0
  d_content.insert(d_content.end(), blob.begin(), blob.end());
385
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrBlob(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrBlob(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
386
387
template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlobNoSpaces(const string& blob, int  )
388
0
{
389
0
  xfrBlob(blob);
390
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrBlobNoSpaces(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrBlobNoSpaces(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
391
392
template <typename Container> void GenericDNSPacketWriter<Container>::xfrHexBlob(const string& blob, bool /* keepReading */)
393
0
{
394
0
  xfrBlob(blob);
395
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrHexBlob(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrHexBlob(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
396
397
template <typename Container> void GenericDNSPacketWriter<Container>::xfrSvcParamKeyVals(const std::set<SvcParam> &kvs)
398
0
{
399
0
  for (auto const &param : kvs) {
400
    // Key first!
401
0
    xfr16BitInt(param.getKey());
402
403
0
    switch (param.getKey())
404
0
    {
405
0
    case SvcParam::mandatory:
406
0
      xfr16BitInt(2 * param.getMandatory().size());
407
0
      for (auto const &m: param.getMandatory()) {
408
0
        xfr16BitInt(m);
409
0
      }
410
0
      break;
411
0
    case SvcParam::alpn:
412
0
    {
413
0
      uint16_t totalSize = param.getALPN().size(); // All 1 octet size headers for each value
414
0
      for (auto const &a : param.getALPN()) {
415
0
        totalSize += a.length();
416
0
      }
417
0
      xfr16BitInt(totalSize);
418
0
      for (auto const &a : param.getALPN()) {
419
0
        xfrUnquotedText(a, true); // will add the 1-byte length field
420
0
      }
421
0
      break;
422
0
    }
423
0
    case SvcParam::no_default_alpn:
424
0
      xfr16BitInt(0); // no size :)
425
0
      break;
426
0
    case SvcParam::port:
427
0
      xfr16BitInt(2); // size
428
0
      xfr16BitInt(param.getPort());
429
0
      break;
430
0
    case SvcParam::ipv4hint:
431
0
      xfr16BitInt(param.getIPHints().size() * 4); // size
432
0
      for (const auto& a: param.getIPHints()) {
433
0
        xfrCAWithoutPort(param.getKey(), a);
434
0
      }
435
0
      break;
436
0
    case SvcParam::ipv6hint:
437
0
      xfr16BitInt(param.getIPHints().size() * 16); // size
438
0
      for (const auto& a: param.getIPHints()) {
439
0
        xfrCAWithoutPort(param.getKey(), a);
440
0
      }
441
0
      break;
442
0
    case SvcParam::ech:
443
0
      xfr16BitInt(param.getECH().size()); // size
444
0
      xfrBlobNoSpaces(param.getECH());
445
0
      break;
446
0
    default:
447
0
      xfr16BitInt(param.getValue().size());
448
0
      xfrBlob(param.getValue());
449
0
      break;
450
0
    }
451
0
  }
452
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::xfrSvcParamKeyVals(std::__1::set<SvcParam, std::__1::less<SvcParam>, std::__1::allocator<SvcParam> > const&)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::xfrSvcParamKeyVals(std::__1::set<SvcParam, std::__1::less<SvcParam>, std::__1::allocator<SvcParam> > const&)
453
454
// call __before commit__
455
template <typename Container> void GenericDNSPacketWriter<Container>::getRecordPayload(string& records)
456
0
{
457
0
  records.assign(d_content.begin() + d_sor, d_content.end());
458
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::getRecordPayload(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::getRecordPayload(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
459
460
// call __before commit__
461
template <typename Container> void GenericDNSPacketWriter<Container>::getWireFormatContent(string& record)
462
0
{
463
0
  record.assign(d_content.begin() + d_rollbackmarker, d_content.end());
464
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::getWireFormatContent(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::getWireFormatContent(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
465
466
template <typename Container> uint32_t GenericDNSPacketWriter<Container>::size() const
467
0
{
468
0
  return d_content.size();
469
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::size() const
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::size() const
470
471
template <typename Container> void GenericDNSPacketWriter<Container>::rollback()
472
0
{
473
0
  d_content.resize(d_rollbackmarker);
474
0
  d_sor = 0;
475
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::rollback()
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::rollback()
476
477
template <typename Container> void GenericDNSPacketWriter<Container>::truncate()
478
0
{
479
0
  d_content.resize(d_truncatemarker);
480
0
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
481
0
  dh->ancount = dh->nscount = dh->arcount = 0;
482
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::truncate()
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::truncate()
483
484
template <typename Container> void GenericDNSPacketWriter<Container>::commit()
485
0
{
486
0
  if(!d_sor)
487
0
    return;
488
0
  uint16_t rlen = d_content.size() - d_sor;
489
0
  d_content[d_sor-2]=rlen >> 8;
490
0
  d_content[d_sor-1]=rlen & 0xff;
491
0
  d_sor=0;
492
0
  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
493
0
  switch(d_recordplace) {
494
0
  case DNSResourceRecord::QUESTION:
495
0
    dh->qdcount = htons(ntohs(dh->qdcount) + 1);
496
0
    break;
497
0
  case DNSResourceRecord::ANSWER:
498
0
    dh->ancount = htons(ntohs(dh->ancount) + 1);
499
0
    break;
500
0
  case DNSResourceRecord::AUTHORITY:
501
0
    dh->nscount = htons(ntohs(dh->nscount) + 1);
502
0
    break;
503
0
  case DNSResourceRecord::ADDITIONAL:
504
0
    dh->arcount = htons(ntohs(dh->arcount) + 1);
505
0
    break;
506
0
  }
507
508
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::commit()
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::commit()
509
510
template <typename Container> size_t GenericDNSPacketWriter<Container>::getSizeWithOpts(const optvect_t& options) const
511
0
{
512
0
  size_t result = size() + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE + DNS_RDLENGTH_SIZE;
513
514
0
  for(auto const &option : options) {
515
0
    result += 4;
516
0
    result += option.second.size();
517
0
  }
518
519
0
  return result;
520
0
}
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::getSizeWithOpts(std::__1::vector<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&) const
Unexecuted instantiation: GenericDNSPacketWriter<std::__1::vector<unsigned char, noinit_adaptor<std::__1::allocator<unsigned char> > > >::getSizeWithOpts(std::__1::vector<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&) const
521
522
template class GenericDNSPacketWriter<std::vector<uint8_t>>;
523
#include "noinitvector.hh"
524
template class GenericDNSPacketWriter<PacketBuffer>;