summary refs log tree commit diff
path: root/src/nm-cloud-setup
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-05-13 15:11:15 +0200
committerMichael Biebl <biebl@debian.org>2022-05-13 15:11:15 +0200
commit87d61411bb3453587d21487da04fcf770fee7d55 (patch)
treee84f1bcc59ec448f8d6f8754391974f0f9bd6cd9 /src/nm-cloud-setup
parent9959fdb2e8ddd06f2161798ca0a39c77d67c652d (diff)
New upstream version 1.38.0 upstream/1.38.0
Diffstat (limited to 'src/nm-cloud-setup')
-rw-r--r--src/nm-cloud-setup/nmcs-provider-aliyun.c109
-rw-r--r--src/nm-cloud-setup/nmcs-provider-azure.c4
-rw-r--r--src/nm-cloud-setup/nmcs-provider-ec2.c33
-rw-r--r--src/nm-cloud-setup/nmcs-provider-gcp.c4
-rw-r--r--src/nm-cloud-setup/nmcs-provider.c32
-rw-r--r--src/nm-cloud-setup/nmcs-provider.h43
6 files changed, 159 insertions, 66 deletions
diff --git a/src/nm-cloud-setup/nmcs-provider-aliyun.c b/src/nm-cloud-setup/nmcs-provider-aliyun.c
index 31c9830d..1a5e5459 100644
--- a/src/nm-cloud-setup/nmcs-provider-aliyun.c
+++ b/src/nm-cloud-setup/nmcs-provider-aliyun.c
@@ -123,29 +123,26 @@ detect(NMCSProvider *provider, GTask *task)
 typedef enum {
     GET_CONFIG_FETCH_DONE_TYPE_SUBNET_VPC_CIDR_BLOCK,
     GET_CONFIG_FETCH_DONE_TYPE_PRIVATE_IPV4S,
+    GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS,
     GET_CONFIG_FETCH_DONE_TYPE_NETMASK,
     GET_CONFIG_FETCH_DONE_TYPE_GATEWAY,
 } GetConfigFetchDoneType;
 
 static void
-_get_config_fetch_done_cb(NMHttpClient          *http_client,
-                          GAsyncResult          *result,
-                          gpointer               user_data,
-                          GetConfigFetchDoneType fetch_type)
+_get_config_fetch_done_cb(NMHttpClient                   *http_client,
+                          GAsyncResult                   *result,
+                          NMCSProviderGetConfigIfaceData *config_iface_data,
+                          GetConfigFetchDoneType          fetch_type)
 {
-    NMCSProviderGetConfigTaskData  *get_config_data;
-    gs_unref_bytes GBytes          *response = NULL;
-    gs_free_error GError           *error    = NULL;
-    NMCSProviderGetConfigIfaceData *config_iface_data;
-    in_addr_t                       tmp_addr;
-    int                             tmp_prefix;
-    in_addr_t                       netmask_bin;
-    in_addr_t                       gateway_bin;
-    gs_free const char            **s_addrs = NULL;
-    gsize                           i;
-    gsize                           len;
-
-    nm_utils_user_data_unpack(user_data, &get_config_data, &config_iface_data);
+    gs_unref_bytes GBytes *response = NULL;
+    gs_free_error GError  *error    = NULL;
+    in_addr_t              tmp_addr;
+    int                    tmp_prefix;
+    in_addr_t              netmask_bin;
+    in_addr_t              gateway_bin;
+    gs_free const char   **s_addrs = NULL;
+    gsize                  i;
+    gsize                  len;
 
     nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
 
@@ -177,6 +174,16 @@ _get_config_fetch_done_cb(NMHttpClient          *http_client,
         }
         break;
 
+    case GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS:
+
+        if (nm_utils_parse_inaddr_bin(AF_INET, g_bytes_get_data(response, NULL), NULL, &tmp_addr)) {
+            nm_assert(config_iface_data->priv.aliyun.primary_ip_address == 0);
+            nm_assert(!config_iface_data->priv.aliyun.has_primary_ip_address);
+            config_iface_data->priv.aliyun.primary_ip_address     = tmp_addr;
+            config_iface_data->priv.aliyun.has_primary_ip_address = TRUE;
+        }
+        break;
+
     case GET_CONFIG_FETCH_DONE_TYPE_SUBNET_VPC_CIDR_BLOCK:
 
         if (nm_utils_parse_inaddr_prefix_bin(AF_INET,
@@ -212,9 +219,30 @@ _get_config_fetch_done_cb(NMHttpClient          *http_client,
         break;
     }
 
+    if (!config_iface_data->priv.aliyun.ipv4s_arr_ordered
+        && config_iface_data->priv.aliyun.has_primary_ip_address
+        && config_iface_data->ipv4s_len > 0) {
+        for (i = 0; i < config_iface_data->ipv4s_len; i++) {
+            if (config_iface_data->ipv4s_arr[i]
+                != config_iface_data->priv.aliyun.primary_ip_address)
+                continue;
+            if (i > 0) {
+                /* OK, at position [i] we found the primary address.
+                 * Move the elements from [0..(i-1)] to [1..i] and then set [0]. */
+                memmove(&config_iface_data->ipv4s_arr[1],
+                        &config_iface_data->ipv4s_arr[0],
+                        i * sizeof(in_addr_t));
+                config_iface_data->ipv4s_arr[0] = config_iface_data->priv.aliyun.primary_ip_address;
+            }
+            break;
+        }
+        config_iface_data->priv.aliyun.ipv4s_arr_ordered = TRUE;
+    }
+
 out:
-    get_config_data->n_pending--;
-    _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
+    config_iface_data->get_config_data->n_pending--;
+    _nmcs_provider_get_config_task_maybe_return(config_iface_data->get_config_data,
+                                                g_steal_pointer(&error));
 }
 
 static void
@@ -236,6 +264,17 @@ _get_config_fetch_done_cb_private_ipv4s(GObject *source, GAsyncResult *result, g
 }
 
 static void
+_get_config_fetch_done_cb_primary_ip_address(GObject      *source,
+                                             GAsyncResult *result,
+                                             gpointer      user_data)
+{
+    _get_config_fetch_done_cb(NM_HTTP_CLIENT(source),
+                              result,
+                              user_data,
+                              GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS);
+}
+
+static void
 _get_config_fetch_done_cb_netmask(GObject *source, GAsyncResult *result, gpointer user_data)
 {
     _get_config_fetch_done_cb(NM_HTTP_CLIENT(source),
@@ -297,6 +336,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
         gs_free char                   *uri2 = NULL;
         gs_free char                   *uri3 = NULL;
         gs_free char                   *uri4 = NULL;
+        gs_free char                   *uri5 = NULL;
 
         config_iface_data = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
 
@@ -309,9 +349,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             }
 
             config_iface_data =
-                nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
-                                                           FALSE,
-                                                           v_hwaddr);
+                nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, v_hwaddr);
         }
 
         nm_assert(config_iface_data->iface_idx == -1);
