static gboolean
real_need_secrets (NMVPNPlugin *plugin,
                   NMConnection *connection,
                   char **setting_name,
                   GError **error)
{
	NMSettingVPN *s_vpn;
	gboolean need_secrets = FALSE;

	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
	if (!s_vpn) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
		             "%s",
		             "Could not process the request because the VPN connection settings were invalid.");
		return FALSE;
	}

	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENSSH_KEY_PASSWORD))
		need_secrets = TRUE;

	if (need_secrets)
		*setting_name = NM_SETTING_VPN_SETTING_NAME;

	return need_secrets;
}
Пример #2
0
gboolean
nm_team_update_slave_connection (NMDevice *slave, NMConnection *connection)
{
	NMSettingTeamPort *s_port;
	const char *iface = nm_device_get_iface (slave);
	char *port_config = NULL;
	gboolean with_teamdctl = FALSE;
	int err = 0;
#if WITH_TEAMDCTL
	const char *master_iface;
	int master_ifindex;
	struct teamdctl *tdc;
	const char *team_port_config = NULL;
#endif

	g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

#if WITH_TEAMDCTL
	master_ifindex = nm_platform_link_get_master (nm_device_get_ifindex (slave));
	g_assert (master_ifindex > 0);
	master_iface = nm_platform_link_get_name (master_ifindex);
	g_assert (master_iface);

	tdc = teamdctl_alloc ();
	g_assert (tdc);
	err = teamdctl_connect (tdc, master_iface, NULL, NULL);
	if (err) {
		nm_log_err (LOGD_TEAM, "(%s): failed to connect to teamd for master %s (err=%d)",
		            iface, master_iface, err);
		teamdctl_free (tdc);
		return FALSE;
	}
	err = teamdctl_port_config_get_raw_direct (tdc, iface, (char **)&team_port_config);
	port_config = g_strdup (team_port_config);
	teamdctl_free (tdc);
	with_teamdctl = TRUE;
#endif

	s_port = nm_connection_get_setting_team_port (connection);
	if (!s_port) {
		s_port = (NMSettingTeamPort *) nm_setting_team_port_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_port));
	}

	g_object_set (G_OBJECT (s_port), NM_SETTING_TEAM_PORT_CONFIG, port_config, NULL);
	g_free (port_config);

	if (!with_teamdctl || err != 0) {
		if (!with_teamdctl)
			nm_log_err (LOGD_TEAM, "(%s): failed to read teamd port configuration "
			                       " (compiled without libteamdctl support)", iface);
		else
			nm_log_err (LOGD_TEAM, "(%s): failed to read teamd port configuration (err=%d)",
			            iface, err);
		return FALSE;
	}

	return TRUE;
}
static gboolean
real_need_secrets (NMVpnServicePlugin *plugin,
                   NMConnection *connection,
                   const char **setting_name,
                   GError **error)
{
	NMSettingVpn *s_vpn;
	NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;

	g_return_val_if_fail (NM_IS_VPN_SERVICE_PLUGIN (plugin), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	s_vpn = nm_connection_get_setting_vpn (connection);

	nm_setting_get_secret_flags (NM_SETTING (s_vpn), NM_SSTP_KEY_PASSWORD, &flags, NULL);

	/* Don't need the password if it's not required */
	if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
		return FALSE;

	/* Don't need the password if we already have one */
	if (nm_setting_vpn_get_secret (NM_SETTING_VPN (s_vpn), NM_SSTP_KEY_PASSWORD))
		return FALSE;

	/* Otherwise we need a password */
	*setting_name = NM_SETTING_VPN_SETTING_NAME;
	return TRUE;
}
Пример #4
0
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;
}
NMActRequest *
nm_act_request_new (NMConnection *connection,
                    const char *specific_object,
                    gboolean user_requested,
                    gboolean assumed,
                    gpointer *device)
{
	GObject *object;
	NMActRequestPrivate *priv;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
	g_return_val_if_fail (NM_DEVICE (device), NULL);

	object = g_object_new (NM_TYPE_ACT_REQUEST, NULL);
	if (!object)
		return NULL;

	priv = NM_ACT_REQUEST_GET_PRIVATE (object);

	priv->connection = g_object_ref (connection);
	if (specific_object)
		priv->specific_object = g_strdup (specific_object);

	priv->device = NM_DEVICE (device);
	g_signal_connect (device, "state-changed",
	                  G_CALLBACK (device_state_changed),
	                  NM_ACT_REQUEST (object));

	priv->user_requested = user_requested;
	priv->assumed = assumed;

	return NM_ACT_REQUEST (object);
}
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;
}
/**
 * nm_act_request_new:
 *
 * @connection: the connection to activate @device with
 * @specific_object: the object path of the specific object (ie, WiFi access point,
 *    etc) that will be used to activate @connection and @device
 * @user_requested: pass %TRUE if the activation was requested via D-Bus,
 *    otherwise %FALSE if requested internally by NM (ie, autoconnect)
 * @user_uid: if @user_requested is %TRUE, the Unix UID of the user that requested
 * @dbus_sender: if @user_requested is %TRUE, the D-BUS sender that requested
 *    the activation
 * @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
 *    existing connection made before this instance of NM started
 * @device: the device/interface to configure according to @connection
 * @master: if the activation depends on another device (ie, bond or bridge
 *    master to which this device will be enslaved) pass the #NMDevice that this
 *    activation request be enslaved to
 *
 * Begins activation of @device using the given @connection and other details.
 *
 * Returns: the new activation request on success, %NULL on error.
 */
