~ubuntu-branches/ubuntu/trusty/pdns/trusty-backports

« back to all changes in this revision

Viewing changes to pdns/speedtest.cc

  • Committer: Package Import Robot
  • Author(s): Matthijs Möhlmann
  • Date: 2011-11-19 11:58:10 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20111119115810-5u926cmriehkt5j7
Tags: 3.0-1
* New upstream version (Closes: #624330, #626909, #617476, #498918, #500572)
  (Closes: #645539, #623036, #521791, #583161, #590285, #499396)
* Update Standards-Version to 3.9.2
* Add lua backend.
* Use new style dh instead of individual dh_* commands.
* Add Homepage to debian/control (Closes: #634947)
* Add pdnssec and dnsreplay utility.
* Use dbconfig-common to populate / upgrade databases.
* Update patch addconfigdir, do not parse ucf-dist files.
* Update manpage pdns_control and include a list of options (Closes: #621724)
* Add manpage for pdnssec.
* Add prerm scripts to the backends, stop the pdns server.
* Add patch from upstream to properly parse priority. (Closes: #533023)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "dnsparser.hh"
 
2
#include "sstuff.hh"
 
3
#include "misc.hh"
 
4
#include "dnswriter.hh"
 
5
#include "dnsrecords.hh"
 
6
#include <boost/format.hpp>
 
7
#include "config.h"
 
8
#ifndef RECURSOR
 
9
#include "statbag.hh"
 
10
StatBag S;
 
11
#endif
 
12
 
 
13
volatile bool g_ret; // make sure the optimizer does not get too smart
 
14
uint64_t g_totalRuns;
 
15
 
 
16
volatile bool g_stop;
 
17
 
 
18
void alarmHandler(int)
 
19
{
 
20
  g_stop=true;
 
21
}
 
22
 
 
23
template<typename C> void doRun(const C& cmd, int mseconds=100)
 
24
{
 
25
  struct itimerval it;
 
26
  it.it_value.tv_sec=mseconds/1000;
 
27
  it.it_value.tv_usec = 1000* (mseconds%1000);
 
28
  it.it_interval.tv_sec=0;
 
29
  it.it_interval.tv_usec=0;
 
30
 
 
31
  signal(SIGVTALRM, alarmHandler);
 
32
  setitimer(ITIMER_VIRTUAL, &it, 0);
 
33
  
 
34
  unsigned int runs=0;
 
35
  g_stop=false;
 
36
  DTime dt;
 
37
  dt.set();
 
38
  while(runs++, !g_stop) {
 
39
    cmd();
 
40
  }
 
41
  double delta=dt.udiff()/1000000.0;
 
42
  boost::format fmt("'%s' %.02f seconds: %.1f runs/s, %.02f usec/run");
 
43
 
 
44
  cerr<< (fmt % cmd.getName() % delta % (runs/delta) % (delta* 1000000.0/runs)) << endl;
 
45
  g_totalRuns += runs;
 
46
}
 
47
 
 
48
struct ARecordTest
 
49
{
 
50
  explicit ARecordTest(int records) : d_records(records) {}
 
51
 
 
52
  string getName() const
 
53
  {
 
54
    return (boost::format("%d a records") % d_records).str();
 
55
  }
 
56
 
 
57
  void operator()() const
 
58
  {
 
59
    vector<uint8_t> packet;
 
60
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
 
61
    for(int records = 0; records < d_records; records++) {
 
62
      pw.startRecord("outpost.ds9a.nl", QType::A);
 
63
      ARecordContent arc("1.2.3.4");
 
64
      arc.toPacket(pw);
 
65
    }
 
66
    pw.commit();
 
67
  }
 
68
  int d_records;
 
69
};
 
70
 
 
71
 
 
72
struct MakeStringFromCharStarTest
 
73
{
 
74
  MakeStringFromCharStarTest() : d_size(0){}
 
75
  string getName() const
 
76
  {
 
77
    return (boost::format("make a std::string")).str();
 
78
  }
 
79
 
 
80
  void operator()() const
 
81
  {
 
82
    string name("outpost.ds9a.nl");
 
83
    d_size += name.length();
 
84
    
 
85
  }
 
86
  mutable int d_size;
 
87
};
 
88
 
 
89
 
 
90
struct GetTimeTest
 
91
{
 
92
  string getName() const
 
93
  {
 
94
    return "gettimeofday-test";
 
95
  }
 
96
 
 
97
  void operator()() const
 
98
  {
 
99
    struct timeval tv;
 
100
    gettimeofday(&tv, 0);
 
101
  }
 
102
};
 
103
 
 
104
pthread_mutex_t s_testlock=PTHREAD_MUTEX_INITIALIZER;
 
105
 
 
106
struct GetLockUncontendedTest
 
107
{
 
108
  string getName() const
 
109
  {
 
110
    return "getlock-uncontended-test";
 
111
  }
 
112
 
 
113
  void operator()() const
 
114
  {
 
115
    pthread_mutex_lock(&s_testlock);
 
116
    pthread_mutex_unlock(&s_testlock);
 
117
  }
 
118
};
 
119
 
 
120
 
 
121
struct StaticMemberTest
 
122
{
 
123
  string getName() const
 
124
  {
 
125
    return "static-member-test";
 
126
  }
 
127
 
 
128
  void operator()() const
 
129
  {
 
130
    static string* s_ptr;
 
131
    if(!s_ptr)
 
132
      s_ptr = new string();
 
133
  }
 
134
};
 
135
 
 
136
 
 
137
struct MakeARecordTest
 
138
{
 
139
  string getName() const
 
140
  {
 
141
    return (boost::format("make a-record")).str();
 
142
  }
 
143
 
 
144
  void operator()() const
 
145
  {
 
146
      static string src("1.2.3.4");
 
147
      ARecordContent arc(src);
 
148
      //ARecordContent arc(0x01020304);
 
149
 
 
150
  }
 
151
};
 
152
 
 
153
struct MakeARecordTestMM
 
154
{
 
155
  string getName() const
 
156
  {
 
157
    return (boost::format("make a-record (mm)")).str();
 
158
  }
 
159
 
 
160
  void operator()() const
 
161
  {
 
162
      DNSRecordContent*drc = DNSRecordContent::mastermake(QType::A, 1, 
 
163
                                                          "1.2.3.4");
 
164
      delete drc;
 
165
  }
 
166
};
 
167
 
 
168
 
 
169
struct A2RecordTest
 
170
{
 
171
  explicit A2RecordTest(int records) : d_records(records) {}
 
172
 
 
173
  string getName() const
 
174
  {
 
175
    return (boost::format("%d a records") % d_records).str();
 
176
  }
 
177
 
 
178
  void operator()() const
 
179
  {
 
180
    vector<uint8_t> packet;
 
181
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
 
182
    ARecordContent arc("1.2.3.4");
 
183
    string name("outpost.ds9a.nl");
 
184
    for(int records = 0; records < d_records; records++) {
 
185
      pw.startRecord(name, QType::A);
 
186
 
 
187
      arc.toPacket(pw);
 
188
    }
 
189
    pw.commit();
 
190
  }
 
191
  int d_records;
 
192
};
 
193
 
 
194
 
 
195
struct TXTRecordTest
 
196
{
 
197
  explicit TXTRecordTest(int records) : d_records(records) {}
 
198
 
 
199
  string getName() const
 
200
  {
 
201
    return (boost::format("%d TXT records") % d_records).str();
 
202
  }
 
203
 
 
204
  void operator()() const
 
205
  {
 
206
    vector<uint8_t> packet;
 
207
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::TXT);
 
208
    for(int records = 0; records < d_records; records++) {
 
209
      pw.startRecord("outpost.ds9a.nl", QType::TXT);
 
210
      TXTRecordContent arc("\"een leuk verhaaltje in een TXT\"");
 
211
      arc.toPacket(pw);
 
212
    }
 
213
    pw.commit();
 
214
  }
 
215
  int d_records;
 
216
};
 
217
 
 
218
 
 
219
struct GenericRecordTest
 
220
{
 
221
  explicit GenericRecordTest(int records, uint16_t type, const std::string& content) 
 
222
    : d_records(records), d_type(type), d_content(content) {}
 
223
 
 
224
  string getName() const
 
225
  {
 
226
    return (boost::format("%d %s records") % d_records % 
 
227
            DNSRecordContent::NumberToType(d_type)).str();
 
228
  }
 
229
 
 
230
  void operator()() const
 
231
  {
 
232
    vector<uint8_t> packet;
 
233
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", d_type);
 
234
    for(int records = 0; records < d_records; records++) {
 
235
      pw.startRecord("outpost.ds9a.nl", d_type);
 
236
      DNSRecordContent*drc = DNSRecordContent::mastermake(d_type, 1, 
 
237
                                                          d_content);
 
238
      drc->toPacket(pw);
 
239
      delete drc;
 
240
    }
 
241
    pw.commit();
 
242
  }
 
243
  int d_records;
 
244
  uint16_t d_type;
 
245
  string d_content;
 
246
};
 
247
 
 
248
 
 
249
struct AAAARecordTest
 
250
{
 
251
  explicit AAAARecordTest(int records) : d_records(records) {}
 
252
 
 
253
  string getName() const
 
254
  {
 
255
    return (boost::format("%d aaaa records (mm)") % d_records).str();
 
256
  }
 
257
 
 
258
  void operator()() const
 
259
  {
 
260
    vector<uint8_t> packet;
 
261
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::AAAA);
 
262
    for(int records = 0; records < d_records; records++) {
 
263
      pw.startRecord("outpost.ds9a.nl", QType::AAAA);
 
264
      DNSRecordContent*drc = DNSRecordContent::mastermake(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441");
 
265
      drc->toPacket(pw);
 
266
      delete drc;
 
267
    }
 
268
    pw.commit();
 
269
  }
 
270
  int d_records;
 
271
};
 
272
 
 
273
struct SOARecordTest
 
274
{
 
275
  explicit SOARecordTest(int records) : d_records(records) {}
 
276
 
 
277
  string getName() const
 
278
  {
 
279
    return (boost::format("%d soa records (mm)") % d_records).str();
 
280
  }
 
281
 
 
282
  void operator()() const
 
283
  {
 
284
    vector<uint8_t> packet;
 
285
    DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
 
286
 
 
287
    for(int records = 0; records < d_records; records++) {
 
288
      pw.startRecord("outpost.ds9a.nl", QType::SOA);
 
289
      DNSRecordContent*drc = DNSRecordContent::mastermake(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400");
 
290
      drc->toPacket(pw);
 
291
      delete drc;
 
292
    }
 
293
    pw.commit();
 
294
  }
 
295
  int d_records;
 
296
};
 
297
 
 
298
vector<uint8_t> makeEmptyQuery()
 
299
{
 
300
  vector<uint8_t> packet;
 
301
  DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
 
302
  return  packet;
 
303
}
 
304
 
 
305
 
 
306
vector<uint8_t> makeRootReferral()
 
307
{
 
308
  vector<uint8_t> packet;
 
309
  DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
 
310
 
 
311
  // nobody reads what we output, but it appears to be the magic that shuts some nameservers up
 
312
  static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "128.8.10.90", "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53", 
 
313
                     "192.36.148.17","192.58.128.30", "193.0.14.129", "198.32.64.12", "202.12.27.33"};
 
314
  static char templ[40];
 
315
  strncpy(templ,"a.root-servers.net", sizeof(templ) - 1);
 
316
  
 
317
  
 
318
  for(char c='a';c<='m';++c) {
 
319
    *templ=c;
 
320
    pw.startRecord(".", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
 
321
    DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, templ);
 
322
    drc->toPacket(pw);
 
323
    delete drc;
 
324
  }
 
325
 
 
326
  for(char c='a';c<='m';++c) {
 
327
    *templ=c;
 
328
    pw.startRecord(".", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
 
329
    DNSRecordContent* drc = DNSRecordContent::mastermake(QType::A, 1, ips[c-'a']);
 
330
    drc->toPacket(pw);
 
331
    delete drc;
 
332
  }
 
333
  pw.commit();
 
334
  return  packet;
 
335
 
 
336
}
 
337
 
 
338
vector<uint8_t> makeTypicalReferral()
 
339
{
 
340
  vector<uint8_t> packet;
 
341
  DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
 
342
 
 
343
  pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
 
344
  DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, "ns1.ds9a.nl");
 
345
  drc->toPacket(pw);
 
346
  delete drc;
 
347
 
 
348
  pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
 
349
  drc = DNSRecordContent::mastermake(QType::NS, 1, "ns2.ds9a.nl");
 
350
  drc->toPacket(pw);
 
351
  delete drc;
 
352
 
 
353
 
 
354
  pw.startRecord("ns1.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
 
355
  drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4");
 
356
  drc->toPacket(pw);
 
357
  delete drc;
 
358
 
 
359
  pw.startRecord("ns2.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
 
360
  drc = DNSRecordContent::mastermake(QType::A, 1, "4.3.2.1");
 
361
  drc->toPacket(pw);
 
362
  delete drc;
 
363
 
 
364
  pw.commit();
 
365
  return  packet;
 
366
}
 
367
 
 
368
 
 
369
 
 
370
struct RootRefTest
 
371
{
 
372
  string getName() const
 
373
  {
 
374
    return "write rootreferral";
 
375
  }
 
376
 
 
377
  void operator()() const
 
378
  {
 
379
    vector<uint8_t> packet=makeRootReferral();
 
380
  }
 
381
 
 
382
};
 
383
 
 
384
struct StackMallocTest
 
385
{
 
386
  string getName() const
 
387
  {
 
388
    return "stack allocation";
 
389
  }
 
390
 
 
391
  void operator()() const
 
392
  {
 
393
    char *buffer= new char[200000];
 
394
    delete buffer;
 
395
  }
 
396
 
 
397
};
 
398
 
 
399
 
 
400
struct EmptyQueryTest
 
401
{
 
402
  string getName() const
 
403
  {
 
404
    return "write empty query";
 
405
  }
 
406
 
 
407
  void operator()() const
 
408
  {
 
409
    vector<uint8_t> packet=makeEmptyQuery();
 
410
  }
 
411
 
 
412
};
 
413
 
 
414
struct TypicalRefTest
 
415
{
 
416
  string getName() const
 
417
  {
 
418
    return "write typical referral";
 
419
  }
 
420
 
 
421
  void operator()() const
 
422
  {
 
423
    vector<uint8_t> packet=makeTypicalReferral();
 
424
  }
 
425
 
 
426
};
 
427
 
 
428
struct TCacheComp
 
429
{
 
430
  bool operator()(const pair<string, QType>& a, const pair<string, QType>& b) const
 
431
  {
 
432
    int cmp=strcasecmp(a.first.c_str(), b.first.c_str());
 
433
    if(cmp < 0)
 
434
      return true;
 
435
    if(cmp > 0)
 
436
      return false;
 
437
 
 
438
    return a.second < b.second;
 
439
  }
 
440
};
 
441
 
 
442
struct NegCacheEntry
 
443
{
 
444
  string d_name;
 
445
  QType d_qtype;
 
446
  string d_qname;
 
447
  uint32_t d_ttd;
 
448
};
 
449
 
 
450
struct timeval d_now;
 
451
 
 
452
static bool magicAddrMatch(const QType& query, const QType& answer)
 
453
{
 
454
  if(query.getCode() != QType::ADDR)
 
455
    return false;
 
456
  return answer.getCode() == QType::A || answer.getCode() == QType::AAAA;
 
457
}
 
458
 
 
459
 
 
460
bool moreSpecificThan(const string& a, const string &b)
 
461
{
 
462
  static string dot(".");
 
463
  int counta=(a!=dot), countb=(b!=dot);
 
464
  
 
465
  for(string::size_type n=0;n<a.size();++n)
 
466
    if(a[n]=='.')
 
467
      counta++;
 
468
  for(string::size_type n=0;n<b.size();++n)
 
469
    if(b[n]=='.')
 
470
      countb++;
 
471
  return counta>countb;
 
472
}
 
473
 
 
474
 
 
475
struct ParsePacketTest
 
476
{
 
477
  explicit ParsePacketTest(const vector<uint8_t>& packet, const std::string& name) 
 
478
    : d_packet(packet), d_name(name)
 
479
  {}
 
480
 
 
481
  string getName() const
 
482
  {
 
483
    return "parse '"+d_name+"'";
 
484
  }
 
485
 
 
486
  void operator()() const
 
487
  {
 
488
    MOADNSParser mdp((const char*)&*d_packet.begin(), d_packet.size());
 
489
    typedef map<pair<string, QType>, set<DNSResourceRecord>, TCacheComp > tcache_t;
 
490
    tcache_t tcache;
 
491
    
 
492
    struct {
 
493
            vector<DNSResourceRecord> d_result;
 
494
            bool d_aabit;
 
495
            int d_rcode;
 
496
    } lwr;
 
497
    DNSResourceRecord rr;
 
498
    for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {          
 
499
      DNSResourceRecord rr;
 
500
      rr.qtype=i->first.d_type;
 
501
      rr.qname=i->first.d_label;
 
502
    
 
503
      rr.ttl=i->first.d_ttl;
 
504
      rr.content=i->first.d_content->getZoneRepresentation();  // this should be the serialised form
 
505
      rr.d_place=(DNSResourceRecord::Place) i->first.d_place;
 
506
      lwr.d_result.push_back(rr);
 
507
    }
 
508
 
 
509
    
 
510
    
 
511
 
 
512
      // reap all answers from this packet that are acceptable
 
513
      for(vector<DNSResourceRecord>::iterator i=lwr.d_result.begin();i != lwr.d_result.end();++i) {
 
514
        if(i->qtype.getCode() == QType::OPT) {
 
515
          // <<prefix<<qname<<": skipping OPT answer '"<<i->qname<<"' from '"<<auth<<"' nameservers" <<endl;
 
516
          continue;
 
517
        }
 
518
        // LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ";
 
519
        if(i->qtype.getCode()==QType::ANY) {
 
520
          // LOG<<"NO! - we don't accept 'ANY' data"<<endl;
 
521
          continue;
 
522
        }
 
523
        string auth(".");
 
524
        if(dottedEndsOn(i->qname, auth)) {
 
525
          if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && 0) {
 
526
            // LOG<<"NO! Is from delegation-only zone"<<endl;
 
527
            // s_nodelegated++;
 
528
            return; // RCode::NXDomain;
 
529
          }
 
530
          else {
 
531
            // LOG<<"YES!"<<endl;
 
532
 
 
533
          //  i->ttl=min(s_maxcachettl, i->ttl);
 
534
            
 
535
            DNSResourceRecord rr=*i;
 
536
            rr.d_place=DNSResourceRecord::ANSWER;
 
537
 
 
538
            // rr.ttl += d_now.tv_sec;
 
539
 
 
540
            if(rr.qtype.getCode() == QType::NS) // people fiddle with the case
 
541
              rr.content=toLower(rr.content); // this must stay! (the cache can't be case-insensitive on the RHS of records)
 
542
            tcache[make_pair(i->qname,i->qtype)].insert(rr);
 
543
          }
 
544
        }         
 
545
        else
 
546
          ; // LOG<<"NO!"<<endl;
 
547
      }
 
548
    
 
549
      // supplant
 
550
      for(tcache_t::iterator i=tcache.begin();i!=tcache.end();++i) {
 
551
        if(i->second.size() > 1) {  // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
 
552
          uint32_t lowestTTL=numeric_limits<uint32_t>::max();
 
553
          for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j)
 
554
            lowestTTL=min(lowestTTL, j->ttl);
 
555
          
 
556
          for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j)
 
557
            ((tcache_t::value_type::second_type::value_type*)&(*j))->ttl=lowestTTL;
 
558
        }
 
559
 
 
560
        // RC.replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit);
 
561
      }
 
562
      set<string, CIStringCompare> nsset;  
 
563
      // LOG<<prefix<<qname<<": determining status after receiving this packet"<<endl;
 
564
 
 
565
      bool done=false, realreferral=false, negindic=false;
 
566
      string newauth, soaname, newtarget;
 
567
      string qname(".");
 
568
      vector<DNSResourceRecord> ret;
 
569
      QType qtype(QType::A);
 
570
      string auth(".");
 
571
 
 
572
      for(vector<DNSResourceRecord>::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) {
 
573
        if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
 
574
           lwr.d_rcode==RCode::NXDomain) {
 
575
          // LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"'"<<endl;
 
576
          ret.push_back(*i);
 
577
 
 
578
          NegCacheEntry ne;
 
579
 
 
580
          ne.d_qname=i->qname;
 
581
          ne.d_ttd=d_now.tv_sec + min(i->ttl, 3600U); // controversial
 
582
          ne.d_name=qname;
 
583
          ne.d_qtype=QType(0); // this encodes 'whole record'
 
584
          
 
585
          {
 
586
            // Lock l(&s_negcachelock);
 
587
            // replacing_insert(s_negcache, ne);
 
588
          }
 
589
          negindic=true;
 
590
        }
 
591
        else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
 
592
          ret.push_back(*i);
 
593
          newtarget=i->content;
 
594
        }
 
595
        // for ANY answers we *must* have an authoritive answer
 
596
        else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && 
 
597
                (
 
598
                 i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) )
 
599
                ) 
 
600
               )   
 
601
          {
 
602
          
 
603
          // LOG<<prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl;
 
604
 
 
605
          done=true;
 
606
          ret.push_back(*i);
 
607
        }
 
608
        else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { 
 
609
          if(moreSpecificThan(i->qname,auth)) {
 
610
            newauth=i->qname;
 
611
            // LOG<<prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl;
 
612
            realreferral=true;
 
613
          }
 
614
          else 
 
615
            ;// // LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl;
 
616
          nsset.insert(i->content);
 
617
        }
 
618
        else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
 
619
           lwr.d_rcode==RCode::NoError) {
 
620
          // LOG<<prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+i->qtype.getName()+"'") <<endl;
 
621
          ret.push_back(*i);
 
622
          
 
623
          NegCacheEntry ne;
 
624
          ne.d_qname=i->qname;
 
625
          ne.d_ttd=d_now.tv_sec + i->ttl;
 
626
          ne.d_name=qname;
 
627
          ne.d_qtype=qtype;
 
628
          if(qtype.getCode()) {  // prevents us from blacking out a whole domain
 
629
           // Lock l(&s_negcachelock);
 
630
            // replacing_insert(s_negcache, ne);
 
631
          }
 
632
          negindic=true;
 
633
        }
 
