~ubuntu-branches/ubuntu/precise/pdns/precise

« back to all changes in this revision

Viewing changes to pdns/tcpreceiver.cc

  • Committer: Package Import Robot
  • Author(s): Jean-Louis Dupond
  • Date: 2012-02-14 01:36:30 UTC
  • mfrom: (1.1.8) (12.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120214013630-z26d5ugoxnau5ok3
Tags: 3.0-1.1ubuntu1
* Merge from Debian testing. (LP: #931133)  Remaining changes:
  - debian/rules: Fix FTBFS with multiarch libmysqlclient.
  - debian/control: Build-depend on libtdb-dev rather than tdb-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
    PowerDNS Versatile Database Driven Nameserver
3
 
    Copyright (C) 2002-2008  PowerDNS.COM BV
 
3
    Copyright (C) 2002-2011  PowerDNS.COM BV
4
4
 
5
5
    This program is free software; you can redistribute it and/or modify
6
6
    it under the terms of the GNU General Public License version 2
17
17
*/
18
18
#include "packetcache.hh"
19
19
#include "utility.hh"
 
20
#include "dnssecinfra.hh"
 
21
#include "dnsseckeeper.hh"
20
22
#include <cstdio>
 
23
#include "base32.hh"
21
24
#include <cstring>
22
25
#include <cstdlib>
23
26
#include <sys/types.h>
25
28
#include <string>
26
29
#include "tcpreceiver.hh"
27
30
#include "sstuff.hh"
28
 
 
 
31
#include <boost/foreach.hpp>
29
32
#include <errno.h>
30
33
#include <signal.h>
31
 
 
 
34
#include "base64.hh"
32
35
#include "ueberbackend.hh"
33
36
#include "dnspacket.hh"
34
37
#include "nameserver.hh"
41
44
#include "statbag.hh"
42
45
#include "resolver.hh"
43
46
#include "communicator.hh"
44
 
using namespace boost;
45
 
 
 
47
#include "namespaces.hh"
 
48
#include "signingpipe.hh"
46
49
extern PacketCache PC;
47
50
extern StatBag S;
48
51
 
87
90
    ret=read(fd, ptr, bytes);
88
91
    if(ret < 0) {
89
92
      if(errno==EAGAIN) {
90
 
        ret=waitForData(fd, 5);
91
 
        if(ret < 0)
92
 
          throw NetworkError("Waiting for data read");
93
 
        if(!ret)
94
 
          throw NetworkError("Timeout reading data");
95
 
        continue;
 
93
        ret=waitForData(fd, 5);
 
94
        if(ret < 0)
 
95
          throw NetworkError("Waiting for data read");
 
96
        if(!ret)
 
97
          throw NetworkError("Timeout reading data");
 
98
        continue;
96
99
      }
97
100
      else
98
 
        throw NetworkError("Reading data: "+stringerror());
 
101
        throw NetworkError("Reading data: "+stringerror());
99
102
    }
100
103
    if(!ret) {
101
104
      if(!throwOnEOF && n == bytes)
102
 
        return 0;
 
105
        return 0;
103
106
      else
104
 
        throw NetworkError("Did not fulfill read from TCP due to EOF");
 
107
        throw NetworkError("Did not fulfill read from TCP due to EOF");
105
108
    }
106
109
    
107
110
    ptr += ret;
120
123
    ret=write(fd, ptr, bytes);
121
124
    if(ret < 0) {
122
125
      if(errno==EAGAIN) {
123
 
        ret=waitForRWData(fd, false, 5, 0);
124
 
        if(ret < 0)
125
 
          throw NetworkError("Waiting for data write");
126
 
        if(!ret)
127
 
          throw NetworkError("Timeout writing data");
128
 
        continue;
 
126
        ret=waitForRWData(fd, false, 5, 0);
 
127
        if(ret < 0)
 
128
          throw NetworkError("Waiting for data write");
 
129
        if(!ret)
 
130
          throw NetworkError("Timeout writing data");
 
131
        continue;
129
132
      }
130
133
      else
131
 
        throw NetworkError("Writing data: "+stringerror());
 
134
        throw NetworkError("Writing data: "+stringerror());
132
135
    }
133
136
    if(!ret) {
134
137
      throw NetworkError("Did not fulfill TCP write due to EOF");
172
175
 
173
176
void TCPNameserver::sendPacket(shared_ptr<DNSPacket> p, int outsock)
174
177
{
175
 
  const char *buf=p->getData();
176
 
  uint16_t len=htons(p->len);
 
178
  const string buffer = p->getString();
 
179
  uint16_t len=htons(buffer.length());
177
180
  writenWithTimeout(outsock, &len, 2);
178
 
  writenWithTimeout(outsock, buf, p->len);
 
181
  writenWithTimeout(outsock, buffer.c_str(), buffer.length());
179
182
}
180
183
 
181
184
 
241
244
    char mesg[512];
242
245
    
243
246
    DLOG(L<<"TCP Connection accepted on fd "<<fd<<endl);
244
 
    
 
247
    bool logDNSQueries= ::arg().mustDo("log-dns-queries");
245
248
    for(;;) {
246
249
      ComboAddress remote;
247
250
      socklen_t remotelen=sizeof(remote);
248
251
      if(getpeername(fd, (struct sockaddr *)&remote, &remotelen) < 0) {
249
 
        L<<Logger::Error<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl;
250
 
        break;
 
252
        L<<Logger::Error<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl;
 
253
        break;
251
254
      }
252
255
 
253
256
      uint16_t pktlen;
254
257
      if(!readnWithTimeout(fd, &pktlen, 2, false))
255
 
        break;
 
258
        break;
256
259
      else
257
 
        pktlen=ntohs(pktlen);
 
260
        pktlen=ntohs(pktlen);
258
261
 
259
262
      if(pktlen>511) {
260
 
        L<<Logger::Error<<"Received an overly large question from "<<remote.toString()<<", dropping"<<endl;
261
 
        break;
 
263
        L<<Logger::Error<<"Received an overly large question from "<<remote.toString()<<", dropping"<<endl;
 
264
        break;
262
265
      }
263
266
      
264
 
      getQuestion(fd,mesg,pktlen,remote);
 
267
      getQuestion(fd, mesg, pktlen, remote);
265
268
      S.inc("tcp-queries");      
266
269
 
267
270
      packet=shared_ptr<DNSPacket>(new DNSPacket);
269
272
      packet->d_tcp=true;
270
273
      packet->setSocket(fd);
271
274
      if(packet->parse(mesg, pktlen)<0)
272
 
        break;
 
275
        break;
273
276
      
274
277
      if(packet->qtype.getCode()==QType::AXFR || packet->qtype.getCode()==QType::IXFR ) {
275
 
        if(doAXFR(packet->qdomain, packet, fd)) 
276
 
          S.inc("tcp-answers");  
277
 
        continue;
 
278
        if(doAXFR(packet->qdomain, packet, fd)) 
 
279
          S.inc("tcp-answers");  
 
280
        continue;
278
281
      }
279
282
 
280
283
      shared_ptr<DNSPacket> reply; 
281
284
      shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new DNSPacket);
282
 
 
283
 
      if(!packet->d.rd && (PC.get(packet.get(), cached.get()))) { // short circuit - does the PacketCache recognize this question?
284
 
        cached->setRemote(&packet->remote);
285
 
        cached->spoofID(packet->d.id);
286
 
        sendPacket(cached, fd);
287
 
        S.inc("tcp-answers");
288
 
        continue;
 
285
      if(logDNSQueries) 
 
286
        L << Logger::Notice<<"TCP Remote "<< packet->d_remote.toString() <<" wants '" << packet->qdomain<<"|"<<packet->qtype.getName() << 
 
287
        "', do = " <<packet->d_dnssecOk <<", bufsize = "<< packet->getMaxReplyLen()<<": ";
 
288
 
 
289
 
 
290
      if(!packet->d.rd && packet->couldBeCached() && PC.get(packet.get(), cached.get())) { // short circuit - does the PacketCache recognize this question?
 
291
        if(logDNSQueries)
 
292
          L<<"packetcache HIT"<<endl;
 
293
        cached->setRemote(&packet->d_remote);
 
294
        cached->d.id=packet->d.id;
 
295
        cached->d.rd=packet->d.rd; // copy in recursion desired bit 
 
296
        cached->commitD(); // commit d to the packet                        inlined
 
297
 
 
298
        sendPacket(cached, fd); // presigned, don't do it again
 
299
        S.inc("tcp-answers");
 
300
        continue;
289
301
      }
290
 
        
 
302
      if(logDNSQueries)
 
303
          L<<"packetcache MISS"<<endl;  
291
304
      {
292
 
        Lock l(&s_plock);
293
 
        if(!s_P) {
294
 
          L<<Logger::Error<<"TCP server is without backend connections, launching"<<endl;
295
 
          s_P=new PacketHandler;
296
 
        }
297
 
        bool shouldRecurse;
298
 
 
299
 
        reply=shared_ptr<DNSPacket>(s_P->questionOrRecurse(packet.get(), &shouldRecurse)); // we really need to ask the backend :-)
300
 
 
301
 
        if(shouldRecurse) {
302
 
          proxyQuestion(packet);
303
 
          continue;
304
 
        }
 
305
        Lock l(&s_plock);
 
306
        if(!s_P) {
 
307
          L<<Logger::Error<<"TCP server is without backend connections, launching"<<endl;
 
308
          s_P=new PacketHandler;
 
309
        }
 
310
        bool shouldRecurse;
 
311
 
 
312
        reply=shared_ptr<DNSPacket>(s_P->questionOrRecurse(packet.get(), &shouldRecurse)); // we really need to ask the backend :-)
 
313
 
 
314
        if(shouldRecurse) {
 
315
          proxyQuestion(packet);
 
316
          continue;
 
317
        }
305
318
      }
306
319
 
307
320
      if(!reply)  // unable to write an answer?
308
 
        break;
309
 
        
 
321
        break;
 
322
        
310
323
      S.inc("tcp-answers");
311
324
      sendPacket(reply, fd);
312
325
    }
341
354
  return 0;
342
355
}
343
356
 
 
357
 
 
358
 
344
359
bool TCPNameserver::canDoAXFR(shared_ptr<DNSPacket> q)
345
360
{
346
361
  if(::arg().mustDo("disable-axfr"))
347
362
    return false;
348
363
 
349
 
  if( ::arg()["allow-axfr-ips"].empty() || d_ng.match( (ComboAddress *) &q->remote ) )
 
364
  if(q->d_havetsig) { // if you have one, it must be good
 
365
    TSIGRecordContent trc;
 
366
    string keyname, secret;
 
367
    Lock l(&s_plock);
 
368
    if(!checkForCorrectTSIG(q.get(), s_P->getBackend(), &keyname, &secret, &trc))
 
369
      return false;
 
370
    
 
371
    DNSSECKeeper dk;
 
372
    
 
373
    if(!dk.TSIGGrantsAccess(q->qdomain, keyname, trc.d_algoName)) {
 
374
      L<<Logger::Error<<"AXFR '"<<q->qdomain<<"' denied: key with name '"<<keyname<<"' and algorithm '"<<trc.d_algoName<<"' does not grant access to zone"<<endl;
 
375
      return false;
 
376
    }
 
377
    else {
 
378
      L<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: TSIG signed request with authorized key '"<<keyname<<"' and algorithm '"<<trc.d_algoName<<"'"<<endl;
 
379
      return true;
 
380
    }
 
381
  }
 
382
    
 
383
 
 
384
  if(!::arg().mustDo("per-zone-axfr-acls") && (::arg()["allow-axfr-ips"].empty() || d_ng.match( (ComboAddress *) &q->d_remote )))
350
385
    return true;
351
 
 
 
386
#if 0
 
387
  if(::arg().mustDo("per-zone-axfr-acls")) {
 
388
    SOAData sd;
 
389
    sd.db=(DNSBackend *)-1;
 
390
    if(s_P->getBackend()->getSOA(q->qdomain,sd)) {
 
391
      DNSBackend *B=sd.db;
 
392
      if (B->checkACL(string("allow-axfr"), q->qdomain, q->getRemote())) {
 
393
        return true;
 
394
      }
 
395
    }  
 
396
  }
 
397
#endif
352
398
  extern CommunicatorClass Communicator;
353
399
 
354
400
  if(Communicator.justNotified(q->qdomain, q->getRemote())) { // we just notified this ip 
359
405
  return false;
360
406
}
361
407
 
 
408
namespace {
 
409
struct NSECXEntry
 
410
{
 
411
  set<uint16_t> d_set;
 
412
  unsigned int d_ttl;
 
413
};
 
414
 
 
415
DNSResourceRecord makeDNSRRFromSOAData(const SOAData& sd)
 
416
{
 
417
  DNSResourceRecord soa;
 
418
  soa.qname= sd.qname;
 
419
  soa.qtype=QType::SOA;
 
420
  soa.content=serializeSOAData(sd);
 
421
  soa.ttl=sd.ttl;
 
422
  soa.domain_id=sd.domain_id;
 
423
  soa.auth = true;
 
424
  soa.d_place=DNSResourceRecord::ANSWER;
 
425
  return soa;
 
426
}
 
427
 
 
428
shared_ptr<DNSPacket> getFreshAXFRPacket(shared_ptr<DNSPacket> q)
 
429
{
 
430
  shared_ptr<DNSPacket> ret = shared_ptr<DNSPacket>(q->replyPacket());
 
431
  ret->setCompress(false);
 
432
  ret->d_dnssecOk=false; // RFC 5936, 2.2.5
 
433
  ret->d_tcp = true;
 
434
  return ret;
 
435
}
 
436
 
 
437
}
362
438
/** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
363
439
int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int outsock)
364
440
{
365
 
  shared_ptr<DNSPacket> outpacket;
366
 
  if(!canDoAXFR(q)) {
 
441
  bool noAXFRBecauseOfNSEC3Narrow=false;
 
442
  NSEC3PARAMRecordContent ns3pr;
 
443
  bool narrow;
 
444
  bool NSEC3Zone=false;
 
445
  
 
446
  DNSSECKeeper dk;
 
447
  bool securedZone = dk.isSecuredZone(target);
 
448
  if(dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
 
449
    NSEC3Zone=true;
 
450
    if(narrow) {
 
451
      L<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone.."<<endl;
 
452
      noAXFRBecauseOfNSEC3Narrow=true;
 
453
    }
 
454
  }
 
455
 
 
456
  shared_ptr<DNSPacket> outpacket= getFreshAXFRPacket(q);
 
457
  if(q->d_dnssecOk)
 
458
    outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
 
459
  
 
460
  if(!canDoAXFR(q) || noAXFRBecauseOfNSEC3Narrow) {
367
461
    L<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
368
 
 
369
 
    outpacket=shared_ptr<DNSPacket>(q->replyPacket());
370
462
    outpacket->setRcode(RCode::Refused); 
371
463
    // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
372
464
    sendPacket(outpacket,outsock);
373
465
    return 0;
374
466
  }
 
467
  
375
468
  L<<Logger::Error<<"AXFR of domain '"<<target<<"' initiated by "<<q->getRemote()<<endl;
376
 
  outpacket=shared_ptr<DNSPacket>(q->replyPacket());
377
 
 
378
 
  DNSResourceRecord soa;  
379
 
  DNSResourceRecord rr;
380
469
 
381
470
  SOAData sd;
382
471
  sd.db=(DNSBackend *)-1; // force uncached answer
383
472
  {
384
473
    Lock l(&s_plock);
385
 
    
386
 
    // find domain_id via SOA and list complete domain. No SOA, no AXFR
387
 
    
388
 
    DLOG(L<<"Looking for SOA"<<endl);
 
474
    DLOG(L<<"Looking for SOA"<<endl);    // find domain_id via SOA and list complete domain. No SOA, no AXFR
389
475
    if(!s_P) {
390
476
      L<<Logger::Error<<"TCP server is without backend connections in doAXFR, launching"<<endl;
391
477
      s_P=new PacketHandler;
392
478
    }
393
479
 
394
 
    if(!s_P->getBackend()->getSOA(target,sd)) {
 
480
    if(!s_P->getBackend()->getSOA(target, sd)) {
395
481
      L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative"<<endl;
396
482
      outpacket->setRcode(9); // 'NOTAUTH'
397
483
      sendPacket(outpacket,outsock);
398
484
      return 0;
399
485
    }
400
 
 
401
486
  }
402
 
  PacketHandler P; // now open up a database connection, we'll need it
403
 
 
 
487
 
 
488
  UeberBackend db;
404
489
  sd.db=(DNSBackend *)-1; // force uncached answer
405
 
  if(!P.getBackend()->getSOA(target, sd)) {
406
 
      L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
 
490
  if(!db.getSOA(target, sd)) {
 
491
    L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
407
492
    outpacket->setRcode(9); // 'NOTAUTH'
408
493
    sendPacket(outpacket,outsock);
409
494
    return 0;
410
495
  }
411
496
 
412
 
  soa.qname=target;
413
 
  soa.qtype=QType::SOA;
414
 
  soa.content=serializeSOAData(sd);
415
 
  soa.ttl=sd.ttl;
416
 
  soa.domain_id=sd.domain_id;
417
 
  soa.d_place=DNSResourceRecord::ANSWER;
418
 
    
419
497
  if(!sd.db || sd.db==(DNSBackend *)-1) {
420
498
    L<<Logger::Error<<"Error determining backend for domain '"<<target<<"' trying to serve an AXFR"<<endl;
421
499
    outpacket->setRcode(RCode::ServFail);
422
500
    sendPacket(outpacket,outsock);
423
501
    return 0;
424
502
  }
425
 
 
426
 
  DLOG(L<<"Issuing list command - opening dedicated database connection"<<endl);
427
 
 
428
 
  DNSBackend *B=sd.db; // get the RIGHT backend
429
 
 
430
 
  // now list zone
431
 
  if(!(B->list(target, sd.domain_id))) {  
 
503
 
 
504
  TSIGRecordContent trc;
 
505
  string tsigkeyname, tsigsecret;
 
506
 
 
507
  q->getTSIGDetails(&trc, &tsigkeyname, 0);
 
508
 
 
509
  if(!tsigkeyname.empty()) {
 
510
    string tsig64, algorithm;
 
511
    Lock l(&s_plock);
 
512
    s_P->getBackend()->getTSIGKey(tsigkeyname, &algorithm, &tsig64);
 
513
    B64Decode(tsig64, tsigsecret);
 
514
  }
 
515
  
 
516
  
 
517
  UeberBackend signatureDB; 
 
518
  
 
519
  // SOA *must* go out first, our signing pipe might reorder
 
520
  DLOG(L<<"Sending out SOA"<<endl);
 
521
  DNSResourceRecord soa = makeDNSRRFromSOAData(sd);
 
522
  outpacket->addRecord(soa);
 
523
  editSOA(dk, sd.qname, outpacket.get());
 
524
  if(securedZone)
 
525
    addRRSigs(dk, signatureDB, target, outpacket->getRRS());
 
526
  
 
527
  if(!tsigkeyname.empty())
 
528
    outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
 
529
  
 
530
  sendPacket(outpacket, outsock);
 
531
  
 
532
  trc.d_mac = outpacket->d_trc.d_mac;
 
533
  outpacket = getFreshAXFRPacket(q);
 
534
  
 
535
  ChunkedSigningPipe csp(target, securedZone, "", ::arg().asNum("signing-threads"));
 
536
  
 
537
  typedef map<string, NSECXEntry> nsecxrepo_t;
 
538
  nsecxrepo_t nsecxrepo;
 
539
  
 
540
  // this is where the DNSKEYs go  in
 
541
  
 
542
  DNSSECKeeper::keyset_t keys = dk.getKeys(target);
 
543
  
 
544
  DNSResourceRecord rr;
 
545
  
 
546
  BOOST_FOREACH(const DNSSECKeeper::keyset_t::value_type& value, keys) {
 
547
    rr.qname = target;
 
548
    rr.qtype = QType(QType::DNSKEY);
 
549
    rr.ttl = sd.default_ttl;
 
550
    rr.auth = 1; // please sign! 
 
551
    rr.content = value.first.getDNSKEY().getZoneRepresentation();
 
552
    string keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
 
553
    NSECXEntry& ne = nsecxrepo[keyname];
 
554
    
 
555
    ne.d_set.insert(rr.qtype.getCode());
 
556
    ne.d_ttl = rr.ttl;
 
557
    csp.submit(rr);
 
558
  }
 
559
  
 
560
  if(NSEC3Zone) { // now stuff in the NSEC3PARAM
 
561
    rr.qtype = QType(QType::NSEC3PARAM);
 
562
    ns3pr.d_flags = 0;
 
563
    rr.content = ns3pr.getZoneRepresentation();
 
564
    ns3pr.d_flags = 1;
 
565
    string keyname = hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname);
 
566
    NSECXEntry& ne = nsecxrepo[keyname];
 
567
    
 
568
    ne.d_set.insert(rr.qtype.getCode());
 
569
    csp.submit(rr);
 
570
  }
 
571
  
 
572
  // now start list zone
 
573
  if(!(sd.db->list(target, sd.domain_id))) {  
432
574
    L<<Logger::Error<<"Backend signals error condition"<<endl;
433
575
    outpacket->setRcode(2); // 'SERVFAIL'
434
576
    sendPacket(outpacket,outsock);
435
577
    return 0;
436
578
  }
437
 
  /* write first part of answer */
438
 
 
439
 
  DLOG(L<<"Sending out SOA"<<endl);
440
 
  outpacket->addRecord(soa); // AXFR format begins and ends with a SOA record, so we add one
441
 
  sendPacket(outpacket, outsock);
442
579
 
443
580
  /* now write all other records */
444
 
 
445
 
  int count=0;
446
 
  int chunk=100; // FIXME: this should probably be autosizing
447
 
  if(::arg().mustDo("strict-rfc-axfrs"))
448
 
    chunk=1;
449
 
 
450
 
  outpacket=shared_ptr<DNSPacket>(q->replyPacket());
451
 
  outpacket->setCompress(false);
452
 
 
453
 
  while(B->get(rr)) {
454
 
    if(rr.qtype.getCode()==6)
 
581
  
 
582
  string keyname;
 
583
  DTime dt;
 
584
  dt.set();
 
585
  int records=0;
 
586
  while(sd.db->get(rr)) {
 
587
    records++;
 
588
    if(securedZone && (rr.auth || rr.qtype.getCode() == QType::NS || rr.qtype.getCode() == QType::DS)) { // this is probably NSEC specific, NSEC3 is different
 
589
      keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
 
590
      NSECXEntry& ne = nsecxrepo[keyname];
 
591
      ne.d_set.insert(rr.qtype.getCode());
 
592
      ne.d_ttl = rr.ttl;
 
593
    }
 
594
    if(rr.qtype.getCode() == QType::SOA)
455
595
      continue; // skip SOA - would indicate end of AXFR
456
596
 
457
 
    outpacket->addRecord(rr);
458
 
 
459
 
    if(!((++count)%chunk)) {
460
 
      count=0;
461
 
    
 
597
    if(csp.submit(rr)) {
 
598
      for(;;) {
 
599
        outpacket->getRRS() = csp.getChunk();
 
600
        if(!outpacket->getRRS().empty()) {
 
601
          if(!tsigkeyname.empty())
 
602
            outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); 
 
603
          sendPacket(outpacket, outsock);
 
604
          trc.d_mac=outpacket->d_trc.d_mac;
 
605
          outpacket=getFreshAXFRPacket(q);
 
606
        }
 
607
        else
 
608
          break;
 
609
      }
 
610
    }
 
611
  }
 
612
  unsigned int udiff=dt.udiffNoReset();
 
613
  /*
 
614
  cerr<<"Starting NSEC: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
 
615
  cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
 
616
  cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
 
617
  */
 
618
  if(securedZone) {   
 
619
    if(NSEC3Zone) {
 
620
      for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
 
621
        NSEC3RecordContent n3rc;
 
622
        n3rc.d_set = iter->second.d_set;
 
623
        n3rc.d_set.insert(QType::RRSIG);
 
624
        n3rc.d_salt=ns3pr.d_salt;
 
625
        n3rc.d_flags = 0;
 
626
        n3rc.d_iterations = ns3pr.d_iterations;
 
627
        n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now
 
628
        if(boost::next(iter) != nsecxrepo.end()) {
 
629
          n3rc.d_nexthash = boost::next(iter)->first;
 
630
        }
 
631
        else
 
632
          n3rc.d_nexthash=nsecxrepo.begin()->first;
 
633
    
 
634
        rr.qname = dotConcat(toLower(toBase32Hex(iter->first)), sd.qname);
 
635
    
 
636
        rr.ttl = iter->second.d_ttl;
 
637
        rr.content = n3rc.getZoneRepresentation();
 
638
        rr.qtype = QType::NSEC3;
 
639
        rr.d_place = DNSResourceRecord::ANSWER;
 
640
        rr.auth=true;
 
641
        if(csp.submit(rr)) {
 
642
          for(;;) {
 
643
            outpacket->getRRS() = csp.getChunk();
 
644
            if(!outpacket->getRRS().empty()) {
 
645
              if(!tsigkeyname.empty())
 
646
                outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
 
647
              sendPacket(outpacket, outsock);
 
648
              trc.d_mac=outpacket->d_trc.d_mac;
 
649
              outpacket=getFreshAXFRPacket(q);
 
650
            }
 
651
            else
 
652
              break;
 
653
          }
 
654
        }
 
655
      }
 
656
    }
 
657
    else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
 
658
      NSECRecordContent nrc;
 
659
      nrc.d_set = iter->second.d_set;
 
660
      nrc.d_set.insert(QType::RRSIG);
 
661
      nrc.d_set.insert(QType::NSEC);
 
662
      if(boost::next(iter) != nsecxrepo.end()) {
 
663
        nrc.d_next = labelReverse(boost::next(iter)->first);
 
664
      }
 
665
      else
 
666
        nrc.d_next=labelReverse(nsecxrepo.begin()->first);
 
667
  
 
668
      rr.qname = labelReverse(iter->first);
 
669
  
 
670
      rr.ttl = iter->second.d_ttl;
 
671
      rr.content = nrc.getZoneRepresentation();
 
672
      rr.qtype = QType::NSEC;
 
673
      rr.d_place = DNSResourceRecord::ANSWER;
 
674
      rr.auth=true;
 
675
      
 
676
      if(csp.submit(rr)) {
 
677
        for(;;) {
 
678
          outpacket->getRRS() = csp.getChunk();
 
679
          if(!outpacket->getRRS().empty()) {
 
680
            if(!tsigkeyname.empty())
 
681
              outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); 
 
682
            sendPacket(outpacket, outsock);
 
683
            trc.d_mac=outpacket->d_trc.d_mac;
 
684
            outpacket=getFreshAXFRPacket(q);
 
685
          }
 
686
          else
 
687
            break;
 
688
        }
 
689
      }
 
690
    }
 
691
  }
 
692
  udiff=dt.udiffNoReset();
 
693
  /*
 
694
  cerr<<"Flushing pipe: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
 
695
  cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
 
696
  cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
 
697
  * */
 
698
  for(;;) { 
 
699
    outpacket->getRRS() = csp.getChunk(true); // flush the pipe
 
700
    if(!outpacket->getRRS().empty()) {
 
701
      if(!tsigkeyname.empty())
 
702
        outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); // first answer is 'normal'
462
703
      sendPacket(outpacket, outsock);
463
 
 
464
 
      outpacket=shared_ptr<DNSPacket>(q->replyPacket());
465
 
      outpacket->setCompress(false);
466
 
      // FIXME: Subsequent messages SHOULD NOT have a question section, though the final message MAY.
 
704
      trc.d_mac=outpacket->d_trc.d_mac;
 
705
      outpacket=getFreshAXFRPacket(q);
467
706
    }
468
 
  }
469
 
  if(count) {
470
 
    sendPacket(outpacket, outsock);
471
 
  }
472
 
 
 
707
    else 
 
708
      break;
 
709
  }
 
710
  
 
711
  udiff=dt.udiffNoReset();
 
712
  if(securedZone) 
 
713
    L<<Logger::Info<<"Done signing: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<endl;
 
714
  
473
715
  DLOG(L<<"Done writing out records"<<endl);
474
716
  /* and terminate with yet again the SOA record */
475
 
  outpacket=shared_ptr<DNSPacket>(q->replyPacket());
 
717
  outpacket=getFreshAXFRPacket(q);
476
718
  outpacket->addRecord(soa);
 
719
  editSOA(dk, sd.qname, outpacket.get());
 
720
  if(!tsigkeyname.empty())
 
721
    outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); 
 
722
  
477
723
  sendPacket(outpacket, outsock);
 
724
  
478
725
  DLOG(L<<"last packet - close"<<endl);
479
726
  L<<Logger::Error<<"AXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
480
727
 
512
759
#ifndef WIN32
513
760
  signal(SIGPIPE,SIG_IGN);
514
761
#endif // WIN32
515
 
  FD_ZERO(&d_rfds);  
516
762
 
517
763
  for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
518
764
    int s=socket(AF_INET,SOCK_STREAM,0); 