@@ -338,7 +376,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_vpc_cidr_block,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
 
         get_config_data->n_pending++;
         nm_http_client_poll_get(
@@ -355,13 +393,30 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_private_ipv4s,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
 
         get_config_data->n_pending++;
         nm_http_client_poll_get(
             http_client,
             (uri3 = _aliyun_uri_interfaces(v_mac_data->path,
                                            NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
+                                           "primary-ip-address")),
+            HTTP_TIMEOUT_MS,
+            512 * 1024,
+            10000,
+            1000,
+            NULL,
+            get_config_data->intern_cancellable,
+            NULL,
+            NULL,
+            _get_config_fetch_done_cb_primary_ip_address,
+            config_iface_data);
+
+        get_config_data->n_pending++;
+        nm_http_client_poll_get(
+            http_client,
+            (uri4 = _aliyun_uri_interfaces(v_mac_data->path,
+                                           NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
                                            "netmask")),
             HTTP_TIMEOUT_MS,
             512 * 1024,
@@ -372,12 +427,12 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_netmask,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
 
         get_config_data->n_pending++;
         nm_http_client_poll_get(
             http_client,
-            (uri4 = _aliyun_uri_interfaces(v_mac_data->path,
+            (uri5 = _aliyun_uri_interfaces(v_mac_data->path,
                                            NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
                                            "gateway")),
             HTTP_TIMEOUT_MS,
@@ -389,7 +444,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_gateway,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
     }
 
     _nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c
index 06f23ea7..9b27af28 100644
--- a/src/nm-cloud-setup/nmcs-provider-azure.c
+++ b/src/nm-cloud-setup/nmcs-provider-azure.c
@@ -387,9 +387,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
             goto out_done;
         }
         iface_data->iface_get_config =
-            nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
-                                                       FALSE,
-                                                       v_hwaddr);
+            nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, v_hwaddr);
     } else {
         if (iface_data->iface_get_config->iface_idx >= 0) {
             _LOGI("interface[%" G_GSSIZE_FORMAT "]: duplicate MAC address %s returned",
diff --git a/src/nm-cloud-setup/nmcs-provider-ec2.c b/src/nm-cloud-setup/nmcs-provider-ec2.c
index ee4e2a95..d6fa0311 100644
--- a/src/nm-cloud-setup/nmcs-provider-ec2.c
+++ b/src/nm-cloud-setup/nmcs-provider-ec2.c
@@ -116,19 +116,15 @@ detect(NMCSProvider *provider, GTask *task)
 /*****************************************************************************/
 
 static void
-_get_config_fetch_done_cb(NMHttpClient *http_client,
-                          GAsyncResult *result,
-                          gpointer      user_data,
-                          gboolean      is_local_ipv4)
+_get_config_fetch_done_cb(NMHttpClient                   *http_client,
+                          GAsyncResult                   *result,
+                          NMCSProviderGetConfigIfaceData *config_iface_data,
+                          gboolean                        is_local_ipv4)
 {
-    NMCSProviderGetConfigTaskData  *get_config_data;
-    gs_unref_bytes GBytes          *response = NULL;
-    gs_free_error GError           *error    = NULL;
-    NMCSProviderGetConfigIfaceData *config_iface_data;
-    in_addr_t                       tmp_addr;
-    int                             tmp_prefix;
-
-    nm_utils_user_data_unpack(user_data, &get_config_data, &config_iface_data);
+    gs_unref_bytes GBytes *response = NULL;
+    gs_free_error GError  *error    = NULL;
+    in_addr_t              tmp_addr;
+    int                    tmp_prefix;
 
     nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
 
@@ -173,8 +169,9 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
     }
 
 out:
-    get_config_data->n_pending--;
-    _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
+    config_iface_data->get_config_data->n_pending--;
+    _nmcs_provider_get_config_task_maybe_return(config_iface_data->get_config_data,
+                                                g_steal_pointer(&error));
 }
 
 static void
@@ -244,9 +241,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
                 continue;
             }
             config_iface_data =
-                nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
-                                                           FALSE,
-                                                           v_hwaddr);
+                nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, v_hwaddr);
         }
 
         nm_assert(config_iface_data->iface_idx == -1);