634
      }
 
635
 
 
636
  }
 
637
  const vector<uint8_t>& d_packet;
 
638
  std::string d_name;
 
639
};
 
640
 
 
641
struct ParsePacketBareTest
 
642
{
 
643
  explicit ParsePacketBareTest(const vector<uint8_t>& packet, const std::string& name) 
 
644
    : d_packet(packet), d_name(name)
 
645
  {}
 
646
 
 
647
  string getName() const
 
648
  {
 
649
    return "parse '"+d_name+"' bare";
 
650
  }
 
651
 
 
652
  void operator()() const
 
653
  {
 
654
    MOADNSParser mdp((const char*)&*d_packet.begin(), d_packet.size());
 
655
  }
 
656
  const vector<uint8_t>& d_packet;
 
657
  std::string d_name;
 
658
};
 
659
 
 
660
 
 
661
struct SimpleCompressTest
 
662
{
 
663
  explicit SimpleCompressTest(const std::string& name) 
 
664
    : d_name(name)
 
665
  {}
 
666
 
 
667
  string getName() const
 
668
  {
 
669
    return "compress '"+d_name+"'";
 
670
  }
 
671
 
 
672
  void operator()() const
 
673
  {
 
674
    simpleCompress(d_name);
 
675
  }
 
676
  std::string d_name;
 
677
};
 