NMActRequest *
nm_act_request_new (NMConnection *connection,
                    const char *specific_object,
                    gboolean user_requested,
                    gulong user_uid,
                    const char *dbus_sender,
                    gboolean assumed,
                    NMDevice *device,
                    NMDevice *master)
{
	GObject *object;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
	g_return_val_if_fail (NM_DEVICE (device), NULL);

	object = g_object_new (NM_TYPE_ACT_REQUEST,
	                       NM_ACTIVE_CONNECTION_INT_CONNECTION, connection,
	                       NM_ACTIVE_CONNECTION_INT_DEVICE, device,
	                       NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
	                       NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, user_requested,
	                       NM_ACTIVE_CONNECTION_INT_USER_UID, user_uid,
	                       NM_ACTIVE_CONNECTION_INT_ASSUMED, assumed,
	                       NM_ACTIVE_CONNECTION_INT_MASTER, master,
	                       NULL);
	if (object) {
		nm_active_connection_export (NM_ACTIVE_CONNECTION (object));
		NM_ACT_REQUEST_GET_PRIVATE (object)->dbus_sender = g_strdup (dbus_sender);
	}

	return (NMActRequest *) object;
}
NMConnectionEditor *
nm_connection_editor_new (GtkWindow *parent_window,
                          NMConnection *connection,
                          NMClient *client)
{
	NMConnectionEditor *editor;
	GtkWidget *hbox;
	gboolean is_new;
	GError *error = NULL;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	is_new = !nm_client_get_connection_by_uuid (client, nm_connection_get_uuid (connection));

	editor = g_object_new (NM_TYPE_CONNECTION_EDITOR, NULL);
	editor->parent_window = parent_window ? g_object_ref (parent_window) : NULL;
	editor->client = g_object_ref (client);
	editor->is_new_connection = is_new;

	editor->can_modify = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM);
	editor->permission_id = g_signal_connect (editor->client,
	                                          "permission-changed",
	                                          G_CALLBACK (permissions_changed_cb),
	                                          editor);

	editor->ok_button = ce_polkit_button_new (_("_Save"),
	                                          _("Save any changes made to this connection."),
	                                          _("Authenticate to save this connection for all users of this machine."),
	                                          GTK_STOCK_APPLY,
	                                          client,
	                                          NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM);
	gtk_button_set_use_underline (GTK_BUTTON (editor->ok_button), TRUE);

	g_signal_connect (editor->ok_button, "actionable",
	                  G_CALLBACK (ok_button_actionable_cb), editor);
	g_signal_connect (editor->ok_button, "authorized",
	                  G_CALLBACK (ok_button_actionable_cb), editor);
	hbox = GTK_WIDGET (gtk_builder_get_object (editor->builder, "action_area_hbox"));
	gtk_box_pack_end (GTK_BOX (hbox), editor->ok_button, TRUE, TRUE, 0);
	gtk_widget_show_all (editor->ok_button);

	if (!nm_connection_editor_set_connection (editor, connection, &error)) {
		nm_connection_editor_error (parent_window,
		                            is_new ? _("Could not create connection") : _("Could not edit connection"),
		                            "%s",
		                            error ? error->message : _("Unknown error creating connection editor dialog."));
		g_clear_error (&error);
		g_object_unref (editor);
		return NULL;
	}

	if (!active_editors)
		active_editors = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
	g_hash_table_insert (active_editors, g_object_ref (connection), editor);

	return editor;
}
Пример #9
0
/**
 * nm_active_connection_authorize:
 * @self: the #NMActiveConnection
 * @initial_connection: (allow-none): for add-and-activate, there
 *   is no @settings_connection available when creating the active connection.
 *   Instead pass an alternative connection.
 * @result_func: function to be called on success or error
 * @user_data1: pointer passed to @result_func
 * @user_data2: additional pointer passed to @result_func
 *
 * Checks whether the subject that initiated the active connection (read from
 * the #NMActiveConnection::subject property) is authorized to complete this
 * activation request.
 */
