1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 *
3 * Copyright (C) 2015 Peter Hatina <phatina@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "config.h"
21
22 #include <glib/gi18n-lib.h>
23
24 #include <src/udiskslogging.h>
25 #include <src/udisksdaemon.h>
26 #include <src/udisksdaemonutil.h>
27
28 #include "udisksiscsitypes.h"
29 #include "udisksiscsiutil.h"
30 #include "udiskslinuxiscsisession.h"
31 #include "udiskslinuxiscsisessionobject.h"
32
33 /**
34 * SECTION:udiskslinuxiscsisession
35 * @title: UDisksLinuxISCSISession
36 * @short_description: Linux implementation of #UDisksISCSISession
37 *
38 * This type provides an implementation of #UDisksISCSISession interface
39 * on Linux.
40 */
41
42 /**
43 * UDisksLinuxISCSISession:
44 *
45 * The #UDisksLinuxISCSISession structure contains only private data and
46 * should only be accessed using provided API.
47 */
48 struct _UDisksLinuxISCSISession {
49 UDisksISCSISessionSkeleton parent_instance;
50 };
51
52 struct _UDisksLinuxISCSISessionClass {
53 UDisksISCSISessionSkeletonClass parent_class;
54 };
55
56 static void udisks_linux_iscsi_session_iface_init (UDisksISCSISessionIface *iface);
57
58 G_DEFINE_TYPE_WITH_CODE (UDisksLinuxISCSISession, udisks_linux_iscsi_session,
59 UDISKS_TYPE_ISCSI_SESSION_SKELETON,
60 G_IMPLEMENT_INTERFACE (UDISKS_TYPE_ISCSI_SESSION,
61 udisks_linux_iscsi_session_iface_init));
62
63 static void
udisks_linux_iscsi_session_class_init(UDisksLinuxISCSISessionClass * klass)64 udisks_linux_iscsi_session_class_init (UDisksLinuxISCSISessionClass *klass)
65 {
66 }
67
68 static void
udisks_linux_iscsi_session_init(UDisksLinuxISCSISession * self)69 udisks_linux_iscsi_session_init (UDisksLinuxISCSISession *self)
70 {
71 g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (self),
72 G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
73 }
74
75 /**
76 * udisks_linux_iscsi_session_new:
77 *
78 * Creates a new #UDisksLinuxISCSISession instance.
79 *
80 * Returns: A new #UDisksLinuxISCSISession. Free with g_object_unref().
81 */
82 UDisksLinuxISCSISession *
udisks_linux_iscsi_session_new(void)83 udisks_linux_iscsi_session_new (void)
84 {
85 return g_object_new (UDISKS_TYPE_LINUX_ISCSI_SESSION, NULL);
86 }
87
88 /**
89 * udisks_linux_iscsi_session_update:
90 * @session: A #UDisksLinuxISCSISession
91 * @object: The enclosing #UDisksLinuxISCSISessionObject instance.
92 *
93 * Updates the interface.
94 *
95 * Returns: %TRUE if configuration has changed, %FALSE otherwise.
96 */
97 gboolean
udisks_linux_iscsi_session_update(UDisksLinuxISCSISession * session,UDisksLinuxISCSISessionObject * object)98 udisks_linux_iscsi_session_update (UDisksLinuxISCSISession *session,
99 UDisksLinuxISCSISessionObject *object)
100 {
101 return FALSE;
102 }
103
104 static gboolean
handle_logout_interface(UDisksISCSISession * session,GDBusMethodInvocation * invocation,const gchar * arg_iface,GVariant * arg_options)105 handle_logout_interface (UDisksISCSISession *session,
106 GDBusMethodInvocation *invocation,
107 const gchar *arg_iface,
108 GVariant *arg_options)
109 {
110 UDisksLinuxModuleISCSI *module;
111 UDisksDaemon *daemon;
112 UDisksLinuxISCSISessionObject *object;
113 GError *error = NULL;
114 gchar *errorstr = NULL;
115 gint err;
116 const gchar *name;
117 const gchar *address;
118 guint32 tpgt;
119 guint32 port;
120
121 object = udisks_daemon_util_dup_object (session, &error);
122 if (! object)
123 {
124 g_dbus_method_invocation_take_error (invocation, error);
125 goto out;
126 }
127
128 module = udisks_linux_iscsi_session_object_get_module (object);
129 daemon = udisks_module_get_daemon (UDISKS_MODULE (module));
130
131 /* Policy check. */
132 UDISKS_DAEMON_CHECK_AUTHORIZATION (daemon,
133 UDISKS_OBJECT (object),
134 ISCSI_MODULE_POLICY_ACTION_ID,
135 arg_options,
136 N_("Authentication is required to perform iSCSI logout"),
137 invocation);
138
139 /* Parameters */
140 name = udisks_iscsi_session_get_target_name (session);
141 address = udisks_iscsi_session_get_address (session);
142 tpgt = udisks_iscsi_session_get_tpgt (session);
143 port = udisks_iscsi_session_get_persistent_port (session);
144
145 /* Enter a critical section. */
146 udisks_linux_module_iscsi_lock_libiscsi_context (module);
147
148 /* Logout */
149 err = iscsi_logout (module, name, tpgt, address, port, arg_iface, arg_options, &errorstr);
150
151 /* Leave the critical section. */
152 udisks_linux_module_iscsi_unlock_libiscsi_context (module);
153
154 if (err != 0)
155 {
156 /* Logout failed. */
157 g_dbus_method_invocation_return_error (invocation,
158 UDISKS_ERROR,
159 UDISKS_ERROR_FAILED,
160 N_("Logout failed: %s"),
161 errorstr);
162 goto out;
163 }
164
165 /* now sit and wait until the device and session disappear on dbus */
166 if (!udisks_daemon_wait_for_object_to_disappear_sync (daemon,
167 wait_for_iscsi_object,
168 g_strdup (name),
169 g_free,
170 UDISKS_DEFAULT_WAIT_TIMEOUT,
171 &error))
172 {
173 g_prefix_error (&error, "Error waiting for iSCSI device to disappear: ");
174 g_dbus_method_invocation_take_error (invocation, error);
175 goto out;
176 }
177
178 if (!udisks_daemon_wait_for_object_to_disappear_sync (daemon,
179 wait_for_iscsi_session_object,
180 g_strdup (name),
181 g_free,
182 UDISKS_DEFAULT_WAIT_TIMEOUT,
183 &error))
184 {
185 g_prefix_error (&error, "Error waiting for iSCSI session object to disappear: ");
186 g_dbus_method_invocation_take_error (invocation, error);
187 goto out;
188 }
189
190 /* Complete DBus call. */
191 udisks_iscsi_session_complete_logout (session,
192 invocation);
193
194 out:
195 g_clear_object (&object);
196 g_free (errorstr);
197
198 /* Indicate that we handled the method invocation. */
199 return TRUE;
200 }
201
202 static gboolean
handle_logout(UDisksISCSISession * object,GDBusMethodInvocation * invocation,GVariant * arg_options)203 handle_logout (UDisksISCSISession *object,
204 GDBusMethodInvocation *invocation,
205 GVariant *arg_options)
206 {
207 /* Logout the "default" interface. */
208 return handle_logout_interface (object, invocation, "default", arg_options);
209 }
210
211 /* -------------------------------------------------------------------------- */
212
udisks_linux_iscsi_session_iface_init(UDisksISCSISessionIface * iface)213 void udisks_linux_iscsi_session_iface_init (UDisksISCSISessionIface *iface)
214 {
215 iface->handle_logout_interface = handle_logout_interface;
216 iface->handle_logout = handle_logout;
217 }
218