From 70b7ad1a761405f4ac9398832d0365c47cd5aa0f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 12:14:13 +0200 Subject: [PATCH 1/7] glib-aux: add _nm_utils_ascii_str_to_int64_bin() helper --- src/libnm-glib-aux/nm-shared-utils.c | 39 ++++++++++++++++++++++++++++ src/libnm-glib-aux/nm-shared-utils.h | 7 +++++ 2 files changed, 46 insertions(+) diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index aa1be1f28f..f8b12c47ac 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -1443,6 +1443,45 @@ _nm_utils_ascii_str_to_uint64(const char *str, /*****************************************************************************/ +gint64 +_nm_utils_ascii_str_to_int64_bin(const char *str, + gssize len, + guint base, + gint64 min, + gint64 max, + gint64 fallback) +{ + gs_free char *str_clone = NULL; + + /* This is like _nm_utils_ascii_str_to_int64(), but the user may provide + * an optional string length, in which case str is not assumed to be NUL + * terminated. In that case, any NUL characters inside the first len characters + * lead to a failure, except one last NUL character is allowed. */ + + if (len >= 0) { + gsize l = len; + + nm_assert(l == 0 || str); + + if (l > 0 && str[l - 1u] == '\0') { + /* we accept one '\0' at the end of the string. */ + l--; + } + + if (l > 0 && memchr(str, '\0', l)) { + /* but we don't accept other NUL characters in the middle. */ + errno = EINVAL; + return fallback; + } + + str = nm_strndup_a(300, str, len, &str_clone); + } + + return _nm_utils_ascii_str_to_int64(str, base, min, max, fallback); +} + +/*****************************************************************************/ + int nm_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data) { diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index d173db7c4d..36f05d6730 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -985,6 +985,13 @@ guint64 _nm_utils_ascii_str_to_uint64(const char *str, guint64 max, guint64 fallback); +gint64 _nm_utils_ascii_str_to_int64_bin(const char *str, + gssize len, + guint base, + gint64 min, + gint64 max, + gint64 fallback); + int _nm_utils_ascii_str_to_bool(const char *str, int default_value); /*****************************************************************************/ From d3f07d5ca2a459e3410611902d2de02bb7be1ae7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 13:46:29 +0200 Subject: [PATCH 2/7] cloud-setup: remove redundant check in Azure's _get_net_ifaces_list_cb() This condition always true, because there is a check above. --- src/nm-cloud-setup/nmcs-provider-azure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index a46f56a40d..af2062476c 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-cloud-setup/nmcs-provider-azure.c @@ -432,7 +432,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); From a2fded3cee0f6d4da86962bfc671f03bfe4c5da4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 13:46:47 +0200 Subject: [PATCH 3/7] cloud-setup: use _nm_utils_ascii_str_to_int64_bin() in Azure's _get_config_fetch_done_cb() --- src/nm-cloud-setup/nmcs-provider-azure.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index af2062476c..02b42ce6a6 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-cloud-setup/nmcs-provider-azure.c @@ -154,14 +154,9 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, iface_get_config->has_ipv4s = TRUE; iface_get_config->ipv4s_len++; } else { - int tmp_prefix = -1; - - if (fip_len > 0 && memchr(fip_str, '\0', fip_len - 1)) { - /* we have an embedded "\0" inside the string (except trailing). That is not - * allowed*/ - } else - tmp_prefix = _nm_utils_ascii_str_to_int64(fip_str, 10, 0, 32, -1); + int tmp_prefix; + tmp_prefix = _nm_utils_ascii_str_to_int64_bin(fip_str, fip_len, 10, 0, 32, -1); if (tmp_prefix == -1) { _LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix", iface_data->intern_iface_idx); error = @@ -244,7 +239,6 @@ _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; From 89f326785910ca7a4e6994b9d4052f8ab43fc63e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 13:49:04 +0200 Subject: [PATCH 4/7] cloud-setup/trivial: rename variables in Azure's _get_config_fetch_done_cb() The previous name seem not very expressive/fitting. Naming is hard, but I think these are better names. --- src/nm-cloud-setup/nmcs-provider-azure.c | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index 02b42ce6a6..834db5e52b 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-cloud-setup/nmcs-provider-azure.c @@ -98,7 +98,7 @@ typedef struct { NMCSProviderGetConfigIfaceData *iface_get_config; gssize intern_iface_idx; gssize extern_iface_idx; - guint n_ips_prefix_pending; + guint n_iface_data_pending; const char * hwaddr; } AzureIfaceData; @@ -118,8 +118,8 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, NMCSProviderGetConfigIfaceData *iface_get_config; gs_unref_bytes GBytes *response = NULL; gs_free_error GError *error = NULL; - const char * fip_str = NULL; - gsize fip_len; + const char * resp_str = NULL; + gsize resp_len; nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error); @@ -131,8 +131,8 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, if (error) goto out_done; - fip_str = g_bytes_get_data(response, &fip_len); - nm_assert(fip_str[fip_len] == '\0'); + resp_str = g_bytes_get_data(response, &resp_len); + nm_assert(resp_str[resp_len] == '\0'); iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, iface_data->hwaddr); @@ -142,7 +142,7 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, char tmp_addr_str[NM_UTILS_INET_ADDRSTRLEN]; in_addr_t tmp_addr; - if (!nmcs_utils_ipaddr_normalize_bin(AF_INET, fip_str, fip_len, NULL, &tmp_addr)) { + 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; @@ -156,7 +156,7 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, } else { int tmp_prefix; - tmp_prefix = _nm_utils_ascii_str_to_int64_bin(fip_str, fip_len, 10, 0, 32, -1); + tmp_prefix = _nm_utils_ascii_str_to_int64_bin(resp_str, resp_len, 10, 0, 32, -1); if (tmp_prefix == -1) { _LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix", iface_data->intern_iface_idx); error = @@ -173,8 +173,8 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, out_done: if (!error) { - --iface_data->n_ips_prefix_pending; - if (iface_data->n_ips_prefix_pending > 0) + --iface_data->n_iface_data_pending; + if (iface_data->n_iface_data_pending > 0) return; } @@ -246,7 +246,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u gs_free const char *uri = NULL; char buf[100]; - iface_data->n_ips_prefix_pending++; + iface_data->n_iface_data_pending++; nm_http_client_poll_get( NM_HTTP_CLIENT(source), @@ -269,13 +269,13 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u } iface_data->iface_get_config->ipv4s_len = 0; - iface_data->iface_get_config->ipv4s_arr = g_new(in_addr_t, iface_data->n_ips_prefix_pending); + 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]; - iface_data->n_ips_prefix_pending++; + iface_data->n_iface_data_pending++; nm_http_client_poll_get( NM_HTTP_CLIENT(source), (uri = _azure_uri_interfaces( @@ -439,7 +439,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat .iface_get_config = NULL, .intern_iface_idx = intern_iface_idx, .extern_iface_idx = extern_iface_idx_cnt++, - .n_ips_prefix_pending = 0, + .n_iface_data_pending = 0, .hwaddr = NULL, }; g_ptr_array_add(ifaces_arr, iface_data); From c9fc3f5b037422e7ead7f5ef1a56fcd2a750d152 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 14:31:58 +0200 Subject: [PATCH 5/7] cloud-setup/azure: cleanup constructing URI in _get_config_ips_prefix_list_cb() --- src/nm-cloud-setup/nmcs-provider-azure.c | 56 +++++++++++------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index 834db5e52b..b09becb2f6 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-cloud-setup/nmcs-provider-azure.c @@ -207,6 +207,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); @@ -222,12 +223,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; @@ -242,45 +247,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++; - 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); - } + 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, From 889498c12cc5cd4ab718cbc8adbccc1f197adda5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 14:56:15 +0200 Subject: [PATCH 6/7] cloud-setup/azure: refactor callback for _get_config_ips_prefix_list_cb() --- src/nm-cloud-setup/nmcs-provider-azure.c | 65 +++++++++++++++--------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c index b09becb2f6..486c3dbbce 100644 --- a/src/nm-cloud-setup/nmcs-provider-azure.c +++ b/src/nm-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; @@ -109,10 +114,10 @@ _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; @@ -120,13 +125,17 @@ _get_config_fetch_done_cb(NMHttpClient * http_client, gs_free_error GError *error = 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,27 +143,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'); - iface_data->iface_get_config = - g_hash_table_lookup(get_config_data->result_dict, iface_data->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) { @@ -164,11 +169,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: @@ -183,17 +188,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 @@ -236,6 +249,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'; @@ -244,6 +258,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; @@ -263,7 +278,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); } @@ -285,7 +300,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; From c2629f72b0e6b438bf3f2b93967f58c9defafea6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Apr 2021 10:52:04 +0200 Subject: [PATCH 7/7] 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),