void
nm_active_connection_authorize (NMActiveConnection *self,
                                NMConnection *initial_connection,
                                NMActiveConnectionAuthResultFunc result_func,
                                gpointer user_data1,
                                gpointer user_data2)
{
	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
	const char *wifi_permission = NULL;
	NMConnection *con;

	g_return_if_fail (result_func != NULL);
	g_return_if_fail (priv->chain == NULL);

	if (initial_connection) {
		g_return_if_fail (NM_IS_CONNECTION (initial_connection));
		g_return_if_fail (!priv->settings_connection);
		g_return_if_fail (!priv->applied_connection);
		con = initial_connection;
	} else {
		g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection));
		g_return_if_fail (NM_IS_CONNECTION (priv->applied_connection));
		con = priv->applied_connection;
	}

	priv->chain = nm_auth_chain_new_subject (priv->subject, NULL, auth_done, self);
	g_assert (priv->chain);

	/* Check that the subject is allowed to use networking at all */
	nm_auth_chain_add_call (priv->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);

	/* Shared wifi connections require special permissions too */
	wifi_permission = nm_utils_get_shared_wifi_permission (con);
	if (wifi_permission) {
		priv->wifi_shared_permission = wifi_permission;
		nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE);
	}

	/* Wait for authorization */
	priv->result_func = result_func;
	priv->user_data1 = user_data1;
	priv->user_data2 = user_data2;
}
Пример #10
0
gboolean
ce_page_last_update (CEPage *self, NMConnection *connection, GError **error)
{
	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	if (CE_PAGE_GET_CLASS (self)->last_update)
		return CE_PAGE_GET_CLASS (self)->last_update (self, connection, error);

	return TRUE;
}
/**
 * nm_act_request_new:
 *
 * @connection: the connection to activate @device with
 * @specific_object: the object path of the specific object (ie, WiFi access point,
 *    etc) that will be used to activate @connection and @device
 * @user_requested: pass %TRUE if the activation was requested via D-Bus,
 *    otherwise %FALSE if requested internally by NM (ie, autoconnect)
 * @user_uid: if @user_requested is %TRUE, the Unix UID of the user that requested
 * @dbus_sender: if @user_requested is %TRUE, the D-BUS sender that requested
 *    the activation
 * @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
 *    existing connection made before this instance of NM started
 * @device: the device/interface to configure according to @connection
 * @dependency: if the activation depends on another device (ie, VLAN slave,
 *    bond slave, etc) pass the #NMActiveConnection that this activation request
 *    should wait for before proceeding
 *
 * Begins activation of @device using the given @connection and other details.
 *
 * Returns: the new activation request on success, %NULL on error.
 */
