mirror of
https://github.com/matrix-construct/construct
synced 2024-05-18 10:53:48 +02:00
ircd::net::dns: Add support for netdb; interface to getservbyname(3).
This commit is contained in:
parent
4b41efcdc8
commit
0e25a2e055
|
@ -921,6 +921,7 @@ dnl unix platform
|
|||
RB_CHK_SYSHEADER(unistd.h, [UNISTD_H])
|
||||
RB_CHK_SYSHEADER(signal.h, [SIGNAL_H])
|
||||
RB_CHK_SYSHEADER(ifaddrs.h, [IFADDRS_H])
|
||||
RB_CHK_SYSHEADER(netdb.h, [NETDB_H])
|
||||
RB_CHK_SYSHEADER(fcntl.h, [FCNTL_H])
|
||||
RB_CHK_SYSHEADER(elf.h, [ELF_H])
|
||||
RB_CHK_SYSHEADER(link.h, [LINK_H])
|
||||
|
|
|
@ -37,9 +37,13 @@ namespace ircd::net::dns
|
|||
bool expired(const json::object &rr, const time_t &rr_ts, const time_t &min_ttl);
|
||||
bool expired(const json::object &rr, const time_t &rr_ts);
|
||||
json::object random_choice(const json::array &);
|
||||
|
||||
string_view make_SRV_key(const mutable_buffer &out, const hostport &, const opts &);
|
||||
string_view unmake_SRV_key(const string_view &);
|
||||
|
||||
uint16_t service_port(std::nothrow_t, const string_view &name, const string_view &prot = {});
|
||||
uint16_t service_port(const string_view &name, const string_view &prot = {});
|
||||
|
||||
// Callback-based interface
|
||||
void resolve(const hostport &, const opts &, callback);
|
||||
void resolve(const hostport &, const opts &, callback_one); // convenience
|
||||
|
@ -86,6 +90,10 @@ struct ircd::net::dns::opts
|
|||
/// the returned record is a reference to the cached error.
|
||||
bool nxdomain_exceptions {true};
|
||||
|
||||
/// When false, queries to translate service strings to port numbers using
|
||||
/// netdb (i.e. /etc/services) will be disabled if they were to occur.
|
||||
bool service_port {true};
|
||||
|
||||
opts() = default;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#include <RB_INC_NETDB_H
|
||||
#include <ircd/net/dns_cache.h>
|
||||
|
||||
namespace ircd::net::dns
|
||||
|
@ -112,16 +113,22 @@ ircd::net::dns::resolve(const hostport &hp,
|
|||
}
|
||||
|
||||
void
|
||||
ircd::net::dns::resolve(const hostport &hp,
|
||||
ircd::net::dns::resolve(const hostport &hp_,
|
||||
const opts &opts,
|
||||
callback cb)
|
||||
{
|
||||
hostport hp(hp_);
|
||||
if(unlikely(!opts.qtype))
|
||||
throw error
|
||||
{
|
||||
"Query type is required; not specified; cannot be deduced here."
|
||||
};
|
||||
|
||||
// Make any necessary attempt to translate a service name into a portnum.
|
||||
if(likely(opts.service_port))
|
||||
if(!port(hp) && service(hp))
|
||||
port(hp) = service_port(std::nothrow, service(hp), opts.proto);
|
||||
|
||||
// Try to satisfy from the cache first. This requires a ctx.
|
||||
if(likely(ctx::current && opts.cache_check))
|
||||
if(cache::get(hp, opts, cb))
|
||||
|
@ -532,3 +539,77 @@ ircd::net::dns::new_record(mutable_buffer &buf,
|
|||
consume(buf, sizeof(type));
|
||||
return new (pos) type(answer);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
ircd::net::dns::service_port(const string_view &name,
|
||||
const string_view &prot)
|
||||
{
|
||||
const auto ret
|
||||
{
|
||||
service_port(std::nothrow, name, prot)
|
||||
};
|
||||
|
||||
if(unlikely(!ret))
|
||||
throw error
|
||||
{
|
||||
"Port for service %s:%s not found",
|
||||
name,
|
||||
prot?: "*"_sv,
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
uint16_t
|
||||
ircd::net::dns::service_port(std::nothrow_t,
|
||||
const string_view &name,
|
||||
const string_view &prot)
|
||||
try
|
||||
{
|
||||
thread_local struct ::servent res, *ent {nullptr};
|
||||
thread_local char _name[32], _prot[32], buf[2048];
|
||||
|
||||
strlcpy(_name, name);
|
||||
strlcpy(_prot, prot);
|
||||
syscall
|
||||
(
|
||||
::getservbyname_r,
|
||||
_name,
|
||||
prot? _prot : nullptr,
|
||||
&res,
|
||||
buf,
|
||||
sizeof(buf),
|
||||
&ent
|
||||
);
|
||||
|
||||
assert(!ent || ent->s_port != 0);
|
||||
assert(!ent || name == ent->s_name);
|
||||
assert(!ent || !prot || prot == ent->s_proto);
|
||||
return ent?
|
||||
htons(ent->s_port):
|
||||
0U;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::critical
|
||||
{
|
||||
log, "Failure when translating service %s:%s to port number :%s",
|
||||
name,
|
||||
prot?: "*"_sv,
|
||||
e.what(),
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
uint16_t
|
||||
ircd::net::dns::service_port(std::nothrow_t,
|
||||
const string_view &name,
|
||||
const string_view &prot)
|
||||
{
|
||||
//TODO: XXX
|
||||
always_assert(false);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue