2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2012 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
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.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <boost/algorithm/string.hpp>
26 #include "auth-packetcache.hh"
28 #include "dnssecinfra.hh"
29 #include "dnsseckeeper.hh"
34 #include <sys/types.h>
35 #include <netinet/tcp.h>
38 #include "tcpreceiver.hh"
44 #include "ueberbackend.hh"
45 #include "dnspacket.hh"
46 #include "nameserver.hh"
47 #include "distributor.hh"
50 #include "arguments.hh"
52 #include "common_startup.hh"
53 #include "packethandler.hh"
55 #include "resolver.hh"
56 #include "communicator.hh"
57 #include "namespaces.hh"
58 #include "signingpipe.hh"
59 #include "stubresolver.hh"
60 extern AuthPacketCache PC
;
65 \brief This file implements the tcpreceiver that receives and answers questions over TCP/IP
68 pthread_mutex_t
TCPNameserver::s_plock
= PTHREAD_MUTEX_INITIALIZER
;
69 Semaphore
*TCPNameserver::d_connectionroom_sem
;
70 PacketHandler
*TCPNameserver::s_P
;
71 NetmaskGroup
TCPNameserver::d_ng
;
72 size_t TCPNameserver::d_maxTransactionsPerConn
;
73 size_t TCPNameserver::d_maxConnectionsPerClient
;
74 unsigned int TCPNameserver::d_idleTimeout
;
75 unsigned int TCPNameserver::d_maxConnectionDuration
;
76 std::mutex
TCPNameserver::s_clientsCountMutex
;
77 std::map
<ComboAddress
,size_t,ComboAddress::addressOnlyLessThan
> TCPNameserver::s_clientsCount
;
79 void TCPNameserver::go()
81 L
<<Logger::Error
<<"Creating backend connection for TCP"<<endl
;
84 s_P
=new PacketHandler
;
86 catch(PDNSException
&ae
) {
87 L
<<Logger::Error
<<"TCP server is unable to launch backends - will try again when questions come in: "<<ae
.reason
<<endl
;
89 pthread_create(&d_tid
, 0, launcher
, static_cast<void *>(this));
92 void *TCPNameserver::launcher(void *data
)
94 static_cast<TCPNameserver
*>(data
)->thread();
98 // throws PDNSException if things didn't go according to plan, returns 0 if really 0 bytes were read
99 static int readnWithTimeout(int fd
, void* buffer
, unsigned int n
, unsigned int idleTimeout
, bool throwOnEOF
=true, unsigned int totalTimeout
=0)
101 unsigned int bytes
=n
;
102 char *ptr
= (char*)buffer
;
105 unsigned int remainingTotal
= totalTimeout
;
110 ret
=read(fd
, ptr
, bytes
);
113 ret
=waitForData(fd
, (totalTimeout
== 0 || idleTimeout
<= remainingTotal
) ? idleTimeout
: remainingTotal
);
115 throw NetworkError("Waiting for data read");
117 throw NetworkError("Timeout reading data");
121 throw NetworkError("Reading data: "+stringerror());
124 if(!throwOnEOF
&& n
== bytes
)
127 throw NetworkError("Did not fulfill read from TCP due to EOF");
133 time_t now
= time(NULL
);
134 unsigned int elapsed
= now
- start
;
135 if (elapsed
>= remainingTotal
) {
136 throw NetworkError("Timeout while reading data");
139 remainingTotal
-= elapsed
;
146 static void writenWithTimeout(int fd
, const void *buffer
, unsigned int n
, unsigned int idleTimeout
)
148 unsigned int bytes
=n
;
149 const char *ptr
= (char*)buffer
;
152 ret
=write(fd
, ptr
, bytes
);
155 ret
=waitForRWData(fd
, false, idleTimeout
, 0);
157 throw NetworkError("Waiting for data write");
159 throw NetworkError("Timeout writing data");
163 throw NetworkError("Writing data: "+stringerror());
166 throw NetworkError("Did not fulfill TCP write due to EOF");
174 void connectWithTimeout(int fd
, struct sockaddr
* remote
, size_t socklen
)
177 Utility::socklen_t len
=sizeof(err
);
179 if((err
=connect(fd
, remote
, socklen
))<0 && errno
!=EINPROGRESS
)
180 throw NetworkError("connect: "+stringerror());
185 err
=waitForRWData(fd
, false, 5, 0);
187 throw NetworkError("Timeout connecting to remote");
189 throw NetworkError("Error connecting to remote");
191 if(getsockopt(fd
, SOL_SOCKET
,SO_ERROR
,(char *)&err
,&len
)<0)
192 throw NetworkError("Error connecting to remote: "+stringerror()); // Solaris
195 throw NetworkError("Error connecting to remote: "+string(strerror(err
)));
201 void TCPNameserver::sendPacket(shared_ptr
<DNSPacket
> p
, int outsock
)
203 g_rs
.submitResponse(*p
, false);
205 uint16_t len
=htons(p
->getString().length());
206 string
buffer((const char*)&len
, 2);
207 buffer
.append(p
->getString());
208 writenWithTimeout(outsock
, buffer
.c_str(), buffer
.length(), d_idleTimeout
);
212 void TCPNameserver::getQuestion(int fd
, char *mesg
, int pktlen
, const ComboAddress
&remote
, unsigned int totalTime
)
215 readnWithTimeout(fd
, mesg
, pktlen
, d_idleTimeout
, true, totalTime
);
217 catch(NetworkError
& ae
) {
218 throw NetworkError("Error reading DNS data from TCP client "+remote
.toString()+": "+ae
.what());
221 static void incTCPAnswerCount(const ComboAddress
& remote
)
223 S
.inc("tcp-answers");
224 if(remote
.sin4
.sin_family
== AF_INET6
)
225 S
.inc("tcp6-answers");
227 S
.inc("tcp4-answers");
230 static bool maxConnectionDurationReached(unsigned int maxConnectionDuration
, time_t start
, unsigned int& remainingTime
)
232 if (maxConnectionDuration
) {
233 time_t elapsed
= time(NULL
) - start
;
234 if (elapsed
>= maxConnectionDuration
) {
237 remainingTime
= maxConnectionDuration
- elapsed
;
242 void TCPNameserver::decrementClientCount(const ComboAddress
& remote
)
244 if (d_maxConnectionsPerClient
) {
245 std::lock_guard
<std::mutex
> lock(s_clientsCountMutex
);
246 s_clientsCount
[remote
]--;
247 if (s_clientsCount
[remote
] == 0) {
248 s_clientsCount
.erase(remote
);
253 void *TCPNameserver::doConnection(void *data
)
255 shared_ptr
<DNSPacket
> packet
;
256 // Fix gcc-4.0 error (on AMD64)
257 int fd
=(int)(long)data
; // gotta love C (generates a harmless warning on opteron)
259 socklen_t remotelen
=sizeof(remote
);
260 size_t transactions
= 0;
262 if (d_maxConnectionDuration
) {
266 pthread_detach(pthread_self());
267 if(getpeername(fd
, (struct sockaddr
*)&remote
, &remotelen
) < 0) {
268 L
<<Logger::Warning
<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl
;
269 d_connectionroom_sem
->post();
273 catch(const PDNSException
& e
) {
274 L
<<Logger::Error
<<"Error closing TCP socket: "<<e
.reason
<<endl
;
282 scoped_array
<char> mesg(new char[mesgsize
]);
284 DLOG(L
<<"TCP Connection accepted on fd "<<fd
<<endl
);
285 bool logDNSQueries
= ::arg().mustDo("log-dns-queries");
287 unsigned int remainingTime
= 0;
289 if (d_maxTransactionsPerConn
&& transactions
> d_maxTransactionsPerConn
) {
290 L
<< Logger::Notice
<<"TCP Remote "<< remote
<<" exceeded the number of transactions per connection, dropping.";
293 if (maxConnectionDurationReached(d_maxConnectionDuration
, start
, remainingTime
)) {
294 L
<< Logger::Notice
<<"TCP Remote "<< remote
<<" exceeded the maximum TCP connection duration, dropping.";
299 if(!readnWithTimeout(fd
, &pktlen
, 2, d_idleTimeout
, false, remainingTime
))
302 pktlen
=ntohs(pktlen
);
304 // this check will always be false *if* no one touches
305 // the mesg array. pktlen can be maximum of 65535 as
306 // it is 2 byte unsigned variable. In getQuestion, we
307 // write to 0 up to pktlen-1 so 65535 is just right.
309 // do not remove this check as it will catch if someone
310 // decreases the mesg buffer size for some reason.
311 if(pktlen
> mesgsize
) {
312 L
<<Logger::Warning
<<"Received an overly large question from "<<remote
.toString()<<", dropping"<<endl
;
316 if (maxConnectionDurationReached(d_maxConnectionDuration
, start
, remainingTime
)) {
317 L
<< Logger::Notice
<<"TCP Remote "<< remote
<<" exceeded the maximum TCP connection duration, dropping.";
321 getQuestion(fd
, mesg
.get(), pktlen
, remote
, remainingTime
);
322 S
.inc("tcp-queries");
323 if(remote
.sin4
.sin_family
== AF_INET6
)
324 S
.inc("tcp6-queries");
326 S
.inc("tcp4-queries");
328 packet
=shared_ptr
<DNSPacket
>(new DNSPacket(true));
329 packet
->setRemote(&remote
);
331 packet
->setSocket(fd
);
332 if(packet
->parse(mesg
.get(), pktlen
)<0)
335 if(packet
->qtype
.getCode()==QType::AXFR
) {
336 if(doAXFR(packet
->qdomain
, packet
, fd
))
337 incTCPAnswerCount(remote
);
341 if(packet
->qtype
.getCode()==QType::IXFR
) {
342 if(doIXFR(packet
, fd
))
343 incTCPAnswerCount(remote
);
347 shared_ptr
<DNSPacket
> reply
;
348 shared_ptr
<DNSPacket
> cached
= shared_ptr
<DNSPacket
>(new DNSPacket(false));
351 if(packet
->hasEDNSSubnet())
352 remote_text
= packet
->getRemote().toString() + "<-" + packet
->getRealRemote().toString();
354 remote_text
= packet
->getRemote().toString();
355 L
<< Logger::Notice
<<"TCP Remote "<< remote_text
<<" wants '" << packet
->qdomain
<<"|"<<packet
->qtype
.getName() <<
356 "', do = " <<packet
->d_dnssecOk
<<", bufsize = "<< packet
->getMaxReplyLen()<<": ";
360 if(packet
->couldBeCached() && PC
.get(packet
.get(), cached
.get())) { // short circuit - does the PacketCache recognize this question?
362 L
<<"packetcache HIT"<<endl
;
363 cached
->setRemote(&packet
->d_remote
);
364 cached
->d
.id
=packet
->d
.id
;
365 cached
->d
.rd
=packet
->d
.rd
; // copy in recursion desired bit
366 cached
->commitD(); // commit d to the packet inlined
368 sendPacket(cached
, fd
); // presigned, don't do it again
372 L
<<"packetcache MISS"<<endl
;
376 L
<<Logger::Error
<<"TCP server is without backend connections, launching"<<endl
;
377 s_P
=new PacketHandler
;
380 reply
=shared_ptr
<DNSPacket
>(s_P
->doQuestion(packet
.get())); // we really need to ask the backend :-)
383 if(!reply
) // unable to write an answer?
386 sendPacket(reply
, fd
);
389 catch(PDNSException
&ae
) {
392 s_P
= 0; // on next call, backend will be recycled
393 L
<<Logger::Error
<<"TCP nameserver had error, cycling backend: "<<ae
.reason
<<endl
;
395 catch(NetworkError
&e
) {
396 L
<<Logger::Info
<<"TCP Connection Thread died because of network error: "<<e
.what()<<endl
;
399 catch(std::exception
&e
) {
400 L
<<Logger::Error
<<"TCP Connection Thread died because of STL error: "<<e
.what()<<endl
;
404 L
<< Logger::Error
<< "TCP Connection Thread caught unknown exception." << endl
;
406 d_connectionroom_sem
->post();
411 catch(const PDNSException
& e
) {
412 L
<<Logger::Error
<<"Error closing TCP socket: "<<e
.reason
<<endl
;
414 decrementClientCount(remote
);
420 // call this method with s_plock held!
421 bool TCPNameserver::canDoAXFR(shared_ptr
<DNSPacket
> q
)
423 if(::arg().mustDo("disable-axfr"))
426 if(q
->d_havetsig
) { // if you have one, it must be good
427 TSIGRecordContent trc
;
430 if(!q
->checkForCorrectTSIG(s_P
->getBackend(), &keyname
, &secret
, &trc
)) {
433 getTSIGHashEnum(trc
.d_algoName
, q
->d_tsig_algo
);
434 if (q
->d_tsig_algo
== TSIG_GSS
) {
435 GssContext
gssctx(keyname
);
436 if (!gssctx
.getPeerPrincipal(q
->d_peer_principal
)) {
437 L
<<Logger::Warning
<<"Failed to extract peer principal from GSS context with keyname '"<<keyname
<<"'"<<endl
;
444 if (q
->d_tsig_algo
== TSIG_GSS
) {
445 vector
<string
> princs
;
446 s_P
->getBackend()->getDomainMetadata(q
->qdomain
, "GSS-ALLOW-AXFR-PRINCIPAL", princs
);
447 for(const std::string
& princ
: princs
) {
448 if (q
->d_peer_principal
== princ
) {
449 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' allowed: TSIG signed request with authorized principal '"<<q
->d_peer_principal
<<"' and algorithm 'gss-tsig'"<<endl
;
453 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' denied: TSIG signed request with principal '"<<q
->d_peer_principal
<<"' and algorithm 'gss-tsig' is not permitted"<<endl
;
457 if(!dk
.TSIGGrantsAccess(q
->qdomain
, keyname
)) {
458 L
<<Logger::Error
<<"AXFR '"<<q
->qdomain
<<"' denied: key with name '"<<keyname
<<"' and algorithm '"<<getTSIGAlgoName(q
->d_tsig_algo
)<<"' does not grant access to zone"<<endl
;
462 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' allowed: TSIG signed request with authorized key '"<<keyname
<<"' and algorithm '"<<getTSIGAlgoName(q
->d_tsig_algo
)<<"'"<<endl
;
467 // cerr<<"checking allow-axfr-ips"<<endl;
468 if(!(::arg()["allow-axfr-ips"].empty()) && d_ng
.match( (ComboAddress
*) &q
->d_remote
)) {
469 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' allowed: client IP "<<q
->getRemote()<<" is in allow-axfr-ips"<<endl
;
475 // cerr<<"doing per-zone-axfr-acls"<<endl;
477 if(s_P
->getBackend()->getSOAUncached(q
->qdomain
,sd
)) {
478 // cerr<<"got backend and SOA"<<endl;
481 s_P
->getBackend()->getDomainMetadata(q
->qdomain
, "ALLOW-AXFR-FROM", acl
);
482 for (vector
<string
>::const_iterator i
= acl
.begin(); i
!= acl
.end(); ++i
) {
483 // cerr<<"matching against "<<*i<<endl;
484 if(pdns_iequals(*i
, "AUTO-NS")) {
485 // cerr<<"AUTO-NS magic please!"<<endl;
487 DNSResourceRecord rr
;
490 B
->lookup(QType(QType::NS
),q
->qdomain
);
492 nsset
.insert(DNSName(rr
.content
));
493 for(const auto & j
: nsset
) {
494 vector
<string
> nsips
=fns
.lookup(j
, s_P
->getBackend());
495 for(vector
<string
>::const_iterator k
=nsips
.begin();k
!=nsips
.end();++k
) {
496 // cerr<<"got "<<*k<<" from AUTO-NS"<<endl;
497 if(*k
== q
->getRemote().toString())
499 // cerr<<"got AUTO-NS hit"<<endl;
500 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' allowed: client IP "<<q
->getRemote()<<" is in NSset"<<endl
;
508 Netmask nm
= Netmask(*i
);
509 if(nm
.match( (ComboAddress
*) &q
->d_remote
))
511 L
<<Logger::Warning
<<"AXFR of domain '"<<q
->qdomain
<<"' allowed: client IP "<<q
->getRemote()<<" is in per-domain ACL"<<endl
;
512 // cerr<<"hit!"<<endl;
519 extern CommunicatorClass Communicator
;
521 if(Communicator
.justNotified(q
->qdomain
, q
->getRemote().toString())) { // we just notified this ip
522 L
<<Logger::Warning
<<"Approved AXFR of '"<<q
->qdomain
<<"' from recently notified slave "<<q
->getRemote()<<endl
;
526 L
<<Logger::Error
<<"AXFR of domain '"<<q
->qdomain
<<"' denied: client IP "<<q
->getRemote()<<" has no permission"<<endl
;
538 DNSZoneRecord
makeEditedDNSZRFromSOAData(DNSSECKeeper
& dk
, const SOAData
& sd
)
541 edited
.serial
= calculateEditSOA(sd
.serial
, dk
, sd
.qname
);
544 soa
.d_name
= sd
.qname
;
545 soa
.d_type
= QType::SOA
;
547 soa
.d_place
= DNSResourceRecord::ANSWER
;
548 soa
.d_content
= makeSOAContent(edited
);
557 shared_ptr
<DNSPacket
> getFreshAXFRPacket(shared_ptr
<DNSPacket
> q
)
559 shared_ptr
<DNSPacket
> ret
= shared_ptr
<DNSPacket
>(q
->replyPacket());
560 ret
->setCompress(false);
561 ret
->d_dnssecOk
=false; // RFC 5936, 2.2.5
568 /** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
569 int TCPNameserver::doAXFR(const DNSName
&target
, shared_ptr
<DNSPacket
> q
, int outsock
)
571 shared_ptr
<DNSPacket
> outpacket
= getFreshAXFRPacket(q
);
573 outpacket
->d_dnssecOk
=true; // RFC 5936, 2.2.5 'SHOULD'
575 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' initiated by "<<q
->getRemote()<<endl
;
577 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
581 DLOG(L
<<"Looking for SOA"<<endl
); // find domain_id via SOA and list complete domain. No SOA, no AXFR
583 L
<<Logger::Error
<<"TCP server is without backend connections in doAXFR, launching"<<endl
;
584 s_P
=new PacketHandler
;
588 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' failed: "<<q
->getRemote()<<" may not request AXFR"<<endl
;
589 outpacket
->setRcode(RCode::NotAuth
);
590 sendPacket(outpacket
,outsock
);
594 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
595 if(!s_P
->getBackend()->getSOAUncached(target
, sd
)) {
596 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' failed: not authoritative"<<endl
;
597 outpacket
->setRcode(RCode::NotAuth
);
598 sendPacket(outpacket
,outsock
);
604 if(!db
.getSOAUncached(target
, sd
)) {
605 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' failed: not authoritative in second instance"<<endl
;
606 outpacket
->setRcode(RCode::NotAuth
);
607 sendPacket(outpacket
,outsock
);
612 dk
.clearCaches(target
);
613 bool securedZone
= dk
.isSecuredZone(target
);
614 bool presignedZone
= dk
.isPresigned(target
);
616 bool noAXFRBecauseOfNSEC3Narrow
=false;
617 NSEC3PARAMRecordContent ns3pr
;
619 bool NSEC3Zone
=false;
620 if(securedZone
&& dk
.getNSEC3PARAM(target
, &ns3pr
, &narrow
)) {
623 L
<<Logger::Error
<<"Not doing AXFR of an NSEC3 narrow zone '"<<target
<<"' for "<<q
->getRemote()<<endl
;
624 noAXFRBecauseOfNSEC3Narrow
=true;
628 if(noAXFRBecauseOfNSEC3Narrow
) {
629 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' denied to "<<q
->getRemote()<<endl
;
630 outpacket
->setRcode(RCode::Refused
);
631 // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
632 sendPacket(outpacket
,outsock
);
636 TSIGRecordContent trc
;
640 bool haveTSIGDetails
= q
->getTSIGDetails(&trc
, &tsigkeyname
);
642 if(haveTSIGDetails
&& !tsigkeyname
.empty()) {
644 DNSName algorithm
=trc
.d_algoName
; // FIXME400: check
645 if (algorithm
== DNSName("hmac-md5.sig-alg.reg.int"))
646 algorithm
= DNSName("hmac-md5");
647 if (algorithm
!= DNSName("gss-tsig")) {
649 if(!s_P
->getBackend()->getTSIGKey(tsigkeyname
, &algorithm
, &tsig64
)) {
650 L
<<Logger::Error
<<"TSIG key '"<<tsigkeyname
<<"' for domain '"<<target
<<"' not found"<<endl
;
653 if (B64Decode(tsig64
, tsigsecret
) == -1) {
654 L
<<Logger::Error
<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname
<<"' for domain '"<<target
<<"'"<<endl
;
661 UeberBackend signatureDB
;
663 // SOA *must* go out first, our signing pipe might reorder
664 DLOG(L
<<"Sending out SOA"<<endl
);
665 DNSZoneRecord soa
= makeEditedDNSZRFromSOAData(dk
, sd
);
666 outpacket
->addRecord(soa
);
667 if(securedZone
&& !presignedZone
) {
668 set
<DNSName
> authSet
;
669 authSet
.insert(target
);
670 addRRSigs(dk
, signatureDB
, authSet
, outpacket
->getRRS());
673 if(haveTSIGDetails
&& !tsigkeyname
.empty())
674 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
); // first answer is 'normal'
676 sendPacket(outpacket
, outsock
);
678 trc
.d_mac
= outpacket
->d_trc
.d_mac
;
679 outpacket
= getFreshAXFRPacket(q
);
681 ChunkedSigningPipe
csp(target
, (securedZone
&& !presignedZone
), ::arg().asNum("signing-threads", 1));
683 typedef map
<DNSName
, NSECXEntry
, CanonDNSNameCompare
> nsecxrepo_t
;
684 nsecxrepo_t nsecxrepo
;
686 // this is where the DNSKEYs go in
688 DNSSECKeeper::keyset_t keys
= dk
.getKeys(target
);
692 zrr
.dr
.d_name
= target
;
693 zrr
.dr
.d_ttl
= sd
.default_ttl
;
694 zrr
.auth
= 1; // please sign!
696 string publishCDNSKEY
, publishCDS
;
697 dk
.getFromMeta(q
->qdomain
, "PUBLISH-CDNSKEY", publishCDNSKEY
);
698 dk
.getFromMeta(q
->qdomain
, "PUBLISH-CDS", publishCDS
);
699 vector
<DNSZoneRecord
> cds
, cdnskey
;
700 DNSSECKeeper::keyset_t entryPoints
= dk
.getEntryPoints(q
->qdomain
);
701 set
<uint32_t> entryPointIds
;
702 for (auto const& value
: entryPoints
)
703 entryPointIds
.insert(value
.second
.id
);
705 for(const DNSSECKeeper::keyset_t::value_type
& value
: keys
) {
706 zrr
.dr
.d_type
= QType::DNSKEY
;
707 zrr
.dr
.d_content
= std::make_shared
<DNSKEYRecordContent
>(value
.first
.getDNSKEY());
708 DNSName keyname
= NSEC3Zone
? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr
, zrr
.dr
.d_name
))) : zrr
.dr
.d_name
;
709 NSECXEntry
& ne
= nsecxrepo
[keyname
];
711 ne
.d_set
.insert(zrr
.dr
.d_type
);
712 ne
.d_ttl
= sd
.default_ttl
;
715 // generate CDS and CDNSKEY records
716 if(entryPointIds
.count(value
.second
.id
) > 0){
717 if(publishCDNSKEY
== "1") {
718 zrr
.dr
.d_type
=QType::CDNSKEY
;
719 zrr
.dr
.d_content
= std::make_shared
<DNSKEYRecordContent
>(value
.first
.getDNSKEY());
720 cdnskey
.push_back(zrr
);
723 if(!publishCDS
.empty()){
724 zrr
.dr
.d_type
=QType::CDS
;
725 vector
<string
> digestAlgos
;
726 stringtok(digestAlgos
, publishCDS
, ", ");
727 for(auto const &digestAlgo
: digestAlgos
) {
728 zrr
.dr
.d_content
=std::make_shared
<DSRecordContent
>(makeDSFromDNSKey(target
, value
.first
.getDNSKEY(), pdns_stou(digestAlgo
)));
735 if(::arg().mustDo("direct-dnskey")) {
736 sd
.db
->lookup(QType(QType::DNSKEY
), target
, NULL
, sd
.domain_id
);
737 while(sd
.db
->get(zrr
)) {
738 zrr
.dr
.d_ttl
= sd
.default_ttl
;
745 if(NSEC3Zone
) { // now stuff in the NSEC3PARAM
746 flags
= ns3pr
.d_flags
;
747 zrr
.dr
.d_type
= QType::NSEC3PARAM
;
749 zrr
.dr
.d_content
= std::make_shared
<NSEC3PARAMRecordContent
>(ns3pr
);
750 ns3pr
.d_flags
= flags
;
751 DNSName keyname
= DNSName(toBase32Hex(hashQNameWithSalt(ns3pr
, zrr
.dr
.d_name
)));
752 NSECXEntry
& ne
= nsecxrepo
[keyname
];
754 ne
.d_set
.insert(zrr
.dr
.d_type
);
758 // now start list zone
759 if(!(sd
.db
->list(target
, sd
.domain_id
))) {
760 L
<<Logger::Error
<<"Backend signals error condition"<<endl
;
761 outpacket
->setRcode(RCode::ServFail
);
762 sendPacket(outpacket
,outsock
);
767 const bool rectify
= !(presignedZone
|| ::arg().mustDo("disable-axfr-rectify"));
768 set
<DNSName
> qnames
, nsset
, terms
;
769 vector
<DNSZoneRecord
> zrrs
;
771 // Add the CDNSKEY and CDS records we created earlier
772 for (auto const &synth_zrr
: cds
)
773 zrrs
.push_back(synth_zrr
);
775 for (auto const &synth_zrr
: cdnskey
)
776 zrrs
.push_back(synth_zrr
);
778 while(sd
.db
->get(zrr
)) {
779 zrr
.dr
.d_name
.makeUsLowerCase();
780 if(zrr
.dr
.d_name
.isPartOf(target
)) {
781 if (zrr
.dr
.d_type
== QType::ALIAS
&& ::arg().mustDo("outgoing-axfr-expand-alias")) {
782 vector
<DNSZoneRecord
> ips
;
783 int ret1
= stubDoResolve(getRR
<ALIASRecordContent
>(zrr
.dr
)->d_content
, QType::A
, ips
);
784 int ret2
= stubDoResolve(getRR
<ALIASRecordContent
>(zrr
.dr
)->d_content
, QType::AAAA
, ips
);
785 if(ret1
!= RCode::NoError
|| ret2
!= RCode::NoError
) {
786 L
<<Logger::Error
<<"Error resolving for ALIAS "<<zrr
.dr
.d_content
->getZoneRepresentation()<<", aborting AXFR"<<endl
;
787 outpacket
->setRcode(RCode::ServFail
);
788 sendPacket(outpacket
,outsock
);
791 for(const auto& ip
: ips
) {
792 zrr
.dr
.d_type
= ip
.dr
.d_type
;
793 zrr
.dr
.d_content
= ip
.dr
.d_content
;
801 qnames
.insert(zrr
.dr
.d_name
);
802 if(zrr
.dr
.d_type
== QType::NS
&& zrr
.dr
.d_name
!=target
)
803 nsset
.insert(zrr
.dr
.d_name
);
805 // remove existing ents
812 L
<<Logger::Warning
<<"Zone '"<<target
<<"' contains out-of-zone data '"<<zrr
.dr
.d_name
<<"|"<<DNSRecordContent::NumberToType(zrr
.dr
.d_type
)<<"', ignoring"<<endl
;
816 // Group records by name and type, signpipe stumbles over interrupted rrsets
817 sort(zrrs
.begin(), zrrs
.end(), [](const DNSZoneRecord
& a
, const DNSZoneRecord
& b
) {
818 return tie(a
.dr
.d_name
, a
.dr
.d_type
) < tie(b
.dr
.d_name
, b
.dr
.d_type
);
823 for(DNSZoneRecord
&loopZRR
: zrrs
) {
825 if (loopZRR
.dr
.d_type
!= QType::NS
|| loopZRR
.dr
.d_name
!=target
) {
826 DNSName
shorter(loopZRR
.dr
.d_name
);
828 if (shorter
==target
) // apex is always auth
830 if(nsset
.count(shorter
) && !(loopZRR
.dr
.d_name
==shorter
&& loopZRR
.dr
.d_type
== QType::DS
)) {
834 } while(shorter
.chopOff());
839 // ents are only required for NSEC3 zones
840 uint32_t maxent
= ::arg().asNum("max-ent-entries");
841 set
<DNSName
> nsec3set
, nonterm
;
842 for (auto &loopZRR
: zrrs
) {
844 DNSName shorter
= loopZRR
.dr
.d_name
;
845 if (shorter
!= target
&& shorter
.chopOff() && shorter
!= target
) {
847 if(nsset
.count(shorter
)) {
851 } while(shorter
.chopOff() && shorter
!= target
);
853 shorter
= loopZRR
.dr
.d_name
;
854 if(!skip
&& (loopZRR
.dr
.d_type
!= QType::NS
|| !ns3pr
.d_flags
)) {
856 if(!nsec3set
.count(shorter
)) {
857 nsec3set
.insert(shorter
);
859 } while(shorter
!= target
&& shorter
.chopOff());
863 for(DNSZoneRecord
&loopZRR
: zrrs
) {
864 DNSName
shorter(loopZRR
.dr
.d_name
);
865 while(shorter
!= target
&& shorter
.chopOff()) {
866 if(!qnames
.count(shorter
) && !nonterm
.count(shorter
) && nsec3set
.count(shorter
)) {
868 L
<<Logger::Warning
<<"Zone '"<<target
<<"' has too many empty non terminals."<<endl
;
871 nonterm
.insert(shorter
);
877 for(const auto& nt
: nonterm
) {
878 DNSZoneRecord tempRR
;
880 tempRR
.dr
.d_type
=QType::ENT
;
882 zrrs
.push_back(tempRR
);
888 /* now write all other records */
895 for(DNSZoneRecord
&loopZRR
: zrrs
) {
896 if (!presignedZone
&& loopZRR
.dr
.d_type
== QType::RRSIG
)
899 // only skip the DNSKEY, CDNSKEY and CDS if direct-dnskey is enabled, to avoid changing behaviour
900 // when it is not enabled.
901 if(::arg().mustDo("direct-dnskey") && (loopZRR
.dr
.d_type
== QType::DNSKEY
|| loopZRR
.dr
.d_type
== QType::CDNSKEY
|| loopZRR
.dr
.d_type
== QType::CDS
))
905 if(securedZone
&& (loopZRR
.auth
|| loopZRR
.dr
.d_type
== QType::NS
)) {
906 if (NSEC3Zone
|| loopZRR
.dr
.d_type
) {
907 if (presignedZone
&& NSEC3Zone
&& loopZRR
.dr
.d_type
== QType::RRSIG
&& getRR
<RRSIGRecordContent
>(loopZRR
.dr
)->d_type
== QType::NSEC3
) {
908 keyname
= loopZRR
.dr
.d_name
.makeRelative(sd
.qname
);
910 keyname
= NSEC3Zone
? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr
, loopZRR
.dr
.d_name
))) : loopZRR
.dr
.d_name
;
912 NSECXEntry
& ne
= nsecxrepo
[keyname
];
913 ne
.d_ttl
= sd
.default_ttl
;
914 ne
.d_auth
= (ne
.d_auth
|| loopZRR
.auth
|| (NSEC3Zone
&& (!ns3pr
.d_flags
)));
915 if (loopZRR
.dr
.d_type
&& loopZRR
.dr
.d_type
!= QType::RRSIG
) {
916 ne
.d_set
.insert(loopZRR
.dr
.d_type
);
921 if (!loopZRR
.dr
.d_type
)
922 continue; // skip empty non-terminals
924 if(loopZRR
.dr
.d_type
== QType::SOA
)
925 continue; // skip SOA - would indicate end of AXFR
927 if(csp
.submit(loopZRR
)) {
929 outpacket
->getRRS() = csp
.getChunk();
930 if(!outpacket
->getRRS().empty()) {
931 if(haveTSIGDetails
&& !tsigkeyname
.empty())
932 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
, true);
933 sendPacket(outpacket
, outsock
);
934 trc
.d_mac
=outpacket
->d_trc
.d_mac
;
935 outpacket
=getFreshAXFRPacket(q
);
943 udiff=dt.udiffNoReset();
944 cerr<<"Starting NSEC: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
945 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
946 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
950 for(nsecxrepo_t::const_iterator iter
= nsecxrepo
.begin(); iter
!= nsecxrepo
.end(); ++iter
) {
951 if(iter
->second
.d_auth
) {
952 NSEC3RecordContent n3rc
;
953 n3rc
.d_set
= iter
->second
.d_set
;
954 if (n3rc
.d_set
.size() && (n3rc
.d_set
.size() != 1 || !n3rc
.d_set
.count(QType::NS
)))
955 n3rc
.d_set
.insert(QType::RRSIG
);
956 n3rc
.d_salt
=ns3pr
.d_salt
;
957 n3rc
.d_flags
= ns3pr
.d_flags
;
958 n3rc
.d_iterations
= ns3pr
.d_iterations
;
959 n3rc
.d_algorithm
= 1; // SHA1, fixed in PowerDNS for now
960 nsecxrepo_t::const_iterator inext
= iter
;
962 if(inext
== nsecxrepo
.end())
963 inext
= nsecxrepo
.begin();
964 while(!inext
->second
.d_auth
&& inext
!= iter
)
967 if(inext
== nsecxrepo
.end())
968 inext
= nsecxrepo
.begin();
970 n3rc
.d_nexthash
= fromBase32Hex(inext
->first
.toStringNoDot());
971 zrr
.dr
.d_name
= iter
->first
+sd
.qname
;
973 zrr
.dr
.d_ttl
= sd
.default_ttl
;
974 zrr
.dr
.d_content
= std::make_shared
<NSEC3RecordContent
>(n3rc
);
975 zrr
.dr
.d_type
= QType::NSEC3
;
976 zrr
.dr
.d_place
= DNSResourceRecord::ANSWER
;
978 if(csp
.submit(zrr
)) {
980 outpacket
->getRRS() = csp
.getChunk();
981 if(!outpacket
->getRRS().empty()) {
982 if(haveTSIGDetails
&& !tsigkeyname
.empty())
983 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
, true);
984 sendPacket(outpacket
, outsock
);
985 trc
.d_mac
=outpacket
->d_trc
.d_mac
;
986 outpacket
=getFreshAXFRPacket(q
);
995 else for(nsecxrepo_t::const_iterator iter
= nsecxrepo
.begin(); iter
!= nsecxrepo
.end(); ++iter
) {
996 NSECRecordContent nrc
;
997 nrc
.d_set
= iter
->second
.d_set
;
998 nrc
.d_set
.insert(QType::RRSIG
);
999 nrc
.d_set
.insert(QType::NSEC
);
1001 if(boost::next(iter
) != nsecxrepo
.end())
1002 nrc
.d_next
= boost::next(iter
)->first
;
1004 nrc
.d_next
=nsecxrepo
.begin()->first
;
1005 zrr
.dr
.d_name
= iter
->first
;
1007 zrr
.dr
.d_ttl
= sd
.default_ttl
;
1008 zrr
.dr
.d_content
= std::make_shared
<NSECRecordContent
>(nrc
);
1009 zrr
.dr
.d_type
= QType::NSEC
;
1010 zrr
.dr
.d_place
= DNSResourceRecord::ANSWER
;
1012 if(csp
.submit(zrr
)) {
1014 outpacket
->getRRS() = csp
.getChunk();
1015 if(!outpacket
->getRRS().empty()) {
1016 if(haveTSIGDetails
&& !tsigkeyname
.empty())
1017 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
, true);
1018 sendPacket(outpacket
, outsock
);
1019 trc
.d_mac
=outpacket
->d_trc
.d_mac
;
1020 outpacket
=getFreshAXFRPacket(q
);
1029 udiff=dt.udiffNoReset();
1030 cerr<<"Flushing pipe: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
1031 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
1032 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
1035 outpacket
->getRRS() = csp
.getChunk(true); // flush the pipe
1036 if(!outpacket
->getRRS().empty()) {
1037 if(haveTSIGDetails
&& !tsigkeyname
.empty())
1038 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
, true); // first answer is 'normal'
1039 sendPacket(outpacket
, outsock
);
1040 trc
.d_mac
=outpacket
->d_trc
.d_mac
;
1041 outpacket
=getFreshAXFRPacket(q
);
1047 udiff
=dt
.udiffNoReset();
1049 L
<<Logger::Info
<<"Done signing: "<<csp
.d_signed
/(udiff
/1000000.0)<<" sigs/s, "<<endl
;
1051 DLOG(L
<<"Done writing out records"<<endl
);
1052 /* and terminate with yet again the SOA record */
1053 outpacket
=getFreshAXFRPacket(q
);
1054 outpacket
->addRecord(soa
);
1055 if(haveTSIGDetails
&& !tsigkeyname
.empty())
1056 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
, true);
1058 sendPacket(outpacket
, outsock
);
1060 DLOG(L
<<"last packet - close"<<endl
);
1061 L
<<Logger::Error
<<"AXFR of domain '"<<target
<<"' to "<<q
->getRemote()<<" finished"<<endl
;
1066 int TCPNameserver::doIXFR(shared_ptr
<DNSPacket
> q
, int outsock
)
1068 shared_ptr
<DNSPacket
> outpacket
=getFreshAXFRPacket(q
);
1070 outpacket
->d_dnssecOk
=true; // RFC 5936, 2.2.5 'SHOULD'
1072 uint32_t serial
= 0;
1073 MOADNSParser
mdp(false, q
->getString());
1074 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!= mdp
.d_answers
.end(); ++i
) {
1075 const DNSRecord
*rr
= &i
->first
;
1076 if (rr
->d_type
== QType::SOA
&& rr
->d_place
== DNSResourceRecord::AUTHORITY
) {
1077 vector
<string
>parts
;
1078 stringtok(parts
, rr
->d_content
->getZoneRepresentation());
1079 if (parts
.size() >= 3) {
1081 serial
=pdns_stou(parts
[2]);
1083 catch(const std::out_of_range
& oor
) {
1084 L
<<Logger::Error
<<"Invalid serial in IXFR query"<<endl
;
1085 outpacket
->setRcode(RCode::FormErr
);
1086 sendPacket(outpacket
,outsock
);
1090 L
<<Logger::Error
<<"No serial in IXFR query"<<endl
;
1091 outpacket
->setRcode(RCode::FormErr
);
1092 sendPacket(outpacket
,outsock
);
1095 } else if (rr
->d_type
!= QType::TSIG
&& rr
->d_type
!= QType::OPT
) {
1096 L
<<Logger::Error
<<"Additional records in IXFR query, type: "<<QType(rr
->d_type
).getName()<<endl
;
1097 outpacket
->setRcode(RCode::FormErr
);
1098 sendPacket(outpacket
,outsock
);
1103 L
<<Logger::Error
<<"IXFR of domain '"<<q
->qdomain
<<"' initiated by "<<q
->getRemote()<<" with serial "<<serial
<<endl
;
1105 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
1109 DLOG(L
<<"Looking for SOA"<<endl
); // find domain_id via SOA and list complete domain. No SOA, no IXFR
1111 L
<<Logger::Error
<<"TCP server is without backend connections in doIXFR, launching"<<endl
;
1112 s_P
=new PacketHandler
;
1115 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
1116 if(!canDoAXFR(q
) || !s_P
->getBackend()->getSOAUncached(q
->qdomain
, sd
)) {
1117 L
<<Logger::Error
<<"IXFR of domain '"<<q
->qdomain
<<"' failed: not authoritative"<<endl
;
1118 outpacket
->setRcode(RCode::NotAuth
);
1119 sendPacket(outpacket
,outsock
);
1125 NSEC3PARAMRecordContent ns3pr
;
1128 dk
.clearCaches(q
->qdomain
);
1129 bool securedZone
= dk
.isSecuredZone(q
->qdomain
);
1130 if(dk
.getNSEC3PARAM(q
->qdomain
, &ns3pr
, &narrow
)) {
1132 L
<<Logger::Error
<<"Not doing IXFR of an NSEC3 narrow zone."<<endl
;
1133 L
<<Logger::Error
<<"IXFR of domain '"<<q
->qdomain
<<"' denied to "<<q
->getRemote()<<endl
;
1134 outpacket
->setRcode(RCode::Refused
);
1135 sendPacket(outpacket
,outsock
);
1140 DNSName target
= q
->qdomain
;
1143 if(!db
.getSOAUncached(target
, sd
)) {
1144 L
<<Logger::Error
<<"IXFR of domain '"<<target
<<"' failed: not authoritative in second instance"<<endl
;
1145 outpacket
->setRcode(RCode::NotAuth
);
1146 sendPacket(outpacket
,outsock
);
1150 if (!rfc1982LessThan(serial
, calculateEditSOA(sd
.serial
, dk
, sd
.qname
))) {
1151 TSIGRecordContent trc
;
1152 DNSName tsigkeyname
;
1155 bool haveTSIGDetails
= q
->getTSIGDetails(&trc
, &tsigkeyname
);
1157 if(haveTSIGDetails
&& !tsigkeyname
.empty()) {
1159 DNSName algorithm
=trc
.d_algoName
; // FIXME400: was toLowerCanonic, compare output
1160 if (algorithm
== DNSName("hmac-md5.sig-alg.reg.int"))
1161 algorithm
= DNSName("hmac-md5");
1163 if(!s_P
->getBackend()->getTSIGKey(tsigkeyname
, &algorithm
, &tsig64
)) {
1164 L
<<Logger::Error
<<"TSIG key '"<<tsigkeyname
<<"' for domain '"<<target
<<"' not found"<<endl
;
1167 if (B64Decode(tsig64
, tsigsecret
) == -1) {
1168 L
<<Logger::Error
<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname
<<"' for domain '"<<target
<<"'"<<endl
;
1173 UeberBackend signatureDB
;
1175 // SOA *must* go out first, our signing pipe might reorder
1176 DLOG(L
<<"Sending out SOA"<<endl
);
1177 DNSZoneRecord soa
= makeEditedDNSZRFromSOAData(dk
, sd
);
1178 outpacket
->addRecord(soa
);
1180 set
<DNSName
> authSet
;
1181 authSet
.insert(target
);
1182 addRRSigs(dk
, signatureDB
, authSet
, outpacket
->getRRS());
1185 if(haveTSIGDetails
&& !tsigkeyname
.empty())
1186 outpacket
->setTSIGDetails(trc
, tsigkeyname
, tsigsecret
, trc
.d_mac
); // first answer is 'normal'
1188 sendPacket(outpacket
, outsock
);
1190 L
<<Logger::Error
<<"IXFR of domain '"<<target
<<"' to "<<q
->getRemote()<<" finished"<<endl
;
1195 L
<<Logger::Error
<<"IXFR fallback to AXFR for domain '"<<target
<<"' our serial "<<sd
.serial
<<endl
;
1196 return doAXFR(q
->qdomain
, q
, outsock
);
1199 TCPNameserver::~TCPNameserver()
1201 delete d_connectionroom_sem
;
1204 TCPNameserver::TCPNameserver()
1206 d_maxTransactionsPerConn
= ::arg().asNum("max-tcp-transactions-per-conn");
1207 d_idleTimeout
= ::arg().asNum("tcp-idle-timeout");
1208 d_maxConnectionDuration
= ::arg().asNum("max-tcp-connection-duration");
1209 d_maxConnectionsPerClient
= ::arg().asNum("max-tcp-connections-per-client");
1211 // sem_init(&d_connectionroom_sem,0,::arg().asNum("max-tcp-connections"));
1212 d_connectionroom_sem
= new Semaphore( ::arg().asNum( "max-tcp-connections" ));
1214 vector
<string
>locals
;
1215 stringtok(locals
,::arg()["local-address"]," ,");
1217 vector
<string
>locals6
;
1218 stringtok(locals6
,::arg()["local-ipv6"]," ,");
1220 if(locals
.empty() && locals6
.empty())
1221 throw PDNSException("No local address specified");
1223 d_ng
.toMasks(::arg()["allow-axfr-ips"] );
1225 signal(SIGPIPE
,SIG_IGN
);
1227 for(vector
<string
>::const_iterator laddr
=locals
.begin();laddr
!=locals
.end();++laddr
) {
1228 int s
=socket(AF_INET
,SOCK_STREAM
,0);
1231 throw PDNSException("Unable to acquire TCP socket: "+stringerror());
1235 ComboAddress
local(*laddr
, ::arg().asNum("local-port"));
1238 if(setsockopt(s
,SOL_SOCKET
,SO_REUSEADDR
,(char*)&tmp
,sizeof tmp
)<0) {
1239 L
<<Logger::Error
<<"Setsockopt failed"<<endl
;
1243 if (::arg().asNum("tcp-fast-open") > 0) {
1245 int fastOpenQueueSize
= ::arg().asNum("tcp-fast-open");
1246 if (setsockopt(s
, IPPROTO_TCP
, TCP_FASTOPEN
, &fastOpenQueueSize
, sizeof fastOpenQueueSize
) < 0) {
1247 L
<<Logger::Error
<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno
)<<endl
;
1250 L
<<Logger::Warning
<<"TCP Fast Open configured but not supported for listening socket"<<endl
;
1254 if( ::arg().mustDo("non-local-bind") )
1255 Utility::setBindAny(AF_INET
, s
);
1257 if(::bind(s
, (sockaddr
*)&local
, local
.getSocklen())<0) {
1259 if( errno
== EADDRNOTAVAIL
&& ! ::arg().mustDo("local-address-nonexist-fail") ) {
1260 L
<<Logger::Error
<<"IPv4 Address " << *laddr
<< " does not exist on this server - skipping TCP bind" << endl
;
1263 L
<<Logger::Error
<<"Unable to bind to TCP socket " << *laddr
<< ": "<<strerror(errno
)<<endl
;
1264 throw PDNSException("Unable to bind to TCP socket");
1269 L
<<Logger::Error
<<"TCP server bound to "<<local
.toStringWithPort()<<endl
;
1270 d_sockets
.push_back(s
);
1272 memset(&pfd
, 0, sizeof(pfd
));
1274 pfd
.events
= POLLIN
;
1276 d_prfds
.push_back(pfd
);
1279 for(vector
<string
>::const_iterator laddr
=locals6
.begin();laddr
!=locals6
.end();++laddr
) {
1280 int s
=socket(AF_INET6
,SOCK_STREAM
,0);
1283 throw PDNSException("Unable to acquire TCPv6 socket: "+stringerror());
1287 ComboAddress
local(*laddr
, ::arg().asNum("local-port"));
1290 if(setsockopt(s
,SOL_SOCKET
,SO_REUSEADDR
,(char*)&tmp
,sizeof tmp
)<0) {
1291 L
<<Logger::Error
<<"Setsockopt failed"<<endl
;
1295 if (::arg().asNum("tcp-fast-open") > 0) {
1297 int fastOpenQueueSize
= ::arg().asNum("tcp-fast-open");
1298 if (setsockopt(s
, IPPROTO_TCP
, TCP_FASTOPEN
, &fastOpenQueueSize
, sizeof fastOpenQueueSize
) < 0) {
1299 L
<<Logger::Error
<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno
)<<endl
;
1302 L
<<Logger::Warning
<<"TCP Fast Open configured but not supported for listening socket"<<endl
;
1306 if( ::arg().mustDo("non-local-bind") )
1307 Utility::setBindAny(AF_INET6
, s
);
1308 if(setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &tmp
, sizeof(tmp
)) < 0) {
1309 L
<<Logger::Error
<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno
)<<endl
;
1311 if(bind(s
, (const sockaddr
*)&local
, local
.getSocklen())<0) {
1313 if( errno
== EADDRNOTAVAIL
&& ! ::arg().mustDo("local-ipv6-nonexist-fail") ) {
1314 L
<<Logger::Error
<<"IPv6 Address " << *laddr
<< " does not exist on this server - skipping TCP bind" << endl
;
1317 L
<<Logger::Error
<<"Unable to bind to TCPv6 socket" << *laddr
<< ": "<<strerror(errno
)<<endl
;
1318 throw PDNSException("Unable to bind to TCPv6 socket");
1323 L
<<Logger::Error
<<"TCPv6 server bound to "<<local
.toStringWithPort()<<endl
; // this gets %eth0 right
1324 d_sockets
.push_back(s
);
1327 memset(&pfd
, 0, sizeof(pfd
));
1329 pfd
.events
= POLLIN
;
1331 d_prfds
.push_back(pfd
);
1336 //! Start of TCP operations thread, we launch a new thread for each incoming TCP question
1337 void TCPNameserver::thread()
1342 ComboAddress remote
;
1343 Utility::socklen_t addrlen
=remote
.getSocklen();
1345 int ret
=poll(&d_prfds
[0], d_prfds
.size(), -1); // blocks, forever if need be
1350 for(const pollfd
& pfd
: d_prfds
) {
1351 if(pfd
.revents
== POLLIN
) {
1353 remote
.sin4
.sin_family
= AF_INET6
;
1354 addrlen
=remote
.getSocklen();
1356 if((fd
=accept(sock
, (sockaddr
*)&remote
, &addrlen
))<0) {
1357 L
<<Logger::Error
<<"TCP question accept error: "<<strerror(errno
)<<endl
;
1360 L
<<Logger::Error
<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl
;
1365 if (d_maxConnectionsPerClient
) {
1366 std::lock_guard
<std::mutex
> lock(s_clientsCountMutex
);
1367 if (s_clientsCount
[remote
] >= d_maxConnectionsPerClient
) {
1368 L
<<Logger::Notice
<<"Limit of simultaneous TCP connections per client reached for "<< remote
<<", dropping"<<endl
;
1372 s_clientsCount
[remote
]++;
1376 d_connectionroom_sem
->wait(); // blocks if no connections are available
1379 d_connectionroom_sem
->getValue( &room
);
1381 L
<<Logger::Warning
<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl
;
1383 if(pthread_create(&tid
, 0, &doConnection
, reinterpret_cast<void*>(fd
))) {
1384 L
<<Logger::Error
<<"Error creating thread: "<<stringerror()<<endl
;
1385 d_connectionroom_sem
->post();
1387 decrementClientCount(remote
);
1394 catch(PDNSException
&AE
) {
1395 L
<<Logger::Error
<<"TCP Nameserver thread dying because of fatal error: "<<AE
.reason
<<endl
;
1398 L
<<Logger::Error
<<"TCPNameserver dying because of an unexpected fatal error"<<endl
;
1400 _exit(1); // take rest of server with us