]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/lwres.cc
teach Netmask is can be 'empty', like DNSName.
[thirdparty/pdns.git] / pdns / lwres.cc
CommitLineData
e14f094b
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
a5c1b943 3 Copyright (C) 2002 - 2015 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 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
e14f094b
BH
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
e14f094b 21*/
705f31ae
BH
22
23
870a0fe4
AT
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
36c5ee42 27#include "utility.hh"
e14f094b 28#include "lwres.hh"
e14f094b 29#include <iostream>
81883dcc 30#include "dnsrecords.hh"
e14f094b
BH
31#include <errno.h>
32#include "misc.hh"
33#include <algorithm>
34#include <sstream>
35#include <cstring>
36#include <string>
37#include <vector>
e14f094b
BH
38#include "dns.hh"
39#include "qtype.hh"
5c409fa2 40#include "pdnsexception.hh"
e14f094b 41#include "arguments.hh"
5c633640
BH
42#include "sstuff.hh"
43#include "syncres.hh"
ea634573
BH
44#include "dnswriter.hh"
45#include "dnsparser.hh"
aab4adb0 46#include "logger.hh"
51e2144e 47#include "dns_random.hh"
263f6a5a 48#include <boost/scoped_array.hpp>
51e2144e 49#include <boost/algorithm/string.hpp>
c4443ccb 50#include "ednssubnet.hh"
51e2144e 51
81883dcc
BH
52//! returns -2 for OS limits error, -1 for permanent error that has to do with remote **transport**, 0 for timeout, 1 for success
53/** lwr is only filled out in case 1 was returned, and even when returning 1 for 'success', lwr might contain DNS errors
54 Never throws!
55 */
376effcf 56int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult *lwr)
e14f094b 57{
263f6a5a
BH
58 int len;
59 int bufsize=1500;
60 scoped_array<unsigned char> buf(new unsigned char[bufsize]);
ea634573 61 vector<uint8_t> vpacket;
51e2144e 62 // string mapped0x20=dns0x20(domain);
ea634573
BH
63 DNSPacketWriter pw(vpacket, domain, type);
64
c1d73d94 65 pw.getHeader()->rd=sendRDQuery;
51e2144e 66 pw.getHeader()->id=dns_random(0xffff);
81883dcc
BH
67
68 string ping;
69
81883dcc
BH
70 if(EDNS0Level && !doTCP) {
71 DNSPacketWriter::optvect_t opts;
376effcf 72 if(srcmask) {
73 EDNSSubnetOpts eo;
74 eo.source = *srcmask;
75 cout<<"Adding request mask: "<<eo.source.toString()<<endl;
76 opts.push_back(make_pair(8, makeEDNSSubnetOptsString(eo)));
77 srcmask=boost::optional<Netmask>(); // this is also our return value
78 }
93d4a890 79
57769f13 80 pw.addOpt(1200, 0, EDNSOpts::DNSSECOK, opts); // 1200 bytes answer size
2188dcc3
BH
81 pw.commit();
82 }
81883dcc 83 lwr->d_rcode = 0;
81883dcc 84 lwr->d_haveEDNS = false;
eefd15f9
BH
85 int ret;
86
87 DTime dt;
4c4765c1 88 dt.set();
89 *now=dt.getTimeval();
263f6a5a 90 errno=0;
5c633640 91 if(!doTCP) {
4ef015cd 92 int queryfd;
996c89cc
BH
93 if(ip.sin4.sin_family==AF_INET6)
94 g_stats.ipv6queries++;
95
787e5eab 96 if((ret=asendto((const char*)&*vpacket.begin(), (int)vpacket.size(), 0, ip, pw.getHeader()->id,
232f0877 97 domain, type, &queryfd)) < 0) {
998a4334 98 return ret; // passes back the -2 EMFILE
5c633640
BH
99 }
100
101 // sleep until we see an answer to this, interface to mtasker
102
263f6a5a 103 ret=arecvfrom(reinterpret_cast<char *>(buf.get()), bufsize-1,0, ip, &len, pw.getHeader()->id,
232f0877 104 domain, type, queryfd, now);
e14f094b 105 }
5c633640 106 else {
998a4334 107 try {
93f4e5ce 108 Socket s(ip.sin4.sin_family, SOCK_STREAM);
fdf05fd4 109
998a4334 110 s.setNonBlocking();
1652a63e 111 ComboAddress local = getQueryLocalAddress(ip.sin4.sin_family, 0);
3ac2a2ab 112
5a38281c 113 s.bind(local);
4957a608 114
fdf05fd4
BH
115 ComboAddress remote = ip;
116 remote.sin4.sin_port = htons(53);
117 s.connect(remote);
998a4334 118
263f6a5a
BH
119 uint16_t tlen=htons(vpacket.size());
120 char *lenP=(char*)&tlen;
998a4334
BH
121 const char *msgP=(const char*)&*vpacket.begin();
122 string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size());
123
124 ret=asendtcp(packet, &s);
125 if(!(ret>0))
4957a608 126 return ret;
998a4334
BH
127
128 packet.clear();
825fa717 129 ret=arecvtcp(packet, 2, &s, false);
998a4334 130 if(!(ret > 0))
4957a608 131 return ret;
998a4334 132
263f6a5a
BH
133 memcpy(&tlen, packet.c_str(), 2);
134 len=ntohs(tlen); // switch to the 'len' shared with the rest of the function
998a4334 135
825fa717 136 ret=arecvtcp(packet, len, &s, false);
998a4334 137 if(!(ret > 0))
4957a608 138 return ret;
998a4334 139
263f6a5a 140 if(len > bufsize) {
4957a608
BH
141 bufsize=len;
142 scoped_array<unsigned char> narray(new unsigned char[bufsize]);
143 buf.swap(narray);
998a4334 144 }
263f6a5a
BH
145 memcpy(buf.get(), packet.c_str(), len);
146
998a4334
BH
147 ret=1;
148 }
149 catch(NetworkError& ne) {
150 ret = -2; // OS limits error
66ab6a63 151 }
5c633640 152 }
998a4334 153
81883dcc 154
26de3092
BH
155 lwr->d_usec=dt.udiff();
156 *now=dt.getTimeval();
157
263f6a5a
BH
158 if(ret <= 0) // includes 'timeout'
159 return ret;
e14f094b 160
e325f20c 161 lwr->d_records.clear();
c836dc19 162 try {
f1f85f12 163 lwr->d_tcbit=0;
263f6a5a
BH
164 MOADNSParser mdp((const char*)buf.get(), len);
165 lwr->d_aabit=mdp.d_header.aa;
166 lwr->d_tcbit=mdp.d_header.tc;
167 lwr->d_rcode=mdp.d_header.rcode;
168
81883dcc
BH
169 if(mdp.d_header.rcode == RCode::FormErr && mdp.d_qname.empty() && mdp.d_qtype == 0 && mdp.d_qclass == 0) {
170 return 1; // this is "success", the error is set in lwr->d_rcode
171 }
172
e325f20c 173 if(domain != mdp.d_qname) {
c5c066bf 174 if(!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) {// embedded nulls are too noisy, plus empty domains are too
4957a608 175 L<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl;
01608dca 176 }
284aa5c2 177 // unexpected count has already been done @ pdns_recursor.cc
2353fffa
BH
178 goto out;
179 }
e325f20c 180
181 for(const auto& a : mdp.d_answers)
182 lwr->d_records.push_back(a.first);
81883dcc
BH
183
184 EDNSOpts edo;
57769f13 185 if(EDNS0Level > 0 && getEDNSOpts(mdp, &edo)) {
81883dcc 186 lwr->d_haveEDNS = true;
376effcf 187
188 for(const auto& opt : edo.d_options) {
189 if(opt.first==8) {
190 EDNSSubnetOpts reso;
191 if(getEDNSSubnetOptsFromString(opt.second, &reso)) {
192 cerr<<"EDNS Subnet response: "<<reso.source.toString()<<", scope: "<<reso.scope.toString()<<", family = "<<reso.scope.getNetwork().sin4.sin_family<<endl;
193 if(srcmask)
194 srcmask = reso.scope;
195 }
196 }
197
198 }
81883dcc
BH
199 }
200
263f6a5a 201 return 1;
c836dc19 202 }
fdbf35ac 203 catch(std::exception &mde) {
aab4adb0 204 if(::arg().mustDo("log-common-errors"))
263f6a5a 205 L<<Logger::Notice<<"Unable to parse packet from remote server "<<ip.toString()<<": "<<mde.what()<<endl;
81883dcc
BH
206 lwr->d_rcode = RCode::FormErr;
207 g_stats.serverParseError++;
208 return 1; // success - oddly enough
aab4adb0 209 }
c836dc19 210 catch(...) {
ad1bb608 211 L<<Logger::Notice<<"Unknown error parsing packet from remote server"<<endl;
c836dc19 212 }
263f6a5a 213
aab4adb0 214 g_stats.serverParseError++;
263f6a5a 215
2353fffa 216 out:
81883dcc
BH
217 if(!lwr->d_rcode)
218 lwr->d_rcode=RCode::ServFail;
263f6a5a
BH
219
220 return -1;
e14f094b
BH
221}
222