Blob Blame History Raw
From 49983db85eb0c4737271b27e83e70c1216419096 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Tue, 12 Nov 2013 14:26:20 -0600
Subject: [PATCH] settings: convert NMDefaultWiredConnection into a plain
 NMSettingsConnection (rh #1029464) (bgo #712188)

Changing the default wired connection has always deleted the connection
(thus disconnecting the interface) and re-added it as a settings plugin
connection.  That was always sub-optimal, but until the 'unsaved' connection
stuff landed this summer, we couldn't do anything about that.  Clean
that all up, adding the connection as an unsaved connection right from
the start, which allows changes to the connection without having to
delete and recreate it, thus preventing disconnection of any interface
that is using the connection.

A new signal is added to NMSettingsConnection that is only emitted when
the connection is changed from D-Bus (thus indicating an explicit user-
requested change) since the connection may be modified internally by
NetworkManager.  NM-triggered changes should not result in the connection
no longer being a default-wired connection.

https://bugzilla.gnome.org/show_bug.cgi?id=712188
https://bugzilla.redhat.com/show_bug.cgi?id=1029464
---
 src/Makefile.am                            |   2 -
 src/settings/nm-default-wired-connection.c | 190 ---------------------------
 src/settings/nm-default-wired-connection.h |  55 --------
 src/settings/nm-settings-connection.c      |  14 ++
 src/settings/nm-settings-connection.h      |   3 +
 src/settings/nm-settings.c                 | 204 ++++++++++++++---------------
 6 files changed, 119 insertions(+), 349 deletions(-)
 delete mode 100644 src/settings/nm-default-wired-connection.c
 delete mode 100644 src/settings/nm-default-wired-connection.h

diff --git a/src/Makefile.am b/src/Makefile.am
index bcac9ac..34b7339 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -159,16 +159,14 @@ nm_sources = \
 	\
 	ppp-manager/nm-ppp-manager.c \
 	ppp-manager/nm-ppp-manager.h \
 	ppp-manager/nm-ppp-status.h \
 	\
 	settings/nm-agent-manager.c \
 	settings/nm-agent-manager.h \
-	settings/nm-default-wired-connection.c \
-	settings/nm-default-wired-connection.h \
 	settings/nm-inotify-helper.c \
 	settings/nm-inotify-helper.h \
 	settings/nm-secret-agent.c \
 	settings/nm-secret-agent.h \
 	settings/nm-settings-connection.c \
 	settings/nm-settings-connection.h \
 	settings/nm-settings-error.c \
diff --git a/src/settings/nm-default-wired-connection.c b/src/settings/nm-default-wired-connection.c
deleted file mode 100644
index 6c8ce41..0000000
--- a/src/settings/nm-default-wired-connection.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager system settings service
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2008 Novell, Inc.
- * (C) Copyright 2009 - 2011 Red Hat, Inc.
- */
-
-#include "config.h"
-
-#include <netinet/ether.h>
-
-#include <NetworkManager.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-utils.h>
-
-#include "nm-dbus-glib-types.h"
-#include "nm-default-wired-connection.h"
-#include "nm-device-ethernet.h"
-
-G_DEFINE_TYPE (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SETTINGS_CONNECTION)
-
-#define NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionPrivate))
-
-typedef struct {
-	NMDevice *device;
-} NMDefaultWiredConnectionPrivate;
-
-enum {
-	TRY_UPDATE,
-	DELETED,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/****************************************************************/
-
-NMDevice *
-nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired)
-{
-	g_return_val_if_fail (NM_IS_DEFAULT_WIRED_CONNECTION (wired), NULL);
-
-	return NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (wired)->device;
-}
-
-static void
-commit_changes (NMSettingsConnection *connection,
-                NMSettingsConnectionCommitFunc callback,
-                gpointer user_data)
-{
-	NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection);
-
-	/* Keep the object alive over try-update since it might get removed
-	 * from the settings service there, but we still need it for the callback.
-	 */
-	g_object_ref (connection);
-	g_signal_emit (self, signals[TRY_UPDATE], 0);
-	callback (connection, NULL, user_data);
-	g_object_unref (connection);
-}
-
-static void 
-do_delete (NMSettingsConnection *connection,
-	       NMSettingsConnectionDeleteFunc callback,
-	       gpointer user_data)
-{
-	g_signal_emit (connection, signals[DELETED], 0);
-	NM_SETTINGS_CONNECTION_CLASS (nm_default_wired_connection_parent_class)->delete (connection,
-	                                                                                 callback,
-	                                                                                 user_data);
-}
-
-/****************************************************************/
-
-NMDefaultWiredConnection *
-nm_default_wired_connection_new (NMDevice *device,
-                                 const char *defname,
-                                 gboolean read_only)
-{
-	NMDefaultWiredConnection *self;
-	NMDefaultWiredConnectionPrivate *priv;
-	NMSetting *setting;
-	char *uuid;
-	const guint8 *hw_address;
-	guint len = 0;
-	GByteArray *mac;
-
-	g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
-	g_return_val_if_fail (defname != NULL, NULL);
-
-	self = (NMDefaultWiredConnection *) g_object_new (NM_TYPE_DEFAULT_WIRED_CONNECTION, NULL);
-
-	priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (self);
-	priv->device = g_object_ref (device);
-
-	setting = nm_setting_connection_new ();
-
-	uuid = nm_utils_uuid_generate ();
-	g_object_set (setting,
-	              NM_SETTING_CONNECTION_ID, defname,
-	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
-	              NM_SETTING_CONNECTION_UUID, uuid,
-	              NM_SETTING_CONNECTION_READ_ONLY, read_only,
-	              NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
-	              NULL);
-	g_free (uuid);
-
-	nm_connection_add_setting (NM_CONNECTION (self), setting);
-
-	/* Lock the connection to the specific device */
-	hw_address = nm_device_get_hw_address (device, &len);
-	mac = g_byte_array_sized_new (len);
-	g_byte_array_append (mac, hw_address, len);
-
-	setting = nm_setting_wired_new ();
-	g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
-	nm_connection_add_setting (NM_CONNECTION (self), setting);
-
-	g_byte_array_unref (mac);
-
-	return self;
-}
-
-static void
-nm_default_wired_connection_init (NMDefaultWiredConnection *self)
-{
-}
-
-static void
-dispose (GObject *object)
-{
-	NMDefaultWiredConnectionPrivate *priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
-
-	g_clear_object (&priv->device);
-
-	G_OBJECT_CLASS (nm_default_wired_connection_parent_class)->dispose (object);
-}
-
-static void
-nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (klass);
-
-	g_type_class_add_private (klass, sizeof (NMDefaultWiredConnectionPrivate));
-
-	/* Virtual methods */
-	object_class->dispose = dispose;
-	settings_class->commit_changes = commit_changes;
-	settings_class->delete = do_delete;
-
-	/* Signals */
-	signals[TRY_UPDATE] =
-		g_signal_new ("try-update",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      0, NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-
-	/* The 'deleted' signal is used to signal intentional deletions (like
-	 * updating or user-requested deletion) rather than using the
-	 * superclass' 'removed' signal, since that signal doesn't have the
-	 * semantics we want; it gets emitted as a side-effect of various operations
-	 * and is meant more for D-Bus clients instead of in-service uses.
-	 */
-	signals[DELETED] =
-		g_signal_new ("deleted",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      0, NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-}
diff --git a/src/settings/nm-default-wired-connection.h b/src/settings/nm-default-wired-connection.h
deleted file mode 100644
index 3661a7b..0000000
--- a/src/settings/nm-default-wired-connection.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager system settings service
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2008 Novell, Inc.
- * (C) Copyright 2009 - 2011 Red Hat, Inc.
- */
-
-#ifndef NM_DEFAULT_WIRED_CONNECTION_H
-#define NM_DEFAULT_WIRED_CONNECTION_H
-
-#include "nm-settings-connection.h"
-#include "nm-device.h"
-
-G_BEGIN_DECLS
-
-#define NM_TYPE_DEFAULT_WIRED_CONNECTION            (nm_default_wired_connection_get_type ())
-#define NM_DEFAULT_WIRED_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnection))
-#define NM_DEFAULT_WIRED_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionClass))
-#define NM_IS_DEFAULT_WIRED_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION))
-#define NM_IS_DEFAULT_WIRED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEFAULT_WIRED_CONNECTION))
-#define NM_DEFAULT_WIRED_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionClass))
-
-typedef struct {
-	NMSettingsConnection parent;
-} NMDefaultWiredConnection;
-
-typedef struct {
-	NMSettingsConnectionClass parent;
-} NMDefaultWiredConnectionClass;
-
-GType nm_default_wired_connection_get_type (void);
-
-NMDefaultWiredConnection *nm_default_wired_connection_new (NMDevice *device,
-                                                           const char *defname,
-                                                           gboolean read_only);
-
-NMDevice *nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired);
-
-G_END_DECLS
-
-#endif /* NM_DEFAULT_WIRED_CONNECTION_H */
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index f1bc3c3..53c606f 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -79,14 +79,15 @@ enum {
 	PROP_VISIBLE,
 	PROP_UNSAVED,
 };
 
 enum {
 	UPDATED,
 	REMOVED,
+	DBUS_UPDATED,
 	LAST_SIGNAL
 };
 static guint signals[LAST_SIGNAL] = { 0 };
 
 typedef struct {
 	gboolean disposed;
 
@@ -1232,14 +1233,16 @@ con_update_cb (NMSettingsConnection *self,
 		 */
 		for_agent = nm_connection_duplicate (NM_CONNECTION (self));
 		nm_connection_clear_secrets_with_flags (for_agent,
 		                                        secrets_filter_cb,
 		                                        GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
 		nm_agent_manager_save_secrets (info->agent_mgr, for_agent, TRUE, info->sender_uid);
 		g_object_unref (for_agent);
+
+		g_signal_emit (self, signals[DBUS_UPDATED], 0);
 	}
 
 	update_complete (self, info, error);
 }
 
 static void
 update_auth_cb (NMSettingsConnection *self,
@@ -2031,23 +2034,34 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class)
 		                       "TRUE when the connection has not yet been saved "
 		                       "to permanent storage (eg disk) or when it "
 		                       "has been changed but not yet saved.",
 		                       FALSE,
 		                       G_PARAM_READABLE));
 
 	/* Signals */
