]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/lwres.cc
fix TCP related crashes due to HUUUUGE daum.net records (3.5kbyte!)
[thirdparty/pdns.git] / pdns / lwres.cc
CommitLineData
e14f094b
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
d0166f4a 3 Copyright (C) 2002 - 2005 PowerDNS.COM BV
e14f094b
BH
4
5 This program is free software; you can redistribute it and/or modify
d0166f4a
BH
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
e14f094b
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*/
36c5ee42 18#include "utility.hh"
e14f094b
BH
19#include "lwres.hh"
20#include <pthread.h>
21#include <semaphore.h>
22#include <iostream>
23#include <errno.h>
24#include "misc.hh"
25#include <algorithm>
26#include <sstream>
27#include <cstring>
28#include <string>
29#include <vector>
30#include "dnspacket.hh"
31#include "dns.hh"
32#include "qtype.hh"
33#include "tcpreceiver.hh"
34#include "ahuexception.hh"
35#include "statbag.hh"
36#include "arguments.hh"
5c633640
BH
37#include "sstuff.hh"
38#include "syncres.hh"
e14f094b
BH
39
40LWRes::LWRes()
41{
42 d_sock=-1;
43 d_timeout=500000;
b636533b
BH
44 d_bufsize=1500;
45 d_buf=new unsigned char[d_bufsize];
e14f094b
BH
46}
47
48LWRes::~LWRes()
49{
50 if(d_sock>=0)
51 Utility::closesocket(d_sock);
52 delete[] d_buf;
53}
54
55
56//! returns -1 for permanent error, 0 for timeout, 1 for success
57/** Never throws! */
5c633640 58int LWRes::asyncresolve(const string &ip, const char *domain, int type, bool doTCP)
e14f094b
BH
59{
60 DNSPacket p;
61 p.setQuestion(Opcode::Query,domain,type);
62 p.setRD(false);
63 p.wrapup();
64
65 d_domain=domain;
66 d_type=type;
67 d_inaxfr=false;
36f5e3db 68 d_rcode=0;
e14f094b
BH
69
70 struct sockaddr_in toaddr;
71 struct in_addr inp;
5c633640 72 Utility::socklen_t addrlen=sizeof(toaddr);
e14f094b
BH
73 Utility::inet_aton(ip.c_str(),&inp);
74 toaddr.sin_addr.s_addr=inp.s_addr;
75
76 toaddr.sin_port=htons(53);
77 toaddr.sin_family=AF_INET;
78
eefd15f9
BH
79 int ret;
80
81 DTime dt;
82 dt.set();
5c633640
BH
83
84 if(!doTCP) {
85 if(asendto(p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr),p.d.id)<0) {
86 return -1;
87 }
88
89 // sleep until we see an answer to this, interface to mtasker
90
91 ret=arecvfrom(reinterpret_cast<char *>(d_buf), d_bufsize-1,0,(struct sockaddr*)(&toaddr), &addrlen, &d_len, p.d.id);
e14f094b 92 }
5c633640 93 else {
66ab6a63 94 // cerr<<"do tcp"<<endl;
5c633640
BH
95 Socket s(InterNetwork, Stream);
96 IPEndpoint ie(ip, 53);
97 s.setNonBlocking();
98 s.connect(ie);
99
66ab6a63 100 unsigned int len=htons(p.len);
5c633640
BH
101 char *lenP=(char*)&len;
102 const char *msgP=p.getData();
103 string packet=string(lenP, lenP+2)+string(msgP, msgP+p.len);
104
105 if(asendtcp(packet, &s) == 0) {
d0166f4a
BH
106 // cerr<<"asendtcp: timeout"<<endl;
107 return 0;
5c633640 108 }
eefd15f9 109
5c633640
BH
110 packet.clear();
111 if(arecvtcp(packet,2, &s)==0) {
d0166f4a
BH
112 // cerr<<"arecvtcp: timeout"<<endl;
113 return 0;
5c633640
BH
114 }
115
116 memcpy(&len, packet.c_str(), 2);
117 len=ntohs(len);
118
119 // cerr<<"Now reading "<<len<<" bytes"<<endl;
120
121 if(arecvtcp(packet, len, &s)==0) {
d0166f4a
BH
122 // cerr<<"arecvtcp: timeout"<<endl;
123 return 0;
5c633640 124 }
66ab6a63
BH
125 if(len > d_bufsize) {
126 d_bufsize=len;
127 delete[] d_buf;
128 d_buf = new unsigned char[d_bufsize];
129 }
5c633640
BH
130 memcpy(d_buf, packet.c_str(), len);
131 d_len=len;
132 ret=1;
133 }
134 d_usec=dt.udiff();
36c5ee42 135
eefd15f9 136 return ret;
e14f094b
BH
137}
138
139
eefd15f9 140LWRes::res_t LWRes::result()
e14f094b
BH
141{
142 DNSPacket p;
143
c836dc19
BH
144 try {
145 if(p.parse((char *)d_buf, d_len)<0)
146 throw LWResException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
eefd15f9 147 d_aabit=p.d.aa;
d0166f4a 148 d_tcbit=p.d.tc;
c836dc19
BH
149 d_rcode=p.d.rcode;
150 return p.getAnswers();
151 }
152 catch(...) {
153 d_rcode=RCode::ServFail;
154 LWRes::res_t empty;
155 return empty;
156 }
e14f094b
BH
157}
158