pull/1615/head
Jason Rhinelander 3 years ago
parent b9363c8d21
commit 1d48cd6d35

@ -786,8 +786,10 @@ namespace llarp
Router()->loop()->add_ticker([this] { Flush(); });
// Attempt to register DNS on the interface
systemd_resolved_set_dns(m_IfName, m_LocalResolverAddr.createSockAddr(),
false /* just .loki/.snode DNS initially */);
systemd_resolved_set_dns(
m_IfName,
m_LocalResolverAddr.createSockAddr(),
false /* just .loki/.snode DNS initially */);
if (m_OnUp)
{

@ -2,8 +2,11 @@
#ifndef WITH_SYSTEMD
namespace llarp {
bool systemd_resolved_set_dns(std::string, llarp::SockAddr, bool) {
namespace llarp
{
bool
systemd_resolved_set_dns(std::string, llarp::SockAddr, bool)
{
LogDebug("lokinet is not build with systemd support, cannot set systemd resolved DNS");
return false;
}
@ -15,21 +18,26 @@ namespace llarp {
#include <stdexcept>
extern "C" {
extern "C"
{
#include <systemd/sd-bus.h>
#include <net/if.h>
}
using namespace std::literals;
namespace llarp {
namespace {
namespace llarp
{
namespace
{
template <typename... T>
void resolved_call(sd_bus* bus, const char* method, const char* arg_format, T... args) {
void
resolved_call(sd_bus* bus, const char* method, const char* arg_format, T... args)
{
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *msg = nullptr;
int r = sd_bus_call_method(bus,
sd_bus_message* msg = nullptr;
int r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
@ -46,40 +54,59 @@ namespace llarp {
sd_bus_error_free(&error);
}
struct sd_bus_deleter { void operator()(sd_bus* ptr) const { sd_bus_unref(ptr); } };
}
struct sd_bus_deleter
{
void
operator()(sd_bus* ptr) const
{
sd_bus_unref(ptr);
}
};
} // namespace
bool systemd_resolved_set_dns(std::string ifname, llarp::SockAddr dns, bool global) {
bool
systemd_resolved_set_dns(std::string ifname, llarp::SockAddr dns, bool global)
{
unsigned int if_ndx = if_nametoindex(ifname.c_str());
if (if_ndx == 0) {
if (if_ndx == 0)
{
LogWarn("No such interface '", ifname, "'");
return false;
}
// Connect to the system bus
sd_bus *bus = nullptr;
sd_bus* bus = nullptr;
int r = sd_bus_open_system(&bus);
if (r < 0) {
if (r < 0)
{
LogWarn("Failed to connect to system bus to set DNS: ", strerror(-r));
return false;
}
std::unique_ptr<sd_bus, sd_bus_deleter> bus_ptr{bus};
try {
try
{
// This passing address by bytes and using two separate calls for ipv4/ipv6 is gross, but the
// alternative is to build up a bunch of crap with va_args, which is slightly more gross.
if (dns.isIPv6()) {
if (dns.isIPv6())
{
auto ipv6 = dns.getIPv6();
static_assert(sizeof(ipv6) == 16);
auto* a = reinterpret_cast<const uint8_t*>(&ipv6);
resolved_call(bus, "SetLinkDNSEx", "ia(iayqs)",
(int32_t) if_ndx,
(int) 1, // number of "iayqs"s we are passing
(int32_t) AF_INET6, // network address type
(int) 16, // network addr byte size
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], // yuck
(uint16_t) dns.getPort(),
nullptr // dns server name (for TLS SNI which we don't care about)
resolved_call(
bus,
"SetLinkDNSEx",
"ia(iayqs)",
(int32_t)if_ndx,
(int)1, // number of "iayqs"s we are passing
(int32_t)AF_INET6, // network address type
(int)16, // network addr byte size
// clang-format off
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], // yuck
// clang-format on
(uint16_t)dns.getPort(),
nullptr // dns server name (for TLS SNI which we don't care about)
);
}
else
@ -87,14 +114,19 @@ namespace llarp {
auto ipv4 = dns.getIPv4();
static_assert(sizeof(ipv4) == 4);
auto* a = reinterpret_cast<const uint8_t*>(&ipv4);
resolved_call(bus, "SetLinkDNSEx", "ia(iayqs)",
(int32_t) if_ndx,
(int) 1, // number of "iayqs"s we are passing
(int32_t) AF_INET, // network address type
(int) 4, // network addr byte size
resolved_call(
bus,
"SetLinkDNSEx",
"ia(iayqs)",
(int32_t)if_ndx,
(int)1, // number of "iayqs"s we are passing
(int32_t)AF_INET, // network address type
(int)4, // network addr byte size
// clang-format off
a[0], a[1], a[2], a[3], // yuck
(uint16_t) dns.getPort(),
nullptr // dns server name (for TLS SNI which we don't care about)
// clang-format on
(uint16_t)dns.getPort(),
nullptr // dns server name (for TLS SNI which we don't care about)
);
}
@ -102,31 +134,39 @@ namespace llarp {
// Setting "." as a routing domain gives this DNS server higher priority in resolution
// compared to dns servers that are set without a domain (e.g. the default for a
// DHCP-configured DNS server)
resolved_call(bus, "SetLinkDomains", "ia(sb)",
(int32_t) if_ndx,
(int) 1, // array size
"." // global DNS root
);
resolved_call(
bus,
"SetLinkDomains",
"ia(sb)",
(int32_t)if_ndx,
(int)1, // array size
"." // global DNS root
);
else
// Only resolve .loki and .snode through lokinet (so you keep using your local DNS server for
// everything else, which is nicer than forcing everything though lokinet's upstream DNS).
resolved_call(bus, "SetLinkDomains", "ia(sb)",
(int32_t) if_ndx,
(int) 2, // array size
"loki", // domain
(int) 1, // routing domain = true
"snode", // domain
(int) 1 // routing domain = true
);
// Only resolve .loki and .snode through lokinet (so you keep using your local DNS server
// for everything else, which is nicer than forcing everything though lokinet's upstream
// DNS).
resolved_call(
bus,
"SetLinkDomains",
"ia(sb)",
(int32_t)if_ndx,
(int)2, // array size
"loki", // domain
(int)1, // routing domain = true
"snode", // domain
(int)1 // routing domain = true
);
return true;
} catch (const std::exception& e) {
}
catch (const std::exception& e)
{
LogWarn("Failed to set DNS via systemd-resolved: ", e.what());
}
return false;
}
#endif // WITH_SYSTEMD
#endif // WITH_SYSTEMD
} // namespace llarp
} // namespace llarp

@ -14,5 +14,6 @@ namespace llarp
/// \param dns -- the listening address of the lokinet DNS server
/// \param global -- whether to set up lokinet for all DNS queries (true) or just .loki & .snode
/// addresses (false).
bool systemd_resolved_set_dns(std::string if_name, llarp::SockAddr dns, bool global);
}
bool
systemd_resolved_set_dns(std::string if_name, llarp::SockAddr dns, bool global);
} // namespace llarp

Loading…
Cancel
Save