+
+	/* Emitted when the connection is changed for any reason */
 	signals[UPDATED] = 
 		g_signal_new (NM_SETTINGS_CONNECTION_UPDATED,
 		              G_TYPE_FROM_CLASS (class),
 		              G_SIGNAL_RUN_FIRST,
 		              0,
 		              NULL, NULL,
 		              g_cclosure_marshal_VOID__VOID,
 		              G_TYPE_NONE, 0);
 
+	/* Emitted when connection is changed from D-Bus */
+	signals[DBUS_UPDATED] =
+		g_signal_new (NM_SETTINGS_CONNECTION_DBUS_UPDATED,
+		              G_TYPE_FROM_CLASS (class),
+		              G_SIGNAL_RUN_FIRST,
+		              0, NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0);
+
 	signals[REMOVED] = 
 		g_signal_new (NM_SETTINGS_CONNECTION_REMOVED,
 		              G_TYPE_FROM_CLASS (class),
 		              G_SIGNAL_RUN_FIRST,
 		              0,
 		              NULL, NULL,
 		              g_cclosure_marshal_VOID__VOID,
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index 8b995ab..a687ddb 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -37,14 +37,17 @@ G_BEGIN_DECLS
 
 /* Signals */
 #define NM_SETTINGS_CONNECTION_UPDATED "updated"
 #define NM_SETTINGS_CONNECTION_REMOVED "removed"
 #define NM_SETTINGS_CONNECTION_GET_SECRETS "get-secrets"
 #define NM_SETTINGS_CONNECTION_CANCEL_SECRETS "cancel-secrets"
 
+/* Emitted when connection is changed from D-Bus */
+#define NM_SETTINGS_CONNECTION_DBUS_UPDATED "dbus-updated"
+
 /* Properties */
 #define NM_SETTINGS_CONNECTION_VISIBLE "visible"
 #define NM_SETTINGS_CONNECTION_UNSAVED "unsaved"
 
 typedef struct _NMSettingsConnection NMSettingsConnection;
 typedef struct _NMSettingsConnectionClass NMSettingsConnectionClass;
 
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 49d64d1..e384a17 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -54,15 +54,14 @@
 #include <nm-utils.h>
 
 #include "nm-device-ethernet.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-settings.h"
 #include "nm-settings-connection.h"
 #include "nm-settings-error.h"
-#include "nm-default-wired-connection.h"
 #include "nm-logging.h"
 #include "nm-dbus-manager.h"
 #include "nm-manager-auth.h"
 #include "nm-session-monitor.h"
 #include "plugins/keyfile/plugin.h"
 #include "nm-agent-manager.h"
 #include "nm-settings-utils.h"
@@ -874,29 +873,14 @@ claim_connection (NMSettings *self,
 		g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_ADDED, connection);
 
 		/* Exported D-Bus signal */
 		g_signal_emit (self, signals[NEW_CONNECTION], 0, connection);
 	}
 }
 
