]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pdns_recursor.cc
"I can't belieeeeeve it!" same bug twice
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
CommitLineData
288f4aa9
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
22c012a8 3 Copyright (C) 2003 - 2006 PowerDNS.COM BV
288f4aa9
BH
4
5 This program is free software; you can redistribute it and/or modify
f28307ad
BH
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
288f4aa9
BH
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
caa6eefa
BH
18
19#include "utility.hh"
288f4aa9
BH
20#include <iostream>
21#include <errno.h>
22#include <map>
23#include <set>
caa6eefa 24#ifndef WIN32
288f4aa9 25#include <netdb.h>
caa6eefa 26#endif // WIN32
97bb160b 27#include "recursor_cache.hh"
288f4aa9 28#include <stdio.h>
c75a6a9e 29#include <signal.h>
288f4aa9
BH
30#include <stdlib.h>
31#include <unistd.h>
32#include "mtasker.hh"
33#include <utility>
34#include "dnspacket.hh"
35#include "statbag.hh"
36#include "arguments.hh"
37#include "syncres.hh"
88def049
BH
38#include <fcntl.h>
39#include <fstream>
5c633640
BH
40#include "sstuff.hh"
41#include <boost/tuple/tuple.hpp>
42#include <boost/tuple/tuple_comparison.hpp>
72df400f 43#include <boost/shared_array.hpp>
ea634573
BH
44#include <boost/lexical_cast.hpp>
45#include "dnsparser.hh"
46#include "dnswriter.hh"
47#include "dnsrecords.hh"
f814d7c8 48#include "zoneparser-tng.hh"
1d5b3ce6
BH
49#include "rec_channel.hh"
50
51// using namespace boost;
5c633640 52
27adc173 53#ifdef __FreeBSD__ // see cvstrac ticket #26
7f617eb9
BH
54#include <pthread.h>
55#include <semaphore.h>
56#endif
57
eefd15f9 58MemRecursorCache RC;
1d5b3ce6
BH
59RecursorStats g_stats;
60bool g_quiet;
88def049 61string s_programname="pdns_recursor";
288f4aa9 62
ea634573 63struct DNSComboWriter {
c9e9e5e0 64 DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), d_tcp(false), d_socket(-1)
ea634573
BH
65 {}
66 MOADNSParser d_mdp;
67 void setRemote(struct sockaddr* sa, socklen_t len)
68 {
69 memcpy((void *)d_remote, (void *)sa, len);
70 d_socklen=len;
71 }
72
73 void setSocket(int sock)
74 {
75 d_socket=sock;
76 }
a1754c6a
BH
77
78 string getRemote() const
79 {
80 return sockAddrToString((struct sockaddr_in *)d_remote, d_socklen);
81 }
82
c9e9e5e0 83 struct timeval d_now;
ea634573
BH
84 char d_remote[sizeof(sockaddr_in6)];
85 socklen_t d_socklen;
86 bool d_tcp;
87 int d_socket;
88};
89
90
27adc173
BH
91#ifndef WIN32
92#ifndef __FreeBSD__
288f4aa9
BH
93extern "C" {
94 int sem_init(sem_t*, int, unsigned int){return 0;}
95 int sem_wait(sem_t*){return 0;}
96 int sem_trywait(sem_t*){return 0;}
97 int sem_post(sem_t*){return 0;}
98 int sem_getvalue(sem_t*, int*){return 0;}
dcf9bd8f 99 pthread_t pthread_self(void){return (pthread_t) 0;}
98e05fce 100 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr){ return 0; }
dcf9bd8f
BH
101 int pthread_mutex_lock(pthread_mutex_t *mutex){ return 0; }
102 int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
df38dbe8 103 int pthread_mutex_destroy(pthread_mutex_t *mutex) { return 0; }
288f4aa9 104}
27adc173 105#endif // __FreeBSD__
caa6eefa 106#endif // WIN32
288f4aa9
BH
107
108StatBag S;
109ArgvMap &arg()
110{
111 static ArgvMap theArg;
112 return theArg;
113}
bacc40d9 114static int d_clientsock;
f28307ad 115static vector<int> d_udpserversocks;
288f4aa9 116
cd50f30d
BH
117typedef vector<int> tcpserversocks_t;
118static tcpserversocks_t s_tcpserversocks;
5c633640 119
5c633640
BH
120static map<int,PacketID> d_tcpclientreadsocks, d_tcpclientwritesocks;
121
122MTasker<PacketID,string>* MT;
123
124int asendtcp(const string& data, Socket* sock)
125{
126 PacketID pident;
127 pident.sock=sock;
128 pident.outMSG=data;
129 string packet;
130
5c633640
BH
131 d_tcpclientwritesocks[sock->getHandle()]=pident;
132
9170fbaf
BH
133 int ret=MT->waitEvent(pident,&packet,1);
134 if(!ret || ret==-1) { // timeout
5c633640 135 d_tcpclientwritesocks.erase(sock->getHandle());
5c633640 136 }
9170fbaf 137 return ret;
5c633640
BH
138}
139
9170fbaf 140// -1 is error, 0 is timeout, 1 is success
5c633640 141int arecvtcp(string& data, int len, Socket* sock)
288f4aa9 142{
5c633640
BH
143 data="";
144 PacketID pident;
145 pident.sock=sock;
146 pident.inNeeded=len;
147
5c633640
BH
148 d_tcpclientreadsocks[sock->getHandle()]=pident;
149
9170fbaf
BH
150 int ret=MT->waitEvent(pident,&data,1);
151 if(!ret || ret==-1) { // timeout
5c633640 152 d_tcpclientreadsocks.erase(sock->getHandle());
288f4aa9 153 }
9170fbaf 154 return ret;
288f4aa9
BH
155}
156
288f4aa9
BH
157
158/* these two functions are used by LWRes */
9170fbaf 159// -1 is error, > 1 is success
288f4aa9
BH
160int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int addrlen, int id)
161{
162 return sendto(d_clientsock, data, len, flags, toaddr, addrlen);
163}
164
9170fbaf 165// -1 is error, 0 is timeout, 1 is success
caa6eefa 166int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id)
288f4aa9
BH
167{
168 PacketID pident;
169 pident.id=id;
29a14b24 170 memcpy(&pident.remote, toaddr, sizeof(pident.remote));
b636533b 171
288f4aa9 172 string packet;
29a14b24 173 int ret=MT->waitEvent(pident, &packet, 1);
9170fbaf
BH
174 if(ret > 0) {
175 *d_len=packet.size();
176 memcpy(data,packet.c_str(),min(len,*d_len));
288f4aa9 177 }
9170fbaf 178 return ret;
288f4aa9
BH
179}
180
ce8deb27
BH
181void setReceiveBuffer(int fd, uint32_t size)
182{
183 uint32_t psize;
91e4ecf3 184 socklen_t len=sizeof(psize);
ce8deb27
BH
185 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&psize, &len);
186 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, sizeof(size)) < 0 )
187 L<<Logger::Error<<"Warning: unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<"\n";
188}
189
190
88def049
BH
191static void writePid(void)
192{
2e3d8a19 193 string fname=::arg()["socket-dir"]+"/"+s_programname+".pid";
88def049
BH
194 ofstream of(fname.c_str());
195 if(of)
369369f6 196 of<< getpid() <<endl;
88def049 197 else
562588a3 198 L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
88def049
BH
199}
200
bdf40704 201void primeHints(void)
288f4aa9
BH
202{
203 // prime root cache
288f4aa9 204 set<DNSResourceRecord>nsset;
f814d7c8 205
2e3d8a19 206 if(::arg()["hint-file"].empty()) {
f814d7c8
BH
207 static 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",
208 "192.36.148.17","192.58.128.30", "193.0.14.129", "198.32.64.12", "202.12.27.33"};
209 DNSResourceRecord arr, nsrr;
210 arr.qtype=QType::A;
211 arr.ttl=time(0)+3600000;
212 nsrr.qtype=QType::NS;
213 nsrr.ttl=time(0)+3600000;
214
91e4ecf3 215 for(char c='A';c<='M';++c) {
f814d7c8 216 static char templ[40];
91e4ecf3 217 strncpy(templ,"A.ROOT-SERVERS.NET", sizeof(templ) - 1);
f814d7c8
BH
218 *templ=c;
219 arr.qname=nsrr.content=templ;
91e4ecf3 220 arr.content=ips[c-'A'];
f814d7c8
BH
221 set<DNSResourceRecord> aset;
222 aset.insert(arr);
223 RC.replace(string(templ), QType(QType::A), aset);
224
225 nsset.insert(nsrr);
226 }
227 }
228 else {
2e3d8a19 229 ZoneParserTNG zpt(::arg()["hint-file"]);
f814d7c8 230 DNSResourceRecord rr;
ea634573 231 set<DNSResourceRecord> aset;
288f4aa9 232
f814d7c8 233 while(zpt.get(rr)) {
f814d7c8
BH
234 rr.ttl+=time(0);
235 if(rr.qtype.getCode()==QType::A) {
236 set<DNSResourceRecord> aset;
237 aset.insert(rr);
238 RC.replace(rr.qname, QType(QType::A), aset);
239 }
240 if(rr.qtype.getCode()==QType::NS) {
241 nsset.insert(rr);
242 }
243 }
288f4aa9 244 }
f814d7c8 245 RC.replace("", QType(QType::NS), nsset); // and stuff in the cache
288f4aa9
BH
246}
247
248void startDoResolve(void *p)
249{
250 try {
ea634573 251 DNSComboWriter* dc=(DNSComboWriter *)p;
b636533b 252
10321a98
BH
253 uint16_t maxudpsize=512;
254 MOADNSParser::EDNSOpts edo;
255 if(dc->d_mdp.getEDNSOpts(&edo)) {
256 maxudpsize=edo.d_packetsize;
257 }
258
ea634573 259 vector<DNSResourceRecord> ret;
9170fbaf 260
ea634573
BH
261 vector<uint8_t> packet;
262 DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
263
264 pw.getHeader()->aa=0;
265 pw.getHeader()->ra=1;
c154c8a4 266 pw.getHeader()->qr=1;
ea634573 267 pw.getHeader()->id=dc->d_mdp.d_header.id;
10321a98 268 pw.getHeader()->rd=dc->d_mdp.d_header.rd;
ea634573 269
9170fbaf 270 // MT->setTitle("udp question for "+P.qdomain+"|"+P.qtype.getName());
c9e9e5e0 271 SyncRes sr(dc->d_now);
1d5b3ce6 272 if(!g_quiet)
8a63d3ce
BH
273 L<<Logger::Error<<"["<<MT->getTid()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
274 <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
c75a6a9e 275
fededf47 276 sr.setId(MT->getTid());
ea634573 277 if(!dc->d_mdp.d_header.rd)
c836dc19
BH
278 sr.setCacheOnly();
279
ea634573 280 int res=sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret);
1d5b3ce6 281 if(res<0) {
ea634573 282 pw.getHeader()->rcode=RCode::ServFail;
1d5b3ce6
BH
283 g_stats.servFails++;
284 }
288f4aa9 285 else {
ea634573 286 pw.getHeader()->rcode=res;
1d5b3ce6 287 switch(res) {
5e4a2466
BH
288 case RCode::ServFail:
289 g_stats.servFails++;
290 break;
1d5b3ce6
BH
291 case RCode::NXDomain:
292 g_stats.nxDomains++;
293 break;
294 case RCode::NoError:
295 g_stats.noErrors++;
296 break;
297 }
298
c154c8a4 299 if(ret.size()) {
e67e250f 300 shuffle(ret);
c154c8a4 301 for(vector<DNSResourceRecord>::const_iterator i=ret.begin();i!=ret.end();++i) {
10321a98 302 pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, 1, (DNSPacketWriter::Place)i->d_place);
c154c8a4
BH
303 shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), 1, i->content));
304 drc->toPacket(pw);
10321a98
BH
305 if(!dc->d_tcp && pw.size() > maxudpsize) {
306 pw.rollback();
1791e3c4
BH
307 if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer
308 pw.getHeader()->tc=1;
10321a98
BH
309 goto sendit; // need to jump over pw.commit
310 }
c154c8a4
BH
311 }
312 pw.commit();
ea634573 313 }
288f4aa9 314 }
10321a98 315 sendit:;
ea634573 316 if(!dc->d_tcp) {
ea634573 317 sendto(dc->d_socket, &*packet.begin(), packet.size(), 0, (struct sockaddr *)(dc->d_remote), dc->d_socklen);
feccc9fc 318 }
9c495589
BH
319 else {
320 char buf[2];
ea634573
BH
321 buf[0]=packet.size()/256;
322 buf[1]=packet.size()%256;
feccc9fc
BH
323
324 struct iovec iov[2];
325
ea634573
BH
326 iov[0].iov_base=(void*)buf; iov[0].iov_len=2;
327 iov[1].iov_base=(void*)&*packet.begin(); iov[1].iov_len = packet.size();
feccc9fc 328
ea634573 329 int ret=writev(dc->d_socket, iov, 2);
feccc9fc
BH
330
331 if(ret <= 0 )
a1754c6a 332 L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< (ret ? strerror(errno) : "EOF") <<endl;
ea634573 333 else if((unsigned int)ret != 2 + packet.size())
a1754c6a 334 L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" - probably would have trouble receiving our answer anyhow (size="<<packet.size()<<")"<<endl;
9c495589
BH
335 }
336
9170fbaf 337 // MT->setTitle("DONE! udp question for "+P.qdomain+"|"+P.qtype.getName());
1d5b3ce6 338 if(!g_quiet) {
8a63d3ce 339 L<<Logger::Error<<"["<<MT->getTid()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
ea634573 340 L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
5c633640 341 sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
c75a6a9e
BH
342 }
343
eefd15f9 344 sr.d_outqueries ? RC.cacheMisses++ : RC.cacheHits++;
fe213470
BH
345 float spent=makeFloat(sr.d_now-dc->d_now);
346 if(spent < 0.001)
347 g_stats.answers0_1++;
348 else if(spent < 0.010)
349 g_stats.answers1_10++;
350 else if(spent < 0.1)
351 g_stats.answers10_100++;
352 else if(spent < 1.0)
353 g_stats.answers100_1000++;
354 else
355 g_stats.answersSlow++;
356
574af7ea 357 uint64_t newLat=(uint64_t)(spent*1000000);
87b8e43a
BH
358 if(newLat < 1000000) // outliers of several minutes exist..
359 g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0.0001*newLat);
ea634573 360 delete dc;
288f4aa9
BH
361 }
362 catch(AhuException &ae) {
c836dc19 363 L<<Logger::Error<<"startDoResolve problem: "<<ae.reason<<endl;
288f4aa9 364 }
c154c8a4
BH
365 catch(exception& e) {
366 L<<Logger::Error<<"STL error: "<<e.what()<<endl;
367 }
288f4aa9 368 catch(...) {
c836dc19 369 L<<Logger::Error<<"Any other exception in a resolver context"<<endl;
288f4aa9
BH
370 }
371}
372
1d5b3ce6
BH
373RecursorControlChannel s_rcc;
374
375void makeControlChannelSocket()
376{
377 s_rcc.listen("pdns_recursor.controlsocket");
378}
379
288f4aa9
BH
380void makeClientSocket()
381{
382 d_clientsock=socket(AF_INET, SOCK_DGRAM,0);
383 if(d_clientsock<0)
384 throw AhuException("Making a socket for resolver: "+stringerror());
ce8deb27 385 setReceiveBuffer(d_clientsock, 250000);
288f4aa9
BH
386 struct sockaddr_in sin;
387 memset((char *)&sin,0, sizeof(sin));
388
389 sin.sin_family = AF_INET;
0d189311 390
2e3d8a19
BH
391 if(!IpToU32(::arg()["query-local-address"], &sin.sin_addr.s_addr))
392 throw AhuException("Unable to resolve local address '"+ ::arg()["query-local-address"] +"'");
0d189311 393
288f4aa9
BH
394 int tries=10;
395 while(--tries) {
092f210a 396 uint16_t port=10000+Utility::random()%10000;
288f4aa9
BH
397 sin.sin_port = htons(port);
398
2e3d8a19 399 if (::bind(d_clientsock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
288f4aa9 400 break;
288f4aa9
BH
401
402 }
403 if(!tries)
404 throw AhuException("Resolver binding to local socket: "+stringerror());
976196d2
BH
405
406 Utility::setNonBlocking(d_clientsock);
ce8deb27 407
0d189311 408 L<<Logger::Error<<"Sending UDP queries from "<<inet_ntoa(sin.sin_addr)<<":"<< ntohs(sin.sin_port) <<endl;
288f4aa9
BH
409}
410
f28307ad 411void makeTCPServerSockets()
9c495589 412{
f28307ad 413 vector<string>locals;
2e3d8a19 414 stringtok(locals,::arg()["local-address"]," ,");
9c495589 415
f28307ad
BH
416 if(locals.empty())
417 throw AhuException("No local address specified");
418
f28307ad
BH
419 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
420 int fd=socket(AF_INET, SOCK_STREAM,0);
421 if(fd<0)
422 throw AhuException("Making a server socket for resolver: "+stringerror());
bacc40d9 423
f28307ad
BH
424 struct sockaddr_in sin;
425 memset((char *)&sin,0, sizeof(sin));
426
427 sin.sin_family = AF_INET;
428 if(!IpToU32(*i, &sin.sin_addr.s_addr))
429 throw AhuException("Unable to resolve local address '"+ *i +"'");
430
431 int tmp=1;
432 if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
433 L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
434 exit(1);
435 }
436
2e3d8a19 437 sin.sin_port = htons(::arg().asNum("local-port"));
f28307ad 438
2e3d8a19 439 if (::bind(fd, (struct sockaddr *)&sin, sizeof(sin))<0)
f28307ad
BH
440 throw AhuException("Binding TCP server socket for "+*i+": "+stringerror());
441
442 Utility::setNonBlocking(fd);
443 listen(fd, 128);
cd50f30d 444 s_tcpserversocks.push_back(fd);
2e3d8a19 445 L<<Logger::Error<<"Listening for TCP queries on "<<inet_ntoa(sin.sin_addr)<<":"<<::arg().asNum("local-port")<<endl;
f28307ad 446 }
9c495589
BH
447}
448
f28307ad 449void makeUDPServerSockets()
288f4aa9 450{
f28307ad 451 vector<string>locals;
2e3d8a19 452 stringtok(locals,::arg()["local-address"]," ,");
288f4aa9 453
f28307ad
BH
454 if(locals.empty())
455 throw AhuException("No local address specified");
456
2e3d8a19 457 if(::arg()["local-address"]=="0.0.0.0") {
c836dc19 458 L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
288f4aa9 459 }
525b8a7c 460
f28307ad
BH
461 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
462 int fd=socket(AF_INET, SOCK_DGRAM,0);
463 if(fd<0)
464 throw AhuException("Making a server socket for resolver: "+stringerror());
ce8deb27 465 setReceiveBuffer(fd, 250000);
f28307ad
BH
466 struct sockaddr_in sin;
467 memset((char *)&sin,0, sizeof(sin));
288f4aa9 468
f28307ad
BH
469 sin.sin_family = AF_INET;
470 if(!IpToU32(*i, &sin.sin_addr.s_addr))
471 throw AhuException("Unable to resolve local address '"+ *i +"'");
472
2e3d8a19 473 sin.sin_port = htons(::arg().asNum("local-port"));
f28307ad 474
2e3d8a19 475 if (::bind(fd, (struct sockaddr *)&sin, sizeof(sin))<0)
f28307ad
BH
476 throw AhuException("Resolver binding to server socket for "+*i+": "+stringerror());
477
478 Utility::setNonBlocking(fd);
479 d_udpserversocks.push_back(fd);
2e3d8a19 480 L<<Logger::Error<<"Listening for UDP queries on "<<inet_ntoa(sin.sin_addr)<<":"<<::arg().asNum("local-port")<<endl;
f28307ad 481 }
c836dc19 482}
caa6eefa 483
9c495589 484
caa6eefa 485#ifndef WIN32
c836dc19
BH
486void daemonize(void)
487{
488 if(fork())
489 exit(0); // bye bye
490
491 setsid();
492
493 // cleanup open fds, but skip sockets
494 close(0);
495 close(1);
496 close(2);
288f4aa9 497}
caa6eefa
BH
498#endif
499
1d5b3ce6 500uint64_t counter, qcounter;
c75a6a9e
BH
501bool statsWanted;
502
1d5b3ce6 503
c75a6a9e
BH
504void usr1Handler(int)
505{
506 statsWanted=true;
507}
ae1b2e98 508
c9e9e5e0
BH
509
510
9170fbaf
BH
511void usr2Handler(int)
512{
513 SyncRes::setLog(true);
1d5b3ce6
BH
514 g_quiet=false;
515 ::arg().set("quiet")="no";
c9e9e5e0 516
9170fbaf
BH
517}
518
c75a6a9e
BH
519void doStats(void)
520{
521 if(qcounter) {
eefd15f9 522 L<<Logger::Error<<"stats: "<<qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, "
8a5602d4 523 <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl;
2e3d8a19 524 L<<Logger::Error<<"stats: throttle map: "<<SyncRes::s_throttle.size()<<", ns speeds: "
8cd5b55e 525 <<SyncRes::s_nsSpeeds.size()<<endl; // ", bytes: "<<RC.bytes()<<endl;
8a5602d4 526 L<<Logger::Error<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
525b8a7c
BH
527 L<<Logger::Error<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
528 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
5c633640 529 L<<Logger::Error<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<MT->numProcesses()<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
c75a6a9e 530 }
7becf07f
BH
531 else if(statsWanted)
532 L<<Logger::Error<<"stats: no stats yet!"<<endl;
533
c75a6a9e
BH
534 statsWanted=false;
535}
c836dc19 536
29f0b1ce 537static void houseKeeping(void *)
c836dc19 538{
ae1b2e98 539 static time_t last_stat, last_rootupdate, last_prune;
c9e9e5e0
BH
540 struct timeval now;
541 gettimeofday(&now, 0);
542
543 if(now.tv_sec - last_prune > 60) {
5e4a2466
BH
544 DTime dt;
545 dt.setTimeval(now);
eefd15f9 546 RC.doPrune();
8a5602d4 547 int pruned=0;
2e3d8a19 548 for(SyncRes::negcache_t::iterator i = SyncRes::s_negcache.begin(); i != SyncRes::s_negcache.end();)
27ff08dc 549 if(i->second.ttd < now.tv_sec) {
8a5602d4
BH
550 SyncRes::s_negcache.erase(i++);
551 pruned++;
552 }
553 else
554 ++i;
2e3d8a19 555
c9e9e5e0 556 time_t limit=now.tv_sec-300;
2e3d8a19
BH
557 for(SyncRes::nsspeeds_t::iterator i = SyncRes::s_nsSpeeds.begin() ; i!= SyncRes::s_nsSpeeds.end(); )
558 if(i->second.stale(limit))
559 SyncRes::s_nsSpeeds.erase(i++);
560 else
561 ++i;
562
8a5602d4 563 // cerr<<"Pruned "<<pruned<<" records, left "<<SyncRes::s_negcache.size()<<"\n";
5e4a2466 564// cout<<"Prune took "<<dt.udiff()<<"usec\n";
ae1b2e98
BH
565 last_prune=time(0);
566 }
c9e9e5e0 567 if(now.tv_sec - last_stat>1800) {
c75a6a9e 568 doStats();
c836dc19
BH
569 last_stat=time(0);
570 }
c9e9e5e0
BH
571 if(now.tv_sec -last_rootupdate>7200) {
572 SyncRes sr(now);
ea634573 573 vector<DNSResourceRecord> ret;
c836dc19
BH
574
575 sr.setNoCache();
576 int res=sr.beginResolve("", QType(QType::NS), ret);
577 if(!res) {
578 L<<Logger::Error<<"Refreshed . records"<<endl;
c9e9e5e0 579 last_rootupdate=now.tv_sec;
c836dc19
BH
580 }
581 else
582 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
583 }
584}
288f4aa9 585
9c495589
BH
586struct TCPConnection
587{
588 int fd;
589 enum {BYTE0, BYTE1, GETQUESTION} state;
590 int qlen;
591 int bytesread;
592 struct sockaddr_in remote;
593 char data[65535];
cd50f30d 594 time_t startTime;
9c495589
BH
595};
596
d6d5dea7 597#if 0
d6d5dea7
BH
598#include <execinfo.h>
599
c9e9e5e0
BH
600 multimap<uint32_t,string> rev;
601 for(map<string,uint32_t>::const_iterator i=casesptr->begin(); i!=casesptr->end(); ++i) {
602 rev.insert(make_pair(i->second,i->first));
603 }
604 for(multimap<uint32_t,string>::const_iterator i=rev.begin(); i!= rev.end(); ++i)
605 cout<<i->first<<" times: \n"<<i->second<<"\n";
606
607 cout.flush();
608
609map<string,uint32_t>* casesptr;
610static string maketrace()
d6d5dea7
BH
611{
612 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
613 size_t size;
614 char **strings;
615 size_t i;
616
c9e9e5e0 617 size = backtrace (array, 5);
d6d5dea7
BH
618 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
619
c9e9e5e0
BH
620 string ret;
621
d6d5dea7 622 for (i = 0; i < size; i++) //skip useless functions
c9e9e5e0
BH
623 ret+=string(strings[i])+"\n";
624 return ret;
d6d5dea7
BH
625}
626
627extern "C" {
c9e9e5e0 628
d6d5dea7
BH
629int gettimeofday (struct timeval *__restrict __tv,
630 __timezone_ptr_t __tz)
631{
c9e9e5e0
BH
632 static map<string, uint32_t> s_cases;
633 casesptr=&s_cases;
634 s_cases[maketrace()]++;
635 __tv->tv_sec=time(0);
d6d5dea7
BH
636 return 0;
637}
638
639}
c9e9e5e0 640#endif
d6d5dea7 641
288f4aa9
BH
642int main(int argc, char **argv)
643{
8a63d3ce 644 reportBasicTypes();
ea634573 645
22030c37 646 int ret = EXIT_SUCCESS;
caa6eefa
BH
647#ifdef WIN32
648 WSADATA wsaData;
649 WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
650#endif // WIN32
651
288f4aa9 652 try {
caa6eefa 653 Utility::srandom(time(0));
2e3d8a19
BH
654 ::arg().set("soa-minimum-ttl","Don't change")="0";
655 ::arg().set("soa-serial-offset","Don't change")="0";
656 ::arg().set("no-shuffle","Don't change")="off";
657 ::arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
658 ::arg().set("local-port","port to listen on")="53";
659 ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas")="0.0.0.0";
660 ::arg().set("trace","if we should output heaps of logging")="off";
661 ::arg().set("daemon","Operate as a daemon")="yes";
662 ::arg().set("chroot","switch to chroot jail")="";
663 ::arg().set("setgid","If set, change group id to this gid for more security")="";
664 ::arg().set("setuid","If set, change user id to this uid for more security")="";
665 ::arg().set("quiet","Suppress logging of questions and answers")="true";
666 ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
667 ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
668 ::arg().set("delegation-only","Which domains we only accept delegations from")="";
669 ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
670 ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
671 ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
672 ::arg().set("hint-file", "If set, load root hints from this file")="";
673
674 ::arg().setCmd("help","Provide a helpful message");
c75a6a9e 675 L.toConsole(Logger::Warning);
2e3d8a19 676 ::arg().laxParse(argc,argv); // do a lax parse
c75a6a9e 677
2e3d8a19 678 string configname=::arg()["config-dir"]+"/recursor.conf";
c75a6a9e
BH
679 cleanSlashes(configname);
680
2e3d8a19 681 if(!::arg().file(configname.c_str()))
c75a6a9e
BH
682 L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
683
2e3d8a19 684 ::arg().parse(argc,argv);
c836dc19 685
2e3d8a19 686 ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
562588a3 687
2e3d8a19 688 if(::arg().mustDo("help")) {
b636533b 689 cerr<<"syntax:"<<endl<<endl;
2e3d8a19 690 cerr<<::arg().helpstring(::arg()["help"])<<endl;
b636533b
BH
691 exit(99);
692 }
693
c836dc19 694 L.setName("pdns_recursor");
288f4aa9 695
22c012a8 696 L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
0d189311
BH
697#ifdef __GNUC__
698 L<<", gcc "__VERSION__;
699#endif // add other compilers here
700 L<<") starting up"<<endl;
701
22c012a8 702 L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl;
0d189311
BH
703 L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
704 "This is free software, and you are welcome to redistribute it "
705 "according to the terms of the GPL version 2."<<endl;
706
707
4d0217fc 708 g_quiet=::arg().mustDo("quiet");
2e3d8a19 709 if(::arg().mustDo("trace")) {
7b35aa49 710 SyncRes::setLog(true);
2e3d8a19 711 ::arg().set("quiet")="no";
1d5b3ce6 712 g_quiet=false;
878435ce 713 }
4d0217fc 714
288f4aa9 715 makeClientSocket();
f28307ad
BH
716 makeUDPServerSockets();
717 makeTCPServerSockets();
1d5b3ce6
BH
718 makeControlChannelSocket();
719
fededf47 720 MT=new MTasker<PacketID,string>(100000);
562588a3 721
288f4aa9
BH
722 char data[1500];
723 struct sockaddr_in fromaddr;
724
725 PacketID pident;
bdf40704 726 primeHints();
c836dc19 727 L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
caa6eefa 728#ifndef WIN32
2e3d8a19 729 if(::arg().mustDo("daemon")) {
c836dc19
BH
730 L.toConsole(Logger::Critical);
731 daemonize();
732 }
c75a6a9e 733 signal(SIGUSR1,usr1Handler);
9170fbaf 734 signal(SIGUSR2,usr2Handler);
4389619a 735 signal(SIGPIPE,SIG_IGN);
88def049
BH
736
737 writePid();
caa6eefa 738#endif
c75a6a9e 739
08efacea 740 int newgid=0;
2e3d8a19
BH
741 if(!::arg()["setgid"].empty())
742 newgid=Utility::makeGidNumeric(::arg()["setgid"]);
08efacea 743 int newuid=0;
2e3d8a19
BH
744 if(!::arg()["setuid"].empty())
745 newuid=Utility::makeUidNumeric(::arg()["setuid"]);
08efacea
BH
746
747
2e3d8a19
BH
748 if (!::arg()["chroot"].empty()) {
749 if (chroot(::arg()["chroot"].c_str())<0) {
750 L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
08efacea
BH
751 exit(1);
752 }
753 }
754
755 Utility::dropPrivs(newuid, newgid);
756
9c495589 757 vector<TCPConnection> tcpconnections;
49f076e8 758 counter=0;
c9e9e5e0 759 struct timeval now;
2e3d8a19
BH
760 unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
761 int tcpLimit=::arg().asNum("client-tcp-timeout");
288f4aa9 762 for(;;) {
fededf47 763 while(MT->schedule()); // housekeeping, let threads do their thing
288f4aa9 764
c9e9e5e0 765 if(!((counter++)%500))
9170fbaf 766 MT->makeThread(houseKeeping,0,"housekeeping");
f9f05db4 767 if(statsWanted) {
c75a6a9e 768 doStats();
f9f05db4 769 }
c836dc19 770
caa6eefa 771 Utility::socklen_t addrlen=sizeof(fromaddr);
288f4aa9 772 int d_len;
288f4aa9
BH
773
774 struct timeval tv;
775 tv.tv_sec=0;
776 tv.tv_usec=500000;
777
5c633640 778 fd_set readfds, writefds;
288f4aa9 779 FD_ZERO( &readfds );
5c633640 780 FD_ZERO( &writefds );
288f4aa9 781 FD_SET( d_clientsock, &readfds );
1d5b3ce6
BH
782 FD_SET( s_rcc.d_fd, &readfds);
783 int fdmax=max(d_clientsock, s_rcc.d_fd);
f28307ad 784
cd50f30d 785 if(!tcpconnections.empty())
c9e9e5e0 786 gettimeofday(&now, 0);
cd50f30d
BH
787
788 vector<TCPConnection> sweeped;
2e3d8a19 789
cd50f30d 790 for(vector<TCPConnection>::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) {
c9e9e5e0 791 if(now.tv_sec < i->startTime + tcpLimit) {
cd50f30d
BH
792 FD_SET(i->fd, &readfds);
793 fdmax=max(fdmax,i->fd);
794 sweeped.push_back(*i);
795 }
796 else {
797 L<<Logger::Error<<"TCP timeout from client "<<inet_ntoa(i->remote.sin_addr)<<endl;
798 close(i->fd);
799 }
9c495589 800 }
cd50f30d
BH
801 sweeped.swap(tcpconnections);
802
f28307ad
BH
803 for(vector<int>::const_iterator i=d_udpserversocks.begin(); i!=d_udpserversocks.end(); ++i) {
804 FD_SET( *i, &readfds );
805 fdmax=max(fdmax,*i);
806 }
cd50f30d
BH
807 if(tcpconnections.size() < maxTcpClients)
808 for(tcpserversocks_t::const_iterator i=s_tcpserversocks.begin(); i!=s_tcpserversocks.end(); ++i) {
809 FD_SET(*i, &readfds );
810 fdmax=max(fdmax,*i);
811 }
812
5c633640
BH
813 for(map<int,PacketID>::const_iterator i=d_tcpclientreadsocks.begin(); i!=d_tcpclientreadsocks.end(); ++i) {
814 // cerr<<"Adding TCP socket "<<i->first<<" to read select set"<<endl;
815 FD_SET( i->first, &readfds );
816 fdmax=max(fdmax,i->first);
817 }
818
819 for(map<int,PacketID>::const_iterator i=d_tcpclientwritesocks.begin(); i!=d_tcpclientwritesocks.end(); ++i) {
820 // cerr<<"Adding TCP socket "<<i->first<<" to write select set"<<endl;
821 FD_SET( i->first, &writefds );
822 fdmax=max(fdmax,i->first);
823 }
8d022964 824
5c633640 825 int selret = select( fdmax + 1, &readfds, &writefds, NULL, &tv );
c9e9e5e0 826 gettimeofday(&now, 0);
c75a6a9e
BH
827 if(selret<=0)
828 if (selret == -1 && errno!=EINTR)
288f4aa9 829 throw AhuException("Select returned: "+stringerror());
c75a6a9e
BH
830 else
831 continue;
832
1d5b3ce6
BH
833 if(FD_ISSET(s_rcc.d_fd, &readfds)) {
834 string remote;
835 string msg=s_rcc.recv(&remote);
836 RecursorControlParser rcp;
837 s_rcc.send(rcp.getAnswer(msg), &remote);
838 }
839
369369f6 840 if(FD_ISSET(d_clientsock,&readfds)) { // do we have a UDP question response?
288f4aa9 841 d_len=recvfrom(d_clientsock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
c836dc19 842 if(d_len<0)
288f4aa9 843 continue;
ea634573
BH
844
845 try {
c9e9e5e0 846 DNSComboWriter dc(data, d_len, now);
ea634573
BH
847 dc.setRemote((struct sockaddr *)&fromaddr, addrlen);
848
849 if(dc.d_mdp.d_header.qr) {
288f4aa9 850 pident.remote=fromaddr;
ea634573 851 pident.id=dc.d_mdp.d_header.id;
c836dc19 852 string packet;
ea634573
BH
853 packet.assign(data, d_len);
854 MT->sendEvent(pident, &packet);
288f4aa9
BH
855 }
856 else
a1754c6a 857 L<<Logger::Warning<<"Ignoring question on outgoing socket from "<<dc.getRemote()<<endl;
ea634573
BH
858 }
859 catch(MOADNSException& mde) {
a1754c6a 860 L<<Logger::Error<<"Unparseable packet from remote server "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen) <<": "<<mde.what()<<endl;
288f4aa9
BH
861 }
862 }
863
f28307ad
BH
864 for(vector<int>::const_iterator i=d_udpserversocks.begin(); i!=d_udpserversocks.end(); ++i) {
865 if(FD_ISSET(*i,&readfds)) { // do we have a new question on udp?
866 d_len=recvfrom(*i, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
867 if(d_len<0)
868 continue;
ea634573 869
c9e9e5e0
BH
870 g_stats.queryrate.pulse(now);
871
de1890b2 872 try {
c9e9e5e0 873 DNSComboWriter* dc = new DNSComboWriter(data, d_len, now);
de1890b2
BH
874
875 dc->setRemote((struct sockaddr *)&fromaddr, addrlen);
876
877 if(dc->d_mdp.d_header.qr)
878 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
879 else {
880 ++qcounter;
881 dc->setSocket(*i);
882 dc->d_tcp=false;
883 MT->makeThread(startDoResolve, (void*) dc, "udp");
884 }
885 }
886 catch(MOADNSException& mde) {
887 L<<Logger::Error<<"Unparseable packet from remote server "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen) <<": "<<mde.what()<<endl;
288f4aa9
BH
888 }
889 }
890 }
9c495589 891
cd50f30d 892 for(tcpserversocks_t::const_iterator i=s_tcpserversocks.begin(); i!=s_tcpserversocks.end(); ++i) {
369369f6 893 if(FD_ISSET(*i ,&readfds)) { // do we have a new TCP connection?
f28307ad
BH
894 struct sockaddr_in addr;
895 socklen_t addrlen=sizeof(addr);
896 int newsock=accept(*i, (struct sockaddr*)&addr, &addrlen);
897
898 if(newsock>0) {
899 Utility::setNonBlocking(newsock);
900 TCPConnection tc;
901 tc.fd=newsock;
902 tc.state=TCPConnection::BYTE0;
903 tc.remote=addr;
c9e9e5e0 904 tc.startTime=now.tv_sec;
f28307ad
BH
905 tcpconnections.push_back(tc);
906 }
9c495589
BH
907 }
908 }
909
369369f6 910 // have any question answers come in over TCP?
5c633640 911 for(map<int,PacketID>::iterator i=d_tcpclientreadsocks.begin(); i!=d_tcpclientreadsocks.end();) {
72df400f 912 bool haveErased=false;
5c633640 913 if(FD_ISSET(i->first, &readfds)) { // can we receive
72df400f
BH
914 shared_array<char> buffer(new char[i->second.inNeeded]);
915
916 int ret=read(i->first, buffer.get(), min(i->second.inNeeded,200));
5c633640
BH
917 // cerr<<"Read returned "<<ret<<endl;
918 if(ret > 0) {
72df400f 919 i->second.inMSG.append(&buffer[0], &buffer[ret]);
5c633640
BH
920 i->second.inNeeded-=ret;
921 if(!i->second.inNeeded) {
922 // cerr<<"Got entire load of "<<i->second.inMSG.size()<<" bytes"<<endl;
923 PacketID pid=i->second;
924 string msg=i->second.inMSG;
925
926 d_tcpclientreadsocks.erase((i++));
72df400f 927 haveErased=true;
5c633640
BH
928 MT->sendEvent(pid, &msg); // XXX DODGY
929 }
930 else {
931 // cerr<<"Still have "<<i->second.inNeeded<<" left to go"<<endl;
5c633640
BH
932 }
933 }
934 else {
9170fbaf
BH
935 // cerr<<"when reading ret="<<ret<<endl;
936 // XXX FIXME I think some stuff needs to happen here - like send an EOF event
5c633640
BH
937 }
938 }
72df400f 939 if(!haveErased)
5c633640 940 ++i;
5c633640 941 }
369369f6
BH
942
943 // is there data we can send to remote nameservers over TCP?
5c633640 944 for(map<int,PacketID>::iterator i=d_tcpclientwritesocks.begin(); i!=d_tcpclientwritesocks.end(); ) {
72df400f 945 bool haveErased=false;
5c633640
BH
946 if(FD_ISSET(i->first, &writefds)) { // can we send over TCP
947 // cerr<<"Socket "<<i->first<<" available for writing"<<endl;
948 int ret=write(i->first, i->second.outMSG.c_str(), i->second.outMSG.size() - i->second.outPos);
949 if(ret > 0) {
950 i->second.outPos+=ret;
951 if(i->second.outPos==i->second.outMSG.size()) {
952 // cerr<<"Sent out entire load of "<<i->second.outMSG.size()<<" bytes"<<endl;
953 PacketID pid=i->second;
369369f6 954 d_tcpclientwritesocks.erase(i++); // erase!
72df400f 955 haveErased=true;
369369f6 956 MT->sendEvent(pid, 0);
5c633640 957 }
72df400f 958
5c633640
BH
959 }
960 else {
9170fbaf
BH
961 // cerr<<"ret="<<ret<<" when writing"<<endl;
962 // XXX FIXME I think some stuff needs to happen here - like send an EOF event
5c633640
BH
963 }
964 }
72df400f 965 if(!haveErased)
5c633640
BH
966 ++i;
967 }
369369f6
BH
968
969 // very braindead TCP incoming question parser
9c495589
BH
970 for(vector<TCPConnection>::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) {
971 if(FD_ISSET(i->fd, &readfds)) {
972 if(i->state==TCPConnection::BYTE0) {
973 int bytes=read(i->fd,i->data,2);
974 if(bytes==1)
975 i->state=TCPConnection::BYTE1;
976 if(bytes==2) {
977 i->qlen=(i->data[0]<<8)+i->data[1];
978 i->bytesread=0;
979 i->state=TCPConnection::GETQUESTION;
980 }
981 if(!bytes || bytes < 0) {
9c495589
BH
982 close(i->fd);
983 tcpconnections.erase(i);
984 break;
985 }
986 }
987 else if(i->state==TCPConnection::BYTE1) {
988 int bytes=read(i->fd,i->data+1,1);
989 if(bytes==1) {
990 i->state=TCPConnection::GETQUESTION;
991 i->qlen=(i->data[0]<<8)+i->data[1];
992 i->bytesread=0;
993 }
994 if(!bytes || bytes < 0) {
995 L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected after first byte"<<endl;
996 close(i->fd);
997 tcpconnections.erase(i);
998 break;
999 }
1000
1001 }
1002 else if(i->state==TCPConnection::GETQUESTION) {
1003 int bytes=read(i->fd,i->data + i->bytesread,i->qlen - i->bytesread);
1004 if(!bytes || bytes < 0) {
1005 L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected while reading question body"<<endl;
1006 close(i->fd);
1007 tcpconnections.erase(i);
1008 break;
1009 }
1010 i->bytesread+=bytes;
1011 if(i->bytesread==i->qlen) {
1012 i->state=TCPConnection::BYTE0;
a1754c6a 1013 DNSComboWriter* dc=0;
ea634573 1014 try {
c9e9e5e0 1015 dc=new DNSComboWriter(i->data, i->qlen, now);
ea634573
BH
1016 }
1017 catch(MOADNSException &mde) {
a1754c6a 1018 L<<Logger::Error<<"Unparseable packet from remote client "<<sockAddrToString(&i->remote,sizeof(i->remote))<<endl;
9c495589
BH
1019 close(i->fd);
1020 tcpconnections.erase(i);
1021 break;
1022 }
ea634573
BH
1023
1024 dc->setSocket(i->fd);
1025 dc->d_tcp=true;
1026 dc->setRemote((struct sockaddr *)&i->remote,sizeof(i->remote));
1027 if(dc->d_mdp.d_header.qr)
1028 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
1029 else {
1030 ++qcounter;
1031 MT->makeThread(startDoResolve, dc, "tcp");
9c495589
BH
1032 }
1033 }
1034 }
1035 }
1036 }
288f4aa9
BH
1037 }
1038 }
1039 catch(AhuException &ae) {
c836dc19 1040 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
22030c37 1041 ret=EXIT_FAILURE;
288f4aa9
BH
1042 }
1043 catch(exception &e) {
c836dc19 1044 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
22030c37 1045 ret=EXIT_FAILURE;
288f4aa9
BH
1046 }
1047 catch(...) {
c836dc19 1048 L<<Logger::Error<<"any other exception in main: "<<endl;
22030c37 1049 ret=EXIT_FAILURE;
288f4aa9 1050 }
caa6eefa
BH
1051
1052#ifdef WIN32
1053 WSACleanup();
1054#endif // WIN32
1055
22030c37 1056 return ret;
288f4aa9 1057}