/** lwr is only filled out in case 1 was returned, and even when returning 1 for 'success', lwr might contain DNS errors
Never throws!
*/
-static LWResult::Result 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, TCPOutConnectionManager::Connection& connection)
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): https://github.com/PowerDNS/pdns/issues/12791
+static LWResult::Result asyncresolve(const ComboAddress& address, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, const boost::optional<const ResolveContext&>& context, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& outgoingLoggers, [[maybe_unused]] const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstrmLoggers, const std::set<uint16_t>& exportTypes, LWResult* lwr, bool* chained, TCPOutConnectionManager::Connection& connection)
{
size_t len;
size_t bufsize = g_outgoingEDNSBufsize;
// string mapped0x20=dns0x20(domain);
uint16_t qid = dns_random_uint16();
DNSPacketWriter pw(vpacket, domain, type);
- bool dnsOverTLS = SyncRes::s_dot_to_port_853 && ip.getPort() == 853;
+ bool dnsOverTLS = SyncRes::s_dot_to_port_853 && address.getPort() == 853;
pw.getHeader()->rd = sendRDQuery;
pw.getHeader()->id = qid;
if (outgoingLoggers) {
uuid = getUniqueID();
- logOutgoingQuery(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, dnsOverTLS, vpacket.size(), srcmask);
+ logOutgoingQuery(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, address, domain, type, qid, doTCP, dnsOverTLS, vpacket.size(), srcmask);
}
srcmask = boost::none; // this is also our return value, even if EDNS0Level == 0
if (!doTCP) {
int queryfd;
- if (ip.sin4.sin_family == AF_INET6) {
+ if (address.sin4.sin_family == AF_INET6) {
t_Counters.at(rec::Counter::ipv6queries)++;
}
- ret = asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, ip, qid, domain, type, weWantEDNSSubnet, &queryfd);
+ ret = asendto(vpacket.data(), vpacket.size(), 0, address, qid, domain, type, weWantEDNSSubnet, &queryfd);
if (ret != LWResult::Result::Success) {
return ret;
#ifdef HAVE_FSTRM
if (!*chained) {
if (fstrmQEnabled || fstrmREnabled) {
- localip.sin4.sin_family = ip.sin4.sin_family;
- socklen_t slen = ip.getSocklen();
+ localip.sin4.sin_family = address.sin4.sin_family;
+ socklen_t slen = address.getSocklen();
(void)getsockname(queryfd, reinterpret_cast<sockaddr*>(&localip), &slen); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast))
}
if (fstrmQEnabled) {
- logFstreamQuery(fstrmLoggers, queryTime, localip, ip, DnstapMessage::ProtocolType::DoUDP, context ? context->d_auth : boost::none, vpacket);
+ logFstreamQuery(fstrmLoggers, queryTime, localip, address, DnstapMessage::ProtocolType::DoUDP, context ? context->d_auth : boost::none, vpacket);
}
}
#endif /* HAVE_FSTRM */
// sleep until we see an answer to this, interface to mtasker
- ret = arecvfrom(buf, 0, ip, len, qid, domain, type, queryfd, *now);
+ ret = arecvfrom(buf, 0, address, len, qid, domain, type, queryfd, *now);
}
else {
bool isNew;
if (context && !context->d_nsName.empty()) {
nsName = context->d_nsName.toStringNoDot();
}
- isNew = tcpconnect(ip, connection, dnsOverTLS, nsName);
- ret = tcpsendrecv(ip, connection, localip, vpacket, len, buf);
+ isNew = tcpconnect(address, connection, dnsOverTLS, nsName);
+ ret = tcpsendrecv(address, connection, localip, vpacket, len, buf);
#ifdef HAVE_FSTRM
if (fstrmQEnabled) {
- logFstreamQuery(fstrmLoggers, queryTime, localip, ip, !dnsOverTLS ? DnstapMessage::ProtocolType::DoTCP : DnstapMessage::ProtocolType::DoT, context ? context->d_auth : boost::none, vpacket);
+ logFstreamQuery(fstrmLoggers, queryTime, localip, address, !dnsOverTLS ? DnstapMessage::ProtocolType::DoTCP : DnstapMessage::ProtocolType::DoT, context ? context->d_auth : boost::none, vpacket);
}
#endif /* HAVE_FSTRM */
if (ret == LWResult::Result::Success) {
if (ret != LWResult::Result::Success) { // includes 'timeout'
if (outgoingLoggers) {
- logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, dnsOverTLS, srcmask, 0, -1, {}, queryTime, exportTypes);
+ logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, address, domain, type, qid, doTCP, dnsOverTLS, srcmask, 0, -1, {}, queryTime, exportTypes);
}
return ret;
}
if (dnsOverTLS) {
protocol = DnstapMessage::ProtocolType::DoT;
}
- logFstreamResponse(fstrmLoggers, localip, ip, protocol, context ? context->d_auth : boost::none, buf, queryTime, *now);
+ logFstreamResponse(fstrmLoggers, localip, address, protocol, context ? context->d_auth : boost::none, buf, queryTime, *now);
}
#endif /* HAVE_FSTRM */
if (mdp.d_header.rcode == RCode::FormErr && mdp.d_qname.empty() && mdp.d_qtype == 0 && mdp.d_qclass == 0) {
if (outgoingLoggers) {
- logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
+ logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, address, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
}
lwr->d_validpacket = true;
return LWResult::Result::Success; // this is "success", the error is set in lwr->d_rcode
if (domain != mdp.d_qname) {
if (!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) { // embedded nulls are too noisy, plus empty domains are too
- SLOG(g_log << Logger::Notice << "Packet purporting to come from remote server " << ip.toString() << " contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl,
+ SLOG(g_log << Logger::Notice << "Packet purporting to come from remote server " << address.toString() << " contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl,
g_slogout->info(Logr::Notice, "Packet purporting to come from remote server contained wrong answer",
- "server", Logging::Loggable(ip),
+ "server", Logging::Loggable(address),
"qname", Logging::Loggable(domain),
"onwire", Logging::Loggable(mdp.d_qname)));
}
}
if (outgoingLoggers) {
- logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
+ logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, address, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
}
lwr->d_validpacket = true;
}
catch (const std::exception& mde) {
if (::arg().mustDo("log-common-errors")) {
- SLOG(g_log << Logger::Notice << "Unable to parse packet from remote server " << ip.toString() << ": " << mde.what() << endl,
- g_slogout->error(Logr::Notice, mde.what(), "Unable to parse packet from remote server", "server", Logging::Loggable(ip),
+ SLOG(g_log << Logger::Notice << "Unable to parse packet from remote server " << address.toString() << ": " << mde.what() << endl,
+ g_slogout->error(Logr::Notice, mde.what(), "Unable to parse packet from remote server", "server", Logging::Loggable(address),
"exception", Logging::Loggable("std::exception")));
}
t_Counters.at(rec::Counter::serverParseError)++;
if (outgoingLoggers) {
- logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
+ logIncomingResponse(outgoingLoggers, context ? context->d_initialRequestId : boost::none, uuid, address, domain, type, qid, doTCP, dnsOverTLS, srcmask, len, lwr->d_rcode, lwr->d_records, queryTime, exportTypes);
}
return LWResult::Result::Success; // success - oddly enough
}
catch (...) {
SLOG(g_log << Logger::Notice << "Unknown error parsing packet from remote server" << endl,
- g_slogout->info(Logr::Notice, "Unknown error parsing packet from remote server", "server", Logging::Loggable(ip)));
+ g_slogout->info(Logr::Notice, "Unknown error parsing packet from remote server", "server", Logging::Loggable(address)));
}
t_Counters.at(rec::Counter::serverParseError)++;
For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
*/
-LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, const DNSName& domain, const DNSName& auth, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained, const DNSName& nsName) const
+LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& address, bool ednsMANDATORY, const DNSName& domain, [[maybe_unused]] const DNSName& auth, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained, const DNSName& nsName) const
{
/* what is your QUEST?
the goal is to get as many remotes as possible on the best level of EDNS support
SyncRes::EDNSStatus::EDNSMode mode = EDNSStatus::EDNSOK;
{
auto lock = s_ednsstatus.lock();
- auto ednsstatus = lock->find(ip); // does this include port? YES
+ auto ednsstatus = lock->find(address); // does this include port? YES
if (ednsstatus != lock->end()) {
if (ednsstatus->ttd && ednsstatus->ttd < d_now.tv_sec) {
lock->erase(ednsstatus);
}
if (d_asyncResolve) {
- ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
+ ret = d_asyncResolve(address, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
}
else {
- ret = asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServers, d_frameStreamServers, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
+ ret = asyncresolve(address, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServers, d_frameStreamServers, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
}
if (ret == LWResult::Result::PermanentError || ret == LWResult::Result::OSLimitError || ret == LWResult::Result::Spoofed) {
// Determine new mode
if (res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr) {
mode = EDNSStatus::NOEDNS;
- auto ednsstatus = lock->insert(ip).first;
+ auto ednsstatus = lock->insert(address).first;
auto& ind = lock->get<ComboAddress>();
lock->setMode(ind, ednsstatus, mode, d_now.tv_sec);
// This is the only path that re-iterates the loop
continue;
}
else if (!res->d_haveEDNS) {
- auto ednsstatus = lock->insert(ip).first;
+ auto ednsstatus = lock->insert(address).first;
auto& ind = lock->get<ComboAddress>();
lock->setMode(ind, ednsstatus, EDNSStatus::EDNSIGNORANT, d_now.tv_sec);
}
else {
// New status is EDNSOK
- lock->erase(ip);
+ lock->erase(address);
}
}