-static void
-remove_default_wired_connection (NMSettings *self,
-                                 NMSettingsConnection *connection,
-                                 gboolean do_signal)
-{
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	const char *path = nm_connection_get_path (NM_CONNECTION (connection));
-
-	if (g_hash_table_lookup (priv->connections, path)) {
-		if (do_signal)
-			g_signal_emit_by_name (G_OBJECT (connection), NM_SETTINGS_CONNECTION_REMOVED);
-		g_hash_table_remove (priv->connections, path);
-	}
-}
-
 /**
  * nm_settings_add_connection:
  * @self: the #NMSettings object
  * @connection: the source connection to create a new #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
@@ -1483,148 +1467,164 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
 	/* See if there's a known non-NetworkManager configuration for the device */
 	if (nm_device_spec_match_list (device, priv->unrecognized_specs))
 		return TRUE;
 
 	return FALSE;
 }
 
-#define DEFAULT_WIRED_TAG "default-wired"
+#define DEFAULT_WIRED_CONNECTION_TAG "default-wired-connection"
+#define DEFAULT_WIRED_DEVICE_TAG     "default-wired-device"
+
+static void default_wired_clear_tag (NMSettings *self,
+                                     NMDevice *device,
+                                     NMSettingsConnection *connection,
+                                     gboolean add_to_no_auto_default);
 
 static void