NMActRequest *
nm_act_request_new (NMConnection *connection,
                    const char *specific_object,
                    gboolean user_requested,
                    gulong user_uid,
                    const char *dbus_sender,
                    gboolean assumed,
                    gpointer *device,
                    NMActiveConnection *dependency)
{
	GObject *object;
	NMActRequestPrivate *priv;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
	g_return_val_if_fail (NM_DEVICE (device), NULL);

	object = g_object_new (NM_TYPE_ACT_REQUEST,
	                       NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
	                       NULL);
	if (!object)
		return NULL;

	priv = NM_ACT_REQUEST_GET_PRIVATE (object);

	priv->connection = g_object_ref (connection);
	priv->device = NM_DEVICE (device);
	g_signal_connect (device, "state-changed",
	                  G_CALLBACK (device_state_changed),
	                  NM_ACT_REQUEST (object));

	priv->user_uid = user_uid;
	priv->user_requested = user_requested;
	priv->dbus_sender = g_strdup (dbus_sender);
	priv->assumed = assumed;

	if (dependency) {
		priv->dep = dependency;
		g_object_weak_ref (G_OBJECT (dependency), (GWeakNotify) dep_gone, object);
		priv->dep_state_id = g_signal_connect (dependency,
		                                       "notify::" NM_ACTIVE_CONNECTION_STATE,
		                                       G_CALLBACK (dep_state_changed),
		                                       object);
	}

	if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object),
	                                  connection,
	                                  nm_device_get_path (NM_DEVICE (device)))) {
		g_object_unref (object);
		object = NULL;
	}

	return (NMActRequest *) object;
}
Пример #12
0
static const char *
get_connection_id (NMConnection *connection)
{
	NMSettingConnection *s_con;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
	g_return_val_if_fail (s_con != NULL, NULL);

	return nm_setting_connection_get_id (s_con);
}
NMSettingsConnection *
nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
                                           NMConnection *connection,
                                           GError **error)
{
	g_return_val_if_fail (config != NULL, NULL);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection)
		return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, error);

	return NULL;
}
Пример #14
0
/**
 * nm_settings_plugin_add_connection:
 * @config: the #NMSettingsPlugin
 * @connection: the source connection to create a plugin-specific
 * #NMSettingsConnection from
 * @save_to_disk: %TRUE to save the connection to disk immediately, %FALSE to
 * not save to disk
 * @error: on return, a location to store any errors that may occur
 *
 * Creates a new #NMSettingsConnection for the given source @connection.  If the
 * plugin cannot handle the given connection type, it should return %NULL and
 * set @error.  The plugin owns the returned object and the caller must reference
 * the object if it wishes to continue using it.
 *
 * Returns: the new #NMSettingsConnection or %NULL
 */
NMSettingsConnection *
nm_settings_plugin_add_connection (NMSettingsPlugin *config,
                                   NMConnection *connection,
                                   gboolean save_to_disk,
                                   GError **error)
{
	g_return_val_if_fail (config != NULL, NULL);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	if (NM_SETTINGS_PLUGIN_GET_INTERFACE (config)->add_connection)
		return NM_SETTINGS_PLUGIN_GET_INTERFACE (config)->add_connection (config, connection, save_to_disk, error);

	return NULL;
}
Пример #15
0
CEPage *
ce_page_wireless_new (NMConnection *connection, GtkWindow *parent_window, GError **error)
{
	CEPageWireless *self;
	CEPageWirelessPrivate *priv;
	CEPage *parent;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	self = CE_PAGE_WIRELESS (g_object_new (CE_TYPE_PAGE_WIRELESS,
	                                       CE_PAGE_CONNECTION, connection,
	                                       CE_PAGE_PARENT_WINDOW, parent_window,
	                                       NULL));
	parent = CE_PAGE (self);

	parent->xml = glade_xml_new (GLADEDIR "/ce-page-wireless.glade", "WirelessPage", NULL);
	if (!parent->xml) {
		g_set_error (error, 0, 0, "%s", _("Could not load WiFi user interface."));
		g_object_unref (self);
		return NULL;
	}

	parent->page = glade_xml_get_widget (parent->xml, "WirelessPage");
	if (!parent->page) {
		g_set_error (error, 0, 0, "%s", _("Could not load WiFi user interface."));
		g_object_unref (self);
		return NULL;
	}
	g_object_ref_sink (parent->page);

	parent->title = g_strdup (_("Wireless"));

	wireless_private_init (self);
	priv = CE_PAGE_WIRELESS_GET_PRIVATE (self);

	priv->setting = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
	if (!priv->setting) {
		priv->setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
	}

	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
	if (!ce_page_initialize (parent, NULL, error)) {
		g_object_unref (self);
		return NULL;
	}

	return CE_PAGE (self);
}
gboolean
nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
                                           NMConnection *connection,
                                           GError **error)
{
	gboolean success = FALSE;

	g_return_val_if_fail (config != NULL, FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection)
		success = NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, error);

	return success;
}
Пример #17
0
gboolean
ce_page_validate (CEPage *self, NMConnection *connection, GError **error)
{
	g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	if (CE_PAGE_GET_CLASS (self)->ce_page_validate_v) {
		if (!CE_PAGE_GET_CLASS (self)->ce_page_validate_v (self, connection, error)) {
			if (error && !*error)
				g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("unspecified error"));
			return FALSE;
		}
	}

	return TRUE;
}
static gboolean
nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	if (NM_IS_DEVICE_ETHERNET (device))
		return check_ethernet_compatible (NM_DEVICE_ETHERNET (device), connection, error);
	else if (NM_IS_DEVICE_WIFI (device))
		return check_wifi_compatible (NM_DEVICE_WIFI (device), connection, error);
	else if (NM_IS_DEVICE_BT (device))
		return check_bt_compatible (NM_DEVICE_BT (device), connection, error);
