about summary refs log tree commit diff
path: root/src/nm-cloud-setup/nmcs-provider.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2021-09-27 13:36:06 +0200
committerSebastien Bacher <seb128@ubuntu.com>2021-09-27 13:36:06 +0200
commit2bfcbfb13b1672c072e4f902260d2122b3e3c122 (patch)
tree3469f17ea9af91f7ff169b890633bda68b0cf76e /src/nm-cloud-setup/nmcs-provider.c
parentcfb80376641fa49137b9996130352697e7f8b436 (diff)
New upstream version 1.32.12
Diffstat (limited to 'src/nm-cloud-setup/nmcs-provider.c')
-rw-r--r--src/nm-cloud-setup/nmcs-provider.c112
1 files changed, 102 insertions, 10 deletions
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
index 678152aa..138e78d4 100644
--- a/src/nm-cloud-setup/nmcs-provider.c
+++ b/src/nm-cloud-setup/nmcs-provider.c
@@ -49,6 +49,90 @@ nmcs_provider_get_main_context(NMCSProvider *self)
 
     return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client);
 }
+/*****************************************************************************/
+
+static int
+_result_new_sort_iface_data(gconstpointer pa, gconstpointer pb)
+{
+    const NMCSProviderGetConfigIfaceData *a = *((const NMCSProviderGetConfigIfaceData *const *) pa);
+    const NMCSProviderGetConfigIfaceData *b = *((const NMCSProviderGetConfigIfaceData *const *) pb);
+
+    /* negative iface_idx are sorted to the end. */
+    NM_CMP_DIRECT((a->iface_idx < 0), (b->iface_idx < 0));
+
+    NM_CMP_FIELD(a, b, iface_idx);
+    return 0;
+}
+
+static NMCSProviderGetConfigResult *
+nmcs_provider_get_config_result_new(GHashTable *iface_datas)
+{
+    const NMCSProviderGetConfigIfaceData *iface_data;
+    NMCSProviderGetConfigResult *         result;
+    GHashTableIter                        h_iter;
+    guint                                 num_valid_ifaces = 0;
+    guint                                 num_ipv4s        = 0;
+    GPtrArray *                           ptrarr;
+    guint                                 n_iface_datas;
+
+    n_iface_datas = g_hash_table_size(iface_datas);
+
+    ptrarr = g_ptr_array_sized_new(n_iface_datas + 1u);
+
+    g_hash_table_iter_init(&h_iter, iface_datas);
+    while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &iface_data)) {
+        if (nmcs_provider_get_config_iface_data_is_valid(iface_data)) {
+            num_valid_ifaces++;
+            num_ipv4s += iface_data->ipv4s_len;
+        }
+        g_ptr_array_add(ptrarr, (gpointer) iface_data);
+    }
+
+    g_ptr_array_sort(ptrarr, _result_new_sort_iface_data);
+
+    nm_assert(n_iface_datas == ptrarr->len);
+
+    g_ptr_array_add(ptrarr, NULL);
+
+    result  = g_new(NMCSProviderGetConfigResult, 1);
+    *result = (NMCSProviderGetConfigResult){
+        .iface_datas   = g_hash_table_ref(iface_datas),
+        .n_iface_datas = n_iface_datas,
+        .iface_datas_arr =
+            (const NMCSProviderGetConfigIfaceData **) g_ptr_array_free(ptrarr, FALSE),
+        .num_valid_ifaces = num_valid_ifaces,
+        .num_ipv4s        = num_ipv4s,
+    };
+
+#if NM_MORE_ASSERTS > 5
+    {
+        gsize iface_idx_expected = 0;
+        guint i;
+
+        for (i = 0; i < result->n_iface_datas; i++) {
+            if (result->iface_datas_arr[i]->iface_idx < 0) {
+                nm_assert(result->iface_datas_arr[i]->iface_idx == -1);
+                iface_idx_expected = -1;
+                continue;
+            }
+            nm_assert(result->iface_datas_arr[i]->iface_idx == iface_idx_expected);
+            iface_idx_expected++;
+        }
+    }
+#endif
+
+    return result;
+}
+
+void
+nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result)
+{
+    if (result) {
+        nm_g_hash_table_unref(result->iface_datas);
+        g_free((gpointer) result->iface_datas_arr);
+        g_free(result);
+    }
+}
 
 /*****************************************************************************/
 
@@ -90,15 +174,25 @@ nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **e
 /*****************************************************************************/
 
 NMCSProviderGetConfigIfaceData *
-nmcs_provider_get_config_iface_data_new(gboolean was_requested)
+nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
+                                           gboolean    was_requested,
+                                           const char *hwaddr)
 {
     NMCSProviderGetConfigIfaceData *iface_data;
 
+    nm_assert(hwaddr);
+
     iface_data  = g_slice_new(NMCSProviderGetConfigIfaceData);
     *iface_data = (NMCSProviderGetConfigIfaceData){
+        .hwaddr        = g_strdup(hwaddr),
         .iface_idx     = -1,
         .was_requested = was_requested,
     };
+
+    /* 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);
+
     return iface_data;
 }
 
@@ -109,6 +203,7 @@ _iface_data_free(gpointer data)
 
     g_free(iface_data->ipv4s_arr);
     g_free(iface_data->iproutes_arr);
+    g_free((char *) iface_data->hwaddr);
 
     nm_g_slice_free(iface_data);
 }
@@ -137,8 +232,8 @@ _get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, GE
     } else {
         _LOGD("get-config: success");
         g_task_return_pointer(get_config_data->task,
-                              g_hash_table_ref(get_config_data->result_dict),
-                              (GDestroyNotify) g_hash_table_unref);
+                              nmcs_provider_get_config_result_new(get_config_data->result_dict),
+                              (GDestroyNotify) nmcs_provider_get_config_result_free);
     }
 
     nm_clear_g_signal_handler(g_task_get_cancellable(get_config_data->task),
@@ -187,16 +282,13 @@ nmcs_provider_get_config(NMCSProvider *      self,
     *get_config_data = (NMCSProviderGetConfigTaskData){
         .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, g_free, _iface_data_free),
+        .result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, _iface_data_free),
     };
 
     nmcs_wait_for_objects_register(get_config_data->task);
 
-    for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
-        g_hash_table_insert(get_config_data->result_dict,
-                            g_strdup(hwaddrs[0]),
-                            nmcs_provider_get_config_iface_data_new(TRUE));
-    }
+    for (; hwaddrs && hwaddrs[0]; hwaddrs++)
+        nmcs_provider_get_config_iface_data_create(get_config_data->result_dict, TRUE, hwaddrs[0]);
 
     if (cancellable) {
         gulong cancelled_id;
@@ -217,7 +309,7 @@ nmcs_provider_get_config(NMCSProvider *      self,
     NMCS_PROVIDER_GET_CLASS(self)->get_config(self, get_config_data);
 }
 
-GHashTable *
+NMCSProviderGetConfigResult *
 nmcs_provider_get_config_finish(NMCSProvider *self, GAsyncResult *result, GError **error)
 {
     g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE);