mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
resolved: add a helper to check if DNS server is accessible
We check this by opening a UDP socket and attempting to connect. We do not send any traffic on it, but this will tell us if there are routes to the DNS server. This will be used in a later commit.
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-dns-stub.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "resolved-resolv-conf.h"
|
||||
#include "siphash24.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
||||
@@ -69,6 +74,7 @@ int dns_server_new(
|
||||
.ifindex = ifindex,
|
||||
.server_name = TAKE_PTR(name),
|
||||
.config_source = config_source,
|
||||
.accessible = -1,
|
||||
};
|
||||
|
||||
dns_server_reset_features(s);
|
||||
@@ -1128,3 +1134,49 @@ int dns_server_dump_state_to_json(DnsServer *server, sd_json_variant **ret) {
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("PacketInvalid", server->packet_invalid),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("PacketDoOff", server->packet_do_off));
|
||||
}
|
||||
|
||||
int dns_server_is_accessible(DnsServer *s) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
union sockaddr_union sa;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->accessible >= 0)
|
||||
return s->accessible;
|
||||
|
||||
r = sockaddr_set_in_addr(&sa, s->family, &s->address, dns_server_port(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fd = socket(s->family, SOCK_DGRAM|SOCK_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (s->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &s->address)) {
|
||||
/* Connecting to ipv6 link-local requires binding to an interface. */
|
||||
r = socket_bind_to_ifindex(fd, dns_server_ifindex(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = RET_NERRNO(connect(fd, &sa.sa, SOCKADDR_LEN(sa)));
|
||||
if (!IN_SET(r,
|
||||
0,
|
||||
-ENETUNREACH,
|
||||
-EHOSTDOWN,
|
||||
-EHOSTUNREACH,
|
||||
-ENETDOWN,
|
||||
-ENETRESET,
|
||||
-ENONET))
|
||||
/* If we did not receive one of the expected return values,
|
||||
* then leave the accessible flag untouched. */
|
||||
return r;
|
||||
|
||||
return (s->accessible = r >= 0);
|
||||
}
|
||||
|
||||
void dns_server_reset_accessible_all(DnsServer *first) {
|
||||
LIST_FOREACH(servers, s, first)
|
||||
dns_server_reset_accessible(s);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,9 @@ struct DnsServer {
|
||||
|
||||
/* Servers registered via D-Bus are not removed on reload */
|
||||
ResolveConfigSource config_source;
|
||||
|
||||
/* Tri-state to indicate if the DNS server is accessible. */
|
||||
int accessible;
|
||||
};
|
||||
|
||||
int dns_server_new(
|
||||
@@ -187,3 +190,9 @@ static inline bool dns_server_is_fallback(DnsServer *s) {
|
||||
}
|
||||
|
||||
int dns_server_dump_state_to_json(DnsServer *server, sd_json_variant **ret);
|
||||
|
||||
int dns_server_is_accessible(DnsServer *s);
|
||||
static inline void dns_server_reset_accessible(DnsServer *s) {
|
||||
s->accessible = -1;
|
||||
}
|
||||
void dns_server_reset_accessible_all(DnsServer *first);
|
||||
|
||||
@@ -299,6 +299,9 @@ static int link_update_dns_servers(Link *l) {
|
||||
}
|
||||
|
||||
dns_server_unlink_marked(l->dns_servers);
|
||||
|
||||
dns_server_reset_accessible_all(l->dns_servers);
|
||||
|
||||
return 0;
|
||||
|
||||
clear:
|
||||
|
||||
Reference in New Issue
Block a user