//      else if (NM_IS_DEVICE_OLPC_MESH (device))
//              return check_olpc_mesh_compatible (NM_DEVICE_OLPC_MESH (device), connection, error);

	g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device));
	return FALSE;
}
Пример #19
0
gboolean
nm_wimax_nsp_check_compatible (NMWimaxNsp *self,
							   NMConnection *connection)
{
	NMWimaxNspPrivate *priv;
	NMSettingWimax *s_wimax;

	g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	priv = GET_PRIVATE (self);

	s_wimax = nm_connection_get_setting_wimax (connection);
	if (!s_wimax)
		return FALSE;

	return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0;
}
/**
 * nm_settings_interface_add_connection:
 * @settings: a object implementing %NMSettingsInterface
 * @connection: the settings to add; note that this object's settings will be
 *  added, not the object itself
 * @callback: callback to be called when the add operation completes
 * @user_data: caller-specific data passed to @callback
 *
 * Requests that the settings service add the given settings to a new connection.
 *
 * Returns: TRUE if the request was successful, FALSE if it failed
 **/
gboolean
nm_settings_interface_add_connection (NMSettingsInterface *settings,
                                      NMConnection *connection,
                                      NMSettingsAddConnectionFunc callback,
                                      gpointer user_data)
{
	g_return_val_if_fail (settings != NULL, FALSE);
	g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), FALSE);
	g_return_val_if_fail (connection != NULL, FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
	g_return_val_if_fail (callback != NULL, FALSE);

	if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection) {
		return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection (settings,
		                                                                       connection,
		                                                                       callback,
		                                                                       user_data);
	}
	return FALSE;
}
static NMVpnEditor *
get_editor (NMVpnEditorPlugin *iface, NMConnection *connection, GError **error)
{
	g_return_val_if_fail (FORTISSLVPN_IS_EDITOR_PLUGIN (iface), NULL);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
	g_return_val_if_fail (!error || !*error, NULL);

	{
#ifdef NM_VPN_OLD
		return nm_fortisslvpn_editor_new (connection, error);
#else
		return nm_vpn_plugin_utils_load_editor (NM_PLUGIN_DIR"/libnm-vpn-plugin-fortisslvpn-editor.so",
		                                        "nm_vpn_editor_factory_fortisslvpn",
		                                        _call_editor_factory,
		                                        iface,
		                                        connection,
		                                        NULL,
		                                        error);
#endif
	}
}
Пример #22
0
NMVPNConnection *
nm_vpn_service_activate (NMVPNService *service,
                         NMConnection *connection,
                         NMDevice *device,
                         const char *specific_object,
                         gboolean user_requested,
                         gulong user_uid,
                         GError **error)
{
	NMVPNConnection *vpn;
	NMVPNServicePrivate *priv;

	g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), 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);

	priv = NM_VPN_SERVICE_GET_PRIVATE (service);

	clear_quit_timeout (service);

	vpn = nm_vpn_connection_new (connection, device, specific_object, user_requested, user_uid);
	g_signal_connect (vpn, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
	                  G_CALLBACK (connection_vpn_state_changed),
	                  service);

	priv->connections = g_slist_prepend (priv->connections, g_object_ref (vpn));

	if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service)) {
		// FIXME: fill in error when errors happen
		nm_vpn_connection_activate (vpn);
	} else if (priv->start_timeout == 0) {
		nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", priv->name);
		if (!nm_vpn_service_daemon_exec (service, error))
			vpn = NULL;
	}

	return vpn;
}
Пример #23
0
CEPage *
ce_page_wifi_new (NMConnectionEditor *editor,
                  NMConnection *connection,
                  GtkWindow *parent_window,
                  NMClient *client,
                  const char **out_secrets_setting_name,
                  GError **error)
{
	CEPageWifi *self;
	CEPageWifiPrivate *priv;

	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);

	self = CE_PAGE_WIFI (ce_page_new (CE_TYPE_PAGE_WIFI,
	                                  editor,
	                                  connection,
	                                  parent_window,
	                                  client,
	                                  UIDIR "/ce-page-wifi.ui",
	                                  "WifiPage",
	                                  _("Wi-Fi")));
	if (!self) {
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load Wi-Fi user interface."));
		return NULL;
	}

	wifi_private_init (self);
	priv = CE_PAGE_WIFI_GET_PRIVATE (self);

	priv->setting = nm_connection_get_setting_wireless (connection);
	if (!priv->setting) {
		priv->setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
	}

	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);

	return CE_PAGE (self);
}
static gboolean
real_need_secrets (NMVPNPlugin *plugin,
                   NMConnection *connection,
                   char **setting_name,
                   GError **error)
{
	NMSettingVPN *s_vpn;

	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
	if (!s_vpn) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
		             "%s",
		             "Could not process the request because the VPN connection settings were invalid.");
		return FALSE;
	}

	/* We just need the WebVPN cookie, and the final IP address of the gateway
	   (after HTTP redirects, which do happen). All the certificate/SecurID 
	   nonsense can be handled for us, in the user's context, by auth-dialog */
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	return FALSE;
}
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;
}
GtkWidget *
nma_wireless_dialog_new (NMClient *client,
                         NMConnection *connection,
                         NMDevice *device,
                         NMAccessPoint *ap)
{
    NMAWirelessDialog *self;
    NMAWirelessDialogPrivate *priv;
    guint32 dev_caps;

    g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
    g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
    g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
    g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL);

    /* Ensure device validity */
    dev_caps = nm_device_get_capabilities (device);
    g_return_val_if_fail (dev_caps & NM_DEVICE_CAP_NM_SUPPORTED, NULL);
    g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);

    self = NMA_WIRELESS_DIALOG (g_object_new (NMA_TYPE_WIRELESS_DIALOG, NULL));
    if (!self)
        return NULL;

    priv = NMA_WIRELESS_DIALOG_GET_PRIVATE (self);

    priv->client = g_object_ref (client);
    priv->ap = g_object_ref (ap);

    if (!internal_init (self, connection, device, TRUE, FALSE)) {
        nm_warning ("Couldn't create wireless security dialog.");
        g_object_unref (self);
        return NULL;
    }

    return GTK_WIDGET (self);
}
Пример #27
0
/**
 * nm_remote_settings_add_connection:
 * @settings: the %NMRemoteSettings
 * @connection: the connection to add. Note that this object's settings will be
 *   added, not the object itself
 * @callback: (scope async): callback to be called when the add operation completes
 * @user_data: caller-specific data passed to @callback
 *
 * Requests that the remote settings service add the given settings to a new
 * connection.
 *
 * Returns: TRUE if the request was successful, FALSE if it failed
 **/
