]>
Commit | Line | Data |
---|---|---|
e14f094b BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
02ac88c8 | 3 | Copyright (C) 2002 - 2006 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 | |
06bd9ccf | 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
e14f094b | 17 | */ |
705f31ae BH |
18 | |
19 | ||
36c5ee42 | 20 | #include "utility.hh" |
e14f094b | 21 | #include "lwres.hh" |
e14f094b BH |
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> | |
e14f094b BH |
30 | #include "dns.hh" |
31 | #include "qtype.hh" | |
e14f094b | 32 | #include "ahuexception.hh" |
e14f094b | 33 | #include "arguments.hh" |
5c633640 BH |
34 | #include "sstuff.hh" |
35 | #include "syncres.hh" | |
ea634573 BH |
36 | #include "dnswriter.hh" |
37 | #include "dnsparser.hh" | |
aab4adb0 | 38 | #include "logger.hh" |
e14f094b BH |
39 | |
40 | LWRes::LWRes() | |
41 | { | |
42 | d_sock=-1; | |
43 | d_timeout=500000; | |
b636533b | 44 | d_bufsize=1500; |
d39704c0 | 45 | d_buf = 0; |
e14f094b BH |
46 | } |
47 | ||
48 | LWRes::~LWRes() | |
49 | { | |
50 | if(d_sock>=0) | |
51 | Utility::closesocket(d_sock); | |
52 | delete[] d_buf; | |
53 | } | |
54 | ||
998a4334 | 55 | //! returns -2 for OS limits error, -1 for permanent error that has to do with remote, 0 for timeout, 1 for success |
e14f094b | 56 | /** Never throws! */ |
996c89cc | 57 | int LWRes::asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, struct timeval* now) |
e14f094b | 58 | { |
d39704c0 BH |
59 | if(!d_buf) |
60 | d_buf=new unsigned char[d_bufsize]; | |
61 | ||
2353fffa | 62 | d_ip=ip; |
ea634573 BH |
63 | vector<uint8_t> vpacket; |
64 | DNSPacketWriter pw(vpacket, domain, type); | |
65 | ||
66 | pw.getHeader()->rd=0; | |
f14ebffb | 67 | pw.getHeader()->id=Utility::random(); |
e14f094b BH |
68 | d_domain=domain; |
69 | d_type=type; | |
70 | d_inaxfr=false; | |
36f5e3db | 71 | d_rcode=0; |
e14f094b | 72 | |
eefd15f9 BH |
73 | int ret; |
74 | ||
75 | DTime dt; | |
5e3da48d | 76 | dt.setTimeval(*now); |
5c633640 BH |
77 | |
78 | if(!doTCP) { | |
4ef015cd | 79 | int queryfd; |
996c89cc BH |
80 | if(ip.sin4.sin_family==AF_INET6) |
81 | g_stats.ipv6queries++; | |
82 | ||
787e5eab BH |
83 | if((ret=asendto((const char*)&*vpacket.begin(), (int)vpacket.size(), 0, ip, pw.getHeader()->id, |
84 | domain, type, &queryfd)) < 0) { | |
998a4334 | 85 | return ret; // passes back the -2 EMFILE |
5c633640 BH |
86 | } |
87 | ||
88 | // sleep until we see an answer to this, interface to mtasker | |
89 | ||
787e5eab | 90 | ret=arecvfrom(reinterpret_cast<char *>(d_buf), d_bufsize-1,0, ip, &d_len, pw.getHeader()->id, |
f6c254c1 | 91 | domain, type, queryfd, now->tv_sec); |
e14f094b | 92 | } |
5c633640 | 93 | else { |
998a4334 | 94 | try { |
ccd3ed60 | 95 | if(ip.sin4.sin_family != AF_INET) // sstuff isn't yet ready for IPv6 |
996c89cc | 96 | return -1; |
998a4334 | 97 | Socket s(InterNetwork, Stream); |
ccd3ed60 | 98 | IPEndpoint ie(U32ToIP(ntohl(ip.sin4.sin_addr.s_addr)), 53); // WRONG WRONG WRONG XXX FIXME |
998a4334 BH |
99 | s.setNonBlocking(); |
100 | s.connect(ie); | |
101 | ||
4ca15bca | 102 | uint16_t len=htons(vpacket.size()); |
998a4334 BH |
103 | char *lenP=(char*)&len; |
104 | const char *msgP=(const char*)&*vpacket.begin(); | |
105 | string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size()); | |
106 | ||
107 | ret=asendtcp(packet, &s); | |
108 | if(!(ret>0)) | |
109 | return ret; | |
110 | ||
111 | packet.clear(); | |
112 | ret=arecvtcp(packet, 2, &s); | |
113 | if(!(ret > 0)) | |
114 | return ret; | |
115 | ||
116 | memcpy(&len, packet.c_str(), 2); | |
117 | len=ntohs(len); | |
118 | ||
119 | ret=arecvtcp(packet, len, &s); | |
120 | if(!(ret > 0)) | |
121 | return ret; | |
122 | ||
02ac88c8 BH |
123 | if(len > d_bufsize) { |
124 | // cerr<<"Reallocating to "<<len<<" bytes ("<<packet.size()<<")\n"; | |
998a4334 BH |
125 | d_bufsize=len; |
126 | delete[] d_buf; | |
127 | d_buf = new unsigned char[d_bufsize]; | |
128 | } | |
129 | memcpy(d_buf, packet.c_str(), len); | |
130 | d_len=len; | |
131 | ret=1; | |
132 | } | |
133 | catch(NetworkError& ne) { | |
134 | ret = -2; // OS limits error | |
66ab6a63 | 135 | } |
5c633640 | 136 | } |
998a4334 | 137 | |
5c633640 | 138 | d_usec=dt.udiff(); |
5e3da48d | 139 | *now=dt.getTimeval(); |
eefd15f9 | 140 | return ret; |
e14f094b BH |
141 | } |
142 | ||
143 | ||
eefd15f9 | 144 | LWRes::res_t LWRes::result() |
e14f094b | 145 | { |
c836dc19 | 146 | try { |
ea634573 BH |
147 | MOADNSParser mdp((const char*)d_buf, d_len); |
148 | // if(p.parse((char *)d_buf, d_len)<0) | |
149 | // throw LWResException("resolver: unable to parse packet of "+itoa(d_len)+" bytes"); | |
150 | d_aabit=mdp.d_header.aa; | |
151 | d_tcbit=mdp.d_header.tc; | |
152 | d_rcode=mdp.d_header.rcode; | |
153 | ||
705f31ae | 154 | if(Utility::strcasecmp(d_domain.c_str(), mdp.d_qname.c_str())) { |
01608dca | 155 | if(d_domain.find((char)0)==string::npos) {// embedded nulls are too noisy |
ad1bb608 | 156 | L<<Logger::Notice<<"Packet purporting to come from remote server "<<d_ip.toString()<<" contained wrong answer: '" << d_domain << "' != '" << mdp.d_qname << "'" << endl; |
01ed3112 | 157 | g_stats.unexpectedCount++; |
01608dca | 158 | } |
2353fffa BH |
159 | goto out; |
160 | } | |
161 | ||
ea634573 BH |
162 | LWRes::res_t ret; |
163 | for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { | |
164 | // cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type); | |
165 | // cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<endl; | |
166 | DNSResourceRecord rr; | |
167 | rr.qtype=i->first.d_type; | |
168 | rr.qname=i->first.d_label; | |
169 | rr.ttl=i->first.d_ttl; | |
170 | rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form | |
ea634573 BH |
171 | rr.d_place=(DNSResourceRecord::Place) i->first.d_place; |
172 | ret.push_back(rr); | |
173 | } | |
174 | ||
175 | return ret; | |
176 | // return p.getAnswers(); | |
c836dc19 | 177 | } |
aab4adb0 BH |
178 | catch(exception &mde) { |
179 | if(::arg().mustDo("log-common-errors")) | |
ad1bb608 | 180 | L<<Logger::Notice<<"Unable to parse packet from remote server "<<d_ip.toString()<<": "<<mde.what()<<endl; |
aab4adb0 | 181 | } |
c836dc19 | 182 | catch(...) { |
ad1bb608 | 183 | L<<Logger::Notice<<"Unknown error parsing packet from remote server"<<endl; |
c836dc19 | 184 | } |
2353fffa | 185 | |
aab4adb0 | 186 | g_stats.serverParseError++; |
2353fffa BH |
187 | |
188 | out: | |
aab4adb0 BH |
189 | d_rcode=RCode::ServFail; |
190 | LWRes::res_t empty; | |
191 | return empty; | |
e14f094b BH |
192 | } |
193 |