static gboolean fail_stop (gpointer data) { NMVPNPlugin *plugin = NM_VPN_PLUGIN (data); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); return FALSE; }
static gboolean _connect_generic (NMVPNPlugin *plugin, GHashTable *properties, GHashTable *details, GError **error) { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); NMVPNPluginClass *vpn_class = NM_VPN_PLUGIN_GET_CLASS (plugin); NMConnection *connection; gboolean success = FALSE; GError *local = NULL; if (priv->state != NM_VPN_SERVICE_STATE_STOPPED && priv->state != NM_VPN_SERVICE_STATE_INIT) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_WRONG_STATE, "Could not start connection: wrong plugin state %d", priv->state); return FALSE; } connection = nm_connection_new_from_hash (properties, &local); if (!connection) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "Invalid connection: (%d) %s", local->code, local->message); g_clear_error (&local); return FALSE; } priv->interactive = FALSE; if (details && !vpn_class->connect_interactive) { g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, "Plugin does not implement ConnectInteractive()"); return FALSE; } nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); if (details) { priv->interactive = TRUE; success = vpn_class->connect_interactive (plugin, connection, details, error); } else success = vpn_class->connect (plugin, connection, error); if (success) { /* Add a timer to make sure we do not wait indefinitely for the successful connect. */ connect_timer_start (plugin); } else { /* Stop the plugin from an idle handler so that the Connect * method return gets sent before the STOP StateChanged signal. */ schedule_fail_stop (plugin); } g_object_unref (connection); return success; }
static gboolean fail_stop (gpointer data) { NMVPNPlugin *self = NM_VPN_PLUGIN (data); NM_VPN_PLUGIN_GET_PRIVATE (self)->fail_stop_id = 0; nm_vpn_plugin_set_state (self, NM_VPN_SERVICE_STATE_STOPPED); return G_SOURCE_REMOVE; }
/** * signal failure to NM, connecting failed */ static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure) { nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; handler->reset(handler); /* TODO: NM does not handle this failure!? */ nm_vpn_plugin_failure(plugin, failure); nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED); }
static gboolean nm_vpn_plugin_connect (NMVPNPlugin *plugin, NMConnection *connection, GError **err) { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); gboolean ret = FALSE; NMVPNServiceState state; g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); state = nm_vpn_plugin_get_state (plugin); switch (state) { case NM_VPN_SERVICE_STATE_STARTING: g_set_error (err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, "%s", "Could not process the request because the VPN connection is already being started."); break; case NM_VPN_SERVICE_STATE_STARTED: g_set_error (err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, "%s", "Could not process the request because a VPN connection was already active."); break; case NM_VPN_SERVICE_STATE_STOPPING: g_set_error (err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "%s", "Could not process the request because the VPN connection is being stopped."); break; case NM_VPN_SERVICE_STATE_STOPPED: case NM_VPN_SERVICE_STATE_INIT: nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->connect (plugin, connection, err); if (!ret) { /* Stop the plugin from and idle handler so that the Connect * method return gets sent before the STOP StateChanged signal. */ if (priv->fail_stop_id) g_source_remove (priv->fail_stop_id); priv->fail_stop_id = g_idle_add (fail_stop, plugin); } break; default: g_assert_not_reached (); break; } return ret; }
gboolean nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err) { gboolean ret = FALSE; NMVPNServiceState state; g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); state = nm_vpn_plugin_get_state (plugin); switch (state) { case NM_VPN_SERVICE_STATE_STOPPING: g_set_error (err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "%s", "Could not process the request because the VPN connection is already being stopped."); break; case NM_VPN_SERVICE_STATE_STOPPED: g_set_error (err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, "%s", "Could not process the request because no VPN connection was active."); break; case NM_VPN_SERVICE_STATE_STARTING: case NM_VPN_SERVICE_STATE_STARTED: nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING); ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); break; case NM_VPN_SERVICE_STATE_INIT: ret = TRUE; break; default: g_warning ("Unhandled VPN service state %d", state); g_assert_not_reached (); break; } return ret; }
void nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin, GHashTable *ip4_config) { g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); g_return_if_fail (ip4_config != NULL); g_signal_emit (plugin, signals[IP4_CONFIG], 0, ip4_config); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); }
void nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin, GHashTable *ip4_config) { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); GHashTable *combined_config; GHashTableIter iter; gpointer key, value; g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); g_return_if_fail (ip4_config != NULL); priv->got_ip4 = TRUE; /* Old plugins won't send the "config" signal and thus can't send * NM_VPN_PLUGIN_CONFIG_HAS_IP4 either. But since they don't support IPv6, * we can safely assume that, if we don't receive a "config" signal but do * receive an "ip4-config" signal, the old plugin supports IPv4. */ if (!priv->got_config) priv->has_ip4 = TRUE; /* Older NetworkManager daemons expect all config info to be in * the ip4 config, so they won't even notice the "config" signal * being emitted. So just copy all of that data into the ip4 * config too. */ combined_config = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_iter_init (&iter, ip4_config); while (g_hash_table_iter_next (&iter, &key, &value)) g_hash_table_insert (combined_config, key, value); if (G_VALUE_TYPE (&priv->banner) != G_TYPE_INVALID) g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner); if (G_VALUE_TYPE (&priv->tundev) != G_TYPE_INVALID) g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev); if (G_VALUE_TYPE (&priv->gateway) != G_TYPE_INVALID) g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway); if (G_VALUE_TYPE (&priv->mtu) != G_TYPE_INVALID) g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu); g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config); g_hash_table_destroy (combined_config); if ( priv->has_ip4 == priv->got_ip4 && priv->has_ip6 == priv->got_ip6) nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); }
void nm_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin, GHashTable *ip6_config) { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); g_return_if_fail (ip6_config != NULL); priv->got_ip6 = TRUE; g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config); if ( priv->has_ip4 == priv->got_ip4 && priv->has_ip6 == priv->got_ip6) nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); }
static void openconnect_watch_cb (GPid pid, gint status, gpointer user_data) { NMOPENCONNECTPlugin *plugin = NM_OPENCONNECT_PLUGIN (user_data); NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin); guint error = 0; if (WIFEXITED (status)) { error = WEXITSTATUS (status); if (error != 0) g_warning ("openconnect exited with error code %d", error); } else if (WIFSTOPPED (status)) g_warning ("openconnect stopped unexpectedly with signal %d", WSTOPSIG (status)); else if (WIFSIGNALED (status)) g_warning ("openconnect died with signal %d", WTERMSIG (status)); else g_warning ("openconnect died from an unknown cause"); /* Reap child if needed. */ waitpid (priv->pid, NULL, WNOHANG); priv->pid = 0; if (priv->tun_name) { destroy_persistent_tundev (priv->tun_name); g_free (priv->tun_name); priv->tun_name = NULL; } /* Must be after data->state is set since signals use data->state */ switch (error) { case 2: /* Couldn't log in due to bad user/pass */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); break; case 1: /* Other error (couldn't bind to address, etc) */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); break; default: break; } nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED); }
static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object); switch (prop_id) { case PROP_DBUS_SERVICE_NAME: /* Construct-only */ priv->dbus_service_name = g_strdup (g_value_get_string (value)); break; case PROP_STATE: nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object), (NMVPNServiceState) g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void child_watch_cb (GPid pid, gint status, gpointer user_data) { NMVPNPlugin *plugin = NM_VPN_PLUGIN (user_data); NMOpensshPluginPrivate *priv = NM_OPENSSH_PLUGIN_GET_PRIVATE (plugin); NMVPNPluginFailure failure = NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED; guint error = 0; gboolean good_exit = FALSE; if (WIFEXITED (status)) { error = WEXITSTATUS (status); if (error != 0) nm_warning ("sshtun exited with error code %d", error); } else if (WIFSTOPPED (status)) nm_warning ("sshtun stopped unexpectedly with signal %d", WSTOPSIG (status)); else if (WIFSIGNALED (status)) nm_warning ("sshtun died with signal %d", WTERMSIG (status)); else nm_warning ("sshtun died from an unknown cause"); sshtun_stop (priv->handle); sshtun_del (priv->handle); priv->handle = NULL; switch (error) { case 0: good_exit = TRUE; break; default: failure = NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED; break; } if (!good_exit) nm_vpn_plugin_failure (plugin, failure); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); }
static GObject * constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params) { GObject *object; NMVPNPlugin *plugin; NMVPNPluginPrivate *priv; DBusGConnection *connection; DBusGProxy *proxy; guint request_name_result; GError *err = NULL; object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type, n_construct_params, construct_params); if (!object) return NULL; priv = NM_VPN_PLUGIN_GET_PRIVATE (object); if (!priv->dbus_service_name) goto err; connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); if (!connection) goto err; proxy = dbus_g_proxy_new_for_name (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); if (!dbus_g_proxy_call (proxy, "RequestName", &err, G_TYPE_STRING, priv->dbus_service_name, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_result, G_TYPE_INVALID)) { g_object_unref (proxy); goto err; } g_object_unref (proxy); dbus_g_connection_register_g_object (connection, NM_VPN_DBUS_PLUGIN_PATH, object); plugin = NM_VPN_PLUGIN (object); nm_vpn_plugin_set_connection (plugin, connection); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT); return object; err: if (err) { g_warning ("Failed to initialize VPN plugin: %s", err->message); g_error_free (err); } if (object) g_object_unref (object); return NULL; }
static void l2tpd_watch_cb (GPid pid, gint status, gpointer user_data) { NML2tpPlugin *plugin = NM_L2TP_PLUGIN (user_data); NML2tpPluginPrivate *priv = NM_L2TP_PLUGIN_GET_PRIVATE (plugin); guint error = 0; pid_t my_pid = getpid (); char *filename; if (WIFEXITED (status)) { error = WEXITSTATUS (status); if (error != 0) g_warning (_("xl2tpd exited with error code %d"), error); } else if (WIFSTOPPED (status)) g_warning (_("xl2tpd stopped unexpectedly with signal %d"), WSTOPSIG (status)); else if (WIFSIGNALED (status)) g_warning (_("xl2tpd died with signal %d"), WTERMSIG (status)); else g_warning (_("xl2tpd died from an unknown cause")); /* Reap child if needed. */ waitpid (priv->pid_l2tpd, NULL, WNOHANG); priv->pid_l2tpd = 0; if(priv->ipsec_up) { nm_l2tp_stop_ipsec(); } /* Cleaning up config files */ filename = g_strdup_printf ("/var/run/nm-xl2tpd.conf.%d", my_pid); unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ppp-options.xl2tpd.%d", my_pid); unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d/ipsec.conf", my_pid); // unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d/ipsec.secrets", my_pid); // unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d", my_pid); rmdir(filename); g_free(filename); /* Must be after data->state is set since signals use data->state */ switch (error) { case 16: /* hangup */ // FIXME: better failure reason nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); break; case 2: /* Couldn't log in due to bad user/pass */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); break; case 1: /* Other error (couldn't bind to address, etc) */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); break; default: break; } nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED); }