]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lwres.cc
sigh.. some queries have embedded nulls in them, which we log noisily
[thirdparty/pdns.git] / pdns / lwres.cc
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 - 2005 PowerDNS.COM BV
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 version 2 as
7 published by the Free Software Foundation
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 #include "utility.hh"
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 "dns.hh"
31 #include "qtype.hh"
32 #include "ahuexception.hh"
33 #include "arguments.hh"
34 #include "sstuff.hh"
35 #include "syncres.hh"
36 #include "dnswriter.hh"
37 #include "dnsparser.hh"
38 #include "logger.hh"
39
40 LWRes::LWRes()
41 {
42 d_sock=-1;
43 d_timeout=500000;
44 d_bufsize=1500;
45 d_buf=new unsigned char[d_bufsize];
46 }
47
48 LWRes::~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! */
58 int LWRes::asyncresolve(uint32_t ip, const char *domain, int type, bool doTCP, struct timeval* now)
59 {
60 d_ip=ip;
61 vector<uint8_t> vpacket;
62 DNSPacketWriter pw(vpacket, domain, type);
63
64 pw.getHeader()->rd=0;
65 pw.getHeader()->id=random();
66 d_domain=domain;
67 d_type=type;
68 d_inaxfr=false;
69 d_rcode=0;
70
71
72 struct sockaddr_in toaddr;
73 Utility::socklen_t addrlen=sizeof(toaddr);
74 toaddr.sin_addr.s_addr=htonl(ip);
75
76 toaddr.sin_port=htons(53);
77 toaddr.sin_family=AF_INET;
78
79 int ret;
80
81 DTime dt;
82 dt.setTimeval(*now);
83
84 if(!doTCP) {
85 if(asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, (struct sockaddr*)(&toaddr), sizeof(toaddr), pw.getHeader()->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, pw.getHeader()->id);
92 }
93 else {
94 Socket s(InterNetwork, Stream);
95 IPEndpoint ie(U32ToIP(ip), 53);
96 s.setNonBlocking();
97 s.connect(ie);
98
99 unsigned int len=htons(vpacket.size());
100 char *lenP=(char*)&len;
101 const char *msgP=(const char*)&*vpacket.begin();
102 string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size());
103
104 if(asendtcp(packet, &s) == 0) {
105 return 0;
106 }
107
108 packet.clear();
109 if(arecvtcp(packet,2, &s)==0) {
110 return 0;
111 }
112
113 memcpy(&len, packet.c_str(), 2);
114 len=ntohs(len);
115
116 if(arecvtcp(packet, len, &s)==0) {
117 return 0;
118 }
119 if(len > (unsigned int)d_bufsize) {
120 d_bufsize=len;
121 delete[] d_buf;
122 d_buf = new unsigned char[d_bufsize];
123 }
124 memcpy(d_buf, packet.c_str(), len);
125 d_len=len;
126 ret=1;
127 }
128 d_usec=dt.udiff();
129 *now=dt.getTimeval();
130 return ret;
131 }
132
133
134 LWRes::res_t LWRes::result()
135 {
136 try {
137 MOADNSParser mdp((const char*)d_buf, d_len);
138 // if(p.parse((char *)d_buf, d_len)<0)
139 // throw LWResException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
140 d_aabit=mdp.d_header.aa;
141 d_tcbit=mdp.d_header.tc;
142 d_rcode=mdp.d_header.rcode;
143
144 if(strcasecmp(d_domain.c_str(), mdp.d_qname.c_str())) {
145 if(d_domain.find((char)0)==string::npos) {// embedded nulls are too noisy
146 L<<Logger::Error<<"Packet purporting to come from remote server "<<U32ToIP(d_ip)<<" contained wrong answer: '" << d_domain << "' != '" << mdp.d_qname << "'" << endl;
147 g_stats.spoofedCount++;
148 }
149 goto out;
150 }
151
152 LWRes::res_t ret;
153 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
154 // cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
155 // cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<endl;
156 DNSResourceRecord rr;
157 rr.qtype=i->first.d_type;
158 rr.qname=i->first.d_label;
159 rr.ttl=i->first.d_ttl;
160 rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form
161 rr.d_place=(DNSResourceRecord::Place) i->first.d_place;
162 ret.push_back(rr);
163 }
164
165 return ret;
166 // return p.getAnswers();
167 }
168 catch(exception &mde) {
169 if(::arg().mustDo("log-common-errors"))
170 L<<Logger::Error<<"Unable to parse packet from remote server: "<<mde.what()<<endl;
171 }
172 catch(...) {
173 L<<Logger::Error<<"Unknown error parsing packet from remote server"<<endl;
174 }
175
176 g_stats.serverParseError++;
177
178 out:
179 d_rcode=RCode::ServFail;
180 LWRes::res_t empty;
181 return empty;
182 }
183