-default_wired_deleted (NMDefaultWiredConnection *wired,
-                       NMSettings *self)
+default_wired_connection_removed_cb (NMSettingsConnection *connection, NMSettings *self)
 {
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
 	NMDevice *device;
-	NMSettingConnection *s_con;
 
-	device = nm_default_wired_connection_get_device (wired);
-	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_TAG, NULL);
-
-	s_con = nm_connection_get_setting_connection (NM_CONNECTION (wired));
-	g_assert (s_con);
-
-	/* Ignore removals of read-only connections, since they couldn't have
-	 * been removed by the user.
-	 */
-	if (nm_setting_connection_get_read_only (s_con))
-		return;
-
-	/* When the default wired connection is removed (either deleted or saved
-	 * to a new persistent connection by a plugin), write the MAC address of
-	 * the wired device to the config file and don't create a new default wired
+	/* When the default wired connection is removed (either deleted or saved to
+	 * a new persistent connection by a plugin), write the MAC address of the
+	 * wired device to the config file and don't create a new default wired
 	 * connection for that device again.
 	 */
-	nm_config_set_ethernet_no_auto_default (priv->config, NM_CONFIG_DEVICE (device));
+	device = g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG);
+	if (device)
+		default_wired_clear_tag (self, device, connection, TRUE);
 }
 
 static void