536
782
    listen(s,128);
537
783
    L<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
538
784
    d_sockets.push_back(s);
539
 
    FD_SET(s, &d_rfds);
 
785
    struct pollfd pfd;
 
786
    memset(&pfd, 0, sizeof(pfd));
 
787
    pfd.fd = s;
 
788
    pfd.events = POLLIN;
 
789
 
 
790
    d_prfds.push_back(pfd);
 
791
 
540
792
    d_highfd=max(s,d_highfd);
541
793
  }
542
794
 
561
813
    }
562
814
    
563
815
    listen(s,128);
564
 
    L<<Logger::Error<<"TCPv6 server bound to "<<local.toStringWithPort()<<endl;
 
816
    L<<Logger::Error<<"TCPv6 server bound to "<<local.toStringWithPort()<<endl; // this gets %eth0 right
565
817
    d_sockets.push_back(s);
566
 
    FD_SET(s, &d_rfds);
567
 
    d_highfd=max(s,d_highfd);
 
818
 
 
819
    struct pollfd pfd;
 
820
    memset(&pfd, 0, sizeof(pfd));
 
821
    pfd.fd = s;
 
822
    pfd.events = POLLIN;
 
823
 
 
824
    d_prfds.push_back(pfd);
 
825
    d_highfd=max(s, d_highfd);