@@ -273,7 +268,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_subnet_ipv4_cidr_block,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
 
         get_config_data->n_pending++;
         nm_http_client_poll_get(
@@ -290,7 +285,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
             NULL,
             NULL,
             _get_config_fetch_done_cb_local_ipv4s,
-            nm_utils_user_data_pack(get_config_data, config_iface_data));
+            config_iface_data);
     }
 
     _nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
diff --git a/src/nm-cloud-setup/nmcs-provider-gcp.c b/src/nm-cloud-setup/nmcs-provider-gcp.c
index 0df2bdd6..a325f31a 100644
--- a/src/nm-cloud-setup/nmcs-provider-gcp.c
+++ b/src/nm-cloud-setup/nmcs-provider-gcp.c
@@ -282,9 +282,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
             goto out_done;
         }
         iface_data->iface_get_config =
-            nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
-                                                       FALSE,
-                                                       v_hwaddr);
+            nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, v_hwaddr);
         is_requested = FALSE;
     } else {
         if (iface_data->iface_get_config->iface_idx >= 0) {
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
index f14a3d02..fd9a61b8 100644
--- a/src/nm-cloud-setup/nmcs-provider.c
+++ b/src/nm-cloud-setup/nmcs-provider.c
@@ -174,24 +174,38 @@ nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **e
 /*****************************************************************************/
 
 NMCSProviderGetConfigIfaceData *
-nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
-                                           gboolean    was_requested,
-                                           const char *hwaddr)
+nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_config_data,
+                                           gboolean                       was_requested,
+                                           const char                    *hwaddr)
 {
     NMCSProviderGetConfigIfaceData *iface_data;
 
     nm_assert(hwaddr);
+    nm_assert(get_config_data);
+    nm_assert(NMCS_IS_PROVIDER(get_config_data->self));
 
     iface_data  = g_slice_new(NMCSProviderGetConfigIfaceData);
     *iface_data = (NMCSProviderGetConfigIfaceData){
-        .hwaddr        = g_strdup(hwaddr),
-        .iface_idx     = -1,
-        .was_requested = was_requested,
+        .get_config_data = get_config_data,
+        .hwaddr          = g_strdup(hwaddr),
+        .iface_idx       = -1,
+        .was_requested   = was_requested,
     };
 
+    /* "priv" is a union, and according to C, it might not be properly initialized
+     * that all union members are set to false/0/NULL/0.0. We need to know which
+     * union field we are going to use, and that depends on the type of "self".
+     * Also, knowing the type would allow us to initialize to something other than
+     * false/0/NULL/0.0. */
+    if (G_OBJECT_TYPE(get_config_data->self) == nmcs_provider_aliyun_get_type()) {
+        iface_data->priv.aliyun = (typeof(iface_data->priv.aliyun)){
+            .has_primary_ip_address = FALSE,
+        };
+    }
+
     /* the has does not own the key (iface_datta->hwaddr), the lifetime of the
      * key is associated with the iface_data instance. */
-    g_hash_table_replace(iface_datas, (char *) iface_data->hwaddr, iface_data);
+    g_hash_table_replace(get_config_data->result_dict, (char *) iface_data->hwaddr, iface_data);
 
     return iface_data;
 }
