connectivity: fix constructing hosts list for CURLOPT_RESOLVE

Curl's CURLOPT_RESOLVE expects one list entry per host. That
documentation ([1]) also makes that clear that the form is
"[+]HOST:PORT:ADDRESS[,ADDRESS]".

The way we constructed the list, only the last entry was honored:

  <trace> [1647551393.5362] connectivity: (eth0,IPv4,25) adding 'fedoraproject.org:80:18.159.254.57' to curl resolve list
  <trace> [1647551393.5363] connectivity: (eth0,IPv4,25) adding 'fedoraproject.org:80:152.19.134.142' to curl resolve list
  <trace> [1647551393.5363] connectivity: (eth0,IPv4,25) adding 'fedoraproject.org:80:18.192.40.85' to curl resolve list
  ...
  <trace> [1647551393.5366] connectivity: (eth0,IPv4,25) adding 'fedoraproject.org:80:85.236.55.6' to curl resolve list
  <trace> [1647551393.5366] connectivity: (eth0,IPv4,25) adding 'fedoraproject.org:80:38.145.60.20' to curl resolve list
  ...
  <trace> [1647551393.5415] connectivity: (eth0,IPv4,25) libcurl: == Info: Added fedoraproject.org:80:18.159.254.57 to DNS cache\012
  <trace> [1647551393.5416] connectivity: (eth0,IPv4,25) libcurl: == Info: RESOLVE fedoraproject.org:80 is - old addresses discarded!\012
  <trace> [1647551393.5416] connectivity: (eth0,IPv4,25) libcurl: == Info: Added fedoraproject.org:80:152.19.134.142 to DNS cache\012
  <trace> [1647551393.5417] connectivity: (eth0,IPv4,25) libcurl: == Info: RESOLVE fedoraproject.org:80 is - old addresses discarded!\012
  ...
  <trace> [1647551393.5422] connectivity: (eth0,IPv4,25) libcurl: == Info: RESOLVE fedoraproject.org:80 is - old addresses discarded!\012
  <trace> [1647551393.5423] connectivity: (eth0,IPv4,25) libcurl: == Info: Added fedoraproject.org:80:38.145.60.20 to DNS cache\012
  <trace> [1647551393.5424] connectivity: (eth0,IPv4,25) libcurl: == Info: Hostname fedoraproject.org was found in DNS cache\012
  <trace> [1647551393.5424] connectivity: (eth0,IPv4,25) libcurl: == Info:   Trying 38.145.60.20:80...\012

There are two possible fixes. Either join all addresses in one
entry, or use the '+' modifier. Do the former.

Now we get:

  <trace> [1647551967.0378] connectivity: (eth0,IPv4,25) set curl resolve list to 'fedoraproject.org:80:38.145.60.21,152.19.134.142,152...
  ...
  <trace> [1647551967.0559] connectivity: (eth0,IPv4,25) libcurl: == Info: Added fedoraproject.org:80:38.145.60.21,152.19.134.142,152.1...
  <trace> [1647551967.0560] connectivity: (eth0,IPv4,25) libcurl: == Info: Hostname fedoraproject.org was found in DNS cache\012
  <trace> [1647551967.0561] connectivity: (eth0,IPv4,25) libcurl: == Info:   Trying 38.145.60.21:80...\012

[1] https://curl.se/libcurl/c/CURLOPT_RESOLVE.html

Reported-by: Bastien Nocera <hadess@hadess.net>

Fixes: 2cec94bacc ('connectivity: use systemd-resolved for resolving the check endpoint')

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/648#note_1301596

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1153
This commit is contained in:
Thomas Haller 2022-03-17 22:01:24 +01:00
parent 1916c55d3a
commit 14b9a9bd9d
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728

View file

@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>
#include "c-list/src/c-list.h"
#include "libnm-glib-aux/nm-str-buf.h"
#include "libnm-platform/nmp-object.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-config.h"
@ -758,7 +759,8 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data)
int addr_family;
gsize len = 0;
gsize i;
gs_free_error GError *error = NULL;
gs_free_error GError *error = NULL;
nm_auto_str_buf NMStrBuf strbuf_hosts = NM_STR_BUF_INIT(0, FALSE);
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error);
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@ -781,7 +783,6 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data)
for (i = 0; i < no_addresses; i++) {
gs_unref_variant GVariant *address = NULL;
char str_addr[NM_UTILS_INET_ADDRSTRLEN];
gs_free char *host_entry = NULL;
const guchar *address_buf;
g_variant_get_child(addresses, i, "(ii@ay)", &ifindex, &addr_family, &address);
@ -796,13 +797,21 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data)
if (len != nm_utils_addr_family_to_size(addr_family))
continue;
host_entry = g_strdup_printf("%s:%s:%s",
if (strbuf_hosts.len == 0) {
nm_str_buf_append_printf(&strbuf_hosts,
"%s:%s:",
cb_data->concheck.con_config->host,
cb_data->concheck.con_config->port ?: "80",
nm_utils_inet_ntop(addr_family, address_buf, str_addr));
cb_data->concheck.con_config->port ?: "80");
} else
nm_str_buf_append_c(&strbuf_hosts, ',');
cb_data->concheck.hosts = curl_slist_append(cb_data->concheck.hosts, host_entry);
_LOG2T("adding '%s' to curl resolve list", host_entry);
nm_str_buf_append(&strbuf_hosts, nm_utils_inet_ntop(addr_family, address_buf, str_addr));
}
if (strbuf_hosts.len > 0) {
const char *s = nm_str_buf_get_str(&strbuf_hosts);
cb_data->concheck.hosts = curl_slist_append(NULL, s);
_LOG2T("set curl resolve list to '%s'", s);
}
do_curl_request(cb_data);