]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pdns_recursor.cc
remove some more time(0) calls
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
CommitLineData
288f4aa9
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
36c5ee42 3 Copyright (C) 2005 PowerDNS.COM BV
288f4aa9
BH
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
caa6eefa
BH
19
20#include "utility.hh"
288f4aa9
BH
21#include <iostream>
22#include <errno.h>
23#include <map>
24#include <set>
caa6eefa 25#ifndef WIN32
288f4aa9 26#include <netdb.h>
caa6eefa 27#endif // WIN32
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>
eefd15f9
BH
40#include "recursor_cache.hh"
41
27adc173 42#ifdef __FreeBSD__ // see cvstrac ticket #26
7f617eb9
BH
43#include <pthread.h>
44#include <semaphore.h>
45#endif
46
eefd15f9 47MemRecursorCache RC;
88def049
BH
48
49string s_programname="pdns_recursor";
288f4aa9 50
27adc173
BH
51#ifndef WIN32
52#ifndef __FreeBSD__
288f4aa9
BH
53extern "C" {
54 int sem_init(sem_t*, int, unsigned int){return 0;}
55 int sem_wait(sem_t*){return 0;}
56 int sem_trywait(sem_t*){return 0;}
57 int sem_post(sem_t*){return 0;}
58 int sem_getvalue(sem_t*, int*){return 0;}
dcf9bd8f 59 pthread_t pthread_self(void){return (pthread_t) 0;}
98e05fce 60 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr){ return 0; }
dcf9bd8f
BH
61 int pthread_mutex_lock(pthread_mutex_t *mutex){ return 0; }
62 int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
98e05fce 63
288f4aa9 64}
27adc173 65#endif // __FreeBSD__
caa6eefa 66#endif // WIN32
288f4aa9
BH
67
68StatBag S;
69ArgvMap &arg()
70{
71 static ArgvMap theArg;
72 return theArg;
73}
bacc40d9
BH
74static int d_clientsock;
75static int d_serversock;
76static int d_tcpserversock;
288f4aa9
BH
77
78struct PacketID
79{
80 u_int16_t id;
81 struct sockaddr_in remote;
82};
83
84bool operator<(const PacketID& a, const PacketID& b)
85{
86 if(a.id<b.id)
87 return true;
88
89 if(a.id==b.id) {
90 if(a.remote.sin_addr.s_addr < b.remote.sin_addr.s_addr)
91 return true;
92 if(a.remote.sin_addr.s_addr == b.remote.sin_addr.s_addr)
93 if(a.remote.sin_port < b.remote.sin_port)
94 return true;
95 }
96
97 return false;
98}
99
fededf47 100MTasker<PacketID,string>* MT;
288f4aa9
BH
101
102/* these two functions are used by LWRes */
103int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int addrlen, int id)
104{
105 return sendto(d_clientsock, data, len, flags, toaddr, addrlen);
106}
107
caa6eefa 108int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id)
288f4aa9
BH
109{
110 PacketID pident;
111 pident.id=id;
112 memcpy(&pident.remote,toaddr,sizeof(pident.remote));
b636533b 113
288f4aa9 114 string packet;
fededf47 115 if(!MT->waitEvent(pident,&packet,1)) { // timeout
288f4aa9
BH
116 return 0;
117 }
118
119 *d_len=packet.size();
120 memcpy(data,packet.c_str(),min(len,*d_len));
121
122 return 1;
123}
124
c75a6a9e 125
ae1b2e98
BH
126
127
88def049
BH
128static void writePid(void)
129{
130 string fname=arg()["socket-dir"]+"/"+s_programname+".pid";
131 ofstream of(fname.c_str());
132 if(of)
133 of<<getpid()<<endl;
134 else
562588a3 135 L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
88def049
BH
136}
137
bdf40704 138void primeHints(void)
288f4aa9
BH
139{
140 // prime root cache
49f076e8
BH
141
142 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",
c75a6a9e 143 "192.36.148.17","192.58.128.30", "193.0.14.129", "198.32.64.12", "202.12.27.33"};
288f4aa9
BH
144 DNSResourceRecord arr, nsrr;
145 arr.qtype=QType::A;
146 arr.ttl=time(0)+3600000;
147 nsrr.qtype=QType::NS;
148 nsrr.ttl=time(0)+3600000;
149
150 set<DNSResourceRecord>nsset;
151 for(char c='a';c<='m';++c) {
152 static char templ[40];
153 strncpy(templ,"a.root-servers.net", sizeof(templ) - 1);
154 *templ=c;
155 arr.qname=nsrr.content=templ;
156 arr.content=ips[c-'a'];
157 set<DNSResourceRecord>aset;
158 aset.insert(arr);
eefd15f9 159 RC.replace(string(templ),QType(QType::A),aset);
288f4aa9
BH
160
161 nsset.insert(nsrr);
162 }
eefd15f9 163 RC.replace("",QType(QType::NS),nsset);
288f4aa9
BH
164}
165
166void startDoResolve(void *p)
167{
168 try {
c75a6a9e 169 bool quiet=arg().mustDo("quiet");
288f4aa9 170 DNSPacket P=*(DNSPacket *)p;
b636533b 171
288f4aa9 172 delete (DNSPacket *)p;
b636533b 173
288f4aa9
BH
174 vector<DNSResourceRecord>ret;
175 DNSPacket *R=P.replyPacket();
176 R->setA(false);
177 R->setRA(true);
178
7b35aa49 179 SyncRes sr;
c75a6a9e 180 if(!quiet)
fededf47 181 L<<Logger::Error<<"["<<MT->getTid()<<"] question for '"<<P.qdomain<<"|"<<P.qtype.getName()<<"' from "<<P.getRemote()<<endl;
c75a6a9e 182
fededf47 183 sr.setId(MT->getTid());
c836dc19
BH
184 if(!P.d.rd)
185 sr.setCacheOnly();
186
288f4aa9
BH
187 int res=sr.beginResolve(P.qdomain, P.qtype, ret);
188 if(res<0)
189 R->setRcode(RCode::ServFail);
190 else {
191 R->setRcode(res);
192 for(vector<DNSResourceRecord>::const_iterator i=ret.begin();i!=ret.end();++i)
193 R->addRecord(*i);
194 }
195
196 const char *buffer=R->getData();
9c495589
BH
197 if(!R->getSocket())
198 sendto(d_serversock,buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen);
199 else {
200 char buf[2];
201 buf[0]=R->len/256;
202 buf[1]=R->len%256;
203 if(write(R->getSocket(),buf,2)!=2 || write(R->getSocket(),buffer,R->len)!=R->len)
204 L<<Logger::Error<<"Oops, partial answer sent to "<<P.getRemote()<<" - probably would have trouble receiving our answer anyhow (size="<<R->len<<")"<<endl;
205 }
206
c75a6a9e 207 if(!quiet) {
fededf47 208 L<<Logger::Error<<"["<<MT->getTid()<<"] answer to "<<(P.d.rd?"":"non-rd ")<<"question '"<<P.qdomain<<"|"<<P.qtype.getName();
3de83124 209 L<<"': "<<ntohs(R->d.ancount)<<" answers, "<<ntohs(R->d.arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
d77df2e1 210 sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, rcode="<<res<<endl;
c75a6a9e
BH
211 }
212
eefd15f9 213 sr.d_outqueries ? RC.cacheMisses++ : RC.cacheHits++;
b636533b 214
288f4aa9
BH
215 delete R;
216 }
217 catch(AhuException &ae) {
c836dc19 218 L<<Logger::Error<<"startDoResolve problem: "<<ae.reason<<endl;
288f4aa9
BH
219 }
220 catch(...) {
c836dc19 221 L<<Logger::Error<<"Any other exception in a resolver context"<<endl;
288f4aa9
BH
222 }
223}
224
225void makeClientSocket()
226{
227 d_clientsock=socket(AF_INET, SOCK_DGRAM,0);
228 if(d_clientsock<0)
229 throw AhuException("Making a socket for resolver: "+stringerror());
230
231 struct sockaddr_in sin;
232 memset((char *)&sin,0, sizeof(sin));
233
234 sin.sin_family = AF_INET;
235 sin.sin_addr.s_addr = INADDR_ANY;
236
237 int tries=10;
238 while(--tries) {
caa6eefa 239 u_int16_t port=10000+Utility::random()%10000;
288f4aa9
BH
240 sin.sin_port = htons(port);
241
c836dc19 242 if (bind(d_clientsock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
288f4aa9 243 break;
288f4aa9
BH
244
245 }
246 if(!tries)
247 throw AhuException("Resolver binding to local socket: "+stringerror());
976196d2
BH
248
249 Utility::setNonBlocking(d_clientsock);
288f4aa9
BH
250}
251
9c495589
BH
252void makeTCPServerSocket()
253{
254 d_tcpserversock=socket(AF_INET, SOCK_STREAM,0);
255 if(d_tcpserversock<0)
256 throw AhuException("Making a server socket for resolver: "+stringerror());
257
258 struct sockaddr_in sin;
259 memset((char *)&sin,0, sizeof(sin));
260
261 sin.sin_family = AF_INET;
262
263 if(arg()["local-address"]=="0.0.0.0") {
264 sin.sin_addr.s_addr = INADDR_ANY;
265 }
266 else {
525b8a7c 267 if(!IpToU32(arg()["local-address"], &sin.sin_addr.s_addr))
9c495589 268 throw AhuException("Unable to resolve local address");
9c495589
BH
269 }
270
271 sin.sin_port = htons(arg().asNum("local-port"));
bacc40d9 272
9c495589
BH
273 int tmp=1;
274 if(setsockopt(d_tcpserversock,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
275 L<<Logger::Error<<"Setsockopt failed"<<endl;
276 exit(1);
277 }
bacc40d9
BH
278
279 if (bind(d_tcpserversock, (struct sockaddr *)&sin, sizeof(sin))<0)
280 throw AhuException("TCP Resolver binding to server socket: "+stringerror());
281
282
283 Utility::setNonBlocking(d_tcpserversock);
9c495589
BH
284
285 listen(d_tcpserversock, 128);
286}
287
288f4aa9
BH
288void makeServerSocket()
289{
290 d_serversock=socket(AF_INET, SOCK_DGRAM,0);
291 if(d_serversock<0)
292 throw AhuException("Making a server socket for resolver: "+stringerror());
293
294 struct sockaddr_in sin;
295 memset((char *)&sin,0, sizeof(sin));
296
297 sin.sin_family = AF_INET;
298
299 if(arg()["local-address"]=="0.0.0.0") {
c836dc19 300 L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
288f4aa9
BH
301 sin.sin_addr.s_addr = INADDR_ANY;
302 }
303 else {
288f4aa9 304
525b8a7c
BH
305 if(!IpToU32(arg()["local-address"], &sin.sin_addr.s_addr))
306 throw AhuException("Unable to resolve local address");
307
288f4aa9
BH
308 }
309
310 sin.sin_port = htons(arg().asNum("local-port"));
311
312 if (bind(d_serversock, (struct sockaddr *)&sin, sizeof(sin))<0)
313 throw AhuException("Resolver binding to server socket: "+stringerror());
bacc40d9
BH
314
315 Utility::setNonBlocking(d_serversock);
316
c836dc19
BH
317 L<<Logger::Error<<"Incoming query source port: "<<arg().asNum("local-port")<<endl;
318}
caa6eefa 319
9c495589 320
caa6eefa 321#ifndef WIN32
c836dc19
BH
322void daemonize(void)
323{
324 if(fork())
325 exit(0); // bye bye
326
327 setsid();
328
329 // cleanup open fds, but skip sockets
330 close(0);
331 close(1);
332 close(2);
333
288f4aa9 334}
caa6eefa
BH
335#endif
336
c836dc19 337int counter, qcounter;
c75a6a9e
BH
338bool statsWanted;
339
340void usr1Handler(int)
341{
342 statsWanted=true;
343}
ae1b2e98
BH
344
345
c75a6a9e
BH
346void doStats(void)
347{
348 if(qcounter) {
eefd15f9
BH
349
350 L<<Logger::Error<<"stats: "<<qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, "
351 <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits";
3de83124 352 L<<Logger::Error<<", outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
525b8a7c
BH
353 L<<Logger::Error<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
354 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
e5d684f9 355 L<<Logger::Error<<"queries running: "<<MT->numProcesses()<<endl;
eefd15f9 356
c75a6a9e
BH
357 }
358 statsWanted=false;
359}
c836dc19
BH
360
361void houseKeeping(void *)
362{
ae1b2e98 363 static time_t last_stat, last_rootupdate, last_prune;
36c5ee42
BH
364 time_t now=time(0);
365 if(now - last_stat>60) {
eefd15f9 366 RC.doPrune();
ae1b2e98
BH
367 last_prune=time(0);
368 }
36c5ee42 369 if(now - last_stat>1800) {
c75a6a9e 370 doStats();
c836dc19
BH
371 last_stat=time(0);
372 }
36c5ee42 373 if(now -last_rootupdate>7200) {
7b35aa49 374 SyncRes sr;
c836dc19
BH
375 vector<DNSResourceRecord>ret;
376
377 sr.setNoCache();
378 int res=sr.beginResolve("", QType(QType::NS), ret);
379 if(!res) {
380 L<<Logger::Error<<"Refreshed . records"<<endl;
36c5ee42 381 last_rootupdate=now;
c836dc19
BH
382 }
383 else
384 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
385 }
386}
288f4aa9 387
9c495589
BH
388struct TCPConnection
389{
390 int fd;
391 enum {BYTE0, BYTE1, GETQUESTION} state;
392 int qlen;
393 int bytesread;
394 struct sockaddr_in remote;
395 char data[65535];
396};
397
288f4aa9
BH
398int main(int argc, char **argv)
399{
caa6eefa
BH
400#ifdef WIN32
401 WSADATA wsaData;
402 WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
403#endif // WIN32
404
288f4aa9 405 try {
caa6eefa 406 Utility::srandom(time(0));
b636533b
BH
407 arg().set("soa-minimum-ttl","Don't change")="0";
408 arg().set("soa-serial-offset","Don't change")="0";
87da00e7 409 arg().set("no-shuffle","Don't change")="off";
b636533b 410 arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
c75a6a9e 411 arg().set("local-port","port to listen on")="53";
ba7b2cb5 412 arg().set("local-address","single address to listen on")="0.0.0.0";
7b35aa49 413 arg().set("trace","if we should output heaps of logging")="off";
c75a6a9e
BH
414 arg().set("daemon","Operate as a daemon")="yes";
415 arg().set("quiet","Suppress logging of questions and answers")="off";
416 arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
88def049 417 arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
562588a3 418 arg().set("delegation-only","Which domains we only accept delegations from")="";
b636533b 419 arg().setCmd("help","Provide a helpful message");
c75a6a9e
BH
420 L.toConsole(Logger::Warning);
421 arg().laxParse(argc,argv); // do a lax parse
422
423 string configname=arg()["config-dir"]+"/recursor.conf";
424 cleanSlashes(configname);
425
426 if(!arg().file(configname.c_str()))
427 L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
428
429 arg().parse(argc,argv);
c836dc19 430
562588a3
BH
431 arg().set("delegation-only")=toLower(arg()["delegation-only"]);
432
b636533b
BH
433 if(arg().mustDo("help")) {
434 cerr<<"syntax:"<<endl<<endl;
435 cerr<<arg().helpstring(arg()["help"])<<endl;
436 exit(99);
437 }
438
c836dc19 439 L.setName("pdns_recursor");
288f4aa9 440
c836dc19 441 if(arg().mustDo("trace"))
7b35aa49 442 SyncRes::setLog(true);
288f4aa9
BH
443
444 makeClientSocket();
445 makeServerSocket();
9c495589 446 makeTCPServerSocket();
288f4aa9 447
fededf47 448 MT=new MTasker<PacketID,string>(100000);
562588a3 449
288f4aa9
BH
450 char data[1500];
451 struct sockaddr_in fromaddr;
452
453 PacketID pident;
bdf40704 454 primeHints();
c836dc19 455 L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
caa6eefa 456#ifndef WIN32
c836dc19
BH
457 if(arg().mustDo("daemon")) {
458 L.toConsole(Logger::Critical);
459 daemonize();
460 }
c75a6a9e 461 signal(SIGUSR1,usr1Handler);
88def049
BH
462
463 writePid();
caa6eefa 464#endif
c75a6a9e 465
9c495589 466 vector<TCPConnection> tcpconnections;
49f076e8 467 counter=0;
288f4aa9 468 for(;;) {
fededf47 469 while(MT->schedule()); // housekeeping, let threads do their thing
288f4aa9 470
c75a6a9e 471 if(!((counter++)%100))
fededf47 472 MT->makeThread(houseKeeping,0);
c75a6a9e
BH
473 if(statsWanted)
474 doStats();
c836dc19 475
caa6eefa 476 Utility::socklen_t addrlen=sizeof(fromaddr);
288f4aa9
BH
477 int d_len;
478 DNSPacket P;
479
480 struct timeval tv;
481 tv.tv_sec=0;
482 tv.tv_usec=500000;
483
484 fd_set readfds;
485 FD_ZERO( &readfds );
486 FD_SET( d_clientsock, &readfds );
487 FD_SET( d_serversock, &readfds );
9c495589
BH
488 FD_SET( d_tcpserversock, &readfds );
489 int fdmax=max(d_tcpserversock,max(d_clientsock,d_serversock));
490 for(vector<TCPConnection>::const_iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) {
491 FD_SET(i->fd, &readfds);
492 fdmax=max(fdmax,i->fd);
493 }
8d022964 494
8d022964 495 /* this should listen on a TCP port as well for new connections, */
9c495589 496 int selret = select( fdmax + 1, &readfds, NULL, NULL, &tv );
c75a6a9e
BH
497 if(selret<=0)
498 if (selret == -1 && errno!=EINTR)
288f4aa9 499 throw AhuException("Select returned: "+stringerror());
c75a6a9e
BH
500 else
501 continue;
502
288f4aa9
BH
503 if(FD_ISSET(d_clientsock,&readfds)) { // do we have a question response?
504 d_len=recvfrom(d_clientsock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
c836dc19 505 if(d_len<0)
288f4aa9 506 continue;
288f4aa9
BH
507
508 P.setRemote((struct sockaddr *)&fromaddr, addrlen);
509 if(P.parse(data,d_len)<0) {
c836dc19 510 L<<Logger::Error<<"Unparseable packet from remote server "<<P.getRemote()<<endl;
288f4aa9
BH
511 }
512 else {
513 if(P.d.qr) {
c836dc19 514
288f4aa9
BH
515 pident.remote=fromaddr;
516 pident.id=P.d.id;
c836dc19
BH
517 string packet;
518 packet.assign(data,d_len);
fededf47 519 MT->sendEvent(pident,&packet);
288f4aa9
BH
520 }
521 else
c836dc19 522 L<<Logger::Warning<<"Ignoring question on outgoing socket from "<<P.getRemote()<<endl;
288f4aa9
BH
523 }
524 }
525
9c495589 526 if(FD_ISSET(d_serversock,&readfds)) { // do we have a new question on udp?
288f4aa9 527 d_len=recvfrom(d_serversock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
c836dc19 528 if(d_len<0)
288f4aa9 529 continue;
288f4aa9
BH
530 P.setRemote((struct sockaddr *)&fromaddr, addrlen);
531 if(P.parse(data,d_len)<0) {
c836dc19 532 L<<Logger::Error<<"Unparseable packet from remote client "<<P.getRemote()<<endl;
288f4aa9
BH
533 }
534 else {
535 if(P.d.qr)
c836dc19 536 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
288f4aa9 537 else {
c836dc19 538 ++qcounter;
9c495589 539 P.setSocket(0);
fededf47 540 MT->makeThread(startDoResolve,(void*)new DNSPacket(P));
c836dc19 541
288f4aa9
BH
542 }
543 }
544 }
9c495589
BH
545
546 if(FD_ISSET(d_tcpserversock,&readfds)) { // do we have a new TCP connection
547 struct sockaddr_in addr;
548 socklen_t addrlen=sizeof(addr);
549 int newsock=accept(d_tcpserversock, (struct sockaddr*)&addr, &addrlen);
bacc40d9 550
9c495589 551 if(newsock>0) {
bacc40d9 552 Utility::setNonBlocking(newsock);
9c495589
BH
553 TCPConnection tc;
554 tc.fd=newsock;
555 tc.state=TCPConnection::BYTE0;
556 tc.remote=addr;
9c495589
BH
557 tcpconnections.push_back(tc);
558 }
559 }
560
561 for(vector<TCPConnection>::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) {
562 if(FD_ISSET(i->fd, &readfds)) {
563 if(i->state==TCPConnection::BYTE0) {
564 int bytes=read(i->fd,i->data,2);
565 if(bytes==1)
566 i->state=TCPConnection::BYTE1;
567 if(bytes==2) {
568 i->qlen=(i->data[0]<<8)+i->data[1];
569 i->bytesread=0;
570 i->state=TCPConnection::GETQUESTION;
571 }
572 if(!bytes || bytes < 0) {
9c495589
BH
573 close(i->fd);
574 tcpconnections.erase(i);
575 break;
576 }
577 }
578 else if(i->state==TCPConnection::BYTE1) {
579 int bytes=read(i->fd,i->data+1,1);
580 if(bytes==1) {
581 i->state=TCPConnection::GETQUESTION;
582 i->qlen=(i->data[0]<<8)+i->data[1];
583 i->bytesread=0;
584 }
585 if(!bytes || bytes < 0) {
586 L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected after first byte"<<endl;
587 close(i->fd);
588 tcpconnections.erase(i);
589 break;
590 }
591
592 }
593 else if(i->state==TCPConnection::GETQUESTION) {
594 int bytes=read(i->fd,i->data + i->bytesread,i->qlen - i->bytesread);
595 if(!bytes || bytes < 0) {
596 L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected while reading question body"<<endl;
597 close(i->fd);
598 tcpconnections.erase(i);
599 break;
600 }
601 i->bytesread+=bytes;
602 if(i->bytesread==i->qlen) {
603 i->state=TCPConnection::BYTE0;
604
605 if(P.parse(i->data,i->qlen)<0) {
606 L<<Logger::Error<<"Unparseable packet from remote client "<<P.getRemote()<<endl;
607 close(i->fd);
608 tcpconnections.erase(i);
609 break;
610 }
611 else {
612 P.setSocket(i->fd);
613 P.setRemote((struct sockaddr *)&i->remote,sizeof(i->remote));
614 if(P.d.qr)
615 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
616 else {
617 ++qcounter;
fededf47 618 MT->makeThread(startDoResolve,(void*)new DNSPacket(P));
9c495589
BH
619 }
620 }
621 }
622 }
623 }
624 }
288f4aa9
BH
625 }
626 }
627 catch(AhuException &ae) {
c836dc19 628 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
288f4aa9
BH
629 }
630 catch(exception &e) {
c836dc19 631 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
288f4aa9
BH
632 }
633 catch(...) {
c836dc19 634 L<<Logger::Error<<"any other exception in main: "<<endl;
288f4aa9 635 }
caa6eefa
BH
636
637#ifdef WIN32
638 WSACleanup();
639#endif // WIN32
640
641 return 0;
288f4aa9 642}