gboolean
nm_remote_settings_add_connection (NMRemoteSettings *settings,
                                   NMConnection *connection,
                                   NMRemoteSettingsAddConnectionFunc callback,
                                   gpointer user_data)
{
	NMRemoteSettingsPrivate *priv;
	AddConnectionInfo *info;
	GHashTable *new_settings;

	g_return_val_if_fail (settings != NULL, FALSE);
	g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE);
	g_return_val_if_fail (connection != NULL, FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
	g_return_val_if_fail (callback != NULL, FALSE);

	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
	
	info = g_malloc0 (sizeof (AddConnectionInfo));
	info->self = settings;
	info->callback = callback;
	info->callback_data = user_data;

	new_settings = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
	dbus_g_proxy_begin_call (priv->proxy, "AddConnection",
	                         add_connection_done,
	                         info,
	                         NULL,
	                         DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, new_settings,
	                         G_TYPE_INVALID);
	g_hash_table_destroy (new_settings);

	priv->add_list = g_slist_append (priv->add_list, info);

	return TRUE;
}
Пример #28
0
/**
 * nm_bridge_update_slave_connection:
 * @slave: the slave #NMDevice, is *not* necessarily a bridge interface
 * @connection: the #NMConnection to update with the bridge port settings
 *
 * Reads bridge port configuration and updates @connection with those
 * properties.
 *
 * Returns: %TRUE if the port configuration was read and @connection updated,
 * %FALSE if not.
 */