-delete_cb (NMSettingsConnection *connection, GError *error, gpointer user_data)
+default_wired_connection_dbus_updated_cb (NMSettingsConnection *connection, NMSettings *self)
 {
-}
-
-static void
-default_wired_try_update (NMDefaultWiredConnection *wired,
-                          NMSettings *self)
-{
-	GError *error = NULL;
-	const char *id;
-	NMSettingsConnection *added;
+	NMDevice *device;
 
-	/* Try to move this default wired conneciton to a plugin so that it has
-	 * persistent storage.
+	/* The connection has been changed by the user, it should no longer be
+	 * considered a default wired connection, and should no longer affect
+	 * the no-auto-default configuration option.
 	 */
+	device = g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG);
+	if (device)
+		default_wired_clear_tag (self, device, connection, FALSE);
+}
 
-	/* Keep it alive over removal so we can re-add it if we need to */
-	g_object_ref (wired);
+static void
+default_wired_clear_tag (NMSettings *self,
+                         NMDevice *device,
+                         NMSettingsConnection *connection,
+                         gboolean add_to_no_auto_default)
+{
+	g_return_if_fail (NM_IS_SETTINGS (self));
+	g_return_if_fail (NM_IS_DEVICE (device));
+	g_return_if_fail (NM_IS_CONNECTION (connection));
+	g_return_if_fail (device == g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG));
+	g_return_if_fail (connection == g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG));
 
-	id = nm_connection_get_id (NM_CONNECTION (wired));
-	g_assert (id);
+	g_object_set_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG, NULL);
+	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG, NULL);
 
-	remove_default_wired_connection (self, NM_SETTINGS_CONNECTION (wired), FALSE);
-	added = nm_settings_add_connection (self, NM_CONNECTION (wired), TRUE, &error);
-	if (added) {
-		nm_settings_connection_delete (NM_SETTINGS_CONNECTION (wired), delete_cb, NULL);
+	g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_removed_cb), self);
+	g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_dbus_updated_cb), self);
 
-		g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)),
-		                   DEFAULT_WIRED_TAG,
-		                   NULL);
-		nm_log_info (LOGD_SETTINGS, "Saved default wired connection '%s' to persistent storage", id);
-	} else {
-		nm_log_warn (LOGD_SETTINGS, "couldn't save default wired connection '%s': %d / %s",
-			         id,
-			         error ? error->code : -1,
-			         (error && error->message) ? error->message : "(unknown)");
-		g_clear_error (&error);
-
-		/* If there was an error, don't destroy the default wired connection,
-		 * but add it back to the system settings service. Connection is already
-		 * exported on the bus, don't export it again, thus do_export == FALSE.
-		 */
-		claim_connection (self, NM_SETTINGS_CONNECTION (wired), FALSE);
-	}
-
-	g_object_unref (wired);
+	if (add_to_no_auto_default)
+		nm_config_set_ethernet_no_auto_default (NM_SETTINGS_GET_PRIVATE (self)->config, NM_CONFIG_DEVICE (device));
 }
 
 void
 nm_settings_device_added (NMSettings *self, NMDevice *device)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	NMDefaultWiredConnection *wired;
