about summary refs log tree commit diff
path: root/src/core/nm-priv-helper-call.c
blob: 4f07481daac244d15e4e83fef03306afe5338112 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "src/core/nm-default-daemon.h"

#include "nm-priv-helper-call.h"

#include <gio/gunixfdlist.h>

#include "nm-dbus-manager.h"

/*****************************************************************************/

static void
_nm_priv_helper_call_get_fd_cb(GObject *source, GAsyncResult *res, gpointer user_data)
{
    NMPrivHelperCallGetFDCallback callback;
    gpointer                      callback_data;
    gs_unref_variant GVariant    *ret     = NULL;
    gs_free_error GError         *error   = NULL;
    gs_unref_object GUnixFDList  *fd_list = NULL;
    gs_free int                  *fd_arr  = NULL;

    nm_utils_user_data_unpack(user_data, &callback, &callback_data);

    ret = g_dbus_connection_call_with_unix_fd_list_finish(G_DBUS_CONNECTION(source),
                                                          &fd_list,
                                                          res,
                                                          &error);

    if (error) {
        callback(-1, error, callback_data);
        return;
    }

    if (!fd_list || g_unix_fd_list_get_length(fd_list) != 1) {
        nm_utils_error_set(&error,
                           NM_UTILS_ERROR_UNKNOWN,
                           "Unexpectedly not one FD is returned by nm-priv-helper GetFD()");
        callback(-1, error, callback_data);
        return;
    }

    fd_arr = g_unix_fd_list_steal_fds(fd_list, NULL);

    /* we transfer ownership of the file descriptor! */
    callback(fd_arr[0], NULL, callback_data);
}

static gboolean
_nm_priv_helper_call_get_fd_fail_on_idle(gpointer user_data)
{
    gs_unref_object GCancellable *cancellable = NULL;
    NMPrivHelperCallGetFDCallback callback;
    gpointer                      callback_data;
    gs_free_error GError         *error = NULL;

    nm_utils_user_data_unpack(user_data, &cancellable, &callback, &callback_data);

    if (!g_cancellable_set_error_if_cancelled(cancellable, &error))
        nm_utils_error_set(&error,
                           NM_UTILS_ERROR_UNKNOWN,
                           "Cannot talk to nm-priv-helper without D-Bus");

    callback(-1, error, callback_data);
    return G_SOURCE_REMOVE;
}

void
nm_priv_helper_call_get_fd(NMPrivHelperGetFDType         fd_type,
                           GCancellable                 *cancellable,
                           NMPrivHelperCallGetFDCallback callback,
                           gpointer                      user_data)
{
    GDBusConnection *dbus_connection;

    nm_assert(NM_IN_SET(fd_type, NM_PRIV_HELPER_GET_FD_TYPE_OVSDB_SOCKET));
    nm_assert(!cancellable || G_IS_CANCELLABLE(cancellable));
    nm_assert(callback);

    dbus_connection = NM_MAIN_DBUS_CONNECTION_GET;

    if (!dbus_connection) {
        nm_g_idle_add(_nm_priv_helper_call_get_fd_fail_on_idle,
                      nm_utils_user_data_pack(g_object_ref(cancellable), callback, user_data));
        return;
    }

    g_dbus_connection_call_with_unix_fd_list(dbus_connection,
                                             NM_PRIV_HELPER_DBUS_BUS_NAME,
                                             NM_PRIV_HELPER_DBUS_OBJECT_PATH,
                                             NM_PRIV_HELPER_DBUS_IFACE_NAME,
                                             "GetFD",
                                             g_variant_new("(u)", fd_type),
                                             G_VARIANT_TYPE("()"),
                                             G_DBUS_CALL_FLAGS_NONE,
                                             10000,
                                             NULL,
                                             cancellable,
                                             _nm_priv_helper_call_get_fd_cb,
                                             nm_utils_user_data_pack(callback, user_data));
}