static void dispose (GObject *object) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object); if (priv->monitor_etc) { if (priv->monitor_id_etc) g_signal_handler_disconnect (priv->monitor_etc, priv->monitor_id_etc); g_file_monitor_cancel (priv->monitor_etc); g_clear_object (&priv->monitor_etc); } if (priv->monitor_lib) { if (priv->monitor_id_lib) g_signal_handler_disconnect (priv->monitor_lib, priv->monitor_id_lib); g_file_monitor_cancel (priv->monitor_lib); g_clear_object (&priv->monitor_lib); } while (priv->plugins) nm_vpn_plugin_info_list_remove (&priv->plugins, priv->plugins->data); g_hash_table_unref (priv->active_services); G_OBJECT_CLASS (nm_vpn_manager_parent_class)->dispose (object); }
NMConnection * nm_vpn_manager_get_connection_for_active (NMVPNManager *manager, const char *active_path) { NMVPNManagerPrivate *priv; GHashTableIter iter; gpointer data; GSList *active, *elt; g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); priv = NM_VPN_MANAGER_GET_PRIVATE (manager); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (elt = active; elt; elt = g_slist_next (elt)) { NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); const char *ac_path; ac_path = nm_vpn_connection_get_active_connection_path (vpn); if (ac_path && !strcmp (ac_path, active_path)) return nm_vpn_connection_get_connection (vpn); } } return NULL; }
gboolean nm_vpn_manager_deactivate_connection (NMVPNManager *self, const char *path, NMVPNConnectionStateReason reason) { NMVPNManagerPrivate *priv; GHashTableIter iter; gpointer data; GSList *active, *elt; g_return_val_if_fail (self, FALSE); g_return_val_if_fail (NM_IS_VPN_MANAGER (self), FALSE); g_return_val_if_fail (path != NULL, FALSE); priv = NM_VPN_MANAGER_GET_PRIVATE (self); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (elt = active; elt; elt = g_slist_next (elt)) { NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); const char *vpn_path; vpn_path = nm_vpn_connection_get_active_connection_path (vpn); if (!strcmp (path, vpn_path)) { nm_vpn_connection_disconnect (vpn, reason); return TRUE; } } } return FALSE; }
void nm_vpn_manager_add_active_connections (NMVPNManager *self, NMConnection *filter, GPtrArray *array) { NMVPNManagerPrivate *priv; GHashTableIter iter; gpointer data; GSList *active, *elt; g_return_if_fail (self); g_return_if_fail (NM_IS_VPN_MANAGER (self)); g_return_if_fail (array != NULL); priv = NM_VPN_MANAGER_GET_PRIVATE (self); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (elt = active; elt; elt = g_slist_next (elt)) { NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); const char *path; if (!filter || (nm_vpn_connection_get_connection (vpn) == filter)) { path = nm_vpn_connection_get_active_connection_path (vpn); g_ptr_array_add (array, g_strdup (path)); } } } }
static void try_add_service (NMVPNManager *self, const char *namefile) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVPNService *service = NULL; GError *error = NULL; const char *service_name; char *tmp; g_return_if_fail (g_path_is_absolute (namefile)); /* Make sure we don't add dupes */ tmp = service_name_from_file (namefile); if (tmp) service = g_hash_table_lookup (priv->services, tmp); g_free (tmp); if (service) return; /* New service, add it */ service = nm_vpn_service_new (namefile, &error); if (!service) { nm_log_warn (LOGD_VPN, "failed to load VPN service file %s: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); return; } service_name = nm_vpn_service_get_dbus_service (service); g_hash_table_insert (priv->services, (char *) service_name, service); nm_log_info (LOGD_VPN, "VPN: loaded %s", service_name, service); }
static void nm_vpn_manager_init (NMVPNManager *self) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GFile *file; GDir *dir; const char *fn; char *path; priv->services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); /* Watch the VPN directory for changes */ file = g_file_new_for_path (VPN_NAME_FILES_DIR "/"); priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (priv->monitor) { priv->monitor_id = g_signal_connect (priv->monitor, "changed", G_CALLBACK (vpn_dir_changed), self); } /* Load VPN service files */ dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL); if (dir) { while ((fn = g_dir_read_name (dir))) { /* only parse filenames that end with .name */ if (g_str_has_suffix (fn, ".name")) { path = g_build_filename (VPN_NAME_FILES_DIR, fn, NULL); try_add_service (self, path); g_free (path); } } g_dir_close (dir); } }
static void try_add_service (NMVpnManager *self, const char *namefile) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVpnService *service = NULL; GHashTableIter iter; GError *error = NULL; const char *service_name; g_return_if_fail (g_path_is_absolute (namefile)); /* Make sure we don't add dupes */ g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) { if (g_strcmp0 (namefile, nm_vpn_service_get_name_file (service)) == 0) return; } /* New service */ service = nm_vpn_service_new (namefile, &error); if (service) { service_name = nm_vpn_service_get_dbus_service (service); g_hash_table_insert (priv->services, (char *) service_name, service); nm_log_info (LOGD_VPN, "VPN: loaded %s", service_name); } else { nm_log_warn (LOGD_VPN, "failed to load VPN service file %s: (%d) %s", namefile, error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); } }
NMVPNConnection * nm_vpn_manager_activate_connection (NMVPNManager *manager, NMConnection *connection, NMActRequest *act_request, NMDevice *device, GError **error) { NMSettingVPN *vpn_setting; NMVPNService *service; NMVPNConnection *vpn = NULL; const char *service_name; g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (device), NULL); g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (*error == NULL, NULL); if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) { g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, "%s", "The base device for the VPN connection was not active."); return NULL; } vpn_setting = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); if (!vpn_setting) { g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, "%s", "The connection was not a VPN connection."); return NULL; } vpn = find_active_vpn_connection_by_connection (manager, connection); if (vpn) { nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); vpn = NULL; } service_name = nm_setting_vpn_get_service_type (vpn_setting); g_assert (service_name); service = g_hash_table_lookup (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name); if (!service) { g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "The VPN service '%s' was not installed.", service_name); return NULL; } vpn = nm_vpn_service_activate (service, connection, act_request, device, error); if (vpn) { g_signal_connect (vpn, "vpn-state-changed", G_CALLBACK (connection_vpn_state_changed), manager); } return vpn; }
static NMVPNConnection * find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *connection) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GHashTableIter iter; gpointer data; GSList *active, *aiter; NMVPNConnection *found = NULL; g_return_val_if_fail (connection, NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data) && (found == NULL)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (aiter = active; aiter; aiter = g_slist_next (aiter)) { NMVPNConnection *vpn = NM_VPN_CONNECTION (aiter->data); if (nm_vpn_connection_get_connection (vpn) == connection) { found = vpn; break; } } g_slist_free (active); } return found; }
static void vpn_dir_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { NMVpnManager *self = NM_VPN_MANAGER (user_data); NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVpnPluginInfo *plugin_info; gs_free char *path = NULL; GError *error = NULL; path = g_file_get_path (file); if (!nm_vpn_plugin_info_validate_filename (path)) return; switch (event_type) { case G_FILE_MONITOR_EVENT_DELETED: plugin_info = nm_vpn_plugin_info_list_find_by_filename (priv->plugins, path); if (!plugin_info) break; nm_log_dbg (LOGD_VPN, "vpn: service file %s deleted", path); nm_vpn_plugin_info_list_remove (&priv->plugins, plugin_info); break; case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: plugin_info = nm_vpn_plugin_info_list_find_by_filename (priv->plugins, path); if (plugin_info) { /* we don't support reloading an existing plugin. You can only remove the file * and re-add it. By reloading we want to support the use case of installing * a VPN plugin after NM started. No need to burden ourself with a complete * reload. */ break; } if (!_nm_vpn_plugin_info_check_file (path, TRUE, TRUE, 0, NULL, NULL, &error)) { nm_log_dbg (LOGD_VPN, "vpn: ignore changed service file %s (%s)", path, error->message); g_clear_error (&error); break; } plugin_info = nm_vpn_plugin_info_new_from_file (path, &error); if (!plugin_info) { nm_log_dbg (LOGD_VPN, "vpn: ignore changed service file %s due to invalid content (%s)", path, error->message); g_clear_error (&error); break; } nm_log_dbg (LOGD_VPN, "vpn: service file %s created or modified", path); try_add_plugin (self, plugin_info); g_object_unref (plugin_info); break; default: nm_log_dbg (LOGD_VPN, "vpn: service file %s change event %d", path, event_type); break; } }
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 void stop_all_services (NMVpnManager *self) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GHashTableIter iter; NMVpnService *service; g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) { nm_vpn_service_stop_connections (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); } }
static void vpn_state_changed (NMVpnConnection *vpn, GParamSpec *pspec, NMVpnManager *manager) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (manager); NMActiveConnectionState state = nm_active_connection_get_state (NM_ACTIVE_CONNECTION (vpn)); const char *service_name = nm_vpn_connection_get_service (vpn); if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { g_hash_table_remove (priv->active_services, service_name); g_signal_handlers_disconnect_by_func (vpn, vpn_state_changed, manager); g_object_unref (manager); } }
static void vpn_dir_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { NMVPNManager *self = NM_VPN_MANAGER (user_data); NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVPNService *service; char *path; path = g_file_get_path (file); if (!g_str_has_suffix (path, ".name")) { g_free (path); return; } switch (event_type) { case G_FILE_MONITOR_EVENT_DELETED: nm_log_dbg (LOGD_VPN, "service file %s deleted", path); service = get_service_by_namefile (self, path); if (service) { const char *service_name = nm_vpn_service_get_dbus_service (service); /* Stop active VPN connections and destroy the service */ nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); nm_log_info (LOGD_VPN, "VPN: unloaded %s", service_name, service); g_hash_table_remove (priv->services, service_name); } break; case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: nm_log_dbg (LOGD_VPN, "service file %s created or modified", path); try_add_service (self, path); break; default: nm_log_dbg (LOGD_VPN, "service file %s change event %d", path, event_type); break; } g_free (path); }
static void try_add_plugin (NMVpnManager *self, NMVpnPluginInfo *plugin_info) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); const char *program; program = nm_vpn_plugin_info_get_program (plugin_info); if (!program || !*program) return; /* Make sure we don't add dupes. * We don't really allow reload of the same file. What we do allow is however to * delete a file and re-add it. */ if (nm_vpn_plugin_info_list_find_by_filename (priv->plugins, nm_vpn_plugin_info_get_filename (plugin_info))) return; if (!nm_vpn_plugin_info_list_add (&priv->plugins, plugin_info, NULL)) return; }
GSList * nm_vpn_manager_get_active_connections (NMVPNManager *self) { NMVPNManagerPrivate *priv; GHashTableIter iter; gpointer data; GSList *list = NULL, *active; g_return_val_if_fail (self, NULL); g_return_val_if_fail (NM_IS_VPN_MANAGER (self), NULL); priv = NM_VPN_MANAGER_GET_PRIVATE (self); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); list = g_slist_concat (list, active); } return list; }
gboolean nm_vpn_manager_activate_connection (NMVpnManager *manager, NMVpnConnection *vpn, GError **error) { NMConnection *connection; NMSettingVpn *s_vpn; NMVpnService *service; 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 != NULL, FALSE); g_return_val_if_fail (*error == NULL, FALSE); 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_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, "The base device for the VPN connection was not active."); return FALSE; } connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (vpn)); g_assert (connection); s_vpn = nm_connection_get_setting_vpn (connection); g_assert (s_vpn); service_name = nm_setting_vpn_get_service_type (s_vpn); g_assert (service_name); service = g_hash_table_lookup (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name); if (!service) { g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "The VPN service '%s' was not installed.", service_name); return FALSE; } return nm_vpn_service_activate (service, vpn, error); }
static void nm_vpn_manager_init (NMVpnManager *self) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GFile *file; GSList *infos, *info; const char *conf_dir_etc = _nm_vpn_plugin_info_get_default_dir_etc (); const char *conf_dir_lib = _nm_vpn_plugin_info_get_default_dir_lib (); /* Watch the VPN directory for changes */ file = g_file_new_for_path (conf_dir_lib); priv->monitor_lib = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (priv->monitor_lib) { priv->monitor_id_lib = g_signal_connect (priv->monitor_lib, "changed", G_CALLBACK (vpn_dir_changed), self); } file = g_file_new_for_path (conf_dir_etc); priv->monitor_etc = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (priv->monitor_etc) { priv->monitor_id_etc = g_signal_connect (priv->monitor_etc, "changed", G_CALLBACK (vpn_dir_changed), self); } /* first read conf_dir_lib. The name files are not really user configuration, but * plugin configuration. Hence we expect ~newer~ plugins to install their files * in /usr/lib/NetworkManager. We want to prefer those files. * In case of no-conflict, the order doesn't matter. */ infos = _nm_vpn_plugin_info_list_load_dir (conf_dir_lib, TRUE, 0, NULL, NULL); for (info = infos; info; info = info->next) try_add_plugin (self, info->data); g_slist_free_full (infos, g_object_unref); infos = _nm_vpn_plugin_info_list_load_dir (conf_dir_etc, TRUE, 0, NULL, NULL); for (info = infos; info; info = info->next) try_add_plugin (self, info->data); g_slist_free_full (infos, g_object_unref); priv->active_services = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); }
static void dispose (GObject *object) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object); if (!priv->disposed) { priv->disposed = TRUE; if (priv->monitor) { if (priv->monitor_id) g_signal_handler_disconnect (priv->monitor, priv->monitor_id); g_file_monitor_cancel (priv->monitor); g_object_unref (priv->monitor); } g_hash_table_destroy (priv->services); } G_OBJECT_CLASS (nm_vpn_manager_parent_class)->dispose (object); }
static void dispose (GObject *object) { NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object); if (priv->monitor) { if (priv->monitor_id) g_signal_handler_disconnect (priv->monitor, priv->monitor_id); g_file_monitor_cancel (priv->monitor); g_clear_object (&priv->monitor); } if (priv->services) { stop_all_services (NM_VPN_MANAGER (object)); g_hash_table_destroy (priv->services); priv->services = NULL; } G_OBJECT_CLASS (nm_vpn_manager_parent_class)->dispose (object); }
GSList * nm_vpn_manager_get_active_connections (NMVPNManager *self) { NMVPNManagerPrivate *priv; GHashTableIter iter; gpointer data; GSList *list = NULL, *active, *elt; g_return_val_if_fail (self, NULL); g_return_val_if_fail (NM_IS_VPN_MANAGER (self), NULL); priv = NM_VPN_MANAGER_GET_PRIVATE (self); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (elt = active; elt; elt = g_slist_next (elt)) list = g_slist_append (list, g_object_ref (G_OBJECT (elt->data))); } return list; }
static NMVPNService * get_service_by_namefile (NMVPNManager *self, const char *namefile) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GHashTableIter iter; gpointer data; g_return_val_if_fail (namefile, NULL); g_return_val_if_fail (g_path_is_absolute (namefile), NULL); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { NMVPNService *candidate = NM_VPN_SERVICE (data); const char *service_namefile; service_namefile = nm_vpn_service_get_name_file (candidate); if (!strcmp (namefile, service_namefile)) return candidate; } return NULL; }
static NMVPNConnection * find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *connection) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); GHashTableIter iter; gpointer data; GSList *connections, *elt; g_return_val_if_fail (connection, NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_hash_table_iter_init (&iter, priv->services); while (g_hash_table_iter_next (&iter, NULL, &data)) { connections = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); for (elt = connections; elt; elt = g_slist_next (elt)) { NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); if (nm_vpn_connection_get_connection (vpn) == connection) return vpn; } } return NULL; }