[network-manager-openswan/dcbw/cleanups: 17/17] core: rework connect process and subprocess handling



commit 09e8be26a2b0050b5b01e214aff8650d306a968a
Author: Dan Williams <dcbw redhat com>
Date:   Thu Aug 7 17:50:42 2014 -0500

    core: rework connect process and subprocess handling

 src/Makefile.am           |    7 +-
 src/nm-openswan-service.c |  563 +++++++++++++++++++++++++++++++++------------
 2 files changed, 419 insertions(+), 151 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9ee7f06..9029570 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,9 +22,10 @@ nm_openswan_service_SOURCES = \
                                nm-openswan-service.h
 
 nm_openswan_service_LDADD = \
-                               $(DBUS_LIBS) \
-                               $(GLIB_LIBS) \
-                               $(NM_LIBS)
+       $(DBUS_LIBS) \
+       $(GLIB_LIBS) \
+       $(NM_LIBS) \
+       -lutil
 
 nm_openswan_service_helper_SOURCES = \
                                nm-openswan-service-helper.c
diff --git a/src/nm-openswan-service.c b/src/nm-openswan-service.c
index ecba977..edb9c48 100644
--- a/src/nm-openswan-service.c
+++ b/src/nm-openswan-service.c
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <locale.h>
 #include <stdarg.h>
+#include <pty.h>
 
 #include <glib/gi18n.h>
 
@@ -48,15 +49,41 @@ GMainLoop *loop = NULL;
 
 G_DEFINE_TYPE (NMOPENSWANPlugin, nm_openswan_plugin, NM_TYPE_VPN_PLUGIN)
 
+typedef enum {
+    CONNECT_STEP_FIRST,
+    CONNECT_STEP_IPSEC_START,
+    CONNECT_STEP_CONFIG_ADD,
+    CONNECT_STEP_CONNECT,
+    CONNECT_STEP_LAST
+} ConnectStep;
+
 typedef struct {
-       GPid pid;
+       const char *ipsec_path;
        char *secrets_path;
+
+       GPid pid;
+       guint watch_id;
+       ConnectStep connect_step;
+       NMConnection *connection;
+
+       GIOChannel *channel;
+       guint io_id;
+       char *password;
 } NMOPENSWANPluginPrivate;
 
 #define NM_OPENSWAN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OPENSWAN_PLUGIN, 
NMOPENSWANPluginPrivate))
 
 #define NM_OPENSWAN_HELPER_PATH                LIBEXECDIR"/nm-openswan-service-helper"
 