-	gboolean read_only = TRUE;
-	const char *id;
-	char *defname;
+	NMConnection *connection;
+	NMSettingsConnection *added;
+	NMSetting *setting;
+	GError *error = NULL;
+	const guint8 *hw_address;
+	char *defname, *uuid;
+	guint len = 0;
+	GByteArray *mac;
 
 	if (!NM_IS_DEVICE_ETHERNET (device))
 		return;
 
 	/* If the device isn't managed or it already has a default wired connection,
 	 * ignore it.
 	 */
 	if (   !nm_device_get_managed (device)
-	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG)
+	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG)
 	    || have_connection_for_device (self, device)
 	    || !nm_config_get_ethernet_can_auto_default (priv->config, NM_CONFIG_DEVICE (device)))
 		return;
 
-	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS))
-		read_only = FALSE;
+	hw_address = nm_device_get_hw_address (device, &len);
+	if (!hw_address)
+		return;
+
+	connection = nm_connection_new ();
+	g_assert (connection);
+	setting = nm_setting_connection_new ();
+	g_assert (setting);
+	nm_connection_add_setting (connection, setting);
 
 	defname = nm_settings_utils_get_default_wired_name (priv->connections);
-	wired = nm_default_wired_connection_new (device, defname, read_only);
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (setting,
+	              NM_SETTING_CONNECTION_ID, defname,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
+	              NULL);
+	g_free (uuid);
 	g_free (defname);
-	if (!wired)
+
+	/* Lock the connection to the device */
+	setting = nm_setting_wired_new ();
+	nm_connection_add_setting (connection, setting);
+
+	mac = g_byte_array_sized_new (len);
+	g_byte_array_append (mac, hw_address, len);
+	g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
+	g_byte_array_unref (mac);
+
+	/* Add the connection */
+	added = nm_settings_add_connection (self, connection, FALSE, &error);
+	g_object_unref (connection);
+
+	if (!added) {
+		nm_log_warn (LOGD_SETTINGS, "(%s) couldn't create default wired connection: %s",
+		             nm_device_get_iface (device),
+		             (error && error->message) ? error->message : "(unknown)");
+		g_clear_error (&error);
 		return;
+	}
 
-	id = nm_connection_get_id (NM_CONNECTION (wired));
-	g_assert (id);
+	g_object_set_data (G_OBJECT (added), DEFAULT_WIRED_DEVICE_TAG, device);
+	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG, added);
 
-	nm_log_info (LOGD_SETTINGS, "Added default wired connection '%s' for %s",
-	             id, nm_device_get_udi (device));
+	g_signal_connect (added, NM_SETTINGS_CONNECTION_DBUS_UPDATED,
+	                  G_CALLBACK (default_wired_connection_dbus_updated_cb), self);
+	g_signal_connect (added, NM_SETTINGS_CONNECTION_REMOVED,
+	                  G_CALLBACK (default_wired_connection_removed_cb), self);
 
-	g_signal_connect (wired, "try-update", (GCallback) default_wired_try_update, self);
-	g_signal_connect (wired, "deleted", (GCallback) default_wired_deleted, self);
-	claim_connection (self, NM_SETTINGS_CONNECTION (wired), TRUE);
-	g_object_unref (wired);
-
-	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_TAG, wired);
+	nm_log_info (LOGD_SETTINGS, "(%s): created default wired connection '%s'",
+	             nm_device_get_iface (device),
+	             nm_connection_get_id (NM_CONNECTION (added)));
 }
 
 void
 nm_settings_device_removed (NMSettings *self, NMDevice *device)
 {
-	NMDefaultWiredConnection *connection;
+	NMSettingsConnection *connection;
 
-	if (!NM_IS_DEVICE_ETHERNET (device))
-		return;
-
-	connection = (NMDefaultWiredConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG);
-	if (connection)
-		remove_default_wired_connection (self, NM_SETTINGS_CONNECTION (connection), TRUE);
+	connection = g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG);
+	if (connection) {
+		default_wired_clear_tag (self, device, connection, FALSE);
+		nm_settings_connection_delete (connection, NULL, NULL);
+	}
 }
 
 /***************************************************************/
 
 static gint
 best_connection_sort (gconstpointer a, gconstpointer b, gpointer user_data)
 {
-- 
1.8.3.1