678
 
 
679
struct VectorExpandTest
 
680
{
 
681
  string getName() const
 
682
  {
 
683
    return "vector expand";
 
684
  }
 
685
 
 
686
  void operator()() const
 
687
  {
 
688
    vector<uint8_t> d_record;
 
689
    d_record.resize(12);
 
690
 
 
691
    string out="\x03www\x04ds9a\x02nl";
 
692
    string::size_type len = d_record.size();
 
693
    d_record.resize(len + out.length());
 
694
    memcpy(&d_record[len], out.c_str(), out.length());
 
695
  }
 
696
 
 
697
};
 
698
 
 
699
 
 
700
 
 
701
struct IEqualsTest
 
702
{
 
703
  string getName() const
 
704
  {
 
705
    return "iequals test";
 
706
  }
 
707
 
 
708
  void operator()() const
 
709
  {
 
710
      static string a("www.ds9a.nl"), b("www.lwn.net");
 
711
      g_ret = boost::iequals(a, b);
 
712
  }
 
713
 
 
714
};
 
715
 
 
716
struct MyIEqualsTest
 
717
{
 
718
  string getName() const
 
719
  {
 
720
    return "pdns_iequals test";
 
721
  }
 
722
 
 
723
  void operator()() const
 
724
  {
 
725
      static string a("www.ds9a.nl"), b("www.lwn.net");
 
726
      g_ret = pdns_iequals(a, b);
 
727
  }
 
728
 
 
729
};
 
