static void test_add_connection (void) { NMConnection *connection; time_t start, now; gboolean done = FALSE; connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); nm_client_add_connection_async (client, connection, TRUE, NULL, add_cb, &done); start = time (NULL); do { now = time (NULL); g_main_context_iteration (NULL, FALSE); } while ((done == FALSE) && (now - start < 5)); g_assert (done == TRUE); g_assert (remote != NULL); /* Make sure the connection is the same as what we added */ g_assert (nm_connection_compare (connection, NM_CONNECTION (remote), NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); g_object_unref (connection); }
static void test_nat_export (NMVpnPluginUiInterface *plugin, const char *dir, const char *tmpdir, const char *nat_mode) { NMConnection *connection; NMSettingVPN *s_vpn; NMConnection *reimported; char *path; gboolean success; GError *error = NULL; int ret; connection = get_basic_connection ("nat-export", plugin, dir, "basic.pcf"); ASSERT (connection != NULL, "nat-export", "failed to import connection"); s_vpn = nm_connection_get_setting_vpn (connection); ASSERT (s_vpn != NULL, "nat-export", "imported connection had no VPN setting"); nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, nat_mode); path = g_build_path ("/", tmpdir, NAT_EXPORTED_NAME, NULL); success = nm_vpn_plugin_ui_interface_export (plugin, path, connection, &error); if (!success) { if (!error) FAIL ("nat-export", "export failed with missing error"); else FAIL ("nat-export", "export failed: %s", error->message); } /* Now re-import it and compare the connections to ensure they are the same */ reimported = get_basic_connection ("nat-export", plugin, tmpdir, NAT_EXPORTED_NAME); ret = unlink (path); ASSERT (connection != NULL, "nat-export", "failed to re-import connection"); /* Clear secrets first, since they don't get exported, and thus would * make the connection comparison below fail. */ remove_user_password (connection); /* Since we don't export the user password, but the original connection * had one, we need to add secret flags to the re-imported connection. */ s_vpn = nm_connection_get_setting_vpn (reimported); nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_VPNC_KEY_SECRET, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL); ASSERT (nm_connection_compare (connection, reimported, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, "nat-export", "original and reimported connection differ"); g_object_unref (reimported); g_object_unref (connection); g_free (path); }
static void test_add_connection (void) { gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSettingWired *s_wired; char *uuid; gboolean success; time_t start, now; gboolean done = FALSE; connection = nm_connection_new (); s_con = (NMSettingConnection *) nm_setting_connection_new (); uuid = nm_utils_uuid_generate (); g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_ID, TEST_CON_ID, NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); g_free (uuid); nm_connection_add_setting (connection, NM_SETTING (s_con)); s_wired = (NMSettingWired *) nm_setting_wired_new (); nm_connection_add_setting (connection, NM_SETTING (s_wired)); success = nm_remote_settings_add_connection (settings, connection, add_cb, &done); g_assert (success == TRUE); start = time (NULL); do { now = time (NULL); g_main_context_iteration (NULL, FALSE); } while ((done == FALSE) && (now - start < 5)); g_assert (done == TRUE); g_assert (remote != NULL); /* Make sure the connection is the same as what we added */ g_assert (nm_connection_compare (connection, NM_CONNECTION (remote), NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); }
static void dispose (GObject *object) { NMBluezDevice *self = NM_BLUEZ_DEVICE (object); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); NMConnection *to_delete = NULL; if (priv->pan_connection) { /* Check whether we want to remove the created connection. If so, we take a reference * and delete it at the end of dispose(). */ if ( nm_settings_connection_get_unsaved (NM_SETTINGS_CONNECTION (priv->pan_connection)) && nm_connection_compare (priv->pan_connection, priv->pan_connection_original, NM_SETTING_COMPARE_FLAG_EXACT)) to_delete = g_object_ref (priv->pan_connection); priv->pan_connection = NULL; g_clear_object (&priv->pan_connection_original); } g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_slist_free_full (priv->connections, g_object_unref); priv->connections = NULL; g_clear_object (&priv->adapter5); g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); if (to_delete) { nm_log_dbg (LOGD_BT, "bluez[%s] removing Bluetooth connection for NAP device: '%s' (%s)", priv->path, nm_connection_get_id (to_delete), nm_connection_get_uuid (to_delete)); nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL, NULL); g_object_unref (to_delete); } }
static void reload_connections (gpointer config) { SCPluginIfnet *self = SC_PLUGIN_IFNET (config); SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self); GList *conn_names = NULL, *n_iter = NULL; /* save names for removing unused connections */ GHashTable *new_conn_names = NULL; GHashTableIter iter; gpointer key; gpointer value; if (priv->unmanaged_well_known) return; if (!reload_parsers ()) return; PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Loading connections"); conn_names = ifnet_get_connection_names (); new_conn_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (n_iter = conn_names; n_iter; n_iter = g_list_next (n_iter)) { NMIfnetConnection *exported; NMIfnetConnection *old; gchar *conn_name = g_strdup (n_iter->data); /* add the new connection */ exported = nm_ifnet_connection_new (conn_name); if (!exported) { g_free (conn_name); continue; } g_signal_connect (G_OBJECT (exported), "ifnet_setup_monitors", G_CALLBACK (setup_monitors), config); g_signal_connect (G_OBJECT (exported), "ifnet_cancel_monitors", G_CALLBACK (cancel_monitors), config); old = g_hash_table_lookup (priv->config_connections, conn_name); if (old && exported) { gchar *auto_refresh = ifnet_get_global_setting (IFNET_KEY_FILE_GROUP, "auto_refresh"); if (auto_refresh && is_true (auto_refresh)) { if (!nm_connection_compare (NM_CONNECTION (old), NM_CONNECTION (exported), NM_SETTING_COMPARE_FLAG_EXACT)) { PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Auto refreshing %s", conn_name); g_signal_emit_by_name (old, NM_SETTINGS_CONNECTION_INTERFACE_REMOVED); g_hash_table_remove (priv->config_connections, conn_name); g_hash_table_insert (priv->config_connections, g_strdup (conn_name), exported); if (is_managed (conn_name)) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, exported); } } else update_old_connection (conn_name, old, exported, priv); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } else if (exported) { g_hash_table_insert (priv->config_connections, g_strdup (conn_name), exported); if (is_managed (conn_name)) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, exported); } g_hash_table_insert (new_conn_names, conn_name, conn_name); } /* remove unused connections */ g_hash_table_iter_init (&iter, priv->config_connections); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!g_hash_table_lookup (new_conn_names, key)) { g_signal_emit_by_name (value, NM_SETTINGS_CONNECTION_INTERFACE_REMOVED); g_hash_table_remove (priv->config_connections, key); } } g_hash_table_remove_all (new_conn_names); g_hash_table_destroy (new_conn_names); g_list_free (conn_names); }
static NMIfcfgConnection * update_connection (SCPluginIfcfg *self, NMConnection *source, const char *full_path, NMIfcfgConnection *connection, gboolean protect_existing_connection, GHashTable *protected_connections, GError **error) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); NMIfcfgConnection *connection_new; NMIfcfgConnection *connection_by_uuid; GError *local = NULL; const char *new_unmanaged = NULL, *old_unmanaged = NULL; const char *new_unrecognized = NULL, *old_unrecognized = NULL; gboolean unmanaged_changed = FALSE, unrecognized_changed = FALSE; const char *uuid; g_return_val_if_fail (!source || NM_IS_CONNECTION (source), NULL); g_return_val_if_fail (full_path || source, NULL); if (full_path) _LOGD ("loading from file \"%s\"...", full_path); /* Create a NMIfcfgConnection instance, either by reading from @full_path or * based on @source. */ connection_new = nm_ifcfg_connection_new (source, full_path, error); if (!connection_new) { /* Unexpected failure. Probably the file is invalid? */ if ( connection && !protect_existing_connection && (!protected_connections || !g_hash_table_contains (protected_connections, connection))) remove_connection (self, connection); return NULL; } uuid = nm_connection_get_uuid (NM_CONNECTION (connection_new)); connection_by_uuid = g_hash_table_lookup (priv->connections, uuid); if ( connection && connection != connection_by_uuid) { if ( (protect_existing_connection && connection_by_uuid != NULL) || (protected_connections && g_hash_table_contains (protected_connections, connection))) { NMIfcfgConnection *conflicting = (protect_existing_connection && connection_by_uuid != NULL) ? connection_by_uuid : connection; if (source) _LOGW ("cannot update protected connection "NM_IFCFG_CONNECTION_LOG_FMT" due to conflicting UUID %s", NM_IFCFG_CONNECTION_LOG_ARG (conflicting), uuid); else _LOGW ("cannot load %s due to conflicting UUID for "NM_IFCFG_CONNECTION_LOG_FMT, full_path, NM_IFCFG_CONNECTION_LOG_ARG (conflicting)); g_object_unref (connection_new); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Cannot update protected connection due to conflicting UUID"); return NULL; } /* The new connection has a different UUID then the original one that we * are about to update. Remove @connection. */ remove_connection (self, connection); } /* Check if the found connection with the same UUID is not protected from updating. */ if ( connection_by_uuid && ( (!connection && protect_existing_connection) || (protected_connections && g_hash_table_contains (protected_connections, connection_by_uuid)))) { if (source) _LOGW ("cannot update connection due to conflicting UUID for "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_by_uuid)); else _LOGW ("cannot load %s due to conflicting UUID for "NM_IFCFG_CONNECTION_LOG_FMT, full_path, NM_IFCFG_CONNECTION_LOG_ARG (connection_by_uuid)); g_object_unref (connection_new); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Skip updating protected connection during reload"); return NULL; } /* Evaluate unmanaged/unrecognized flags. */ if (connection_by_uuid) old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (connection_by_uuid); new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (connection_new); unmanaged_changed = g_strcmp0 (old_unmanaged, new_unmanaged); if (connection_by_uuid) old_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (connection_by_uuid); new_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (connection_new); unrecognized_changed = g_strcmp0 (old_unrecognized, new_unrecognized); if (connection_by_uuid) { const char *old_path; old_path = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)); if ( !unmanaged_changed && !unrecognized_changed && nm_connection_compare (NM_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { if (old_path && g_strcmp0 (old_path, full_path) != 0) _LOGI ("rename \"%s\" to "NM_IFCFG_CONNECTION_LOG_FMT" without other changes", nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)), NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); } else { /******************************************************* * UPDATE *******************************************************/ if (source) _LOGI ("update "NM_IFCFG_CONNECTION_LOG_FMT" from %s", NM_IFCFG_CONNECTION_LOG_ARG (connection_new), NM_IFCFG_CONNECTION_LOG_PATH (old_path)); else if (!g_strcmp0 (old_path, nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_new)))) _LOGI ("update "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); else if (old_path) _LOGI ("rename \"%s\" to "NM_IFCFG_CONNECTION_LOG_FMT, old_path, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); else _LOGI ("update and persist "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); g_object_set (connection_by_uuid, NM_IFCFG_CONNECTION_UNMANAGED_SPEC, new_unmanaged, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized, NULL); if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), FALSE, /* don't set Unsaved */ "ifcfg-update", &local)) { /* Shouldn't ever get here as 'connection_new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); } g_assert_no_error (local); if (new_unmanaged || new_unrecognized) { if (!old_unmanaged && !old_unrecognized) { g_object_ref (connection_by_uuid); /* Unexport the connection by telling the settings service it's * been removed. */ nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection_by_uuid)); /* Remove the path so that claim_connection() doesn't complain later when * interface gets managed and connection is re-added. */ nm_connection_set_path (NM_CONNECTION (connection_by_uuid), NULL); /* signal_remove() will end up removing the connection from our hash, * so add it back now. */ g_hash_table_insert (priv->connections, g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection_by_uuid))), connection_by_uuid); } } else { if (old_unmanaged /* && !new_unmanaged */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" and its device because NM_CONTROLLED was true.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid); } else if (old_unrecognized /* && !new_unrecognized */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" because it is now a recognized type.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid); } } if (unmanaged_changed) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); if (unrecognized_changed) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); } nm_settings_connection_set_filename (NM_SETTINGS_CONNECTION (connection_by_uuid), full_path); g_object_unref (connection_new); return connection_by_uuid; } else { /******************************************************* * ADD *******************************************************/ if (source) _LOGI ("add connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); else _LOGI ("new connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); g_hash_table_insert (priv->connections, g_strdup (uuid), connection_new); g_signal_connect (connection_new, NM_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (connection_removed_cb), self); if (nm_ifcfg_connection_get_unmanaged_spec (connection_new)) { const char *spec; const char *device_id; spec = nm_ifcfg_connection_get_unmanaged_spec (connection_new); device_id = strchr (spec, ':'); if (device_id) device_id++; else device_id = spec; _LOGW ("Ignoring connection "NM_IFCFG_CONNECTION_LOG_FMT" / device '%s' due to NM_CONTROLLED=no.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new), device_id); } else if (nm_ifcfg_connection_get_unrecognized_spec (connection_new)) _LOGW ("Ignoring connection "NM_IFCFG_CONNECTION_LOG_FMT" of unrecognized type.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); /* watch changes of ifcfg hardlinks */ g_signal_connect (G_OBJECT (connection_new), "ifcfg-changed", G_CALLBACK (connection_ifcfg_changed), self); if (!source) { /* Only raise the signal if we were called without source, i.e. if we read the connection from file. * Otherwise, we were called by add_connection() which does not expect the signal. */ if (nm_ifcfg_connection_get_unmanaged_spec (connection_new)) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); else if (nm_ifcfg_connection_get_unrecognized_spec (connection_new)) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); else g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_new); } return connection_new; } }
static void wireless_dialog_response_cb (GtkDialog *foo, gint response, gpointer user_data) { NMAWirelessDialog *dialog = NMA_WIRELESS_DIALOG (foo); WirelessDialogClosure *closure = user_data; NMConnection *connection, *fuzzy_match = NULL; NMDevice *device; NMAccessPoint *ap; GSList *all, *iter; if (response != GTK_RESPONSE_OK) goto done; if (!nma_wireless_dialog_get_nag_ignored (dialog)) { GtkWidget *nag_dialog; /* Nag the user about certificates or whatever. Only destroy the dialog * if no nagging was done. */ nag_dialog = nma_wireless_dialog_nag_user (dialog); if (nag_dialog) { gtk_window_set_transient_for (GTK_WINDOW (nag_dialog), GTK_WINDOW (dialog)); g_signal_connect (nag_dialog, "response", G_CALLBACK (nag_dialog_response_cb), dialog); return; } } /* nma_wireless_dialog_get_connection() returns a connection with the * refcount incremented, so the caller must remember to unref it. */ connection = nma_wireless_dialog_get_connection (dialog, &device, &ap); g_assert (connection); g_assert (device); /* Find a similar connection and use that instead */ all = nm_remote_settings_list_connections (closure->settings); for (iter = all; iter; iter = g_slist_next (iter)) { if (nm_connection_compare (connection, NM_CONNECTION (iter->data), (NM_SETTING_COMPARE_FLAG_FUZZY | NM_SETTING_COMPARE_FLAG_IGNORE_ID))) { fuzzy_match = NM_CONNECTION (iter->data); break; } } g_slist_free (all); if (fuzzy_match) { nm_client_activate_connection (closure->client, fuzzy_match, device, ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL, activate_existing_cb, NULL); } else { NMSetting *s_con; NMSettingWireless *s_wifi; const char *mode = NULL; /* Entirely new connection */ /* Don't autoconnect adhoc networks by default for now */ s_wifi = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); if (s_wifi) mode = nm_setting_wireless_get_mode (s_wifi); if (g_strcmp0 (mode, "adhoc") == 0) { s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); if (!s_con) { s_con = nm_setting_connection_new (); nm_connection_add_setting (connection, s_con); } g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); } nm_client_add_and_activate_connection (closure->client, connection, device, ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL, activate_new_cb, NULL); } /* Balance nma_wireless_dialog_get_connection() */ g_object_unref (connection); done: gtk_widget_hide (GTK_WIDGET (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog)); }
static void pan_connection_check_create (NMBluezDevice *self) { NMConnection *connection; NMConnection *added; NMSetting *setting; char *uuid, *id; GError *error = NULL; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); g_return_if_fail (priv->connections == NULL); g_return_if_fail (priv->name); if (priv->pan_connection || priv->pan_connection_no_autocreate) { /* already have a connection or we don't want to create one, nothing to do. */ return; } /* Only try once to create a connection. If it does not succeed, we do not try again. Also, * if the connection gets deleted later, do not create another one for this device. */ priv->pan_connection_no_autocreate = TRUE; /* create a new connection */ connection = nm_simple_connection_new (); /* Setting: Connection */ uuid = nm_utils_uuid_generate (); id = g_strdup_printf (_("%s Network"), priv->name); setting = nm_setting_connection_new (); g_object_set (setting, NM_SETTING_CONNECTION_ID, id, NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, NULL); nm_connection_add_setting (connection, setting); /* Setting: Bluetooth */ setting = nm_setting_bluetooth_new (); g_object_set (G_OBJECT (setting), NM_SETTING_BLUETOOTH_BDADDR, priv->address, NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, NULL); nm_connection_add_setting (connection, setting); /* Setting: IPv4 */ setting = nm_setting_ip4_config_new (); g_object_set (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NM_SETTING_IP4_CONFIG_MAY_FAIL, FALSE, NULL); nm_connection_add_setting (connection, setting); /* Setting: IPv6 */ setting = nm_setting_ip6_config_new (); g_object_set (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, NULL); nm_connection_add_setting (connection, setting); /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) * which then already finds the suitable connection in priv->connections. This is confusing, * so block the signal. check_emit_usable will succeed after this function call returns. */ g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); added = nm_connection_provider_add_connection (priv->provider, connection, FALSE, &error); g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); if (added) { g_assert (!g_slist_find (priv->connections, added)); g_assert (connection_compatible (self, added)); g_assert (nm_connection_compare (added, connection, NM_SETTING_COMPARE_FLAG_EXACT)); priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); priv->pan_connection = added; priv->pan_connection_original = connection; nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); } else { nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %d / %s", priv->path, id, uuid, error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); g_object_unref (connection); } g_free (id); g_free (uuid); }
/* update_connection: * @self: the plugin instance * @source: if %NULL, this re-reads the connection from @full_path * and updates it. When passing @source, this adds a connection from * memory. * @full_path: the filename of the keyfile to be loaded * @connection: an existing connection that might be updated. * If given, @connection must be an existing connection that is currently * owned by the plugin. * @protect_existing_connection: if %TRUE, and !@connection, we don't allow updating * an existing connection with the same UUID. * If %TRUE and @connection, allow updating only if the reload would modify * @connection (without changing its UUID) or if we would create a new connection. * In other words, if this paramter is %TRUE, we only allow creating a * new connection (with an unseen UUID) or updating the passed in @connection * (whereas the UUID cannot change). * Note, that this allows for @connection to be replaced by a new connection. * @protected_connections: (allow-none): if given, we only update an * existing connection if it is not contained in this hash. * @error: error in case of failure * * Loads a connection from file @full_path. This can both be used to * load a connection initially or to update an existing connection. * * If you pass in an existing connection and the reloaded file happens * to have a different UUID, the connection is deleted. * Beware, that means that after the function, you have a dangling pointer * if the returned connection is different from @connection. * * Returns: the updated connection. * */ static NMKeyfileConnection * update_connection (SCPluginKeyfile *self, NMConnection *source, const char *full_path, NMKeyfileConnection *connection, gboolean protect_existing_connection, GHashTable *protected_connections, GError **error) { SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self); NMKeyfileConnection *connection_new; NMKeyfileConnection *connection_by_uuid; GError *local = NULL; const char *uuid; g_return_val_if_fail (!source || NM_IS_CONNECTION (source), NULL); g_return_val_if_fail (full_path || source, NULL); if (full_path) nm_log_dbg (LOGD_SETTINGS, "keyfile: loading from file \"%s\"...", full_path); connection_new = nm_keyfile_connection_new (source, full_path, &local); if (!connection_new) { /* Error; remove the connection */ if (source) nm_log_warn (LOGD_SETTINGS, "keyfile: error creating connection %s: %s", nm_connection_get_uuid (source), local->message); else nm_log_warn (LOGD_SETTINGS, "keyfile: error loading connection from file %s: %s", full_path, local->message); if ( connection && !protect_existing_connection && (!protected_connections || !g_hash_table_contains (protected_connections, connection))) remove_connection (self, connection); g_propagate_error (error, local); return NULL; } uuid = nm_connection_get_uuid (NM_CONNECTION (connection_new)); connection_by_uuid = g_hash_table_lookup (priv->connections, uuid); if ( connection && connection != connection_by_uuid) { if ( (protect_existing_connection && connection_by_uuid != NULL) || (protected_connections && g_hash_table_contains (protected_connections, connection))) { NMKeyfileConnection *conflicting = (protect_existing_connection && connection_by_uuid != NULL) ? connection_by_uuid : connection; if (source) nm_log_warn (LOGD_SETTINGS, "keyfile: cannot update protected "NM_KEYFILE_CONNECTION_LOG_FMT" connection due to conflicting UUID %s", NM_KEYFILE_CONNECTION_LOG_ARG (conflicting), uuid); else nm_log_warn (LOGD_SETTINGS, "keyfile: cannot load %s due to conflicting UUID for "NM_KEYFILE_CONNECTION_LOG_FMT, full_path, NM_KEYFILE_CONNECTION_LOG_ARG (conflicting)); g_object_unref (connection_new); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Cannot update protected connection due to conflicting UUID"); return NULL; } /* The new connection has a different UUID then the original one. * Remove @connection. */ remove_connection (self, connection); } if ( connection_by_uuid && ( (!connection && protect_existing_connection) || (protected_connections && g_hash_table_contains (protected_connections, connection_by_uuid)))) { if (source) nm_log_warn (LOGD_SETTINGS, "keyfile: cannot update connection due to conflicting UUID for "NM_KEYFILE_CONNECTION_LOG_FMT, NM_KEYFILE_CONNECTION_LOG_ARG (connection_by_uuid)); else nm_log_warn (LOGD_SETTINGS, "keyfile: cannot load %s due to conflicting UUID for "NM_KEYFILE_CONNECTION_LOG_FMT, full_path, NM_KEYFILE_CONNECTION_LOG_ARG (connection_by_uuid)); g_object_unref (connection_new); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Skip updating protected connection during reload"); return NULL; } if (connection_by_uuid) { const char *old_path; old_path = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)); if (nm_connection_compare (NM_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { /* Nothing to do... except updating the path. */ if (old_path && g_strcmp0 (old_path, full_path) != 0) nm_log_info (LOGD_SETTINGS, "keyfile: rename \"%s\" to "NM_KEYFILE_CONNECTION_LOG_FMT" without other changes", old_path, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); } else { /* An existing connection changed. */ if (source) nm_log_info (LOGD_SETTINGS, "keyfile: update "NM_KEYFILE_CONNECTION_LOG_FMT" from %s", NM_KEYFILE_CONNECTION_LOG_ARG (connection_new), NM_KEYFILE_CONNECTION_LOG_PATH (old_path)); else if (!g_strcmp0 (old_path, nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_new)))) nm_log_info (LOGD_SETTINGS, "keyfile: update "NM_KEYFILE_CONNECTION_LOG_FMT, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); else if (old_path) nm_log_info (LOGD_SETTINGS, "keyfile: rename \"%s\" to "NM_KEYFILE_CONNECTION_LOG_FMT, old_path, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); else nm_log_info (LOGD_SETTINGS, "keyfile: update and persist "NM_KEYFILE_CONNECTION_LOG_FMT, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), FALSE, /* don't set Unsaved */ "keyfile-update", &local)) { /* Shouldn't ever get here as 'connection_new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); } g_assert_no_error (local); } nm_settings_connection_set_filename (NM_SETTINGS_CONNECTION (connection_by_uuid), full_path); g_object_unref (connection_new); return connection_by_uuid; } else { if (source) nm_log_info (LOGD_SETTINGS, "keyfile: add connection "NM_KEYFILE_CONNECTION_LOG_FMT, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); else nm_log_info (LOGD_SETTINGS, "keyfile: new connection "NM_KEYFILE_CONNECTION_LOG_FMT, NM_KEYFILE_CONNECTION_LOG_ARG (connection_new)); g_hash_table_insert (priv->connections, g_strdup (uuid), connection_new); g_signal_connect (connection_new, NM_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (connection_removed_cb), self); if (!source) { /* Only raise the signal if we were called without source, i.e. if we read the connection from file. * Otherwise, we were called by add_connection() which does not expect the signal. */ g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_new); } return connection_new; } }