gboolean
nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection)
{
	NMSettingBridgePort *s_port;
	int ifindex = nm_device_get_ifindex (slave);
	const Option *option;

	g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	s_port = nm_connection_get_setting_bridge_port (connection);
	if (!s_port) {
		s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_port));
	}

	for (option = slave_options; option->name; option++) {
		gs_free char *str = nm_platform_slave_get_option (ifindex, option->sysname);
		int value;

		if (str) {
			value = strtol (str, NULL, 10);

			/* See comments in set_sysfs_uint() about centiseconds. */
			if (option->user_hz_compensate)
				value /= 100;

			g_object_set (s_port, option->name, value, NULL);
		} else {
			nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge port setting '%s'",
			             nm_device_get_iface (slave), option->sysname);
		}
	}

	return TRUE;
}
static gboolean
nm_connection_editor_set_connection (NMConnectionEditor *editor,
                                     NMConnection *orig_connection,
                                     GError **error)
{
	NMSettingConnection *s_con;
	const char *connection_type;
	const char *slave_type;
	gboolean success = FALSE;
	GSList *iter, *copy;

	g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (orig_connection), FALSE);

	/* clean previous connection */
	if (editor->connection)
		g_object_unref (editor->connection);

	editor->connection = nm_simple_connection_new_clone (orig_connection);

	editor->orig_connection = g_object_ref (orig_connection);
	nm_connection_editor_update_title (editor);

	/* Handle CA cert ignore stuff */
	eap_method_ca_cert_ignore_load (editor->connection);

	s_con = nm_connection_get_setting_connection (editor->connection);
	g_assert (s_con);

	connection_type = nm_setting_connection_get_connection_type (s_con);
	if (!add_page (editor, ce_page_general_new, editor->connection, error))
		goto out;
	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_8021x_security_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_dcb_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
		if (!add_page (editor, ce_page_wifi_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_wifi_security_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vpn_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ip_tunnel_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_dsl_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
	           !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
		if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
		NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (editor->connection);
		const char *type = nm_setting_bluetooth_get_connection_type (s_bt);
		g_assert (type);

		if (!add_page (editor, ce_page_bluetooth_new, editor->connection, error))
			goto out;
		if (!g_strcmp0 (type, "dun")) {
			if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
				goto out;
			if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
				goto out;
		}
	} else if (!strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_infiniband_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bond_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VLAN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vlan_new, editor->connection, error))
			goto out;
	} else {
		g_warning ("Unhandled setting type '%s'", connection_type);
	}

	slave_type = nm_setting_connection_get_slave_type (s_con);
	if (!g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_port_new, editor->connection, error))
			goto out;
	} else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_port_new, editor->connection, error))
			goto out;
	}

	if (   nm_connection_get_setting_ip4_config (editor->connection)
	    && !add_page (editor, ce_page_ip4_new, editor->connection, error))
		goto out;
	if (   nm_connection_get_setting_ip6_config (editor->connection)
	    && !add_page (editor, ce_page_ip6_new, editor->connection, error))
		goto out;

	/* After all pages are created, then kick off secrets requests that any
	 * the pages may need to make; if they don't need any secrets, then let
	 * them finish initialization.  The list might get modified during the loop
	 * which is why copy the list here.
	 */
	copy = g_slist_copy (editor->initializing_pages);
	for (iter = copy; iter; iter = g_slist_next (iter)) {
		CEPage *page = CE_PAGE (iter->data);
		const char *setting_name = g_object_get_data (G_OBJECT (page), SECRETS_TAG);

		if (!setting_name) {
			/* page doesn't need any secrets */
			ce_page_complete_init (page, NULL, NULL, NULL);
		} else if (!NM_IS_REMOTE_CONNECTION (editor->orig_connection)) {
			/* We want to get secrets using ->orig_connection, since that's the
			 * remote connection which can actually respond to secrets requests.
			 * ->connection is a plain NMConnection copy of ->orig_connection
			 * which is what gets changed when users modify anything.  But when
			 * creating or importing, ->orig_connection will be an NMConnection
			 * since the new connection hasn't been added to NetworkManager yet.
			 * So basically, skip requesting secrets if the connection can't
			 * handle a secrets request.
			 */
			ce_page_complete_init (page, setting_name, NULL, NULL);
		} else {
			/* Page wants secrets, get them */
			get_secrets_for_page (editor, page, setting_name);
		}
		g_object_set_data (G_OBJECT (page), SECRETS_TAG, NULL);
	}
	g_slist_free (copy);

	/* set the UI */
	recheck_initialization (editor);
	success = TRUE;

out:
	return success;
}
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;
	}
}