static void _name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { NMVpnService *service = NM_VPN_SERVICE (user_data); NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); gboolean success; char *owner; owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); /* Service changed, no need to wait for the timeout any longer */ if (priv->start_timeout) { g_source_remove (priv->start_timeout); priv->start_timeout = 0; } if (owner && !priv->service_running) { /* service appeared */ priv->service_running = TRUE; nm_log_info (LOGD_VPN, "VPN service '%s' appeared; activating connections", nm_vpn_plugin_info_get_name (priv->plugin_info)); /* Expect success because the VPN service has already appeared */ success = start_active_vpn (service, NULL); g_warn_if_fail (success); } else if (!owner && priv->service_running) { /* service went away */ priv->service_running = FALSE; nm_log_info (LOGD_VPN, "VPN service '%s' disappeared", nm_vpn_plugin_info_get_name (priv->plugin_info)); nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); } g_free (owner); }
GSList * vpn_get_plugin_infos (void) { static gboolean plugins_loaded = FALSE; static GSList *plugins = NULL; GSList *p; if (G_LIKELY (plugins_loaded)) return plugins; plugins_loaded = TRUE; p = nm_vpn_plugin_info_list_load (); plugins = NULL; while (p) { NMVpnPluginInfo *plugin_info = NM_VPN_PLUGIN_INFO (p->data); GError *error = NULL; /* load the editor plugin, and preserve only those NMVpnPluginInfo that can * successfully load the plugin. */ if (nm_vpn_plugin_info_load_editor_plugin (plugin_info, &error)) { plugins = g_slist_prepend (plugins, plugin_info); g_info ("vpn: (%s,%s) loaded", nm_vpn_plugin_info_get_name (plugin_info), nm_vpn_plugin_info_get_filename (plugin_info)); } else { if ( !nm_vpn_plugin_info_get_plugin (plugin_info) && nm_vpn_plugin_info_lookup_property (plugin_info, NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties")) { g_message ("vpn: (%s,%s) cannot load legacy-only plugin", nm_vpn_plugin_info_get_name (plugin_info), nm_vpn_plugin_info_get_filename (plugin_info)); } else if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { g_message ("vpn: (%s,%s) file \"%s\" not found. Did you install the client package?", nm_vpn_plugin_info_get_name (plugin_info), nm_vpn_plugin_info_get_filename (plugin_info), nm_vpn_plugin_info_get_plugin (plugin_info)); } else { g_warning ("vpn: (%s,%s) could not load plugin: %s", nm_vpn_plugin_info_get_name (plugin_info), nm_vpn_plugin_info_get_filename (plugin_info), error->message); } g_clear_error (&error); g_object_unref (plugin_info); } p = g_slist_delete_link (p, p); } /* sort the list of plugins alphabetically. */ plugins = g_slist_sort (plugins, (GCompareFunc) _sort_vpn_plugins); return plugins; }
gboolean nm_vpn_manager_activate_connection (NMVpnManager *manager, NMVpnConnection *vpn, GError **error) { NMVpnManagerPrivate *priv; NMVpnPluginInfo *plugin_info; const char *service_name; NMDevice *device; g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), FALSE); g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), FALSE); g_return_val_if_fail (!error || !*error, FALSE); priv = NM_VPN_MANAGER_GET_PRIVATE (manager); device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); g_assert (device); if ( nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED && nm_device_get_state (device) != NM_DEVICE_STATE_SECONDARIES) { g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, "The base device for the VPN connection was not active."); return FALSE; } service_name = nm_vpn_connection_get_service (vpn); plugin_info = nm_vpn_plugin_info_list_find_by_service (priv->plugins, service_name); if (!plugin_info) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, "The VPN service '%s' was not installed.", service_name); return FALSE; } if ( !nm_vpn_plugin_info_supports_multiple (plugin_info) && g_hash_table_contains (priv->active_services, service_name)) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, "The '%s' plugin only supports a single active connection.", nm_vpn_plugin_info_get_name (plugin_info)); return FALSE; } nm_vpn_connection_activate (vpn, plugin_info); if (!nm_vpn_plugin_info_supports_multiple (plugin_info)) { /* Block activations of the connections of the same service type. */ g_hash_table_add (priv->active_services, g_strdup (service_name)); g_signal_connect (vpn, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (vpn_state_changed), g_object_ref (manager)); } return TRUE; }
static gboolean _daemon_exec_timeout (gpointer data) { NMVpnService *self = NM_VPN_SERVICE (data); NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", nm_vpn_plugin_info_get_name (priv->plugin_info)); priv->start_timeout = 0; nm_vpn_service_stop_connections (self, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); return G_SOURCE_REMOVE; }
static gboolean nm_vpn_service_daemon_exec (NMVpnService *service, GError **error) { NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); GPid pid; char *vpn_argv[2]; gboolean success = FALSE; GError *spawn_error = NULL; g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE); vpn_argv[0] = (char *) nm_vpn_plugin_info_get_program (priv->plugin_info); vpn_argv[1] = NULL; g_assert (vpn_argv[0]); success = g_spawn_async (NULL, vpn_argv, NULL, 0, nm_utils_setpgid, NULL, &pid, &spawn_error); if (success) { nm_log_info (LOGD_VPN, "VPN service '%s' started (%s), PID %ld", nm_vpn_plugin_info_get_name (priv->plugin_info), nm_vpn_service_get_dbus_service (service), (long int) pid); priv->start_timeout = g_timeout_add_seconds (5, _daemon_exec_timeout, service); } else { nm_log_warn (LOGD_VPN, "VPN service '%s': could not launch the VPN service. error: (%d) %s.", nm_vpn_plugin_info_get_name (priv->plugin_info), spawn_error ? spawn_error->code : -1, spawn_error && spawn_error->message ? spawn_error->message : "(unknown)"); g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "%s", spawn_error ? spawn_error->message : "unknown g_spawn_async() error"); nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); if (spawn_error) g_error_free (spawn_error); } return success; }
static gboolean start_active_vpn (NMVpnService *self, GError **error) { NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); if (!priv->active) return TRUE; if (priv->service_running) { /* Just activate the VPN */ nm_vpn_connection_activate (priv->active); return TRUE; } else if (priv->start_timeout == 0) { /* VPN service not running, start it */ nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", nm_vpn_plugin_info_get_name (priv->plugin_info)); return nm_vpn_service_daemon_exec (self, error); } /* Already started VPN service, waiting for it to appear on D-Bus */ return TRUE; }
static gint _sort_vpn_plugins (NMVpnPluginInfo *aa, NMVpnPluginInfo *bb) { return strcmp (nm_vpn_plugin_info_get_name (aa), nm_vpn_plugin_info_get_name (bb)); }