730
 
 
731
 
 
732
struct StrcasecmpTest
 
733
{
 
734
  string getName() const
 
735
  {
 
736
    return "strcasecmp test";
 
737
  }
 
738
 
 
739
  void operator()() const
 
740
  {
 
741
      static string a("www.ds9a.nl"), b("www.lwn.net");
 
742
      g_ret = strcasecmp(a.c_str(), b.c_str());
 
743
  }
 
744
};
 
745
 
 
746
 
 
747
struct NOPTest
 
748
{
 
749
  string getName() const
 
750
  {
 
751
    return "null test";
 
752
  }
 
753
 
 
754
  void operator()() const
 
755
  {
 
756
  }
 
757
 
 
758
};
 
759
 
 
760
 
 
761
 
 
762
int main(int argc, char** argv)
 
763
try
 
764
{
 
765
  reportAllTypes();
 
766
  doRun(NOPTest());
 
767
 
 
768
  doRun(IEqualsTest());
 
769
  doRun(MyIEqualsTest());
 
770
  doRun(StrcasecmpTest());
 
771
 
 
772
  doRun(StackMallocTest());
 
773
 
 
774
  vector<uint8_t> packet = makeRootReferral();
 
775
  doRun(ParsePacketBareTest(packet, "root-referral"));
 
776
  doRun(ParsePacketTest(packet, "root-referral"));
 
777
 
 
778
  doRun(RootRefTest());
 
779
 
 
780
  doRun(EmptyQueryTest());
 
781
  doRun(TypicalRefTest());
 
782
 
 
783
 
 
784
  packet = makeEmptyQuery();
 
785
  doRun(ParsePacketTest(packet, "empty-query"));
 
786
 
 
787
  packet = makeTypicalReferral();
 
788
  cerr<<"typical referral size: "<<packet.size()<<endl;
 
789
  doRun(ParsePacketBareTest(packet, "typical-referral"));
 
790
 
 
791
  doRun(ParsePacketTest(packet, "typical-referral"));
 
792
 
 
793
  doRun(SimpleCompressTest("www.france.ds9a.nl"));
 
794
 
 
795
  
 
796
  doRun(VectorExpandTest());
 
797
 
 
798
  doRun(GetTimeTest());
 
799
  
 
800
  doRun(GetLockUncontendedTest());
 
801
  doRun(StaticMemberTest());
 
802
  
 
803
  doRun(ARecordTest(1));
 
804
  doRun(ARecordTest(2));
 
805
  doRun(ARecordTest(4));
 
806
  doRun(ARecordTest(64));
 
807
 
 
808
  doRun(A2RecordTest(1));
 
809
  doRun(A2RecordTest(2));
 
810
  doRun(A2RecordTest(4));
 
811
  doRun(A2RecordTest(64));
 
812
 
 
813
  doRun(MakeStringFromCharStarTest());
 
814
  doRun(MakeARecordTest());
 
815
  doRun(MakeARecordTestMM());
 
816
 
 
817
  doRun(AAAARecordTest(1));
 
818
  doRun(AAAARecordTest(2));
 
819
  doRun(AAAARecordTest(4));
 
820
  doRun(AAAARecordTest(64));
 
821
 
 
822
  doRun(TXTRecordTest(1));
 
823
  doRun(TXTRecordTest(2));
 
824
  doRun(TXTRecordTest(4));
 
825
  doRun(TXTRecordTest(64));
 
826
 
 
827
  doRun(GenericRecordTest(1, QType::NS, "powerdnssec1.ds9a.nl"));
 
828
  doRun(GenericRecordTest(2, QType::NS, "powerdnssec1.ds9a.nl"));
 
829
  doRun(GenericRecordTest(4, QType::NS, "powerdnssec1.ds9a.nl"));
 
830
  doRun(GenericRecordTest(64, QType::NS, "powerdnssec1.ds9a.nl"));
 
831
 
 
832
 
 
833
 
 
834
  doRun(SOARecordTest(1));
 
835
  doRun(SOARecordTest(2));
 
836
  doRun(SOARecordTest(4));
 
837
  doRun(SOARecordTest(64));
 
838
 
 
839
  cerr<<"Total runs: " << g_totalRuns<<endl;
 
840
 
 
841
}
 
842
catch(std::exception &e)
 
843
{
 
844
  cerr<<"Fatal: "<<e.what()<<endl;
 
845
}
 
846