mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 05:50:06 +01:00
core: restrict connectivity check lookups to per-link DNS if available
Restrict connectivity check DNS lookups to just the relevant link if the link has a per-link DNS resolver configured. This change was previously discussed as part of issue https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1836, and brings NM's behavior back in line with the behavior documented in the man page. The connectivity check checks for a per-link DNS resolver by querying systemd-resolved's `ScopeMask` for the link; this involves a small D-Bus roundtrip, but is ultimately the more flexible solution since it is also capable of dealing with per-link DNS configuration stemming from other sources. Fixes:e6dac4f0b6('core: don't restrict DNS interface when performing connectivity check') (cherry picked from commit6e2de1d2b3) (cherry picked from commit4610511bcd)
This commit is contained in:
parent
ce95405af9
commit
418c36be07
1 changed files with 118 additions and 16 deletions
|
|
@ -77,6 +77,8 @@ struct _NMConnectivityCheckHandle {
|
|||
ConConfig *con_config;
|
||||
|
||||
GCancellable *resolve_cancellable;
|
||||
int resolve_ifindex;
|
||||
GDBusConnection *dbus_connection;
|
||||
CURLM *curl_mhandle;
|
||||
CURL *curl_ehandle;
|
||||
struct curl_slist *request_headers;
|
||||
|
|
@ -953,6 +955,113 @@ systemd_resolved_resolve_cb(GObject *object, GAsyncResult *res, gpointer user_da
|
|||
do_curl_request(cb_data, nm_str_buf_get_str(&strbuf_hosts));
|
||||
}
|
||||
|
||||
static void
|
||||
systemd_resolved_resolve(NMConnectivityCheckHandle *cb_data)
|
||||
{
|
||||
_LOG2D("start request to '%s' (try resolving '%s' using systemd-resolved with ifindex %d)",
|
||||
cb_data->concheck.con_config->uri,
|
||||
cb_data->concheck.con_config->host,
|
||||
cb_data->concheck.resolve_ifindex);
|
||||
|
||||
g_dbus_connection_call(cb_data->concheck.dbus_connection,
|
||||
"org.freedesktop.resolve1",
|
||||
"/org/freedesktop/resolve1",
|
||||
"org.freedesktop.resolve1.Manager",
|
||||
"ResolveHostname",
|
||||
g_variant_new("(isit)",
|
||||
(gint32) cb_data->concheck.resolve_ifindex,
|
||||
cb_data->concheck.con_config->host,
|
||||
(gint32) cb_data->addr_family,
|
||||
SD_RESOLVED_DNS),
|
||||
G_VARIANT_TYPE("(a(iiay)st)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cb_data->concheck.resolve_cancellable,
|
||||
systemd_resolved_resolve_cb,
|
||||
cb_data);
|
||||
}
|
||||
|
||||
static void
|
||||
systemd_resolved_link_scopes_cb(GObject *object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
NMConnectivityCheckHandle *cb_data;
|
||||
gs_unref_variant GVariant *result = NULL;
|
||||
gs_unref_variant GVariant *value = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
guint64 scope_mask = 0;
|
||||
|
||||
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error);
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
return;
|
||||
|
||||
cb_data = user_data;
|
||||
|
||||
if (!result) {
|
||||
_LOG2D("unable to obtain systemd-resolved link ScopesMask for interface %d: %s",
|
||||
cb_data->concheck.resolve_ifindex,
|
||||
error->message);
|
||||
|
||||
cb_data->concheck.resolve_ifindex = 0;
|
||||
systemd_resolved_resolve(cb_data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get(result, "(v)", &value);
|
||||
g_variant_get(value, "t", &scope_mask);
|
||||
|
||||
if (!(scope_mask & SD_RESOLVED_DNS)) {
|
||||
/* there is no per-link DNS configured / active; query all available /
|
||||
* system DNS resolvers instead of restricting the lookup to just this
|
||||
* one, which would turn up no results. */
|
||||
_LOG2D("no per-link DNS available (scope mask %" G_GUINT64_FORMAT
|
||||
"); falling back to system-wide lookups",
|
||||
scope_mask);
|
||||
cb_data->concheck.resolve_ifindex = 0;
|
||||
}
|
||||
|
||||
systemd_resolved_resolve(cb_data);
|
||||
}
|
||||
|
||||
static void
|
||||
systemd_resolved_get_link_cb(GObject *object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
NMConnectivityCheckHandle *cb_data;
|
||||
gs_unref_variant GVariant *result = NULL;
|
||||
gs_free char *link_path = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error);
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
return;
|
||||
|
||||
cb_data = user_data;
|
||||
|
||||
if (!result) {
|
||||
_LOG2D("unable to obtain systemd-resolved link D-Bus object for interface %d: %s",
|
||||
cb_data->concheck.resolve_ifindex,
|
||||
error->message);
|
||||
|
||||
cb_data->concheck.resolve_ifindex = 0;
|
||||
systemd_resolved_resolve(cb_data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get(result, "(o)", &link_path);
|
||||
|
||||
g_dbus_connection_call(cb_data->concheck.dbus_connection,
|
||||
"org.freedesktop.resolve1",
|
||||
link_path,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get",
|
||||
g_variant_new("(ss)", "org.freedesktop.resolve1.Link", "ScopesMask"),
|
||||
G_VARIANT_TYPE("(v)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cb_data->concheck.resolve_cancellable,
|
||||
systemd_resolved_link_scopes_cb,
|
||||
cb_data);
|
||||
}
|
||||
|
||||
static NMConnectivityState
|
||||
check_platform_config(NMConnectivity *self,
|
||||
NMPlatform *platform,
|
||||
|
|
@ -1067,6 +1176,7 @@ nm_connectivity_check_start(NMConnectivity *self,
|
|||
}
|
||||
|
||||
cb_data->concheck.resolve_cancellable = g_cancellable_new();
|
||||
cb_data->concheck.resolve_ifindex = ifindex;
|
||||
|
||||
/* note that we pick up support for systemd-resolved right away when we need it.
|
||||
* We don't need to remember the setting, because we can (cheaply) check anew
|
||||
|
|
@ -1089,10 +1199,8 @@ nm_connectivity_check_start(NMConnectivity *self,
|
|||
has_systemd_resolved = !!nm_dns_manager_get_systemd_resolved(nm_dns_manager_get());
|
||||
|
||||
if (has_systemd_resolved) {
|
||||
GDBusConnection *dbus_connection;
|
||||
|
||||
dbus_connection = NM_MAIN_DBUS_CONNECTION_GET;
|
||||
if (!dbus_connection) {
|
||||
cb_data->concheck.dbus_connection = NM_MAIN_DBUS_CONNECTION_GET;
|
||||
if (!cb_data->concheck.dbus_connection) {
|
||||
/* we have no D-Bus connection? That might happen in configure and quit mode.
|
||||
*
|
||||
* Anyway, something is very odd, just fail connectivity check. */
|
||||
|
|
@ -1103,25 +1211,19 @@ nm_connectivity_check_start(NMConnectivity *self,
|
|||
return cb_data;
|
||||
}
|
||||
|
||||
g_dbus_connection_call(dbus_connection,
|
||||
/* first check whether there has been a per-link DNS configured */
|
||||
g_dbus_connection_call(cb_data->concheck.dbus_connection,
|
||||
"org.freedesktop.resolve1",
|
||||
"/org/freedesktop/resolve1",
|
||||
"org.freedesktop.resolve1.Manager",
|
||||
"ResolveHostname",
|
||||
g_variant_new("(isit)",
|
||||
0,
|
||||
cb_data->concheck.con_config->host,
|
||||
(gint32) cb_data->addr_family,
|
||||
SD_RESOLVED_DNS),
|
||||
G_VARIANT_TYPE("(a(iiay)st)"),
|
||||
"GetLink",
|
||||
g_variant_new("(i)", ifindex),
|
||||
G_VARIANT_TYPE("(o)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cb_data->concheck.resolve_cancellable,
|
||||
systemd_resolved_resolve_cb,
|
||||
systemd_resolved_get_link_cb,
|
||||
cb_data);
|
||||
_LOG2D("start request to '%s' (try resolving '%s' using systemd-resolved)",
|
||||
cb_data->concheck.con_config->uri,
|
||||
cb_data->concheck.con_config->host);
|
||||
return cb_data;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue