diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /clients/cloud-setup/nm-cloud-setup-utils.c | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'clients/cloud-setup/nm-cloud-setup-utils.c')
| -rw-r--r-- | clients/cloud-setup/nm-cloud-setup-utils.c | 902 |
1 files changed, 0 insertions, 902 deletions
diff --git a/clients/cloud-setup/nm-cloud-setup-utils.c b/clients/cloud-setup/nm-cloud-setup-utils.c deleted file mode 100644 index f5550a12..00000000 --- a/clients/cloud-setup/nm-cloud-setup-utils.c +++ /dev/null @@ -1,902 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "libnm/nm-default-client.h" - -#include "nm-cloud-setup-utils.h" - -#include <linux/if_ether.h> -#include <linux/if_infiniband.h> - -#include "nm-glib-aux/nm-time-utils.h" -#include "nm-glib-aux/nm-logging-base.h" -#include "nm-glib-aux/nm-str-buf.h" - -/*****************************************************************************/ - -volatile NMLogLevel _nm_logging_configured_level = LOGL_TRACE; - -void -_nm_logging_enabled_init(const char *level_str) -{ - NMLogLevel level; - - if (!_nm_log_parse_level(level_str, &level)) - level = LOGL_WARN; - else if (level == _LOGL_KEEP) - level = LOGL_WARN; - - _nm_logging_configured_level = level; -} - -void -_nm_log_impl_cs(NMLogLevel level, const char *fmt, ...) -{ - gs_free char *msg = NULL; - va_list ap; - const char * level_str; - gint64 ts; - - va_start(ap, fmt); - msg = g_strdup_vprintf(fmt, ap); - va_end(ap); - - switch (level) { - case LOGL_TRACE: - level_str = "<trace>"; - break; - case LOGL_DEBUG: - level_str = "<debug>"; - break; - case LOGL_INFO: - level_str = "<info> "; - break; - case LOGL_WARN: - level_str = "<warn> "; - break; - default: - nm_assert(level == LOGL_ERR); - level_str = "<error>"; - break; - } - - ts = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME); - - g_print("[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s %s\n", - ts / NM_UTILS_NSEC_PER_SEC, - (ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000, - level_str, - msg); -} - -void -_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, - gint64 offset_sec, - gboolean is_boottime) -{} - -/*****************************************************************************/ - -G_LOCK_DEFINE_STATIC(_wait_for_objects_lock); -static GSList *_wait_for_objects_list; -static GSList *_wait_for_objects_iterate_loops; - -static void -_wait_for_objects_maybe_quit_mainloops_with_lock(void) -{ - GSList *iter; - - if (!_wait_for_objects_list) { - for (iter = _wait_for_objects_iterate_loops; iter; iter = iter->next) - g_main_loop_quit(iter->data); - } -} - -static void -_wait_for_objects_weak_cb(gpointer data, GObject *where_the_object_was) -{ - G_LOCK(_wait_for_objects_lock); - nm_assert(g_slist_find(_wait_for_objects_list, where_the_object_was)); - _wait_for_objects_list = g_slist_remove(_wait_for_objects_list, where_the_object_was); - _wait_for_objects_maybe_quit_mainloops_with_lock(); - G_UNLOCK(_wait_for_objects_lock); -} - -/** - * nmcs_wait_for_objects_register: - * @target: a #GObject to wait for. - * - * Registers @target as a pointer to wait during shutdown. Using - * nmcs_wait_for_objects_iterate_until_done() we keep waiting until - * @target gets destroyed, which means that it gets completely unreferenced. - */ -gpointer -nmcs_wait_for_objects_register(gpointer target) -{ - g_return_val_if_fail(G_IS_OBJECT(target), NULL); - - G_LOCK(_wait_for_objects_lock); - _wait_for_objects_list = g_slist_prepend(_wait_for_objects_list, target); - G_UNLOCK(_wait_for_objects_lock); - - g_object_weak_ref(target, _wait_for_objects_weak_cb, NULL); - return target; -} - -typedef struct { - GMainLoop *loop; - gboolean got_timeout; -} WaitForObjectsData; - -static gboolean -_wait_for_objects_iterate_until_done_timeout_cb(gpointer user_data) -{ - WaitForObjectsData *data = user_data; - - data->got_timeout = TRUE; - g_main_loop_quit(data->loop); - return G_SOURCE_CONTINUE; -} - -static gboolean -_wait_for_objects_iterate_until_done_idle_cb(gpointer user_data) -{ - /* This avoids a race where: - * - * - we check whether there are objects to wait for. - * - the last object to wait for gets removed (issuing g_main_loop_quit()). - * - we run the mainloop (and missed our signal). - * - * It's really a missing feature of GMainLoop where the "is-running" flag is always set to - * TRUE by g_main_loop_run(). That means, you cannot catch a g_main_loop_quit() in a race - * free way while not iterating the loop. - * - * Avoid this, by checking once again after we start running the mainloop. - */ - - G_LOCK(_wait_for_objects_lock); - _wait_for_objects_maybe_quit_mainloops_with_lock(); - G_UNLOCK(_wait_for_objects_lock); - return G_SOURCE_REMOVE; -} - -/** - * nmcs_wait_for_objects_iterate_until_done: - * @context: the #GMainContext to iterate. - * @timeout_msec: timeout or -1 for no timeout. - * - * Iterates the provided @context until all objects that we wait for - * are destroyed. - * - * The purpose of this is to cleanup all objects that we have on exit. That - * is especially because objects have asynchronous operations pending that - * should be cancelled and properly completed during exit. - * - * Returns: %FALSE on timeout or %TRUE if all objects destroyed before timeout. - */ -gboolean -nmcs_wait_for_objects_iterate_until_done(GMainContext *context, int timeout_msec) -{ - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(context, FALSE); - nm_auto_destroy_and_unref_gsource GSource *timeout_source = NULL; - WaitForObjectsData data; - gboolean has_more_objects; - - G_LOCK(_wait_for_objects_lock); - if (!_wait_for_objects_list) { - G_UNLOCK(_wait_for_objects_lock); - return TRUE; - } - _wait_for_objects_iterate_loops = g_slist_prepend(_wait_for_objects_iterate_loops, loop); - G_UNLOCK(_wait_for_objects_lock); - - data = (WaitForObjectsData){ - .loop = loop, - .got_timeout = FALSE, - }; - - if (timeout_msec >= 0) { - timeout_source = nm_g_source_attach( - nm_g_timeout_source_new(timeout_msec, - G_PRIORITY_DEFAULT, - _wait_for_objects_iterate_until_done_timeout_cb, - &data, - NULL), - context); - } - - has_more_objects = TRUE; - while (has_more_objects && !data.got_timeout) { - nm_auto_destroy_and_unref_gsource GSource *idle_source = NULL; - - idle_source = - nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_DEFAULT, - _wait_for_objects_iterate_until_done_idle_cb, - &data, - NULL), - context); - - g_main_loop_run(loop); - - G_LOCK(_wait_for_objects_lock); - has_more_objects = (!!_wait_for_objects_list); - if (data.got_timeout || !has_more_objects) - _wait_for_objects_iterate_loops = g_slist_remove(_wait_for_objects_iterate_loops, loop); - G_UNLOCK(_wait_for_objects_lock); - } - - return !data.got_timeout; -} - -/*****************************************************************************/ - -typedef struct { - GTask * task; - GSource * source_timeout; - GSource * source_next_poll; - GMainContext * context; - GCancellable * internal_cancellable; - NMCSUtilsPollProbeStartFcn probe_start_fcn; - NMCSUtilsPollProbeFinishFcn probe_finish_fcn; - gpointer probe_user_data; - gulong cancellable_id; - gint64 last_poll_start_ms; - int sleep_timeout_ms; - int ratelimit_timeout_ms; - bool completed : 1; -} PollTaskData; - -static void -_poll_task_data_free(gpointer data) -{ - PollTaskData *poll_task_data = data; - - nm_assert(G_IS_TASK(poll_task_data->task)); - nm_assert(!poll_task_data->source_next_poll); - nm_assert(!poll_task_data->source_timeout); - nm_assert(poll_task_data->cancellable_id == 0); - - g_main_context_unref(poll_task_data->context); - - nm_g_slice_free(poll_task_data); -} - -static void -_poll_return(PollTaskData *poll_task_data, GError *error_take) -{ - nm_clear_g_source_inst(&poll_task_data->source_next_poll); - nm_clear_g_source_inst(&poll_task_data->source_timeout); - nm_clear_g_cancellable_disconnect(g_task_get_cancellable(poll_task_data->task), - &poll_task_data->cancellable_id); - - nm_clear_g_cancellable(&poll_task_data->internal_cancellable); - - if (error_take) - g_task_return_error(poll_task_data->task, g_steal_pointer(&error_take)); - else - g_task_return_boolean(poll_task_data->task, TRUE); - - g_object_unref(poll_task_data->task); -} - -static gboolean _poll_start_cb(gpointer user_data); - -static void -_poll_done_cb(GObject *source, GAsyncResult *result, gpointer user_data) -{ - PollTaskData * poll_task_data = user_data; - _nm_unused gs_unref_object GTask *task = - poll_task_data->task; /* balance ref from _poll_start_cb() */ - gs_free_error GError *error = NULL; - gint64 now_ms; - gint64 wait_ms; - gboolean is_finished; - - is_finished = - poll_task_data->probe_finish_fcn(source, result, poll_task_data->probe_user_data, &error); - - if (nm_utils_error_is_cancelled(error)) { - /* we already handle this differently. Nothing to do. */ - return; - } - - if (error || is_finished) { - _poll_return(poll_task_data, g_steal_pointer(&error)); - return; - } - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - if (poll_task_data->ratelimit_timeout_ms > 0) - wait_ms = - (poll_task_data->last_poll_start_ms + poll_task_data->ratelimit_timeout_ms) - now_ms; - else - wait_ms = 0; - if (poll_task_data->sleep_timeout_ms > 0) - wait_ms = MAX(wait_ms, poll_task_data->sleep_timeout_ms); - - poll_task_data->source_next_poll = - nm_g_source_attach(nm_g_timeout_source_new(MAX(1, wait_ms), - G_PRIORITY_DEFAULT, - _poll_start_cb, - poll_task_data, - NULL), - poll_task_data->context); -} - -static gboolean -_poll_start_cb(gpointer user_data) -{ - PollTaskData *poll_task_data = user_data; - - nm_clear_g_source_inst(&poll_task_data->source_next_poll); - - poll_task_data->last_poll_start_ms = nm_utils_get_monotonic_timestamp_msec(); - - g_object_ref(poll_task_data->task); /* balanced by _poll_done_cb() */ - - poll_task_data->probe_start_fcn(poll_task_data->internal_cancellable, - poll_task_data->probe_user_data, - _poll_done_cb, - poll_task_data); - - return G_SOURCE_CONTINUE; -} - -static gboolean -_poll_timeout_cb(gpointer user_data) -{ - PollTaskData *poll_task_data = user_data; - - _poll_return(poll_task_data, nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "timeout expired")); - return G_SOURCE_CONTINUE; -} - -static void -_poll_cancelled_cb(GObject *object, gpointer user_data) -{ - PollTaskData *poll_task_data = user_data; - GError * error = NULL; - - nm_clear_g_signal_handler(g_task_get_cancellable(poll_task_data->task), - &poll_task_data->cancellable_id); - nm_utils_error_set_cancelled(&error, FALSE, NULL); - _poll_return(poll_task_data, error); -} - -/** - * nmcs_utils_poll: - * @poll_timeout_ms: if >= 0, then this is the overall timeout for how long we poll. - * When this timeout expires, the request completes with failure (and error set). - * @ratelimit_timeout_ms: if > 0, we ratelimit the starts from one prope_start_fcn - * call to the next. - * @sleep_timeout_ms: if > 0, then we wait after a probe finished this timeout - * before the next. Together with @ratelimit_timeout_ms this determines how - * frequently we probe. - * @probe_start_fcn: used to start a (asynchronous) probe. A probe must be completed - * by calling the provided callback. While a probe is in progress, we will not - * start another. This function is already invoked the first time synchronously, - * during nmcs_utils_poll(). - * @probe_finish_fcn: will be called from the callback of @probe_start_fcn. If the - * function returns %TRUE (polling done) or an error, polling stops. Otherwise, - * another poll will be started. - * @probe_user_data: user_data for the probe functions. - * @cancellable: cancellable for polling. - * @callback: when polling completes. - * @user_data: for @callback. - * - * This uses the current g_main_context_get_thread_default() for scheduling - * actions. - */ -void -nmcs_utils_poll(int poll_timeout_ms, - int ratelimit_timeout_ms, - int sleep_timeout_ms, - NMCSUtilsPollProbeStartFcn probe_start_fcn, - NMCSUtilsPollProbeFinishFcn probe_finish_fcn, - gpointer probe_user_data, - GCancellable * cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - PollTaskData *poll_task_data; - - poll_task_data = g_slice_new(PollTaskData); - *poll_task_data = (PollTaskData){ - .task = nm_g_task_new(NULL, cancellable, nmcs_utils_poll, callback, user_data), - .probe_start_fcn = probe_start_fcn, - .probe_finish_fcn = probe_finish_fcn, - .probe_user_data = probe_user_data, - .completed = FALSE, - .context = g_main_context_ref_thread_default(), - .sleep_timeout_ms = sleep_timeout_ms, - .ratelimit_timeout_ms = ratelimit_timeout_ms, - .internal_cancellable = g_cancellable_new(), - }; - - nmcs_wait_for_objects_register(poll_task_data->task); - - g_task_set_task_data(poll_task_data->task, poll_task_data, _poll_task_data_free); - - if (poll_timeout_ms >= 0) { - poll_task_data->source_timeout = - nm_g_source_attach(nm_g_timeout_source_new(poll_timeout_ms, - G_PRIORITY_DEFAULT, - _poll_timeout_cb, - poll_task_data, - NULL), - poll_task_data->context); - } - - poll_task_data->source_next_poll = nm_g_source_attach( - nm_g_idle_source_new(G_PRIORITY_DEFAULT, _poll_start_cb, poll_task_data, NULL), - poll_task_data->context); - - if (cancellable) { - gulong signal_id; - - signal_id = g_cancellable_connect(cancellable, - G_CALLBACK(_poll_cancelled_cb), - poll_task_data, - NULL); - if (signal_id == 0) { - /* the request is already cancelled. Return. */ - return; - } - poll_task_data->cancellable_id = signal_id; - } -} - -/** - * nmcs_utils_poll_finish: - * @result: the GAsyncResult from the GAsyncReadyCallback callback. - * @probe_user_data: the user data provided to nmcs_utils_poll(). - * @error: the failure code. - * - * Returns: %TRUE if the polling completed with success. In that case, - * the error won't be set. - * If the request was cancelled, this is indicated by @error and - * %FALSE will be returned. - * If the probe returned a failure, this returns %FALSE and the error - * provided by @probe_finish_fcn. - * If the request times out, this returns %FALSE with error set. - * Error is always set if (and only if) the function returns %FALSE. - */ -gboolean -nmcs_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **error) -{ - GTask * task; - PollTaskData *poll_task_data; - - g_return_val_if_fail(nm_g_task_is_valid(result, NULL, nmcs_utils_poll), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - task = G_TASK(result); - - if (probe_user_data) { - poll_task_data = g_task_get_task_data(task); - NM_SET_OUT(probe_user_data, poll_task_data->probe_user_data); - } - - return g_task_propagate_boolean(task, error); -} - -/*****************************************************************************/ - -char * -nmcs_utils_hwaddr_normalize(const char *hwaddr, gssize len) -{ - gs_free char *hwaddr_clone = NULL; - char * hw; - guint8 buf[ETH_ALEN]; - gsize l; - - nm_assert(len >= -1); - - if (len < 0) { - if (!hwaddr) - return NULL; - l = strlen(hwaddr); - } else { - l = len; - if (l > 0 && hwaddr[l - 1] == '\0') { - /* we accept one '\0' at the end of the string. */ - l--; - } - if (memchr(hwaddr, '\0', l)) { - /* but we don't accept other NUL characters in the middle. */ - return NULL; - } - } - - if (l == 0) - return NULL; - - nm_assert(hwaddr); - hw = nm_strndup_a(300, hwaddr, l, &hwaddr_clone); - - g_strstrip(hw); - - /* we cannot use _nm_utils_hwaddr_aton() because that requires a delimiter. - * Azure exposes MAC addresses without delimiter, so accept that too. */ - if (!nm_utils_hexstr2bin_full(hw, - FALSE, - FALSE, - FALSE, - ":-", - sizeof(buf), - buf, - sizeof(buf), - NULL)) - return NULL; - - return nm_utils_hwaddr_ntoa(buf, sizeof(buf)); -} - -/*****************************************************************************/ - -gboolean -nmcs_utils_ipaddr_normalize_bin(int addr_family, - const char *addr, - gssize len, - int * out_addr_family, - gpointer out_addr_bin) -{ - gs_free char *addr_clone = NULL; - char * ad; - gsize l; - - nm_assert(len >= -1); - - if (len < 0) { - if (!addr) - return FALSE; - l = strlen(addr); - } else { - l = len; - if (l > 0 && addr[l - 1] == '\0') { - /* we accept one '\0' at the end of the string. */ - l--; - } - if (memchr(addr, '\0', l)) { - /* but we don't accept other NUL characters in the middle. */ - return FALSE; - } - } - - if (l == 0) - return FALSE; - - nm_assert(addr); - ad = nm_strndup_a(300, addr, l, &addr_clone); - - g_strstrip(ad); - - return nm_utils_parse_inaddr_bin(addr_family, ad, out_addr_family, out_addr_bin); -} - -char * -nmcs_utils_ipaddr_normalize(int addr_family, const char *addr, gssize len) -{ - NMIPAddr ipaddr; - - if (!nmcs_utils_ipaddr_normalize_bin(addr_family, addr, len, &addr_family, &ipaddr)) - return NULL; - - return nm_utils_inet_ntop_dup(addr_family, &ipaddr); -} - -/*****************************************************************************/ - -const char * -nmcs_utils_parse_memmem(GBytes *mem, const char *needle) -{ - const char *mem_data; - gsize mem_size; - - g_return_val_if_fail(mem, NULL); - g_return_val_if_fail(needle, NULL); - - mem_data = g_bytes_get_data(mem, &mem_size); - return memmem(mem_data, mem_size, needle, strlen(needle)); -} - -const char * -nmcs_utils_parse_get_full_line(GBytes *mem, const char *needle) -{ - const char *mem_data; - gsize mem_size; - gsize c; - gsize l; - - const char *line; - - line = nmcs_utils_parse_memmem(mem, needle); - if (!line) - return NULL; - - mem_data = g_bytes_get_data(mem, &mem_size); - - if (line != mem_data && line[-1] != '\n') { - /* the line must be preceeded either by the begin of the data or - * by a newline. */ - return NULL; - } - - c = mem_size - (line - mem_data); - l = strlen(needle); - - if (c != l && line[l] != '\n') { - /* the end of the needle must be either a newline or the end of the buffer. */ - return NULL; - } - - return line; -} - -/*****************************************************************************/ - -char * -nmcs_utils_uri_build_concat_v(const char *base, const char **components, gsize n_components) -{ - NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); - - nm_assert(base); - nm_assert(base[0]); - nm_assert(!NM_STR_HAS_SUFFIX(base, "/")); - - nm_str_buf_append(&strbuf, base); - - if (n_components > 0 && components[0] && components[0][0] == '/') { - /* the first component starts with a slash. We allow that, and don't add a duplicate - * slash. Otherwise, we add a separator after base. - * - * We only do that for the first component. */ - } else - nm_str_buf_append_c(&strbuf, '/'); - - while (n_components > 0) { - if (!components[0]) { - /* we allow NULL, to indicate nothing to append */ - } else - nm_str_buf_append(&strbuf, components[0]); - components++; - n_components--; - } - - return nm_str_buf_finalize(&strbuf, NULL); -} - -/*****************************************************************************/ - -gboolean -nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip, - NMIPAddress ** entries_arr, - guint entries_len) -{ - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_addresses(s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPAddress *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_address_cmp_full(entry, - nm_setting_ip_config_get_address(s_ip, i_next), - NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) - == 0) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_address(s_ip, --num); - any_changes = TRUE; - } - - if (!nm_setting_ip_config_add_address(s_ip, entry)) - continue; - - i_next++; - } - if (!any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_address(s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; -} - -gboolean -nmcs_setting_ip_replace_ipv4_routes(NMSettingIPConfig *s_ip, - NMIPRoute ** entries_arr, - guint entries_len) -{ - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_routes(s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPRoute *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_route_equal_full(entry, - nm_setting_ip_config_get_route(s_ip, i_next), - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_route(s_ip, --num); - any_changes = TRUE; - } - - if (!nm_setting_ip_config_add_route(s_ip, entry)) - continue; - - i_next++; - } - if (!any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_route(s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; -} - -gboolean -nmcs_setting_ip_replace_ipv4_rules(NMSettingIPConfig *s_ip, - NMIPRoutingRule ** entries_arr, - guint entries_len) -{ - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_routing_rules(s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPRoutingRule *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_routing_rule_cmp(entry, - nm_setting_ip_config_get_routing_rule(s_ip, i_next)) - == 0) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_routing_rule(s_ip, --num); - any_changes = TRUE; - } - - nm_setting_ip_config_add_routing_rule(s_ip, entry); - i_next++; - } - if (!any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_routing_rule(s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; -} - -/*****************************************************************************/ - -typedef struct { - GMainLoop * main_loop; - NMConnection *connection; - GError * error; - guint64 version_id; -} DeviceGetAppliedConnectionData; - -static void -_nmcs_device_get_applied_connection_cb(GObject *source, GAsyncResult *result, gpointer user_data) -{ - DeviceGetAppliedConnectionData *data = user_data; - - data->connection = nm_device_get_applied_connection_finish(NM_DEVICE(source), - result, - &data->version_id, - &data->error); - g_main_loop_quit(data->main_loop); -} - -NMConnection * -nmcs_device_get_applied_connection(NMDevice * device, - GCancellable *cancellable, - guint64 * version_id, - GError ** error) -{ - nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); - DeviceGetAppliedConnectionData data = { - .main_loop = main_loop, - }; - - nm_device_get_applied_connection_async(device, - 0, - cancellable, - _nmcs_device_get_applied_connection_cb, - &data); - - g_main_loop_run(main_loop); - - if (data.error) - g_propagate_error(error, data.error); - NM_SET_OUT(version_id, data.version_id); - return data.connection; -} - -/*****************************************************************************/ - -typedef struct { - GMainLoop *main_loop; - GError * error; -} DeviceReapplyData; - -static void -_nmcs_device_reapply_cb(GObject *source, GAsyncResult *result, gpointer user_data) -{ - DeviceReapplyData *data = user_data; - - nm_device_reapply_finish(NM_DEVICE(source), result, &data->error); - g_main_loop_quit(data->main_loop); -} - -gboolean -nmcs_device_reapply(NMDevice * device, - GCancellable *sigterm_cancellable, - NMConnection *connection, - guint64 version_id, - gboolean * out_version_id_changed, - GError ** error) -{ - nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); - DeviceReapplyData data = { - .main_loop = main_loop, - }; - - nm_device_reapply_async(device, - connection, - version_id, - 0, - sigterm_cancellable, - _nmcs_device_reapply_cb, - &data); - - g_main_loop_run(main_loop); - - if (data.error) { - NM_SET_OUT( - out_version_id_changed, - g_error_matches(data.error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_VERSION_ID_MISMATCH)); - g_propagate_error(error, data.error); - return FALSE; - } - - NM_SET_OUT(out_version_id_changed, FALSE); - return TRUE; -} |