mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
ircd::net::dns: Allow an exception to calling back with nxdomain as an exception.
This commit is contained in:
parent
1d408173dc
commit
4e796c896a
3 changed files with 37 additions and 7 deletions
|
@ -84,6 +84,15 @@ struct ircd::net::dns::opts
|
|||
/// modified to an absolute expiration time. If false, no modification
|
||||
/// occurs from the original value.
|
||||
bool cache_result {true};
|
||||
|
||||
/// When false, nxdomain errors are not treated as exceptions and the
|
||||
/// eptr of a callback will not be set. Instead, the returned record
|
||||
/// will contain some nulled / empty data and the user is obliged to
|
||||
/// know that this is not a real DNS answer but the error's result.
|
||||
/// Note: Requires that cache_result is set to true. If not, this value
|
||||
/// is ignored and always considered to be set to true; this is because
|
||||
/// the returned record is a reference to the cached error.
|
||||
bool nxdomain_exceptions {true};
|
||||
};
|
||||
|
||||
/// (internal) DNS cache
|
||||
|
|
|
@ -41,7 +41,7 @@ struct ircd::net::dns::resolver
|
|||
char reply[64_KiB] alignas(16); // Buffer for recv
|
||||
|
||||
bool handle_error(const error_code &ec) const;
|
||||
bool handle_error(const header &, const rfc1035::question &, const dns::opts &);
|
||||
bool handle_error(const header &, const rfc1035::question &, tag &);
|
||||
void handle_reply(const header &, const const_buffer &body, tag &);
|
||||
void handle_reply(const header &, const const_buffer &body);
|
||||
void handle(const error_code &ec, const size_t &) noexcept;
|
||||
|
|
33
ircd/net.cc
33
ircd/net.cc
|
@ -2384,7 +2384,7 @@ ircd::net::dns::prefetch_A{[]
|
|||
/// an automatic chain of queries such as SRV and A/AAAA based on the input and
|
||||
/// intermediate results.
|
||||
void
|
||||
ircd::net::dns::operator()(const hostport &hostport,
|
||||
ircd::net::dns::operator()(const hostport &hp,
|
||||
const opts &opts,
|
||||
callback_ipport_one callback)
|
||||
{
|
||||
|
@ -2706,7 +2706,7 @@ ircd::net::dns::cache::get(const hostport &hp,
|
|||
// Cached entry is a cached error, we set the eptr, but also
|
||||
// include the record and increment the count like normal.
|
||||
assert(!eptr);
|
||||
if(!rr.tgt || !rr.port)
|
||||
if((!rr.tgt || !rr.port) && opts.nxdomain_exceptions)
|
||||
{
|
||||
//TODO: we don't cache what the error was, assuming it's
|
||||
//TODO: NXDomain can be incorrect and in bad ways downstream...
|
||||
|
@ -3176,7 +3176,7 @@ try
|
|||
for(size_t i(0); i < header.qdcount; ++i)
|
||||
consume(buffer, size(qd.at(i).parse(buffer)));
|
||||
|
||||
if(!handle_error(header, qd.at(0), tag.opts))
|
||||
if(!handle_error(header, qd.at(0), tag))
|
||||
throw rfc1035::error
|
||||
{
|
||||
"protocol error #%u :%s", header.rcode, rfc1035::rcode.at(header.rcode)
|
||||
|
@ -3268,13 +3268,16 @@ catch(const std::exception &e)
|
|||
e.what());
|
||||
|
||||
if(tag.cb)
|
||||
{
|
||||
assert(tag.opts.nxdomain_exceptions);
|
||||
tag.cb(std::current_exception(), {});
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::net::dns::resolver::handle_error(const header &header,
|
||||
const rfc1035::question &question,
|
||||
const dns::opts &opts)
|
||||
tag &tag)
|
||||
{
|
||||
switch(header.rcode)
|
||||
{
|
||||
|
@ -3282,10 +3285,28 @@ ircd::net::dns::resolver::handle_error(const header &header,
|
|||
return true;
|
||||
|
||||
case 3: // NXDomain; exception
|
||||
if(opts.cache_result)
|
||||
cache.put_error(question, header.rcode);
|
||||
{
|
||||
if(!tag.opts.cache_result)
|
||||
return false;
|
||||
|
||||
const auto *record
|
||||
{
|
||||
cache.put_error(question, header.rcode)
|
||||
};
|
||||
|
||||
// When the user doesn't want an eptr for nxdomain we just make
|
||||
// their callback here and then null the cb pointer so it's not
|
||||
// called again. It is done here because we have a reference to
|
||||
// the cached error record readily accessible.
|
||||
if(!tag.opts.nxdomain_exceptions && tag.cb)
|
||||
{
|
||||
assert(record);
|
||||
tag.cb({}, vector_view<const rfc1035::record *>(&record, 1));
|
||||
tag.cb = {};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default: // Unhandled error; exception
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue