]>
Commit | Line | Data |
---|---|---|
e14f094b | 1 | /* |
12471842 PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
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 | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
36c5ee42 | 25 | #include "utility.hh" |
e14f094b | 26 | #include "lwres.hh" |
e14f094b | 27 | #include <iostream> |
81883dcc | 28 | #include "dnsrecords.hh" |
e14f094b BH |
29 | #include <errno.h> |
30 | #include "misc.hh" | |
31 | #include <algorithm> | |
32 | #include <sstream> | |
33 | #include <cstring> | |
34 | #include <string> | |
35 | #include <vector> | |
e14f094b BH |
36 | #include "dns.hh" |
37 | #include "qtype.hh" | |
5c409fa2 | 38 | #include "pdnsexception.hh" |
e14f094b | 39 | #include "arguments.hh" |
5c633640 BH |
40 | #include "sstuff.hh" |
41 | #include "syncres.hh" | |
ea634573 BH |
42 | #include "dnswriter.hh" |
43 | #include "dnsparser.hh" | |
aab4adb0 | 44 | #include "logger.hh" |
51e2144e | 45 | #include "dns_random.hh" |
263f6a5a | 46 | #include <boost/scoped_array.hpp> |
51e2144e | 47 | #include <boost/algorithm/string.hpp> |
12ce523e | 48 | #include "validate-recursor.hh" |
c4443ccb | 49 | #include "ednssubnet.hh" |
51e2144e | 50 | |
4898a348 RG |
51 | #ifdef HAVE_PROTOBUF |
52 | ||
d61aa945 RG |
53 | #include "uuid-utils.hh" |
54 | ||
ebd67986 | 55 | #ifdef HAVE_FSTRM |
522253b0 | 56 | #include "rec-dnstap.hh" |
ebd67986 OM |
57 | #include "fstrm_logger.hh" |
58 | bool g_syslog; | |
59 | ||
10ba6d01 | 60 | static bool isEnabledForQueries(const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstreamLoggers) |
573f4ff0 OM |
61 | { |
62 | if (fstreamLoggers == nullptr) { | |
63 | return false; | |
64 | } | |
65 | for (auto& logger : *fstreamLoggers) { | |
10ba6d01 | 66 | if (logger->logQueries()) { |
573f4ff0 OM |
67 | return true; |
68 | } | |
69 | } | |
70 | return false; | |
71 | } | |
72 | ||
6de48f75 OM |
73 | static void logFstreamQuery(const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstreamLoggers, const struct timeval &queryTime, const ComboAddress& ip, bool doTCP, |
74 | boost::optional<const DNSName&> auth, const vector<uint8_t>& packet) | |
4898a348 | 75 | { |
b9fa43e0 | 76 | if (fstreamLoggers == nullptr) |
4898a348 RG |
77 | return; |
78 | ||
b9fa43e0 OM |
79 | struct timespec ts; |
80 | TIMEVAL_TO_TIMESPEC(&queryTime, &ts); | |
6de48f75 | 81 | RecDnstapMessage message(SyncRes::s_serverID, nullptr, &ip, doTCP, auth, reinterpret_cast<const char*>(&*packet.begin()), packet.size(), &ts, nullptr); |
b9fa43e0 OM |
82 | std::string str; |
83 | message.serialize(str); | |
c165308b | 84 | |
b9fa43e0 OM |
85 | for (auto& logger : *fstreamLoggers) { |
86 | logger->queueData(str); | |
87 | } | |
88 | } | |
4898a348 | 89 | |
10ba6d01 | 90 | static bool isEnabledForResponses(const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstreamLoggers) |
573f4ff0 OM |
91 | { |
92 | if (fstreamLoggers == nullptr) { | |
93 | return false; | |
94 | } | |
95 | for (auto& logger : *fstreamLoggers) { | |
10ba6d01 | 96 | if (logger->logResponses()) { |
573f4ff0 OM |
97 | return true; |
98 | } | |
99 | } | |
100 | return false; | |
101 | } | |
102 | ||
6de48f75 OM |
103 | static void logFstreamResponse(const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstreamLoggers, const ComboAddress& ip, bool doTCP, |
104 | boost::optional<const DNSName&> auth, const std::string& packet, const struct timeval& queryTime, const struct timeval& replyTime) | |
b9fa43e0 OM |
105 | { |
106 | if (fstreamLoggers == nullptr) | |
107 | return; | |
0ff13512 | 108 | |
b9fa43e0 OM |
109 | struct timespec ts1, ts2; |
110 | TIMEVAL_TO_TIMESPEC(&queryTime, &ts1); | |
111 | TIMEVAL_TO_TIMESPEC(&replyTime, &ts2); | |
6de48f75 | 112 | RecDnstapMessage message(SyncRes::s_serverID, nullptr, &ip, doTCP, auth, static_cast<const char*>(&*packet.begin()), packet.size(), &ts1, &ts2); |
b9fa43e0 OM |
113 | std::string str; |
114 | message.serialize(str); | |
b773359c | 115 | |
b9fa43e0 OM |
116 | for (auto& logger : *fstreamLoggers) { |
117 | logger->queueData(str); | |
b773359c | 118 | } |
4898a348 RG |
119 | } |
120 | ||
b9fa43e0 | 121 | #endif // HAVE_FSTRM |
ebd67986 | 122 | |
8623c19a | 123 | static void logOutgoingQuery(const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& outgoingLoggers, boost::optional<RecProtoBufMessage>& message, boost::optional<const boost::uuids::uuid&> initialRequestId, const boost::uuids::uuid& uuid, const ComboAddress& ip, const DNSName& domain, int type, uint16_t qid, bool doTCP, size_t bytes, boost::optional<Netmask>& srcmask) |
4898a348 | 124 | { |
5d6c7a46 | 125 | if (!outgoingLoggers) { |
4898a348 | 126 | return; |
5d6c7a46 RG |
127 | } |
128 | ||
129 | bool log = false; | |
130 | for (auto& logger : *outgoingLoggers) { | |
131 | if (logger->logQueries()) { | |
132 | log = true; | |
133 | break; | |
134 | } | |
135 | } | |
136 | ||
137 | if (!log) { | |
138 | return; | |
139 | } | |
4898a348 | 140 | |
8623c19a RG |
141 | message = RecProtoBufMessage(DNSProtoBufMessage::OutgoingQuery, uuid, nullptr, &ip, domain, type, QClass::IN, qid, doTCP, bytes); |
142 | message->setServerIdentity(SyncRes::s_serverID); | |
c165308b | 143 | |
4898a348 | 144 | if (initialRequestId) { |
8623c19a | 145 | message->setInitialRequestID(*initialRequestId); |
4898a348 RG |
146 | } |
147 | ||
0ff13512 | 148 | if (srcmask) { |
8623c19a | 149 | message->setEDNSSubnet(*srcmask); |
0ff13512 RG |
150 | } |
151 | ||
4898a348 RG |
152 | // cerr <<message.toDebugString()<<endl; |
153 | std::string str; | |
8623c19a | 154 | message->serialize(str); |
b773359c RG |
155 | |
156 | for (auto& logger : *outgoingLoggers) { | |
5d6c7a46 RG |
157 | if (logger->logQueries()) { |
158 | logger->queueData(str); | |
159 | } | |
b773359c | 160 | } |
4898a348 RG |
161 | } |
162 | ||
5d6c7a46 | 163 | static void logIncomingResponse(const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& outgoingLoggers, boost::optional<RecProtoBufMessage>& message, boost::optional<const boost::uuids::uuid&> initialRequestId, const boost::uuids::uuid& uuid, const ComboAddress& ip, const DNSName& domain, int type, uint16_t qid, bool doTCP, boost::optional<Netmask>& srcmask, size_t bytes, int rcode, const std::vector<DNSRecord>& records, const struct timeval& queryTime, const std::set<uint16_t>& exportTypes) |
4898a348 | 164 | { |
5d6c7a46 RG |
165 | if (!outgoingLoggers) { |
166 | return; | |
167 | } | |
168 | ||
169 | bool log = false; | |
170 | for (auto& logger : *outgoingLoggers) { | |
171 | if (logger->logResponses()) { | |
172 | log = true; | |
173 | break; | |
174 | } | |
175 | } | |
176 | ||
177 | if (!log) { | |
4898a348 | 178 | return; |
5d6c7a46 RG |
179 | } |
180 | ||
181 | if (!message) { | |
182 | message = RecProtoBufMessage(DNSProtoBufMessage::IncomingResponse, uuid, nullptr, &ip, domain, type, QClass::IN, qid, doTCP, bytes); | |
183 | message->setServerIdentity(SyncRes::s_serverID); | |
184 | ||
185 | if (initialRequestId) { | |
186 | message->setInitialRequestID(*initialRequestId); | |
187 | } | |
188 | ||
189 | if (srcmask) { | |
190 | message->setEDNSSubnet(*srcmask); | |
191 | } | |
192 | } | |
193 | else { | |
194 | message->updateTime(); | |
195 | message->setType(DNSProtoBufMessage::IncomingResponse); | |
196 | message->setBytes(bytes); | |
197 | } | |
4898a348 | 198 | |
8623c19a | 199 | message->setQueryTime(queryTime.tv_sec, queryTime.tv_usec); |
57f8413e RG |
200 | if (rcode == -1) { |
201 | message->setNetworkErrorResponseCode(); | |
202 | } | |
203 | else { | |
204 | message->setResponseCode(rcode); | |
205 | } | |
8623c19a | 206 | message->addRRs(records, exportTypes); |
4898a348 RG |
207 | |
208 | // cerr <<message.toDebugString()<<endl; | |
209 | std::string str; | |
8623c19a | 210 | message->serialize(str); |
b773359c RG |
211 | |
212 | for (auto& logger : *outgoingLoggers) { | |
5d6c7a46 RG |
213 | if (logger->logResponses()) { |
214 | logger->queueData(str); | |
215 | } | |
b773359c | 216 | } |
4898a348 RG |
217 | } |
218 | #endif /* HAVE_PROTOBUF */ | |
219 | ||
81883dcc BH |
220 | //! returns -2 for OS limits error, -1 for permanent error that has to do with remote **transport**, 0 for timeout, 1 for success |
221 | /** lwr is only filled out in case 1 was returned, and even when returning 1 for 'success', lwr might contain DNS errors | |
222 | Never throws! | |
223 | */ | |
10ba6d01 | 224 | int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& outgoingLoggers, const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstrmLoggers, const std::set<uint16_t>& exportTypes, LWResult *lwr, bool* chained) |
e14f094b | 225 | { |
a683e8bd RG |
226 | size_t len; |
227 | size_t bufsize=g_outgoingEDNSBufsize; | |
78f56b38 RG |
228 | std::string buf; |
229 | buf.resize(bufsize); | |
ea634573 | 230 | vector<uint8_t> vpacket; |
51e2144e | 231 | // string mapped0x20=dns0x20(domain); |
4898a348 | 232 | uint16_t qid = dns_random(0xffff); |
ea634573 BH |
233 | DNSPacketWriter pw(vpacket, domain, type); |
234 | ||
c1d73d94 | 235 | pw.getHeader()->rd=sendRDQuery; |
4898a348 | 236 | pw.getHeader()->id=qid; |
5a7d2a18 PL |
237 | /* RFC 6840 section 5.9: |
238 | * This document further specifies that validating resolvers SHOULD set | |
239 | * the CD bit on every upstream query. This is regardless of whether | |
240 | * the CD bit was set on the incoming query [...] | |
241 | * | |
242 | * sendRDQuery is only true if the qname is part of a forward-zone-recurse (or | |
243 | * set in the forward-zone-file), so we use this as an indicator for it being | |
244 | * an "upstream query". To stay true to "dnssec=off means 3.X behaviour", we | |
245 | * only set +CD on forwarded query in any mode other than dnssec=off. | |
246 | */ | |
e7b18884 | 247 | pw.getHeader()->cd=(sendRDQuery && g_dnssecmode != DNSSECMode::Off); |
5a7d2a18 | 248 | |
81883dcc | 249 | string ping; |
7bb598a0 | 250 | bool weWantEDNSSubnet=false; |
30d4402d RG |
251 | uint8_t outgoingECSBits = 0; |
252 | ComboAddress outgoingECSAddr; | |
fe61f5d8 | 253 | if(EDNS0Level > 0) { |
81883dcc | 254 | DNSPacketWriter::optvect_t opts; |
376effcf | 255 | if(srcmask) { |
256 | EDNSSubnetOpts eo; | |
257 | eo.source = *srcmask; | |
30d4402d RG |
258 | outgoingECSBits = srcmask->getBits(); |
259 | outgoingECSAddr = srcmask->getNetwork(); | |
bf4ab707 | 260 | // cout<<"Adding request mask: "<<eo.source.toString()<<endl; |
30d4402d | 261 | opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(eo))); |
7bb598a0 | 262 | weWantEDNSSubnet=true; |
376effcf | 263 | } |
93d4a890 | 264 | |
12ce523e | 265 | pw.addOpt(g_outgoingEDNSBufsize, 0, g_dnssecmode == DNSSECMode::Off ? 0 : EDNSOpts::DNSSECOK, opts); |
2188dcc3 BH |
266 | pw.commit(); |
267 | } | |
81883dcc | 268 | lwr->d_rcode = 0; |
81883dcc | 269 | lwr->d_haveEDNS = false; |
eefd15f9 BH |
270 | int ret; |
271 | ||
272 | DTime dt; | |
4c4765c1 | 273 | dt.set(); |
274 | *now=dt.getTimeval(); | |
4898a348 RG |
275 | |
276 | #ifdef HAVE_PROTOBUF | |
277 | boost::uuids::uuid uuid; | |
278 | const struct timeval queryTime = *now; | |
8623c19a | 279 | boost::optional<RecProtoBufMessage> pbMessage = boost::none; |
4898a348 | 280 | |
b773359c | 281 | if (outgoingLoggers) { |
d61aa945 | 282 | uuid = getUniqueID(); |
8623c19a | 283 | logOutgoingQuery(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, vpacket.size(), srcmask); |
4898a348 | 284 | } |
b9fa43e0 OM |
285 | #endif /* HAVE_PROTOBUF */ |
286 | #ifdef HAVE_FSTRM | |
573f4ff0 | 287 | if (isEnabledForQueries(fstrmLoggers)) { |
6de48f75 | 288 | logFstreamQuery(fstrmLoggers, queryTime, ip, doTCP, context ? context->d_auth : boost::none, vpacket); |
b9fa43e0 OM |
289 | } |
290 | #endif /* HAVE_FSTRM */ | |
4898a348 | 291 | |
0ff13512 RG |
292 | srcmask = boost::none; // this is also our return value, even if EDNS0Level == 0 |
293 | ||
5c633640 | 294 | if(!doTCP) { |
4ef015cd | 295 | int queryfd; |
996c89cc BH |
296 | if(ip.sin4.sin_family==AF_INET6) |
297 | g_stats.ipv6queries++; | |
298 | ||
4898a348 | 299 | if((ret=asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, ip, qid, |
232f0877 | 300 | domain, type, &queryfd)) < 0) { |
998a4334 | 301 | return ret; // passes back the -2 EMFILE |
5c633640 | 302 | } |
deca7d8f RG |
303 | |
304 | if (queryfd == -1) { | |
305 | *chained = true; | |
306 | } | |
307 | ||
5c633640 BH |
308 | // sleep until we see an answer to this, interface to mtasker |
309 | ||
f128d20d | 310 | ret=arecvfrom(buf, 0, ip, &len, qid, |
232f0877 | 311 | domain, type, queryfd, now); |
e14f094b | 312 | } |
5c633640 | 313 | else { |
998a4334 | 314 | try { |
93f4e5ce | 315 | Socket s(ip.sin4.sin_family, SOCK_STREAM); |
fdf05fd4 | 316 | |
998a4334 | 317 | s.setNonBlocking(); |
1652a63e | 318 | ComboAddress local = getQueryLocalAddress(ip.sin4.sin_family, 0); |
3ac2a2ab | 319 | |
5a38281c | 320 | s.bind(local); |
4957a608 | 321 | |
1bde6efa | 322 | s.connect(ip); |
998a4334 | 323 | |
263f6a5a BH |
324 | uint16_t tlen=htons(vpacket.size()); |
325 | char *lenP=(char*)&tlen; | |
998a4334 BH |
326 | const char *msgP=(const char*)&*vpacket.begin(); |
327 | string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size()); | |
328 | ||
329 | ret=asendtcp(packet, &s); | |
330 | if(!(ret>0)) | |
4957a608 | 331 | return ret; |
998a4334 BH |
332 | |
333 | packet.clear(); | |
825fa717 | 334 | ret=arecvtcp(packet, 2, &s, false); |
998a4334 | 335 | if(!(ret > 0)) |
4957a608 | 336 | return ret; |
998a4334 | 337 | |
a683e8bd | 338 | memcpy(&tlen, packet.c_str(), sizeof(tlen)); |
263f6a5a | 339 | len=ntohs(tlen); // switch to the 'len' shared with the rest of the function |
998a4334 | 340 | |
825fa717 | 341 | ret=arecvtcp(packet, len, &s, false); |
998a4334 | 342 | if(!(ret > 0)) |
4957a608 | 343 | return ret; |
998a4334 | 344 | |
78f56b38 RG |
345 | buf.resize(len); |
346 | memcpy(const_cast<char*>(buf.data()), packet.c_str(), len); | |
263f6a5a | 347 | |
998a4334 BH |
348 | ret=1; |
349 | } | |
350 | catch(NetworkError& ne) { | |
351 | ret = -2; // OS limits error | |
66ab6a63 | 352 | } |
5c633640 | 353 | } |
998a4334 | 354 | |
81883dcc | 355 | |
26de3092 BH |
356 | lwr->d_usec=dt.udiff(); |
357 | *now=dt.getTimeval(); | |
358 | ||
57f8413e RG |
359 | if(ret <= 0) { // includes 'timeout' |
360 | #ifdef HAVE_PROTOBUF | |
361 | if (outgoingLoggers) { | |
362 | logIncomingResponse(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, srcmask, 0, -1, {}, queryTime, exportTypes); | |
363 | } | |
364 | #endif | |
263f6a5a | 365 | return ret; |
57f8413e | 366 | } |
e14f094b | 367 | |
78f56b38 | 368 | buf.resize(len); |
b9fa43e0 OM |
369 | |
370 | #ifdef HAVE_FSTRM | |
573f4ff0 | 371 | if (isEnabledForResponses(fstrmLoggers)) { |
6de48f75 | 372 | logFstreamResponse(fstrmLoggers, ip, doTCP, context ? context->d_auth : boost::none, buf, queryTime, *now); |
b9fa43e0 OM |
373 | } |
374 | #endif /* HAVE_FSTRM */ | |
375 | ||
e325f20c | 376 | lwr->d_records.clear(); |
c836dc19 | 377 | try { |
f1f85f12 | 378 | lwr->d_tcbit=0; |
78f56b38 | 379 | MOADNSParser mdp(false, buf); |
263f6a5a BH |
380 | lwr->d_aabit=mdp.d_header.aa; |
381 | lwr->d_tcbit=mdp.d_header.tc; | |
382 | lwr->d_rcode=mdp.d_header.rcode; | |
383 | ||
81883dcc | 384 | if(mdp.d_header.rcode == RCode::FormErr && mdp.d_qname.empty() && mdp.d_qtype == 0 && mdp.d_qclass == 0) { |
4898a348 | 385 | #ifdef HAVE_PROTOBUF |
b773359c | 386 | if(outgoingLoggers) { |
5d6c7a46 | 387 | logIncomingResponse(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes); |
4898a348 RG |
388 | } |
389 | #endif | |
269ac73d | 390 | lwr->d_validpacket=true; |
81883dcc BH |
391 | return 1; // this is "success", the error is set in lwr->d_rcode |
392 | } | |
393 | ||
e325f20c | 394 | if(domain != mdp.d_qname) { |
c5c066bf | 395 | if(!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) {// embedded nulls are too noisy, plus empty domains are too |
e6a9dde5 | 396 | g_log<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl; |
01608dca | 397 | } |
284aa5c2 | 398 | // unexpected count has already been done @ pdns_recursor.cc |
2353fffa BH |
399 | goto out; |
400 | } | |
f128d20d RG |
401 | |
402 | lwr->d_records.reserve(mdp.d_answers.size()); | |
e325f20c | 403 | for(const auto& a : mdp.d_answers) |
404 | lwr->d_records.push_back(a.first); | |
81883dcc BH |
405 | |
406 | EDNSOpts edo; | |
57769f13 | 407 | if(EDNS0Level > 0 && getEDNSOpts(mdp, &edo)) { |
81883dcc | 408 | lwr->d_haveEDNS = true; |
376effcf | 409 | |
7bb598a0 | 410 | if(weWantEDNSSubnet) { |
411 | for(const auto& opt : edo.d_options) { | |
30d4402d | 412 | if(opt.first==EDNSOptionCode::ECS) { |
7bb598a0 | 413 | EDNSSubnetOpts reso; |
414 | if(getEDNSSubnetOptsFromString(opt.second, &reso)) { | |
415 | // cerr<<"EDNS Subnet response: "<<reso.source.toString()<<", scope: "<<reso.scope.toString()<<", family = "<<reso.scope.getNetwork().sin4.sin_family<<endl; | |
fe61f5d8 RG |
416 | /* rfc7871 states that 0 "indicate[s] that the answer is suitable for all addresses in FAMILY", |
417 | so we might want to still pass the information along to be able to differentiate between | |
418 | IPv4 and IPv6. Still I'm pretty sure it doesn't matter in real life, so let's not duplicate | |
419 | entries in our cache. */ | |
30d4402d RG |
420 | if(reso.scope.getBits()) { |
421 | uint8_t bits = std::min(reso.scope.getBits(), outgoingECSBits); | |
422 | outgoingECSAddr.truncate(bits); | |
423 | srcmask = Netmask(outgoingECSAddr, bits); | |
424 | } | |
7bb598a0 | 425 | } |
426 | } | |
427 | } | |
376effcf | 428 | } |
81883dcc BH |
429 | } |
430 | ||
4898a348 | 431 | #ifdef HAVE_PROTOBUF |
b773359c | 432 | if(outgoingLoggers) { |
5d6c7a46 | 433 | logIncomingResponse(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes); |
4898a348 RG |
434 | } |
435 | #endif | |
269ac73d | 436 | lwr->d_validpacket=true; |
263f6a5a | 437 | return 1; |
c836dc19 | 438 | } |
fdbf35ac | 439 | catch(std::exception &mde) { |
aab4adb0 | 440 | if(::arg().mustDo("log-common-errors")) |
e6a9dde5 | 441 | g_log<<Logger::Notice<<"Unable to parse packet from remote server "<<ip.toString()<<": "<<mde.what()<<endl; |
81883dcc | 442 | lwr->d_rcode = RCode::FormErr; |
4898a348 RG |
443 | g_stats.serverParseError++; |
444 | #ifdef HAVE_PROTOBUF | |
b773359c | 445 | if(outgoingLoggers) { |
5d6c7a46 | 446 | logIncomingResponse(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes); |
4898a348 RG |
447 | } |
448 | #endif | |
269ac73d | 449 | lwr->d_validpacket=false; |
81883dcc | 450 | return 1; // success - oddly enough |
aab4adb0 | 451 | } |
c836dc19 | 452 | catch(...) { |
e6a9dde5 | 453 | g_log<<Logger::Notice<<"Unknown error parsing packet from remote server"<<endl; |
c836dc19 | 454 | } |
263f6a5a | 455 | |
aab4adb0 | 456 | g_stats.serverParseError++; |
263f6a5a | 457 | |
2353fffa | 458 | out: |
81883dcc BH |
459 | if(!lwr->d_rcode) |
460 | lwr->d_rcode=RCode::ServFail; | |
263f6a5a BH |
461 | |
462 | return -1; | |
e14f094b BH |
463 | } |
464 |