0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-11 14:38:57 +02:00
construct/ircd/net_dns_netdb.cc

179 lines
3.5 KiB
C++

// The Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// 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
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];
const prof::syscall_usage_warning timer
{
"net::dns::service_port(%s)", name
};
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);
if(unlikely(!ent || !ent->s_port))
log::error
{
log, "Uknown service %s/%s; please add port number to /etc/services",
name,
prot?: "*"_sv
};
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
ircd::string_view
ircd::net::dns::service_name(const mutable_buffer &out,
const uint16_t &port,
const string_view &prot)
{
const auto ret
{
service_name(std::nothrow, out, port, prot)
};
if(unlikely(!ret))
throw error
{
"Name of service for port %u:%s not found",
port,
prot?: "*"_sv,
};
return ret;
}
#ifdef HAVE_NETDB_H
ircd::string_view
ircd::net::dns::service_name(std::nothrow_t,
const mutable_buffer &out,
const uint16_t &port,
const string_view &prot)
try
{
thread_local struct ::servent res, *ent {nullptr};
thread_local char _prot[32], buf[2048];
const prof::syscall_usage_warning timer
{
"net::dns::service_name(%u)", port
};
strlcpy(_prot, prot);
syscall
(
::getservbyport_r,
ntohs(port),
prot? _prot : nullptr,
&res,
buf,
sizeof(buf),
&ent
);
assert(!ent || ent->s_port == ntohs(port));
assert(!ent || !prot || prot == ent->s_proto);
return ent?
strlcpy(out, ent->s_name):
string_view{};
}
catch(const std::exception &e)
{
log::critical
{
log, "Failure when translating port %u:%s to service name :%s",
port,
prot?: "*"_sv,
e.what(),
};
throw;
}
#else
ircd::string_view
ircd::net::dns::service_name(std::nothrow_t,
const mutable_buffer &out,
const uint16_t &port,
const string_view &prot)
{
//TODO: XXX
always_assert(false);
return {};
}
#endif