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