+#define DEBUG(...) \
+    G_STMT_START { \
+        if (debug) { \
+            g_message (__VA_ARGS__); \
+        } \
+    } G_STMT_END
+
+/****************************************************************/
+
 typedef struct {
        const char *name;
        GType type;
@@ -199,6 +226,8 @@ nm_openswan_secrets_validate (NMSettingVPN *s_vpn, GError **error)
 
 /****************************************************************/
 
+static gboolean connect_step (NMOPENSWANPlugin *self, GError **error);
+
 static const char *ipsec_paths[] =
 {
        "/usr/sbin/ipsec",
@@ -225,54 +254,127 @@ find_ipsec (GError **error)
 }
 
 static void
+connect_cleanup (NMOPENSWANPlugin *self)
+{
+       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+
+       priv->connect_step = CONNECT_STEP_FIRST;
+
+       /* Don't remove the child watch since it needs to reap the child */
+       priv->watch_id = 0;
+
+       if (priv->pid) {
+               kill (priv->pid, SIGTERM);
+               priv->pid = 0;
+       }
+
+       if (priv->io_id) {
+               g_source_remove (priv->io_id);
+               priv->io_id = 0;
+       }
+       g_clear_pointer (&priv->channel, g_io_channel_unref);
+
+       if (priv->password) {
+               memset (priv->password, 0, strlen (priv->password));
+               g_free (priv->password);
+               priv->password = NULL;
+       }
+
+       g_clear_object (&priv->connection);
+}
+
+static void
+delete_secrets_file (NMOPENSWANPlugin *self)
+{
+       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+
+       if (priv->secrets_path) {
+               unlink (priv->secrets_path);
+               g_clear_pointer (&priv->secrets_path, g_free);
+       }
+}
+
+static gboolean
+ipsec_stop (NMOPENSWANPlugin *self, GError **error)
+{
+       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+       const char *argv[4] = { priv->ipsec_path, "setup", "stop", NULL };
+
+       delete_secrets_file (self);
+       return g_spawn_sync (NULL, (char **) argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, error);
+}
+
+static void
+connect_failed (NMOPENSWANPlugin *self, gboolean do_stop, GError *error)
+{
+       if (error) {
+               g_warning ("Connect failed: (%s/%d) %s",
+                          g_quark_to_string (error->domain),
+                          error->code,
+                          error->message);
+       }
+
+       connect_cleanup (self);
+       if (do_stop)
+               ipsec_stop (self, NULL);
+       nm_vpn_plugin_failure (NM_VPN_PLUGIN (self), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
+}
+
+static void
 pluto_watch_cb (GPid pid, gint status, gpointer user_data)
 {
-       NMOPENSWANPlugin *plugin = NM_OPENSWAN_PLUGIN (user_data);
-       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (plugin);
-       guint error = 0;
+       NMOPENSWANPlugin *self = NM_OPENSWAN_PLUGIN (user_data);
+       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+       guint ret = 0;
+       GError *error = NULL;
+       gboolean do_stop = FALSE;
 
-       if (debug)
-               g_message ("pluto_watch: current child pid = %d, pluto pid=%d", pid, priv->pid);
+       if (priv->watch_id == 0)
+               return;
+       if (priv->pid != pid) {
+               waitpid (pid, NULL, WNOHANG);
+               return;
+       }
+
+       priv->watch_id = 0;
+       priv->pid = 0;
+
+       DEBUG ("Spawn: child %d exited", pid);
 
        if (WIFEXITED (status)) {
-               error = WEXITSTATUS (status);
-               if (error != 0) {
-                       g_warning ("pluto_watch: pluto exited with error code %d", error);
-                       nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
-               }
-       } else if (WIFSTOPPED (status))
-               g_warning ("pluto_watch: pluto stopped unexpectedly with signal %d", WSTOPSIG (status));
-       else if (WIFSIGNALED (status))
-               g_warning ("pluto_watch: pluto died with signal %d", WTERMSIG (status));
-       else
-               g_warning ("pluto_watch: pluto died from an unknown cause");
+               ret = WEXITSTATUS (status);
+               if (ret)
+                       g_warning ("Spawn: child %d exited with error code %d", pid, ret);
+       } else
+               g_warning ("Spawn: child %d died unexpectedly", pid);
 
-       /* Reap child if needed. */
+       /* Reap child */
        waitpid (pid, NULL, WNOHANG);
 
-       if (pid == priv->pid) {
-               priv->pid = 0;
-               if (debug)
-                       g_message ("pluto_watch: nm pluto service is stopping");
-       } else {
-               if (debug)
-                       g_message ("pluto_watch: nm pluto service will continue after reaping a child");
+       if (ret == 0) {
+               /* Success; do the next connect step */
+               do_stop = TRUE;
+               priv->connect_step++;
+               if (!connect_step (self, &error))
+                       ret = 1;
        }
 
-       g_spawn_close_pid (pid);
+       if (ret != 0)
+               connect_failed (self, do_stop, error);
+       g_clear_error (&error);
 }
 
-static gboolean do_spawn (gboolean reap_child,
-                          GPid *out_pid,
+static gboolean do_spawn (GPid *out_pid,
                           int *out_stdin,
+                          int *out_stderr,
                           GError **error,
                           const char *progname,
                           ...) G_GNUC_NULL_TERMINATED;
 
 static gboolean
-do_spawn (gboolean reap_child,
-          GPid *out_pid,
+do_spawn (GPid *out_pid,
           int *out_stdin,
+          int *out_stderr,
           GError **error,
           const char *progname,
           ...)
@@ -282,6 +384,7 @@ do_spawn (gboolean reap_child,
        GPtrArray *argv;
        char *cmdline, *arg;
        gboolean success;
+       GPid pid = 0;
 
        argv = g_ptr_array_sized_new (10);
        g_ptr_array_add (argv, (char *) progname);
@@ -294,91 +397,36 @@ do_spawn (gboolean reap_child,
 
        if (debug) {
                cmdline = g_strjoinv (" ", (char **) argv->pdata);
-               g_message ("Spawning: %s", cmdline);
+               g_message ("Spawn: %s", cmdline);
                g_free (cmdline);
        }
 
-       if (out_stdin) {
+       if (out_stdin || out_stderr) {
                success = g_spawn_async_with_pipes (NULL, (char **) argv->pdata, NULL,
-                                                   reap_child ? G_SPAWN_DO_NOT_REAP_CHILD : 0,
-                                                   NULL, NULL, out_pid, out_stdin,
-                                                   NULL, NULL, &local);
+                                                   G_SPAWN_DO_NOT_REAP_CHILD,
+                                                   NULL, NULL, &pid, out_stdin,
+                                                   NULL, out_stderr, &local);
        } else {
                success = g_spawn_async (NULL, (char **) argv->pdata, NULL,
-                                        reap_child ? G_SPAWN_DO_NOT_REAP_CHILD : 0,
-                                        NULL, NULL, out_pid, &local);
+                                        G_SPAWN_DO_NOT_REAP_CHILD,
+                                        NULL, NULL, &pid, &local);
        }
-       if (!success) {
+       if (success) {
+               DEBUG ("Spawn: child process %d", pid);
+       } else {
                g_warning ("Spawn failed: (%s/%d) %s",
                           g_quark_to_string (local->domain),
                           local->code, local->message);
                g_propagate_error (error, local);
        }
 
+       if (out_pid)
+               *out_pid = pid;
+
        g_ptr_array_free (argv, TRUE);
        return success;
 }
 
-static gint
-nm_openswan_start_openswan_binary (NMOPENSWANPlugin *plugin,
-                                   const char *uuid,
-                                   GError **error)
-{
-       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (plugin);
-       const char *ipsec_binary;
-       gint stdin_fd = -1;
-       GPid pid_auto;
-
-       ipsec_binary = find_ipsec (error);
-       if (!ipsec_binary)
-               return -1;
-
-       /* Start the IPSec service */
-       if (!do_spawn (TRUE, &priv->pid, NULL, error, ipsec_binary, "setup", "start", NULL))
-               return -1;
-
-       g_message ("ipsec/pluto started with pid %d", priv->pid);
-       g_child_watch_add (priv->pid, (GChildWatchFunc) pluto_watch_cb, plugin);
-       sleep (2);
-
-       /* Start the helper we write the connection configuration to */
-       if (!do_spawn (TRUE, &pid_auto, &stdin_fd, error,
-                      ipsec_binary, "auto", "--add", "--config", "-", uuid, NULL)) {
-               return -1;
-       }
-
-       if (debug)
-               g_message ("pluto auto started with pid %d", pid_auto);
-
-       g_child_watch_add (pid_auto, (GChildWatchFunc) pluto_watch_cb, plugin);
-
-       return stdin_fd;
-}
-
-static gint
-nm_openswan_start_openswan_connection (NMOPENSWANPlugin *plugin,
-                                       const char *uuid,
-                                       GError **error)
-{
-       GPid pid;
-       const char *ipsec_binary;
-       gint stdin_fd = -1;
-
-       ipsec_binary = find_ipsec (error);
-       if (!ipsec_binary)
-               return -1;
-
-       if (!do_spawn (TRUE, &pid, &stdin_fd, error, ipsec_binary, "auto", "--up", uuid, NULL))
-               return -1;
-
-       if (debug)
-               g_message ("pluto up started with pid %d", pid);
-
-       g_child_watch_add (pid, (GChildWatchFunc) pluto_watch_cb, plugin);
-
-       return stdin_fd;
-}
-
 static inline void
 write_config_option (int fd, const char *format, ...)
 {
@@ -398,18 +446,19 @@ write_config_option (int fd, const char *format, ...)
        va_end (args);
 }
 
-static gboolean
-nm_openswan_config_write (gint fd,
-                          const char *uuid,
-                          NMSettingVPN *s_vpn,
-                          GError **error)
+static void
+nm_openswan_config_write (gint fd, NMConnection *connection, GError **error)
 {
+       NMSettingVPN *s_vpn = nm_connection_get_setting_vpn (connection);
+       const char *uuid = nm_connection_get_uuid (connection);
        const char *props_username;
        const char *default_username;
        const char *phase1_alg_str;
        const char *phase2_alg_str;
 
        g_assert (fd >= 0);
+       g_assert (s_vpn);
+       g_assert (uuid);
 
        write_config_option (fd, "conn %s\n", uuid);
        write_config_option (fd, " aggrmode=yes\n");
@@ -450,8 +499,6 @@ nm_openswan_config_write (gint fd,
        write_config_option (fd, " ikelifetime=24h\n");
        write_config_option (fd, " keyingtries=1\n");
        write_config_option (fd, " auto=add\n");
-
-       return TRUE;
 }
 
 static gboolean
@@ -491,17 +538,250 @@ nm_openswan_config_psk_write (NMSettingVPN *s_vpn,
        return TRUE;
 }
 
-static void
-delete_secrets_file (NMOPENSWANPlugin *self)
+/****************************************************************/
+
+static gboolean spawn_pty (int *out_stdout,
+                           int *out_stderr,
+                           int *out_ptyin,
+                           GPid *out_pid,
+                           GError **error,
+                           const char *progname,
+                           ...) G_GNUC_NULL_TERMINATED;
+
+static gboolean
+spawn_pty (int *out_stdout,
+           int *out_stderr,
+           int *out_ptyin,
+           GPid *out_pid,
+           GError **error,
+           const char *progname,
+           ...)
+{
+       int pty_master_fd, md;
+       int stdout_pipe[2], stderr_pipe[2];
+       pid_t child_pid;
+       struct termios termios_flags;
+       va_list ap;
+       GPtrArray *argv;
+       char *cmdline, *arg;
+
+       argv = g_ptr_array_sized_new (10);
+       g_ptr_array_add (argv, (char *) progname);
+
+       va_start (ap, progname);
+       while ((arg = va_arg (ap, char *)))
+               g_ptr_array_add (argv, arg);
+       va_end (ap);
+       g_ptr_array_add (argv, NULL);
+
+       if (debug) {
+               cmdline = g_strjoinv (" ", (char **) argv->pdata);
+               g_message ("PTY spawn: %s", cmdline);
+               g_free (cmdline);
+       }
+
+       /* The pipes */
+       pipe (stderr_pipe);
+       pipe (stdout_pipe);
+
+       /* Fork the command */
+       child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
+       if (child_pid == 0) {
+               /* in the child */
+
+               close (2);
+               dup (stderr_pipe[1]);
+               close (1);
+               dup (stdout_pipe[1]);
+
+               /* Close unnecessary pipes */
+               close (stderr_pipe[0]);
+               close (stdout_pipe[0]);
+
+               if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
+                       fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
+               if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
+                       fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
+
+               execvp (argv->pdata[0], (char * const*) argv->pdata);
+               g_error ("PTY spawn: cannot exec '%s'", (char *) argv->pdata[0]);
+               _exit (-1);
+       }
+       g_ptr_array_free (argv, TRUE);
+
+       /* Close parent's side pipes */
+       close (stderr_pipe[1]);
+       close (stdout_pipe[1]);
+
+       if (child_pid < 0) {
+               /* Close parent's side pipes */
+               close (stderr_pipe[0]);
+               close (stdout_pipe[0]);
+               g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+                            "PTY spawn failed for '%s' (%d)",
+                            (char *) argv->pdata[0], child_pid);
+               return FALSE;
+       }
+
+       /*  Set pipes none blocking, so we can read big buffers
+        *  in the callback without having to use FIONREAD
+        *  to make sure the callback doesn't block.
+        */
+       if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
+               fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
+       if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
+               fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
+       if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
+               fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
+
+if (0) {
+       tcgetattr (pty_master_fd, &termios_flags);
+       termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON | IXOFF | ISTRIP);
+       termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
+       termios_flags.c_oflag &= ~OPOST;
+       termios_flags.c_cflag &= ~(CSTOPB | PARENB | HUPCL);
+       termios_flags.c_cflag |= CS8 | CLOCAL;
+       termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL | ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH 
| TOSTOP);
+       termios_flags.c_cc[VMIN] = 0;
+       cfsetospeed (&termios_flags, __MAX_BAUD);
+       tcsetattr (pty_master_fd, TCSANOW, &termios_flags);
+}
+
+       if (out_stdout)
+               *out_stdout = stdout_pipe[0];
+       if (out_stderr)
+               *out_stderr = stderr_pipe[0];
+       if (out_ptyin)
+               *out_ptyin = pty_master_fd;
+       if (out_pid)
+               *out_pid = child_pid;
+
+       return TRUE;
+}
+
+/****************************************************************/
+
+static gboolean
+io_cb (GIOChannel *source, GIOCondition condition, gpointer user_data)
 {
+       NMOPENSWANPlugin *self = NM_OPENSWAN_PLUGIN (user_data);
        NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+       char buf[256];
+       GIOStatus status;
+       gsize bytes_read = 0;
+       gboolean ret = G_SOURCE_CONTINUE;
+
+       if (condition & G_IO_ERR) {
+               g_warning ("PTY spawn: pipe error!");
+               ret = G_SOURCE_REMOVE;
+               goto done;
+       }
+       g_assert (condition & G_IO_IN);
 
-       if (priv->secrets_path) {
-               unlink (priv->secrets_path);
-               g_clear_pointer (&priv->secrets_path, g_free);
+       status = g_io_channel_read_chars (source, buf, sizeof (buf) - 1, &bytes_read, NULL);
+       if (status != G_IO_STATUS_NORMAL || bytes_read == 0)
+               return G_SOURCE_CONTINUE;
+
+       buf[bytes_read] = 0;
+       DEBUG ("VPN request '%s'", buf);
+
+       if (strcmp (buf, "Enter passphrase: ") == 0) {
+               GError *error = NULL;
+               gsize bytes_written;
+               const char *password = priv->password;
+
+               if (!password) {
+                       /* FIXME: request new password interactively */
+                       g_warning ("Password required but not provided!");
+                       ret = G_SOURCE_REMOVE;
+                       goto done;
+               }
+
+               do {
+                       g_io_channel_write_chars (source, password, -1, &bytes_written, &error);
+                       g_io_channel_flush (source, NULL);
+                       if (error) {
+                               g_warning ("Failed to write password to ipsec!");
+                               ret = G_SOURCE_REMOVE;
+                               goto done;
+                       }
+                       password += bytes_written;
+               } while (*password);
+
+               g_io_channel_write_chars (source, "\n", -1, NULL, NULL);
+               g_io_channel_flush (source, NULL);
+
+               DEBUG ("Wrote: '%s'", priv->password);
+       }
+
+done:
+       if (ret == G_SOURCE_REMOVE) {
+               priv->io_id = 0;
+               connect_failed (self, TRUE, NULL);
        }
+       return ret;
 }
 
+static gboolean
+connect_step (NMOPENSWANPlugin *self, GError **error)
+{
+       NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
+       const char *uuid;
+       int fd = -1, up_stdout = -1, up_stderr = -1, up_pty = -1;
+
+       g_warn_if_fail (priv->watch_id == 0);
+       priv->watch_id = 0;
+       g_warn_if_fail (priv->pid == 0);
+       priv->pid = 0;
+
+       DEBUG ("Connect: step %d", priv->connect_step);
+
+       uuid = nm_connection_get_uuid (priv->connection);
+       g_assert (uuid);
+
+       switch (priv->connect_step) {
+       case CONNECT_STEP_FIRST:
+               /* fall through */
+               priv->connect_step++;
+
+       case CONNECT_STEP_IPSEC_START:
+               /* Start the IPSec service */
+               if (!do_spawn (&priv->pid, NULL, NULL, error, priv->ipsec_path, "setup", "start", NULL))
+                       return FALSE;
+               priv->watch_id = g_child_watch_add (priv->pid, pluto_watch_cb, self);
+               return TRUE;
+
+       case CONNECT_STEP_CONFIG_ADD:
+               if (!do_spawn (&priv->pid, &fd, NULL, error, priv->ipsec_path,
+                              "auto", "--add", "--config", "-", uuid, NULL))
+                       return FALSE;
+               priv->watch_id = g_child_watch_add (priv->pid, pluto_watch_cb, self);
+               nm_openswan_config_write (fd, priv->connection, error);
+               close (fd);
+               return TRUE;
+
+       case CONNECT_STEP_CONNECT:
+               if (!spawn_pty (&up_stdout, &up_stderr, &up_pty, &priv->pid, error,
+                               priv->ipsec_path, "auto", "--up", uuid, NULL))
+                       return FALSE;
+               priv->watch_id = g_child_watch_add (priv->pid, pluto_watch_cb, self);
+
+               /* Wait for the password request */
+               priv->channel = g_io_channel_unix_new (up_pty);
+               g_io_channel_set_encoding (priv->channel, NULL, NULL);
+               g_io_channel_set_buffered (priv->channel, FALSE);
+               priv->io_id = g_io_add_watch (priv->channel, G_IO_IN | G_IO_ERR, io_cb, self);
+               return TRUE;
+
+       case CONNECT_STEP_LAST:
+               /* Everything successfully set up */
+               priv->pid = 0;
+               connect_cleanup (self);
+               return TRUE;
+       }
+
+       g_assert_not_reached ();
+}
 
 static gboolean
 real_connect (NMVPNPlugin   *plugin,
@@ -512,7 +792,11 @@ real_connect (NMVPNPlugin   *plugin,
        NMOPENSWANPluginPrivate *priv = NM_OPENSWAN_PLUGIN_GET_PRIVATE (self);
        NMSettingVPN *s_vpn;
        const char *uuid = nm_connection_get_uuid (connection);
-       gint fd = -1;
+
+       if (debug)
+               nm_connection_dump (connection);
+
+       ipsec_stop (self, NULL);
 
        s_vpn = nm_connection_get_setting_vpn (connection);
        g_assert (s_vpn);
@@ -523,40 +807,29 @@ real_connect (NMVPNPlugin   *plugin,
        if (!nm_openswan_secrets_validate (s_vpn, error))
                return FALSE;
 
-       /* Write the IPSec secret (group password) */
-       priv->secrets_path = g_strdup_printf (SYSCONFDIR "/ipsec.d/ipsec-%s.secrets", uuid);
-       if (!nm_openswan_config_psk_write (s_vpn, priv->secrets_path, error))
+       if (priv->connect_step != CONNECT_STEP_FIRST) {
+               g_set_error_literal (error,
+                                        NM_VPN_PLUGIN_ERROR,
+                                        NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+                                        "Already connecting!");
                return FALSE;
+       }
 
-       fd = nm_openswan_start_openswan_binary (self, uuid, error);
-       if (fd < 0)
-               goto error;
-
-       if (debug)
-               nm_connection_dump (connection);
+       priv->ipsec_path = find_ipsec (error);
+       if (!priv->ipsec_path)
+               return FALSE;
 
-       /* Start the IPSec service */
-       sleep (1);
-       if (!nm_openswan_config_write (fd, uuid, s_vpn, error))
-               goto error;
-       sleep (3);
-       close (fd);
+       priv->password = g_strdup (nm_setting_vpn_get_secret (s_vpn, NM_OPENSWAN_XAUTH_PASSWORD));
 
-       /* Start the actual IPSec connection */
-       fd = nm_openswan_start_openswan_connection (self, uuid, error);
-       if (fd < 0)
-               goto error;
+       /* Write the IPSec secret (group password) */
+       priv->secrets_path = g_strdup_printf (SYSCONFDIR "/ipsec.d/ipsec-%s.secrets", uuid);
+       if (!nm_openswan_config_psk_write (s_vpn, priv->secrets_path, error))
+               return FALSE;
 
-       /* Write the user password */
-       write_config_option (fd, "%s", nm_setting_vpn_get_secret (s_vpn, NM_OPENSWAN_XAUTH_PASSWORD));
-       close (fd);
-       return TRUE;
+       priv->connection = g_object_ref (connection);
 
-error:
-       if (fd >= 0)
-               close (fd);
-       delete_secrets_file (self);
-       return FALSE;
+       /* Start the connection process */
+       return connect_step (self, error);
 }
 
 static gboolean
@@ -602,15 +875,8 @@ real_need_secrets (NMVPNPlugin *plugin,
 static gboolean
 real_disconnect (NMVPNPlugin *plugin, GError **error)
 {
-       const char *ipsec_binary;
-
-       delete_secrets_file (NM_OPENSWAN_PLUGIN (plugin));
-
-       ipsec_binary = find_ipsec (error);
-       if (!ipsec_binary)
-               return FALSE;
-
-       return do_spawn (FALSE, NULL, NULL, error, ipsec_binary, "setup", "stop", NULL);
+       connect_cleanup (NM_OPENSWAN_PLUGIN (plugin));
+       return ipsec_stop (NM_OPENSWAN_PLUGIN (plugin), error);
 }
 
 static void
@@ -622,6 +888,7 @@ static void
 finalize (GObject *object)
 {
        delete_secrets_file (NM_OPENSWAN_PLUGIN (object));
+       connect_cleanup (NM_OPENSWAN_PLUGIN (object));
 
        G_OBJECT_CLASS (nm_openswan_plugin_parent_class)->finalize (object);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]