From 302779f46c6d04eb92257606826c97c0e226ff29 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 13:46:29 +0200 Subject: [PATCH 1/4] cloud-setup: remove redundant check in Azure's _get_net_ifaces_list_cb() This condition always true, because there is a check above. (cherry picked from commit d3f07d5ca2a459e3410611902d2de02bb7be1ae7) (cherry picked from commit 3256239b1f2b31359861c85c642c7009f07f3797) --- clients/cloud-setup/nmcs-provider-azure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cloud-setup/nmcs-provider-azure.c b/clients/cloud-setup/nmcs-provider-azure.c index a0e6076fd3..b9c0ffc08a 100644 --- a/clients/cloud-setup/nmcs-provider-azure.c +++ b/clients/cloud-setup/nmcs-provider-azure.c @@ -434,7 +434,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat * extra NULL character after the buffer. */ ((char *) line)[line_len] = '\0'; - if (line[line_len - 1] == '/' && line_len != 0) + if (line[line_len - 1] == '/') ((char *) line)[--line_len] = '\0'; intern_iface_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXSSIZE, -1); -- 2.31.1 From 0b885286ad2a350d14933b54002b943cc032ad96 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 14:31:58 +0200 Subject: [PATCH 2/4] cloud-setup/azure: cleanup constructing URI in _get_config_ips_prefix_list_cb() (cherry picked from commit c9fc3f5b037422e7ead7f5ef1a56fcd2a750d152) (cherry picked from commit 57c6a4fddc20af78b1594515981d174fa43383c9) --- clients/cloud-setup/nmcs-provider-azure.c | 58 +++++++++++------------ 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/clients/cloud-setup/nmcs-provider-azure.c b/clients/cloud-setup/nmcs-provider-azure.c index b9c0ffc08a..98b34e2960 100644 --- a/clients/cloud-setup/nmcs-provider-azure.c +++ b/clients/cloud-setup/nmcs-provider-azure.c @@ -216,6 +216,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u NMCSProviderGetConfigTaskData *get_config_data; const char * line; gsize line_len; + char iface_idx_str[30]; nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error); @@ -231,12 +232,16 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u /* NMHttpClient guarantees that there is a trailing NUL after the data. */ nm_assert(response_str[response_len] == 0); - nm_assert(!iface_data->iface_get_config->has_ipv4s); nm_assert(!iface_data->iface_get_config->ipv4s_arr); + nm_assert(!iface_data->iface_get_config->has_ipv4s); nm_assert(!iface_data->iface_get_config->has_cidr); + nm_sprintf_buf(iface_idx_str, "%" G_GSSIZE_FORMAT, iface_data->intern_iface_idx); + while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) { - gint64 ips_prefix_idx; + gint64 ips_prefix_idx; + gs_free char *uri = NULL; + char buf[100]; if (line_len == 0) continue; @@ -251,45 +256,36 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u if (ips_prefix_idx < 0) continue; - { - gs_free const char *uri = NULL; - char buf[100]; - - iface_data->n_iface_data_pending++; - - nm_http_client_poll_get( - NM_HTTP_CLIENT(source), - (uri = _azure_uri_interfaces(nm_sprintf_buf( - buf, - "%" G_GSSIZE_FORMAT "/ipv4/ipAddress/%" G_GINT64_FORMAT "/privateIpAddress", - iface_data->intern_iface_idx, - ips_prefix_idx))), - HTTP_TIMEOUT_MS, - 512 * 1024, - 10000, - 1000, - NM_MAKE_STRV(NM_AZURE_METADATA_HEADER), - get_config_data->intern_cancellable, - NULL, - NULL, - _get_config_fetch_done_cb_private_ipv4s, - iface_data); - } + iface_data->n_iface_data_pending++; + + nm_http_client_poll_get( + NM_HTTP_CLIENT(source), + (uri = _azure_uri_interfaces(iface_idx_str, + "/ipv4/ipAddress/", + nm_sprintf_buf(buf, "%" G_GINT64_FORMAT, ips_prefix_idx), + "/privateIpAddress")), + HTTP_TIMEOUT_MS, + 512 * 1024, + 10000, + 1000, + NM_MAKE_STRV(NM_AZURE_METADATA_HEADER), + get_config_data->intern_cancellable, + NULL, + NULL, + _get_config_fetch_done_cb_private_ipv4s, + iface_data); } iface_data->iface_get_config->ipv4s_len = 0; iface_data->iface_get_config->ipv4s_arr = g_new(in_addr_t, iface_data->n_iface_data_pending); { - gs_free const char *uri = NULL; - char buf[30]; + gs_free char *uri = NULL; iface_data->n_iface_data_pending++; nm_http_client_poll_get( NM_HTTP_CLIENT(source), - (uri = _azure_uri_interfaces( - nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT, iface_data->intern_iface_idx), - "/ipv4/subnet/0/prefix/")), + (uri = _azure_uri_interfaces(iface_idx_str, "/ipv4/subnet/0/prefix/")), HTTP_TIMEOUT_MS, 512 * 1024, 10000, -- 2.31.1 From 9173aee61c088badbe172019de1f05e20e25aa52 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 14:56:15 +0200 Subject: [PATCH 3/4] cloud-setup/azure: refactor callback for _get_config_ips_prefix_list_cb() (cherry picked from commit 889498c12cc5cd4ab718cbc8adbccc1f197adda5) (cherry picked from commit 783d470b6f741c79d2b38d229db0338210343a35) --- clients/cloud-setup/nmcs-provider-azure.c | 75 ++++++++++++----------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/clients/cloud-setup/nmcs-provider-azure.c b/clients/cloud-setup/nmcs-provider-azure.c index 98b34e2960..c7dbc712cb 100644 --- a/clients/cloud-setup/nmcs-provider-azure.c +++ b/clients/cloud-setup/nmcs-provider-azure.c @@ -93,6 +93,11 @@ detect(NMCSProvider *provider, GTask *task) /*****************************************************************************/ +typedef enum { + GET_CONFIG_FETCH_TYPE_IPV4_IPADDRESS_X_PRIVATEIPADDRESS, + GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_PREFIX, +} GetConfigFetchType; + typedef struct { NMCSProviderGetConfigTaskData * get_config_data; NMCSProviderGetConfigIfaceData *iface_get_config; @@ -108,25 +113,28 @@ _azure_iface_data_destroy(AzureIfaceData *iface_data) } static void -_get_config_fetch_done_cb(NMHttpClient * http_client, - GAsyncResult * result, - AzureIfaceData *iface_data, - gboolean is_ipv4) +_get_config_fetch_done_cb(NMHttpClient * http_client, + GAsyncResult * result, + AzureIfaceData * iface_data, + GetConfigFetchType fetch_type) { NMCSProviderGetConfigTaskData * get_config_data; NMCSProviderGetConfigIfaceData *iface_get_config; gs_unref_bytes GBytes *response = NULL; gs_free_error GError *error = NULL; - gs_free char * v_hwaddr = NULL; const char * resp_str = NULL; gsize resp_len; + char tmp_addr_str[NM_UTILS_INET_ADDRSTRLEN]; + in_addr_t tmp_addr; + int tmp_prefix = -1; nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error); if (nm_utils_error_is_cancelled(error)) return; - get_config_data = iface_data->get_config_data; + get_config_data = iface_data->get_config_data; + iface_get_config = iface_data->iface_get_config; if (error) goto out_done; @@ -134,36 +142,23 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, resp_str = g_bytes_get_data(response, &resp_len); nm_assert(resp_str[resp_len] == '\0'); - v_hwaddr = nmcs_utils_hwaddr_normalize_gbytes(response); - if (!v_hwaddr) { - _LOGI("interface[%" G_GSSIZE_FORMAT "]: invalid MAC address returned", - iface_data->intern_iface_idx); - error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, - "invalid MAC address for index %" G_GSSIZE_FORMAT, - iface_data->intern_iface_idx); - goto out_done; - } - - iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr); - iface_get_config = iface_data->iface_get_config; - - if (is_ipv4) { - char tmp_addr_str[NM_UTILS_INET_ADDRSTRLEN]; - in_addr_t tmp_addr; + switch (fetch_type) { + case GET_CONFIG_FETCH_TYPE_IPV4_IPADDRESS_X_PRIVATEIPADDRESS: if (!nmcs_utils_ipaddr_normalize_bin(AF_INET, resp_str, resp_len, NULL, &tmp_addr)) { error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "ip is not a valid private ip address"); goto out_done; } - _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding private ip %s", + _LOGD("interface[%" G_GSSIZE_FORMAT "]: received address %s", iface_data->intern_iface_idx, _nm_utils_inet4_ntop(tmp_addr, tmp_addr_str)); iface_get_config->ipv4s_arr[iface_get_config->ipv4s_len] = tmp_addr; iface_get_config->has_ipv4s = TRUE; iface_get_config->ipv4s_len++; - } else { - int tmp_prefix; + break; + + case GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_PREFIX: tmp_prefix = _nm_utils_ascii_str_to_int64_bin(resp_str, resp_len, 10, 0, 32, -1); if (tmp_prefix == -1) { @@ -173,11 +168,11 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, goto out_done; } - _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding prefix %d", + _LOGD("interface[%" G_GSSIZE_FORMAT "]: received subnet prefix %d", iface_data->intern_iface_idx, tmp_prefix); iface_get_config->cidr_prefix = tmp_prefix; - iface_get_config->has_cidr = TRUE; + break; } out_done: @@ -192,17 +187,25 @@ out_done: } static void -_get_config_fetch_done_cb_private_ipv4s(GObject *source, GAsyncResult *result, gpointer user_data) +_get_config_fetch_done_cb_ipv4_ipaddress_x_privateipaddress(GObject * source, + GAsyncResult *result, + gpointer user_data) { - _get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, TRUE); + _get_config_fetch_done_cb(NM_HTTP_CLIENT(source), + result, + user_data, + GET_CONFIG_FETCH_TYPE_IPV4_IPADDRESS_X_PRIVATEIPADDRESS); } static void -_get_config_fetch_done_cb_subnet_cidr_prefix(GObject * source, - GAsyncResult *result, - gpointer user_data) +_get_config_fetch_done_cb_ipv4_subnet_0_prefix(GObject * source, + GAsyncResult *result, + gpointer user_data) { - _get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, FALSE); + _get_config_fetch_done_cb(NM_HTTP_CLIENT(source), + result, + user_data, + GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_PREFIX); } static void @@ -245,6 +248,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u if (line_len == 0) continue; + /* Truncate the string. It's safe to do, because we own @response an it has an * extra NULL character after the buffer. */ ((char *) line)[line_len] = '\0'; @@ -253,6 +257,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u ((char *) line)[--line_len] = '\0'; ips_prefix_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXINT64, -1); + if (ips_prefix_idx < 0) continue; @@ -272,7 +277,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u get_config_data->intern_cancellable, NULL, NULL, - _get_config_fetch_done_cb_private_ipv4s, + _get_config_fetch_done_cb_ipv4_ipaddress_x_privateipaddress, iface_data); } @@ -294,7 +299,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u get_config_data->intern_cancellable, NULL, NULL, - _get_config_fetch_done_cb_subnet_cidr_prefix, + _get_config_fetch_done_cb_ipv4_subnet_0_prefix, iface_data); } return; -- 2.31.1 From ff2c2c4cabefc178767c4f535b9c82da7d765d6e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 10:52:04 +0200 Subject: [PATCH 4/4] cloud-setup/azure: fix detecting the gateway address The code never set "iface_get_config->cidr_addr", despite setting "cidr_prefix" and "has_cidr". As a result, cloud-setup would think that the subnet is "0.0.0.0/$PLEN", and calculate the gateway as "0.0.0.1". As a result it would add a default route to table 30400 via 0.0.0.1, which is obviously wrong. How to detect the right gateway? Let's try obtain the subnet also via the meta data. That seems mostly correct, except that we only access subnet at index 0. What if there are multiple ones? I don't know. https://bugzilla.redhat.com/show_bug.cgi?id=1912236 (cherry picked from commit c2629f72b0e6b438bf3f2b93967f58c9defafea6) (cherry picked from commit 5d112092bc184ac284cb7f6c5fda68fcd5f5cd22) --- clients/cloud-setup/nmcs-provider-azure.c | 45 +++++++++++++++++++++++ man/nm-cloud-setup.xml | 4 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/clients/cloud-setup/nmcs-provider-azure.c b/clients/cloud-setup/nmcs-provider-azure.c index c7dbc712cb..28019bac42 100644 --- a/clients/cloud-setup/nmcs-provider-azure.c +++ b/clients/cloud-setup/nmcs-provider-azure.c @@ -95,6 +95,7 @@ detect(NMCSProvider *provider, GTask *task) typedef enum { GET_CONFIG_FETCH_TYPE_IPV4_IPADDRESS_X_PRIVATEIPADDRESS, + GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_ADDRESS, GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_PREFIX, } GetConfigFetchType; @@ -158,6 +159,18 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, iface_get_config->ipv4s_len++; break; + case GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_ADDRESS: + + if (!nmcs_utils_ipaddr_normalize_bin(AF_INET, resp_str, resp_len, NULL, &tmp_addr)) { + error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "ip is not a subnet address"); + goto out_done; + } + _LOGD("interface[%" G_GSSIZE_FORMAT "]: received subnet address %s", + iface_data->intern_iface_idx, + _nm_utils_inet4_ntop(tmp_addr, tmp_addr_str)); + iface_get_config->cidr_addr = tmp_addr; + break; + case GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_PREFIX: tmp_prefix = _nm_utils_ascii_str_to_int64_bin(resp_str, resp_len, 10, 0, 32, -1); @@ -180,6 +193,10 @@ out_done: --iface_data->n_iface_data_pending; if (iface_data->n_iface_data_pending > 0) return; + + /* we surely have cidr_addr and cidr_prefix, otherwise + * we would have errored out above. */ + iface_get_config->has_cidr = TRUE; } --get_config_data->n_pending; @@ -197,6 +214,17 @@ _get_config_fetch_done_cb_ipv4_ipaddress_x_privateipaddress(GObject * source GET_CONFIG_FETCH_TYPE_IPV4_IPADDRESS_X_PRIVATEIPADDRESS); } +static void +_get_config_fetch_done_cb_ipv4_subnet_0_address(GObject * source, + GAsyncResult *result, + gpointer user_data) +{ + _get_config_fetch_done_cb(NM_HTTP_CLIENT(source), + result, + user_data, + GET_CONFIG_FETCH_TYPE_IPV4_SUBNET_0_ADDRESS); +} + static void _get_config_fetch_done_cb_ipv4_subnet_0_prefix(GObject * source, GAsyncResult *result, @@ -287,6 +315,23 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u { gs_free char *uri = NULL; + iface_data->n_iface_data_pending++; + nm_http_client_poll_get( + NM_HTTP_CLIENT(source), + (uri = _azure_uri_interfaces(iface_idx_str, "/ipv4/subnet/0/address/")), + HTTP_TIMEOUT_MS, + 512 * 1024, + 10000, + 1000, + NM_MAKE_STRV(NM_AZURE_METADATA_HEADER), + get_config_data->intern_cancellable, + NULL, + NULL, + _get_config_fetch_done_cb_ipv4_subnet_0_address, + iface_data); + + nm_clear_g_free(&uri); + iface_data->n_iface_data_pending++; nm_http_client_poll_get( NM_HTTP_CLIENT(source), diff --git a/man/nm-cloud-setup.xml b/man/nm-cloud-setup.xml index 4ae4042f84..a4ed737bc5 100644 --- a/man/nm-cloud-setup.xml +++ b/man/nm-cloud-setup.xml @@ -329,7 +329,9 @@ Then, for each IP address index fetch the address at http://169.254.169.254/metadata/instance/network/interface/$IFACE_INDEX/ipv4/ipAddress/$ADDR_INDEX/privateIpAddress?format=text&api-version=2017-04-02. - Also fetch the size of the subnet (the netmask) for the interface from + Also fetch the size of the subnet and prefix for the interface from + http://169.254.169.254/metadata/instance/network/interface/$IFACE_INDEX/ipv4/subnet/0/address/?format=text&api-version=2017-04-02. + and http://169.254.169.254/metadata/instance/network/interface/$IFACE_INDEX/ipv4/subnet/0/prefix/?format=text&api-version=2017-04-02. -- 2.31.1