568
826
  }
569
827
#endif // WIN32
570
828
}
582
840
      struct sockaddr_in remote;
583
841
      Utility::socklen_t addrlen=sizeof(remote);
584
842
 
585
 
      fd_set rfds=d_rfds; 
586
 
 
587
 
      int ret=select(d_highfd+1, &rfds, 0, 0,  0); // blocks, forever if need be
 
843
      int ret=poll(&d_prfds[0], d_prfds.size(), -1); // blocks, forever if need be
588
844
      if(ret <= 0)
589
 
        continue;
 
845
        continue;
590
846
 
591
847
      int sock=-1;
592
 
      for(vector<int>::const_iterator i=d_sockets.begin();i!=d_sockets.end();++i) {
593
 
        if(FD_ISSET(*i, &rfds)) {
594
 
          sock=*i;
595
 
          addrlen=sizeof(remote);
596
 
 
597
 
          if((fd=accept(sock, (sockaddr*)&remote, &addrlen))<0) {
598
 
            L<<Logger::Error<<"TCP question accept error: "<<strerror(errno)<<endl;
599
 
            
600
 
            if(errno==EMFILE) {
601
 
              L<<Logger::Error<<Logger::NTLog<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
602
 
              exit(1);
603
 
            }
604
 
          }
605
 
          else {
606
 
            pthread_t tid;
607
 
            d_connectionroom_sem->wait(); // blocks if no connections are available
608
 
 
609
 
            int room;
610
 
            d_connectionroom_sem->getValue( &room);
611
 
            if(room<1)
612
 
              L<<Logger::Warning<<Logger::NTLog<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
613
 
 
614
 
            if(pthread_create(&tid, 0, &doConnection, (void *)fd)) {
615
 
              L<<Logger::Error<<"Error creating thread: "<<stringerror()<<endl;
616
 
              d_connectionroom_sem->post();
617
 
            }
618
 
          }
619
 
        }
 
848
      BOOST_FOREACH(const struct pollfd& pfd, d_prfds) {
 
849
        if(pfd.revents == POLLIN) {
 
850
          sock = pfd.fd;
 
851
          addrlen=sizeof(remote);
 
852
 
 
853
          if((fd=accept(sock, (sockaddr*)&remote, &addrlen))<0) {
 
854
            L<<Logger::Error<<"TCP question accept error: "<<strerror(errno)<<endl;
 
855
            
 
856
            if(errno==EMFILE) {
 
857
              L<<Logger::Error<<Logger::NTLog<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
 
858
              exit(1);
 
859
            }
 
860
          }
 
861
          else {
 
862
            pthread_t tid;
 
863
            d_connectionroom_sem->wait(); // blocks if no connections are available
 
864
 
 
865
            int room;
 
866
            d_connectionroom_sem->getValue( &room);
 
867
            if(room<1)
 
868
              L<<Logger::Warning<<Logger::NTLog<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
 
869
 
 
870
            if(pthread_create(&tid, 0, &doConnection, (void *)fd)) {
 
871
              L<<Logger::Error<<"Error creating thread: "<<stringerror()<<endl;
 
872
              d_connectionroom_sem->post();
 
873
            }
 
874
          }
 
875
        }
620
876
      }
621
877
    }
622
878
  }