From 75386a02773276c470451d72402a08e5ca83a86c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 10:52:04 +0200 Subject: 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 --- man/nm-cloud-setup.xml | 4 ++- src/nm-cloud-setup/nmcs-provider-azure.c | 45 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/man/nm-cloud-setup.xml b/man/nm-cloud-setup.xml index 388ef3ba91..5657c7fcc7 100644 --- a/man/nm-cloud-setup.xml +++ b/man/nm-cloud-setup.xml @@ -317,7 +317,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. diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index 486c3dbbce..9ced8c4571 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-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; @@ -159,6 +160,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); @@ -181,6 +194,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; @@ -198,6 +215,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, @@ -288,6 +316,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), -- cgit v1.2.1