@@ -280,6 +294,8 @@ nmcs_provider_get_config(NMCSProvider       *self,
 
     get_config_data  = g_slice_new(NMCSProviderGetConfigTaskData);
     *get_config_data = (NMCSProviderGetConfigTaskData){
+        /* "self" is kept alive by "task". */
+        .self = self,
         .task = nm_g_task_new(self, cancellable, nmcs_provider_get_config, callback, user_data),
         .any  = any,
         .result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, _iface_data_free),
@@ -288,7 +304,7 @@ nmcs_provider_get_config(NMCSProvider       *self,
     nmcs_wait_for_objects_register(get_config_data->task);
 
     for (; hwaddrs && hwaddrs[0]; hwaddrs++)
-        nmcs_provider_get_config_iface_data_create(get_config_data->result_dict, TRUE, hwaddrs[0]);
+        nmcs_provider_get_config_iface_data_create(get_config_data, TRUE, hwaddrs[0]);
 
     if (cancellable) {
         gulong cancelled_id;
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
index bce41dcb..502f1d03 100644
--- a/src/nm-cloud-setup/nmcs-provider.h
+++ b/src/nm-cloud-setup/nmcs-provider.h
@@ -9,11 +9,16 @@
 
 /*****************************************************************************/
 
+struct _NMCSProvider;
+struct _NMCSProviderGetConfigTaskData;
+
 typedef struct {
     /* And it's exactly the same pointer that is also the key for the iface_datas
      * dictionary. */
     const char *hwaddr;
 
+    struct _NMCSProviderGetConfigTaskData *get_config_data;
+
     in_addr_t *ipv4s_arr;
     gsize      ipv4s_len;
 
@@ -36,6 +41,18 @@ typedef struct {
      * nmcs_provider_get_config(). */
     bool was_requested : 1;
 
+    /* Usually we would want that the parent class NMCSProvider is not aware about
+     * the implementations. However, it's convenient to track implementation specific data
+     * here, thus we violate such separation. In practice, all subclasses are known
+     * at compile time, and it will be simpler this way. */
+    union {
+        struct {
+            in_addr_t primary_ip_address;
+            bool      has_primary_ip_address : 1;
+            bool      ipv4s_arr_ordered : 1;
+        } aliyun;
+    } priv;
+
 } NMCSProviderGetConfigIfaceData;
 
 static inline gboolean
@@ -45,10 +62,6 @@ nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceDat
            && ((config_data->has_ipv4s && config_data->has_cidr) || config_data->iproutes_len);
 }
 
-NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
-                                                                           gboolean was_requested,
-                                                                           const char *hwaddr);
-
 /*****************************************************************************/
 
 typedef struct {
@@ -83,9 +96,11 @@ NM_AUTO_DEFINE_FCN0(NMCSProviderGetConfigResult *,
 
 /*****************************************************************************/
 
-typedef struct {
+typedef struct _NMCSProviderGetConfigTaskData {
     GTask *task;
 
+    struct _NMCSProvider *self;
+
     GHashTable *result_dict;
 
     /* this cancellable should be used for the provider implementation
@@ -105,6 +120,15 @@ typedef struct {
     bool any : 1;
 } NMCSProviderGetConfigTaskData;
 
+/*****************************************************************************/
+
+NMCSProviderGetConfigIfaceData *
+nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_config_data,
+                                           gboolean                       was_requested,
+                                           const char                    *hwaddr);
+
+/*****************************************************************************/
+
 #define NMCS_TYPE_PROVIDER (nmcs_provider_get_type())
 #define NMCS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER, NMCSProvider))
 #define NMCS_PROVIDER_CLASS(klass) \
@@ -118,7 +142,7 @@ typedef struct {
 
 struct _NMCSProviderPrivate;
 
-typedef struct {
+typedef struct _NMCSProvider {
     GObject                      parent;
     struct _NMCSProviderPrivate *_priv;
 } NMCSProvider;
@@ -167,4 +191,11 @@ void nmcs_provider_get_config(NMCSProvider       *provider,
 NMCSProviderGetConfigResult *
 nmcs_provider_get_config_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
 
+/*****************************************************************************/
+
+/* Forward declare the implemented gtype getters so we can use it at a few places without requiring
+ * to include the full header. The other parts of those headers should not be used aside where they
+ * are necessary. */
+GType nmcs_provider_aliyun_get_type(void);
+
 #endif /* __NMCS_PROVIDER_H__ */