about summary refs log tree commit diff
path: root/src/nm-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-device.c')
-rw-r--r--src/nm-device.c5706
1 files changed, 0 insertions, 5706 deletions
diff --git a/src/nm-device.c b/src/nm-device.c
deleted file mode 100644
index a07ef338..00000000
--- a/src/nm-device.c
+++ /dev/null
@@ -1,5706 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * 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.
- *
- * Copyright (C) 2005 - 2012 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <dbus/dbus.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <linux/sockios.h>
-#include <linux/ethtool.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <linux/if.h>
-
-#include "nm-glib-compat.h"
-#include "nm-device.h"
-#include "nm-device-private.h"
-#include "nm-device-ethernet.h"
-#include "NetworkManagerUtils.h"
-#include "nm-system.h"
-#include "nm-dhcp-manager.h"
-#include "nm-dbus-manager.h"
-#include "nm-utils.h"
-#include "nm-logging.h"
-#include "nm-netlink-monitor.h"
-#include "nm-netlink-utils.h"
-#include "nm-netlink-compat.h"
-#include "nm-setting-ip4-config.h"
-#include "nm-setting-ip6-config.h"
-#include "nm-setting-connection.h"
-#include "nm-dnsmasq-manager.h"
-#include "nm-dhcp4-config.h"
-#include "nm-ip6-manager.h"
-#include "nm-marshal.h"
-#include "nm-rfkill.h"
-#include "nm-firewall-manager.h"
-#include "nm-properties-changed-signal.h"
-#include "nm-enum-types.h"
-#include "nm-settings-connection.h"
-#include "nm-connection-provider.h"
-#include "nm-posix-signals.h"
-#include "nm-manager-auth.h"
-#include "nm-dbus-glib-types.h"
-#include "nm-dispatcher.h"
-
-static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
-
-#include "nm-device-interface-glue.h"
-
-#define PENDING_IP4_CONFIG "pending-ip4-config"
-#define PENDING_IP6_CONFIG "pending-ip6-config"
-
-#define DBUS_G_TYPE_UINT_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
-
-/***********************************************************/
-#define NM_DEVICE_ERROR (nm_device_error_quark ())
-
-static GQuark
-nm_device_error_quark (void)
-{
-	static GQuark quark = 0;
-	if (!quark)
-		quark = g_quark_from_static_string ("nm-device-error");
-	return quark;
-}
-
-/***********************************************************/
-
-enum {
-	STATE_CHANGED,
-	AUTOCONNECT_ALLOWED,
-	AUTH_REQUEST,
-	IP4_CONFIG_CHANGED,
-	IP6_CONFIG_CHANGED,
-	LAST_SIGNAL,
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
-enum {
-	PROP_0,
-	PROP_UDI,
-	PROP_IFACE,
-	PROP_IP_IFACE,
-	PROP_DRIVER,
-	PROP_DRIVER_VERSION,
-	PROP_FIRMWARE_VERSION,
-	PROP_CAPABILITIES,
-	PROP_IP4_ADDRESS,
-	PROP_IP4_CONFIG,
-	PROP_DHCP4_CONFIG,
-	PROP_IP6_CONFIG,
-	PROP_DHCP6_CONFIG,
-	PROP_STATE,
-	PROP_STATE_REASON,
-	PROP_ACTIVE_CONNECTION,
-	PROP_DEVICE_TYPE,
-	PROP_MANAGED,
-	PROP_AUTOCONNECT,
-	PROP_FIRMWARE_MISSING,
-	PROP_TYPE_DESC,
-	PROP_RFKILL_TYPE,
-	PROP_IFINDEX,
-	PROP_AVAILABLE_CONNECTIONS,
-	PROP_IS_MASTER,
-	LAST_PROP
-};
-
-#define DEFAULT_AUTOCONNECT TRUE
-
-/***********************************************************/
-
-G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT)
-
-#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
-
-typedef enum {
-	IP_NONE = 0,
-	IP_WAIT,
-	IP_CONF,
-	IP_DONE
-} IpState;
-
-typedef struct {
-	NMDeviceState state;
-	NMDeviceStateReason reason;
-	guint id;
-} QueuedState;
-
-typedef struct {
-	NMDevice *slave;
-	gboolean enslaved;
-	guint watch_id;
-} SlaveInfo;
-
-typedef struct {
-	gboolean disposed;
-	gboolean initialized;
-
-	NMDeviceState state;
-	NMDeviceStateReason state_reason;
-	QueuedState   queued_state;
-
-	char *        udi;
-	char *        path;
-	char *        iface;   /* may change, could be renamed by user */
-	int           ifindex;
-	char *        ip_iface;
-	int           ip_ifindex;
-	NMDeviceType  type;
-	char *        type_desc;
-	guint32       capabilities;
-	char *        driver;
-	char *        driver_version;
-	char *        firmware_version;
-	gboolean      managed; /* whether managed by NM or not */
-	RfKillType    rfkill_type;
-	gboolean      firmware_missing;
-	GHashTable *  available_connections;
-
-	guint32         ip4_address;
-
-	NMActRequest *  act_request;
-	guint           act_source_id;
-	gpointer        act_source_func;
-	guint           act_source6_id;
-	gpointer        act_source6_func;
-	gulong          secrets_updated_id;
-	gulong          secrets_failed_id;
-
-	/* Generic DHCP stuff */
-	NMDHCPManager * dhcp_manager;
-	guint32         dhcp_timeout;
-	GByteArray *    dhcp_anycast_address;
-
-	/* IP4 configuration info */
-	NMIP4Config *   ip4_config;			/* Config from DHCP, PPP, or system config files */
-	IpState         ip4_state;
-	NMDHCPClient *  dhcp4_client;
-	gulong          dhcp4_state_sigid;
-	gulong          dhcp4_timeout_sigid;
-	NMDHCP4Config * dhcp4_config;
-
-	/* dnsmasq stuff for shared connections */
-	NMDnsMasqManager *dnsmasq_manager;
-	gulong            dnsmasq_state_id;
-
-	/* Firewall Manager */
-	NMFirewallManager *fw_manager;
-	DBusGProxyCall    *fw_call;
-
-	/* avahi-autoipd stuff */
-	GPid    aipd_pid;
-	guint   aipd_watch;
-	guint   aipd_timeout;
-
-	/* IP6 configuration info */
-	NMIP6Config *  ip6_config;
-	IpState        ip6_state;
-
-	NMIP6Manager * ip6_manager;
-	gulong         ip6_addrconf_sigid;
-	gulong         ip6_config_changed_sigid;
-	gboolean       ip6_waiting_for_config;
-	/* IP6 config from autoconf */
-	NMIP6Config *  ac_ip6_config;
-
-	char *         ip6_accept_ra_path;
-	gint32         ip6_accept_ra_save;
-
-	/* IPv6 privacy extensions (RFC4941) */
-	char *         ip6_privacy_tempaddr_path;
-	gint32         ip6_privacy_tempaddr_save;
-
-	NMDHCPClient *  dhcp6_client;
-	guint32         dhcp6_mode;
-	gulong          dhcp6_state_sigid;
-	gulong          dhcp6_timeout_sigid;
-	NMDHCP6Config * dhcp6_config;
-	/* IP6 config from DHCP */
-	NMIP6Config *   dhcp6_ip6_config;
-
-	/* allow autoconnect feature */
-	gboolean        autoconnect;
-
-	/* master interface for bridge/bond slave */
-	NMDevice *      master;
-	gboolean        enslaved;
-
-	/* slave management */
-	gboolean        is_master;
-	GSList *        slaves;    /* list of SlaveInfo */
-
-	NMConnectionProvider *con_provider;
-
-	/* connection provider signals for available connections property */
-	guint cp_added_id;
-	guint cp_loaded_id;
-	guint cp_removed_id;
-	guint cp_updated_id;
-} NMDevicePrivate;
-
-static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason);
-
-static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware);
-static gboolean nm_device_is_up (NMDevice *self);
-
-static gboolean nm_device_set_ip4_config (NMDevice *dev,
-                                          NMIP4Config *config,
-                                          gboolean assumed,
-                                          NMDeviceStateReason *reason);
-static gboolean nm_device_set_ip6_config (NMDevice *dev,
-                                          NMIP6Config *config,
-                                          NMDeviceStateReason *reason);
-
-static gboolean nm_device_activate_ip6_config_commit (gpointer user_data);
-
-static gboolean check_connection_available (NMDevice *device, NMConnection *connection);
-
-static void _clear_available_connections (NMDevice *device, gboolean do_signal);
-
-static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release);
-
-static const char *reason_to_string (NMDeviceStateReason reason);
-
-static void cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
-static void cp_connections_loaded (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
-static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
-static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
-
-static const char *state_to_string (NMDeviceState state);
-
-static void
-nm_device_init (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	priv->type = NM_DEVICE_TYPE_UNKNOWN;
-	priv->capabilities = NM_DEVICE_CAP_NONE;
-	priv->state = NM_DEVICE_STATE_UNMANAGED;
-	priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
-	priv->dhcp_timeout = 0;
-	priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
-	priv->autoconnect = DEFAULT_AUTOCONNECT;
-	priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
-}
-
-static void
-update_accept_ra_save (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-	const char *ip_iface;
-	char *new_path;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
-
-	new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", ip_iface);
-	g_assert (new_path);
-
-	if (priv->ip6_accept_ra_path) {
-		/* If the IP iface is different from before, use the new value */
-		if (!strcmp (new_path, priv->ip6_accept_ra_path)) {
-			g_free (new_path);
-			return;
-		}
-		g_free (priv->ip6_accept_ra_path);
-	}
-
-	/* Grab the original value of "accept_ra" so we can restore it when NM exits */
-	priv->ip6_accept_ra_path = new_path;
-	if (!nm_utils_get_proc_sys_net_value_with_bounds (priv->ip6_accept_ra_path,
-	                                                  ip_iface,
-	                                                  &priv->ip6_accept_ra_save,
-	                                                  0, 2)) {
-		g_free (priv->ip6_accept_ra_path);
-		priv->ip6_accept_ra_path = NULL;
-	}
-}
-
-static void
-update_ip6_privacy_save (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-	const char *ip_iface;
-	char *new_path;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
-
-	new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/use_tempaddr", ip_iface);
-	g_assert (new_path);
-
-	if (priv->ip6_privacy_tempaddr_path) {
-		/* If the IP iface is different from before, use the new value */
-		if (!strcmp (new_path, priv->ip6_privacy_tempaddr_path)) {
-			g_free (new_path);
-			return;
-		}
-		g_free (priv->ip6_privacy_tempaddr_path);
-	}
-
-	/* Grab the original value of "use_tempaddr" so we can restore it when NM exits */
-	priv->ip6_privacy_tempaddr_path = new_path;
-	if (!nm_utils_get_proc_sys_net_value (priv->ip6_privacy_tempaddr_path,
-	                                      ip_iface,
-	                                      &priv->ip6_privacy_tempaddr_save)) {
-		g_free (priv->ip6_privacy_tempaddr_path);
-		priv->ip6_privacy_tempaddr_path = NULL;
-	}
-}
-
-/*
- * Get driver info from SIOCETHTOOL ioctl() for 'iface'
- * Returns driver and firmware versions to 'driver_version and' 'firmware_version'
- */
-static gboolean
-device_get_driver_info (const char *iface, char **driver_version, char **firmware_version)
-{
-	struct ethtool_drvinfo drvinfo;
-	struct ifreq req;
-	int fd;
-
-	fd = socket (PF_INET, SOCK_DGRAM, 0);
-	if (fd < 0) {
-		nm_log_warn (LOGD_HW, "couldn't open control socket.");
-		return FALSE;
-	}
-
-	/* Get driver and firmware version info */
-	memset (&drvinfo, 0, sizeof (drvinfo));
-	memset (&req, 0, sizeof (struct ifreq));
-	strncpy (req.ifr_name, iface, IFNAMSIZ);
-	drvinfo.cmd = ETHTOOL_GDRVINFO;
-	req.ifr_data = &drvinfo;
-
-	errno = 0;
-	if (ioctl (fd, SIOCETHTOOL, &req) < 0) {
-		nm_log_dbg (LOGD_HW, "SIOCETHTOOL ioctl() failed: cmd=ETHTOOL_GDRVINFO, iface=%s, errno=%d",
-		            iface, errno);
-		close (fd);
-		return FALSE;
-	}
-	if (driver_version)
-		*driver_version = g_strdup (drvinfo.version);
-	if (firmware_version)
-		*firmware_version = g_strdup (drvinfo.fw_version);
-
-	close (fd);
-	return TRUE;
-}
-
-static GObject*
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
-{
-	GObject *object;
-	NMDevice *dev;
-	NMDevicePrivate *priv;
-
-	object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
-	                         n_construct_params,
-	                         construct_params);
-	if (!object)
-		return NULL;
-
-	dev = NM_DEVICE (object);
-	priv = NM_DEVICE_GET_PRIVATE (dev);
-
-	if (!priv->udi) {
-		nm_log_err (LOGD_DEVICE, "No device udi provided, ignoring");
-		goto error;
-	}
-
-	if (!priv->iface) {
-		nm_log_err (LOGD_DEVICE, "No device interface provided, ignoring");
-		goto error;
-	}
-
-	priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities (dev);
-	if (!(priv->capabilities & NM_DEVICE_CAP_NM_SUPPORTED)) {
-		nm_log_warn (LOGD_DEVICE, "(%s): Device unsupported, ignoring.", priv->iface);
-		goto error;
-	}
-
-	priv->dhcp_manager = nm_dhcp_manager_get ();
-
-	priv->fw_manager = nm_firewall_manager_get ();
-
-	device_get_driver_info (priv->iface, &priv->driver_version, &priv->firmware_version);
-
-	update_accept_ra_save (dev);
-	update_ip6_privacy_save (dev);
-
-	priv->initialized = TRUE;
-	return object;
-
-error:
-	g_object_unref (dev);
-	return NULL;
-}
-
-static void
-constructed (GObject *object)
-{
-	NMDevice *dev = NM_DEVICE (object);
-
-	if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
-
-	if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev);
-
-	if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev);
-
-	if (G_OBJECT_CLASS (nm_device_parent_class)->constructed)
-		G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
-}
-
-static gboolean
-nm_device_hw_is_up (NMDevice *self)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	if (NM_DEVICE_GET_CLASS (self)->hw_is_up)
-		return NM_DEVICE_GET_CLASS (self)->hw_is_up (self);
-
-	return TRUE;
-}
-
-static gboolean
-hw_is_up (NMDevice *device)
-{
-	int ifindex = nm_device_get_ip_ifindex (device);
-
-	return ifindex > 0 ? nm_system_iface_is_up (ifindex) : TRUE;
-}
-
-static guint32
-get_generic_capabilities (NMDevice *dev)
-{
-	return 0;
-}
-
-void
-nm_device_set_path (NMDevice *self, const char *path)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (self != NULL);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->path == NULL);
-
-	priv->path = g_strdup (path);
-}
-
-const char *
-nm_device_get_path (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->path;
-}
-
-const char *
-nm_device_get_udi (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->udi;
-}
-
-/*
- * Get/set functions for iface
- */
-const char *
-nm_device_get_iface (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->iface;
-}
-
-int
-nm_device_get_ifindex (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, 0);
-
-	return NM_DEVICE_GET_PRIVATE (self)->ifindex;
-}
-
-const char *
-nm_device_get_ip_iface (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_val_if_fail (self != NULL, NULL);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	/* If it's not set, default to iface */
-	return priv->ip_iface ? priv->ip_iface : priv->iface;
-}
-
-int
-nm_device_get_ip_ifindex (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_val_if_fail (self != NULL, 0);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	/* If it's not set, default to iface */
-	return priv->ip_iface ? priv->ip_ifindex : priv->ifindex;
-}
-
-void
-nm_device_set_ip_iface (NMDevice *self, const char *iface)
-{
-	NMDevicePrivate *priv;
-	char *old_ip_iface;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	old_ip_iface = priv->ip_iface;
-	priv->ip_ifindex = 0;
-
-	priv->ip_iface = g_strdup (iface);
-	if (priv->ip_iface) {
-		priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface);
-		if (priv->ip_ifindex <= 0) {
-			/* Device IP interface must always be a kernel network interface */
-			nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface);
-		}
-	}
-
-	/* Emit change notification */
-	if (g_strcmp0 (old_ip_iface, priv->ip_iface))
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
-	g_free (old_ip_iface);
-}
-
-const guint8 *
-nm_device_get_hw_address (NMDevice *dev, guint *out_len)
-{
-	g_return_val_if_fail (dev != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (dev), NULL);
-	g_return_val_if_fail (out_len != NULL, NULL);
-	g_return_val_if_fail (*out_len == 0, NULL);
-
-	if (NM_DEVICE_GET_CLASS (dev)->get_hw_address)
-		return NM_DEVICE_GET_CLASS (dev)->get_hw_address (dev, out_len);
-	return NULL;
-}
-
-/*
- * Get/set functions for driver
- */
-const char *
-nm_device_get_driver (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->driver;
-}
-
-const char *
-nm_device_get_driver_version (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->driver_version;
-}
-
-const char *
-nm_device_get_firmware_version (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->firmware_version;
-}
-
-
-/*
- * Get/set functions for type
- */
-NMDeviceType
-nm_device_get_device_type (NMDevice *self)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
-
-	return NM_DEVICE_GET_PRIVATE (self)->type;
-}
-
-
-/**
- * nm_device_get_priority():
- * @dev: the #NMDevice
- *
- * Returns: the device's routing priority.  Lower numbers means a "better"
- *  device, eg higher priority.
- */
-int
-nm_device_get_priority (NMDevice *dev)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (dev), 100);
-
-	/* Device 'priority' is used for two things:
-	 *
-	 * a) two devices on the same IP subnet: the "better" (ie, lower number)
-	 *     device is the default outgoing device for that subnet
-	 * b) default route: the "better" device gets the default route.  This can
-	 *     always be modified by setting a connection to never-default=TRUE, in
-	 *     which case that device will never take the default route when
-	 *     it's using that connection.
-	 */
-
-	switch (nm_device_get_device_type (dev)) {
-	case NM_DEVICE_TYPE_ETHERNET:
-		return 1;
-	case NM_DEVICE_TYPE_INFINIBAND:
-		return 2;
-	case NM_DEVICE_TYPE_ADSL:
-		return 3;
-	case NM_DEVICE_TYPE_WIMAX:
-		return 4;
-	case NM_DEVICE_TYPE_BOND:
-		return 5;
-	case NM_DEVICE_TYPE_VLAN:
-		return 6;
-	case NM_DEVICE_TYPE_MODEM:
-		return 7;
-	case NM_DEVICE_TYPE_BT:
-		return 8;
-	case NM_DEVICE_TYPE_WIFI:
-		return 9;
-	case NM_DEVICE_TYPE_OLPC_MESH:
-		return 10;
-	default:
-		return 20;
-	}
-}
-
-
-/*
- * Accessor for capabilities
- */
-guint32
-nm_device_get_capabilities (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
-
-	return NM_DEVICE_GET_PRIVATE (self)->capabilities;
-}
-
-/*
- * Accessor for type-specific capabilities
- */
-guint32
-nm_device_get_type_capabilities (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
-
-	return NM_DEVICE_GET_CLASS (self)->get_type_capabilities (self);
-}
-
-static guint32
-get_type_capabilities (NMDevice *self)
-{
-	return NM_DEVICE_CAP_NONE;
-}
-
-
-const char *
-nm_device_get_type_desc (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->type_desc;
-}
-
-void
-nm_device_set_connection_provider (NMDevice *device,
-                                   NMConnectionProvider *provider)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (device != NULL);
-	g_return_if_fail (provider != NULL);
-	g_return_if_fail (NM_IS_CONNECTION_PROVIDER (provider));
-
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	g_return_if_fail (priv->con_provider == NULL);
-
-	priv->con_provider = provider;
-	priv->cp_added_id = g_signal_connect (priv->con_provider,
-	                                      NM_CP_SIGNAL_CONNECTION_ADDED,
-	                                      G_CALLBACK (cp_connection_added),
-	                                      device);
-
-	priv->cp_loaded_id = g_signal_connect (priv->con_provider,
-	                                       NM_CP_SIGNAL_CONNECTIONS_LOADED,
-	                                       G_CALLBACK (cp_connections_loaded),
-	                                       device);
-
-	priv->cp_removed_id = g_signal_connect (priv->con_provider,
-	                                        NM_CP_SIGNAL_CONNECTION_REMOVED,
-	                                        G_CALLBACK (cp_connection_removed),
-	                                        device);
-
-	priv->cp_updated_id = g_signal_connect (priv->con_provider,
-	                                        NM_CP_SIGNAL_CONNECTION_UPDATED,
-	                                        G_CALLBACK (cp_connection_updated),
-	                                        device);
-}
-
-NMConnectionProvider *
-nm_device_get_connection_provider (NMDevice *device)
-{
-	g_return_val_if_fail (device != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (device)->con_provider;
-}
-
-static SlaveInfo *
-find_slave_info (NMDevice *self, NMDevice *slave)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	SlaveInfo *info;
-	GSList *iter;
-
-	for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
-		info = iter->data;
-		if (info->slave == slave)
-			return info;
-	}
-	return NULL;
-}
-
-static void
-free_slave_info (SlaveInfo *info)
-{
-	g_signal_handler_disconnect (info->slave, info->watch_id);
-	g_clear_object (&info->slave);
-	memset (info, 0, sizeof (*info));
-	g_free (info);
-}
-
-/**
- * nm_device_enslave_slave:
- * @dev: the master device
- * @slave: the slave device to enslave
- * @connection: the slave device's connection
- *
- * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
- * then this function enslaves @slave.
- *
- * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
- *  other devices.
- */
-static gboolean
-nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection)
-{
-	SlaveInfo *info;
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (dev != NULL, FALSE);
-	g_return_val_if_fail (slave != NULL, FALSE);
-	g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
-	g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
-
-	info = find_slave_info (dev, slave);
-	if (!info)
-		return FALSE;
-
-	g_warn_if_fail (info->enslaved == FALSE);
-	success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection);
-	if (success) {
-		info->enslaved = TRUE;
-		nm_device_slave_notify_enslaved (info->slave, TRUE, FALSE);
-	}
-
-	/* Ensure the device's hardware address is up-to-date; it often changes
-	 * when slaves change.
-	 */
-	if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
-
-	/* Restart IP configuration if we're waiting for slaves.  Do this
-	 * after updating the hardware address as IP config may need the
-	 * new address.
-	 */
-	if (success) {
-		if (NM_DEVICE_GET_PRIVATE (dev)->ip4_state == IP_WAIT)
-			nm_device_activate_stage3_ip4_start (dev);
-
-		if (NM_DEVICE_GET_PRIVATE (dev)->ip6_state == IP_WAIT)
-			nm_device_activate_stage3_ip6_start (dev);
-	}
-
-	return success;
-}
-
-/**
- * nm_device_release_one_slave:
- * @dev: the master device
- * @slave: the slave device to release
- * @failed: %TRUE if the release was unexpected, ie the master failed
- *
- * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
- * then this function releases the previously enslaved @slave.
- *
- * Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
- *  other devices, or if @slave was never enslaved.
- */
-static gboolean
-nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean failed)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
-	SlaveInfo *info;
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (slave != NULL, FALSE);
-	g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->release_slave != NULL, FALSE);
-
-	info = find_slave_info (dev, slave);
-	if (!info)
-		return FALSE;
-
-	if (info->enslaved) {
-		success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
-		g_warn_if_fail (success);
-	}
-	nm_device_slave_notify_enslaved (info->slave, FALSE, failed);
-
-	priv->slaves = g_slist_remove (priv->slaves, info);
-	free_slave_info (info);
-
-	/* Ensure the device's hardware address is up-to-date; it often changes
-	 * when slaves change.
-	 */
-	if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
-
-	return success;
-}
-
-static void
-slave_state_changed (NMDevice *slave,
-                     NMDeviceState slave_new_state,
-                     NMDeviceState slave_old_state,
-                     NMDeviceStateReason reason,
-                     NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	gboolean release = FALSE;
-
-	nm_log_dbg (LOGD_DEVICE, "(%s): slave %s state change %d (%s) -> %d (%s)",
-	            nm_device_get_iface (self),
-	            nm_device_get_iface (slave),
-	            slave_old_state,
-	            state_to_string (slave_old_state),
-	            slave_new_state,
-	            state_to_string (slave_new_state));
-
-	g_assert (priv->state > NM_DEVICE_STATE_DISCONNECTED);
-	g_assert (priv->state <= NM_DEVICE_STATE_ACTIVATED);
-
-	/* Don't try to enslave slaves until the master is ready */
-	if (priv->state < NM_DEVICE_STATE_CONFIG)
-		return;
-
-	if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG)
-		nm_device_enslave_slave (self, slave, nm_device_get_connection (slave));
-	else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED)
-		release = TRUE;
-	else if (   slave_new_state <= NM_DEVICE_STATE_DISCONNECTED
-	         && slave_old_state > NM_DEVICE_STATE_DISCONNECTED) {
-		/* Catch failures due to unavailable or unmanaged */
-		release = TRUE;
-	}
-
-	if (release) {
-		nm_device_release_one_slave (self, slave, FALSE);
-		/* Bridge/bond interfaces are left up until manually deactivated */
-		if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) {
-			nm_log_dbg (LOGD_DEVICE, "(%s): last slave removed; remaining activated",
-			            nm_device_get_iface (self));
-		}
-	}
-}
-
-/**
- * nm_device_master_add_slave:
- * @dev: the master device
- * @slave: the slave device to enslave
- *
- * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
- * then this function adds @slave to the slave list for later enslavement.
- *
- * Returns: %TRUE on success, %FALSE on failure
- */
-gboolean
-nm_device_master_add_slave (NMDevice *dev, NMDevice *slave)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
-	SlaveInfo *info;
-
-	g_return_val_if_fail (dev != NULL, FALSE);
-	g_return_val_if_fail (slave != NULL, FALSE);
-	g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
-	g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
-
-	if (!find_slave_info (dev, slave)) {
-		info = g_malloc0 (sizeof (SlaveInfo));
-		info->slave = g_object_ref (slave);
-		info->watch_id = g_signal_connect (slave, "state-changed",
-		                                   G_CALLBACK (slave_state_changed), dev);
-		priv->slaves = g_slist_prepend (priv->slaves, info);
-	}
-
-	return TRUE;
-}
-
-
-/**
- * nm_device_master_get_slaves:
- * @dev: the master device
- *
- * Returns: any slaves of which @device is the master.  Caller owns returned list.
- */
-GSList *
-nm_device_master_get_slaves (NMDevice *dev)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
-	GSList *slaves = NULL, *iter;
-
-	for (iter = priv->slaves; iter; iter = g_slist_next (iter))
-		slaves = g_slist_prepend (slaves, ((SlaveInfo *) iter->data)->slave);
-
-	return slaves;
-}
-
-/**
- * nm_device_master_get_slave_by_ifindex:
- * @dev: the master device
- * @ifindex: the slave's interface index
- *
- * Returns: the slave with the given @ifindex of which @device is the master,
- *   or %NULL if no device with @ifinidex is a slave of @device.
- */
-NMDevice *
-nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex)
-{
-	GSList *iter;
-
-	for (iter = NM_DEVICE_GET_PRIVATE (dev)->slaves; iter; iter = g_slist_next (iter)) {
-		SlaveInfo *info = iter->data;
-
-		if (nm_device_get_ip_ifindex (info->slave) == ifindex)
-			return info->slave;
-	}
-	return NULL;
-}
-
-/**
- * nm_device_is_master:
- * @dev: the device
- *
- * Returns: whether @dev can enslave other devices (eg, bridge or bond)
- */
-gboolean
-nm_device_is_master (NMDevice *dev)
-{
-	return NM_DEVICE_GET_PRIVATE (dev)->is_master;
-}
-
-/* release all slaves */
-static void
-nm_device_master_release_slaves (NMDevice *self, gboolean failed)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	while (priv->slaves) {
-		SlaveInfo *info = priv->slaves->data;
-
-		nm_device_release_one_slave (self, info->slave, failed);
-	}
-}
-
-
-/**
- * nm_device_slave_notify_enslaved:
- * @dev: the slave device
- * @enslaved: %TRUE if the device is now enslaved, %FALSE if released
- * @master_failed: if released, indicates whether the release was unexpected,
- *   ie the master device failed.
- *
- * Notifies a slave that it has been enslaved or released.  If released, provides
- * information on whether the release was expected or not, and thus whether the
- * slave should fail it's activation or gracefully deactivate.
- */
-void
-nm_device_slave_notify_enslaved (NMDevice *dev,
-                                 gboolean enslaved,
-                                 gboolean master_failed)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
-	NMConnection *connection = nm_device_get_connection (dev);
-
-	if (enslaved) {
-		g_assert (priv->master);
-		g_warn_if_fail (priv->enslaved == FALSE);
-		g_warn_if_fail (priv->state == NM_DEVICE_STATE_IP_CONFIG);
-
-		nm_log_info (LOGD_DEVICE,
-				     "Activation (%s) connection '%s' enslaved, continuing activation",
-				     nm_device_get_iface (dev),
-				     nm_connection_get_id (connection));
-
-		/* Now that we're enslaved, proceed with activation.  Remember, slaves
-		 * don't have any IP configuration, so they skip directly to SECONDARIES.
-		 */
-		priv->enslaved = TRUE;
-		priv->ip4_state = IP_DONE;
-		priv->ip6_state = IP_DONE;
-		nm_device_queue_state (dev, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
-	} else {
-		NMDeviceState new_state = NM_DEVICE_STATE_DISCONNECTED;
-		NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-		if (   priv->state > NM_DEVICE_STATE_DISCONNECTED
-		    && priv->state <= NM_DEVICE_STATE_ACTIVATED) {
-			if (master_failed) {
-				new_state = NM_DEVICE_STATE_FAILED;
-				reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED;
-
-				nm_log_warn (LOGD_DEVICE,
-				             "Activation (%s) connection '%s' master failed",
-				             nm_device_get_iface (dev),
-				             nm_connection_get_id (connection));
-			} else {
-				nm_log_dbg (LOGD_DEVICE,
-				            "Activation (%s) connection '%s' master deactivated",
-				            nm_device_get_iface (dev),
-				            nm_connection_get_id (connection));
-			}
-
-			nm_device_queue_state (dev, new_state, reason);
-		}
-	}
-}
-
-/**
- * nm_device_get_enslaved:
- * @device: the #NMDevice
- *
- * Returns: %TRUE if the device is enslaved to a master device (eg bridge or
- * bond), %FALSE if not
- */
-gboolean
-nm_device_get_enslaved (NMDevice *device)
-{
-	return NM_DEVICE_GET_PRIVATE (device)->enslaved;
-}
-
-/*
- * nm_device_get_act_request
- *
- * Return the devices activation request, if any.
- *
- */
-NMActRequest *
-nm_device_get_act_request (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->act_request;
-}
-
-NMConnection *
-nm_device_get_connection (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	return priv->act_request ? nm_act_request_get_connection (priv->act_request) : NULL;
-}
-
-gboolean
-nm_device_is_available (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->firmware_missing)
-		return FALSE;
-
-	if (NM_DEVICE_GET_CLASS (self)->is_available)
-		return NM_DEVICE_GET_CLASS (self)->is_available (self);
-	return TRUE;
-}
-
-gboolean
-nm_device_get_enabled (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	if (NM_DEVICE_GET_CLASS (self)->get_enabled)
-		return NM_DEVICE_GET_CLASS (self)->get_enabled (self);
-	return TRUE;
-}
-
-void
-nm_device_set_enabled (NMDevice *self, gboolean enabled)
-{
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	if (NM_DEVICE_GET_CLASS (self)->set_enabled)
-		NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled);
-}
-
-RfKillType
-nm_device_get_rfkill_type (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	return NM_DEVICE_GET_PRIVATE (self)->rfkill_type;
-}
-
-static gboolean
-autoconnect_allowed_accumulator (GSignalInvocationHint *ihint,
-                                 GValue *return_accu,
-                                 const GValue *handler_return, gpointer data)
-{
-	if (!g_value_get_boolean (handler_return))
-		g_value_set_boolean (return_accu, FALSE);
-	return TRUE;
-}
-
-gboolean
-nm_device_autoconnect_allowed (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	GValue instance = { 0, };
-	GValue retval = { 0, };
-
-	g_value_init (&instance, G_TYPE_OBJECT);
-	g_value_take_object (&instance, self);
-
-	g_value_init (&retval, G_TYPE_BOOLEAN);
-	if (priv->autoconnect)
-		g_value_set_boolean (&retval, TRUE);
-	else
-		g_value_set_boolean (&retval, FALSE);
-
-	/* Use g_signal_emitv() rather than g_signal_emit() to avoid the return
-	 * value being changed if no handlers are connected */
-	g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval);
-	return g_value_get_boolean (&retval);
-}
-
-NMConnection *
-nm_device_get_best_auto_connection (NMDevice *dev,
-                                    GSList *connections,
-                                    char **specific_object)
-{
-	guint32 caps;
-	GSList *iter, *available_conns;
-	NMConnection *best_connection;
-
-	g_return_val_if_fail (NM_IS_DEVICE (dev), NULL);
-	g_return_val_if_fail (specific_object != NULL, NULL);
-	g_return_val_if_fail (*specific_object == NULL, NULL);
-
-	caps = nm_device_get_capabilities (dev);
-	/* Don't use devices that SUCK */
-	if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED))
-		return NULL;
-
-	if (!NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection)
-		return NULL;
-
-	available_conns = NULL;
-	for (iter = connections; iter; iter = iter->next) {
-		NMConnection *connection = NM_CONNECTION (iter->data);
-		NMSettingConnection *s_con;
-
-		s_con = nm_connection_get_setting_connection (connection);
-		g_assert (s_con);
-		if (nm_setting_connection_get_autoconnect (s_con))
-			available_conns = g_slist_prepend (available_conns, connection);
-	}
-
-	if (!available_conns)
-		return NULL;
-
-	best_connection = NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection (dev, available_conns, specific_object);
-
-	g_slist_free (available_conns);
-	return best_connection;
-}
-
-gboolean
-nm_device_complete_connection (NMDevice *self,
-                               NMConnection *connection,
-                               const char *specific_object,
-                               const GSList *existing_connections,
-                               GError **error)
-{
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (self != NULL, FALSE);
-	g_return_val_if_fail (connection != NULL, FALSE);
-
-	if (!NM_DEVICE_GET_CLASS (self)->complete_connection) {
-		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CONNECTION_INVALID,
-		             "Device class %s had no complete_connection method",
-		             G_OBJECT_TYPE_NAME (self));
-		return FALSE;
-	}
-
-	success = NM_DEVICE_GET_CLASS (self)->complete_connection (self,
-	                                                           connection,
-	                                                           specific_object,
-	                                                           existing_connections,
-	                                                           error);
-	if (success)
-		success = nm_connection_verify (connection, error);
-
-	return success;
-}
-
-gboolean
-nm_device_check_connection_compatible (NMDevice *device,
-                                       NMConnection *connection,
-                                       GError **error)
-{
-	g_return_val_if_fail (device != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-	g_return_val_if_fail (connection != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
-
-	if (NM_DEVICE_GET_CLASS (device)->check_connection_compatible)
-		return NM_DEVICE_GET_CLASS (device)->check_connection_compatible (device, connection, error);
-	return TRUE;
-}
-
-gboolean
-nm_device_can_assume_connections (NMDevice *device)
-{
-	g_return_val_if_fail (device != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-
-	return !!NM_DEVICE_GET_CLASS (device)->connection_match_config;
-}
-
-static void
-dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-
-	switch (status) {
-	case NM_DNSMASQ_STATUS_DEAD:
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
-		break;
-	default:
-		break;
-	}
-}
-
-static void
-activation_source_clear (NMDevice *self, gboolean remove_source, int family)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	guint *act_source_id;
-	gpointer *act_source_func;
-
-	if (family == AF_INET6) {
-		act_source_id = &priv->act_source6_id;
-		act_source_func = &priv->act_source6_func;
-	} else {
-		act_source_id = &priv->act_source_id;
-		act_source_func = &priv->act_source_func;
-	}
-
-	if (*act_source_id) {
-		if (remove_source)
-			g_source_remove (*act_source_id);
-		*act_source_id = 0;
-		*act_source_func = NULL;
-	}
-}
-
-static void
-activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	guint *act_source_id;
-	gpointer *act_source_func;
-
-	if (family == AF_INET6) {
-		act_source_id = &priv->act_source6_id;
-		act_source_func = &priv->act_source6_func;
-	} else {
-		act_source_id = &priv->act_source_id;
-		act_source_func = &priv->act_source_func;
-	}
-
-	if (*act_source_id) {
-		nm_log_err (LOGD_DEVICE, "activation stage already scheduled");
-	}
-
-	/* Don't bother rescheduling the same function that's about to
-	 * run anyway.  Fixes issues with crappy wireless drivers sending
-	 * streams of associate events before NM has had a chance to process
-	 * the first one.
-	 */
-	if (!*act_source_id || (*act_source_func != func)) {
-		activation_source_clear (self, TRUE, family);
-		*act_source_id = g_idle_add (func, self);
-		*act_source_func = func;
-	}
-}
-
-gboolean
-nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
-{
-	NMConnection *connection;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
-
-	g_return_val_if_fail (self != NULL, TRUE);
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	/* Fail the connection if the failed IP method is required to complete */
-	if (ip6) {
-		s_ip6 = nm_connection_get_setting_ip6_config (connection);
-		if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6))
-			return TRUE;
-	} else {
-		s_ip4 = nm_connection_get_setting_ip4_config (connection);
-		if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static NMActStageReturn
-act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
-{
-	return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-/*
- * nm_device_activate_stage1_device_prepare
- *
- * Prepare for device activation
- *
- */
-static gboolean
-nm_device_activate_stage1_device_prepare (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *iface;
-	NMActStageReturn ret;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, 0);
-
-	priv->ip4_state = priv->ip6_state = IP_NONE;
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
-	nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
-
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
-		goto out;
-	} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		goto out;
-	}
-	g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
-
-	nm_device_activate_schedule_stage2_device_config (self);
-
-out:
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) complete.", iface);
-	return FALSE;
-}
-
-
-/*
- * nm_device_activate_schedule_stage1_device_prepare
- *
- * Prepare a device for activation
- *
- */
-void
-nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0);
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...",
-	             nm_device_get_iface (self));
-}
-
-static NMActStageReturn
-act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
-	GSList *iter;
-
-	/* If we have slaves that aren't yet enslaved, do that now */
-	for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
-		SlaveInfo *info = iter->data;
-
-		if (nm_device_get_state (info->slave) == NM_DEVICE_STATE_IP_CONFIG)
-			nm_device_enslave_slave (dev, info->slave, nm_device_get_connection (info->slave));
-	}
-
-	/* Nothing to do */
-	return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-/*
- * nm_device_activate_stage2_device_config
- *
- * Determine device parameters and set those on the device, ie
- * for wireless devices, set SSID, keys, etc.
- *
- */
-static gboolean
-nm_device_activate_stage2_device_config (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	const char *     iface;
-	NMActStageReturn ret;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	gboolean no_firmware = FALSE;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, 0);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface);
-	nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-
-	if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
-		if (no_firmware)
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING);
-		else
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
-		goto out;
-	}
-
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
-		goto out;
-	else if (ret == NM_ACT_STAGE_RETURN_FAILURE)
-	{
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		goto out;
-	}
-	g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);	
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface);
-
-	nm_device_activate_schedule_stage3_ip_config_start (self);
-
-out:
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) complete.", iface);
-	return FALSE;
-}
-
-
-/*
- * nm_device_activate_schedule_stage2_device_config
- *
- * Schedule setup of the hardware device
- *
- */
-void
-nm_device_activate_schedule_stage2_device_config (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	activation_source_schedule (self, nm_device_activate_stage2_device_config, 0);
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) scheduled...",
-	         nm_device_get_iface (self));
-}
-
-/*********************************************/
-/* avahi-autoipd stuff */
-
-static void
-aipd_timeout_remove (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->aipd_timeout) {
-		g_source_remove (priv->aipd_timeout);
-		priv->aipd_timeout = 0;
-	}
-}
-
-static void
-aipd_cleanup (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->aipd_watch) {
-		g_source_remove (priv->aipd_watch);
-		priv->aipd_watch = 0;
-	}
-
-	if (priv->aipd_pid > 0) {
-		kill (priv->aipd_pid, SIGKILL);
-
-		/* ensure the child is reaped */
-		nm_log_dbg (LOGD_AUTOIP4, "waiting for avahi-autoipd pid %d to exit", priv->aipd_pid);
-		waitpid (priv->aipd_pid, NULL, 0);
-		nm_log_dbg (LOGD_AUTOIP4, "avahi-autoip pid %d cleaned up", priv->aipd_pid);
-
-		priv->aipd_pid = -1;
-	}
-
-	aipd_timeout_remove (self);
-}
-
-static NMIP4Config *
-aipd_get_ip4_config (NMDevice *self, struct in_addr lla)
-{
-	NMIP4Config *config = NULL;
-	NMIP4Address *addr;
-	NMIP4Route *route;
-
-	config = nm_ip4_config_new ();
-	g_assert (config);
-
-	addr = nm_ip4_address_new ();
-	nm_ip4_address_set_address (addr, (guint32) lla.s_addr);
-	nm_ip4_address_set_prefix (addr, 16);
-	nm_ip4_config_take_address (config, addr);
-
-	/* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
-	route = nm_ip4_route_new ();
-	nm_ip4_route_set_dest (route, (guint32) htonl (0xE0000000L));
-	nm_ip4_route_set_prefix (route, 4);
-	nm_ip4_route_set_next_hop (route, (guint32) 0);
-	nm_ip4_route_set_metric (route, 0);
-	nm_ip4_config_take_route (config, route);
-
-	return config;	
-}
-
-static void
-autoip_changed (NMDevice *self,
-                NMIP4Config *config,
-                NMSettingIP4Config *s_ip4)
-{
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	nm_utils_merge_ip4_config (config, s_ip4);
-	if (!nm_device_set_ip4_config (self, config, FALSE, &reason)) {
-		nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config in response to autoip event.",
-			        nm_device_get_iface (self));
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-	}
-}
-
-#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
-#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
-
-void
-nm_device_handle_autoip4_event (NMDevice *self,
-                                const char *event,
-                                const char *address)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMConnection *connection = NULL;
-	NMSettingIP4Config *s_ip4 = NULL;
-	const char *iface, *method = NULL;
-
-	g_return_if_fail (event != NULL);
-
-	if (priv->act_request == NULL)
-		return;
-
-	connection = nm_act_request_get_connection (priv->act_request);
-	g_assert (connection);
-
-	/* Ignore if the connection isn't an AutoIP connection */
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (s_ip4)
-		method = nm_setting_ip4_config_get_method (s_ip4);
-
-	if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0)
-		return;
-
-	iface = nm_device_get_iface (self);
-
-	if (strcmp (event, "BIND") == 0) {
-		struct in_addr lla;
-		NMIP4Config *config;
-
-		if (inet_pton (AF_INET, address, &lla) <= 0) {
-			nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd.",
-			            iface, address);
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
-			return;
-		}
-
-		if ((lla.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) {
-			nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd (not link-local).",
-			            iface, address);
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
-			return;
-		}
-
-		config = aipd_get_ip4_config (self, lla);
-		if (config == NULL) {
-			nm_log_err (LOGD_AUTOIP4, "failed to get autoip config");
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-			return;
-		}
-
-		if (priv->ip4_state == IP_CONF) {
-			aipd_timeout_remove (self);
-			nm_device_activate_schedule_ip4_config_result (self, config);
-		} else if (priv->ip4_state == IP_DONE) {
-			autoip_changed (self, config, s_ip4);
-		} else
-			g_assert_not_reached ();
-
-		g_object_unref (config);
-	} else {
-		nm_log_warn (LOGD_AUTOIP4, "(%s): autoip address %s no longer valid because '%s'.",
-		            iface, address, event);
-
-		/* The address is gone; terminate the connection or fail activation */
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
-	}
-}
-
-static void
-aipd_watch_cb (GPid pid, gint status, gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMDeviceState state;
-	const char *iface;
-
-	if (!priv->aipd_watch)
-		return;
-	priv->aipd_watch = 0;
-
-	iface = nm_device_get_iface (self);
-
-	if (WIFEXITED (status)) {
-		nm_log_dbg (LOGD_AUTOIP4, "(%s): avahi-autoipd exited with error code %d",
-		            iface, WEXITSTATUS (status));
-	} else if (WIFSTOPPED (status)) {
-		nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd stopped unexpectedly with signal %d",
-		            iface, WSTOPSIG (status));
-	} else if (WIFSIGNALED (status)) {
-		nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died with signal %d",
-		             iface, WTERMSIG (status));
-	} else {
-		nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died from an unknown cause", iface);
-	}
-
-	aipd_cleanup (self);
-
-	state = nm_device_get_state (self);
-	if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED))
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
-}
-
-static gboolean
-aipd_timeout_cb (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->aipd_timeout) {
-		nm_log_info (LOGD_AUTOIP4, "(%s): avahi-autoipd timed out.", nm_device_get_iface (self));
-		priv->aipd_timeout = 0;
-		aipd_cleanup (self);
-
-		if (priv->ip4_state == IP_CONF)
-			nm_device_activate_schedule_ip4_config_timeout (self);
-	}
-
-	return FALSE;
-}
-
-static void
-aipd_child_setup (gpointer user_data G_GNUC_UNUSED)
-{
-	/* We are in the child process at this point.
-	 * Give child it's own program group for signal
-	 * separation.
-	 */
-	pid_t pid = getpid ();
-	setpgid (pid, pid);
-
-	/*
-	 * We blocked signals in main(). We need to restore original signal
-	 * mask for avahi-autoipd here so that it can receive signals.
-	 */
-	nm_unblock_posix_signals (NULL);
-}
-
-static NMActStageReturn
-aipd_start (NMDevice *self, NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *iface = nm_device_get_iface (self);
-	char *argv[6], *cmdline;
-	const char **aipd_binary = NULL;
-	static const char *aipd_paths[] = {
-		"/usr/sbin/avahi-autoipd",
-		"/usr/local/sbin/avahi-autoipd",
-		NULL
-	};
-	int i = 0;
-	GError *error = NULL;
-
-	aipd_cleanup (self);
-
-	/* Find avahi-autoipd */
-	aipd_binary = aipd_paths;
-	while (*aipd_binary != NULL) {
-		if (g_file_test (*aipd_binary, G_FILE_TEST_EXISTS))
-			break;
-		aipd_binary++;
-	}
-
-	if (!*aipd_binary) {
-		nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4,
-		             "Activation (%s) Stage 3 of 5 (IP Configure Start) failed"
-		             " to start avahi-autoipd: not found", iface);
-		*reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	argv[i++] = (char *) (*aipd_binary);
-	argv[i++] = "--script";
-	argv[i++] = LIBEXECDIR "/nm-avahi-autoipd.action";
-	if (nm_logging_level_enabled (LOGL_DEBUG))
-		argv[i++] = "--debug";
-	argv[i++] = (char *) nm_device_get_ip_iface (self);
-	argv[i++] = NULL;
-
-	cmdline = g_strjoinv (" ", argv);
-	nm_log_dbg (LOGD_AUTOIP4, "running: %s", cmdline);
-	g_free (cmdline);
-
-	if (!g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
-	                    &aipd_child_setup, NULL, &(priv->aipd_pid), &error)) {
-		nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4,
-		             "Activation (%s) Stage 3 of 5 (IP Configure Start) failed"
-		             " to start avahi-autoipd: %s",
-		             iface,
-		             error && error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
-		aipd_cleanup (self);
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4,
-	             "Activation (%s) Stage 3 of 5 (IP Configure Start) started"
-	             " avahi-autoipd...", iface);
-
-	/* Monitor the child process so we know when it dies */
-	priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self);
-
-	/* Start a timeout to bound the address attempt */
-	priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self);
-
-	return NM_ACT_STAGE_RETURN_POSTPONE;
-}
-
-/*********************************************/
-/* DHCPv4 stuff */
-
-static void
-dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data)
-{
-	nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data),
-	                            (const char *) key,
-	                            (const char *) value);
-}
-
-static void
-dhcp4_lease_change (NMDevice *device, NMIP4Config *config)
-{
-	NMConnection *connection;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	if (config == NULL) {
-		nm_log_warn (LOGD_DHCP4, "(%s): failed to get DHCPv4 config for rebind",
-		             nm_device_get_ip_iface (device));
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
-		return;
-	}
-
-	connection = nm_device_get_connection (device);
-	g_assert (connection);
-
-	/* Merge with user overrides */
-	nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection));
-
-	if (!nm_device_set_ip4_config (device, config, FALSE, &reason)) {
-		nm_log_warn (LOGD_DHCP4, "(%s): failed to update IPv4 config in response to DHCP event.",
-		             nm_device_get_ip_iface (device));
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
-		return;
-	}
-
-	/* Notify dispatcher scripts of new DHCP4 config */
-	nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, connection, device, NULL, NULL);
-}
-
-static void
-dhcp4_fail (NMDevice *device, gboolean timeout)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-
-	nm_dhcp4_config_reset (priv->dhcp4_config);
-
-	if (timeout || (priv->ip4_state == IP_CONF))
-		nm_device_activate_schedule_ip4_config_timeout (device);
-	else if (priv->ip4_state == IP_DONE)
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
-}
-
-static void
-dhcp4_state_changed (NMDHCPClient *client,
-                     NMDHCPState state,
-                     gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMDeviceState dev_state;
-	NMIP4Config *config;
-
-	g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE);
-
-	nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d",
-	            nm_device_get_iface (device), state);
-
-	dev_state = nm_device_get_state (device);
-
-	switch (state) {
-	case DHC_BOUND4:     /* lease obtained */
-	case DHC_RENEW4:     /* lease renewed */
-	case DHC_REBOOT:     /* have valid lease, but now obtained a different one */
-	case DHC_REBIND4:    /* new, different lease */
-		config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE);
-
-		/* Update the DHCP4 config object with new DHCP options */
-		nm_dhcp4_config_reset (priv->dhcp4_config);
-		if (config) {
-			nm_dhcp_client_foreach_option (priv->dhcp4_client,
-			                               dhcp4_add_option_cb,
-			                               priv->dhcp4_config);
-		}
-		g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG);
-
-		if (priv->ip4_state == IP_CONF)
-			nm_device_activate_schedule_ip4_config_result (device, config);
-		else if (priv->ip4_state == IP_DONE)
-			dhcp4_lease_change (device, config);
-
-		if (config)
-			g_object_unref (config);
-		break;
-	case DHC_TIMEOUT: /* timed out contacting DHCP server */
-		dhcp4_fail (device, TRUE);
-		break;
-	case DHC_END: /* dhclient exited normally */
-	case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
-	case DHC_ABEND: /* dhclient exited abnormally */
-		/* dhclient quit and can't get/renew a lease; so kill the connection */
-		dhcp4_fail (device, FALSE);
-		break;
-	default:
-		break;
-	}
-}
-
-static void
-dhcp4_timeout (NMDHCPClient *client, gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-
-	g_return_if_fail (nm_device_get_act_request (device) != NULL);
-	g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE);
-
-	nm_dhcp_client_stop (client, FALSE);
-	dhcp4_fail (device, TRUE);
-}
-
-static NMActStageReturn
-dhcp4_start (NMDevice *self,
-             NMConnection *connection,
-             NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMSettingIP4Config *s_ip4;
-	guint8 *anycast = NULL;
-	GByteArray *tmp = NULL;
-	guint hwaddr_len = 0;
-	const guint8 *hwaddr;
-
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-
-	if (priv->dhcp_anycast_address)
-		anycast = priv->dhcp_anycast_address->data;
-
-	/* Clear old exported DHCP options */
-	if (priv->dhcp4_config)
-		g_object_unref (priv->dhcp4_config);
-	priv->dhcp4_config = nm_dhcp4_config_new ();
-
-	hwaddr = nm_device_get_hw_address (self, &hwaddr_len);
-	if (hwaddr) {
-		tmp = g_byte_array_sized_new (hwaddr_len);
-		g_byte_array_append (tmp, hwaddr, hwaddr_len);
-	}
-
-	/* Begin DHCP on the interface */
-	g_warn_if_fail (priv->dhcp4_client == NULL);
-	priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager,
-	                                                nm_device_get_ip_iface (self),
-	                                                tmp,
-	                                                nm_connection_get_uuid (connection),
-	                                                s_ip4,
-	                                                priv->dhcp_timeout,
-	                                                anycast);
-
-	if (tmp)
-		g_byte_array_free (tmp, TRUE);
-
-	if (!priv->dhcp4_client) {
-		*reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client,
-	                                            "state-changed",
-	                                            G_CALLBACK (dhcp4_state_changed),
-	                                            self);
-	priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client,
-	                                              "timeout",
-	                                              G_CALLBACK (dhcp4_timeout),
-	                                              self);
-
-	/* DHCP devices will be notified by the DHCP manager when stuff happens */
-	return NM_ACT_STAGE_RETURN_POSTPONE;
-}
-
-gboolean
-nm_device_dhcp4_renew (NMDevice *self, gboolean release)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	NMDeviceStateReason reason;
-	NMConnection *connection;
-
-	g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE);
-
-	nm_log_info (LOGD_DHCP4, "(%s): DHCPv4 lease renewal requested",
-	             nm_device_get_iface (self));
-
-	/* Terminate old DHCP instance and release the old lease */
-	dhcp4_cleanup (self, TRUE, release);
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	/* Start DHCP again on the interface */
-	ret = dhcp4_start (self, connection, &reason);
-
-	return (ret != NM_ACT_STAGE_RETURN_FAILURE);
-}
-
-/*********************************************/
-
-static GHashTable *shared_ips = NULL;
-
-static void
-release_shared_ip (gpointer data)
-{
-	g_hash_table_remove (shared_ips, data);
-}
-
-static guint32
-reserve_shared_ip (void)
-{
-	guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */
-	guint32 count = 0;
-
-	while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) {
-		count += ntohl (0x100);
-		if (count > ntohl (0xFE00)) {
-			nm_log_err (LOGD_SHARING, "ran out of shared IP addresses!");
-			return 0;
-		}
-	}
-
-	g_hash_table_insert (shared_ips, GUINT_TO_POINTER (start + count), GUINT_TO_POINTER (TRUE));
-	return start + count;
-}
-
-static NMIP4Config *
-shared4_new_config (NMDevice *self, NMDeviceStateReason *reason)
-{
-	NMIP4Config *config = NULL;
-	NMIP4Address *addr;
-	guint32 tmp_addr;
-
-	g_return_val_if_fail (self != NULL, NULL);
-
-	if (G_UNLIKELY (shared_ips == NULL))
-		shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-	tmp_addr = reserve_shared_ip ();
-	if (!tmp_addr) {
-		*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
-		return NULL;
-	}
-
-	config = nm_ip4_config_new ();
-	addr = nm_ip4_address_new ();
-	nm_ip4_address_set_address (addr, tmp_addr);
-	nm_ip4_address_set_prefix (addr, 24);
-	nm_ip4_config_take_address (config, addr);
-
-	/* Remove the address lock when the object gets disposed */
-	g_object_set_data_full (G_OBJECT (config), "shared-ip",
-	                        GUINT_TO_POINTER (tmp_addr), release_shared_ip);
-
-	return config;
-}
-
-/*********************************************/
-
-static gboolean
-have_any_ready_slaves (NMDevice *device, const GSList *slaves)
-{
-	const GSList *iter;
-
-	/* Any enslaved slave is "ready" in the generic case as it's
-	 * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2
-	 * properties set up.
-	 */
-	for (iter = slaves; iter; iter = g_slist_next (iter)) {
-		if (nm_device_get_enslaved (iter->data))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-ip4_requires_slaves (NMConnection *connection)
-{
-	NMSettingIP4Config *s_ip4;
-	const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (s_ip4)
-		method = nm_setting_ip4_config_get_method (s_ip4);
-
-	return g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0;
-}
-
-static NMActStageReturn
-act_stage3_ip4_config_start (NMDevice *self,
-                             NMIP4Config **out_config,
-                             NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMConnection *connection;
-	NMSettingIP4Config *s_ip4;
-	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
-	const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-	GSList *slaves;
-	gboolean ready_slaves;
-
-	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	if (priv->is_master && ip4_requires_slaves (connection)) {
-		/* If the master has no ready slaves, and depends on slaves for
-		 * a successful IPv4 attempt, then postpone IPv4 addressing.
-		 */
-		slaves = nm_device_master_get_slaves (self);
-		ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves);
-		g_slist_free (slaves);
-
-		if (ready_slaves == FALSE) {
-			nm_log_info (LOGD_DEVICE | LOGD_IP4,
-			             "(%s): IPv4 config waiting until slaves are ready",
-			             nm_device_get_ip_iface (self));
-			return NM_ACT_STAGE_RETURN_WAIT;
-		}
-	}
-
-	/* If we did not receive IP4 configuration information, default to DHCP.
-	 * Slaves, on the other hand, never have any IP configuration themselves,
-	 * since the master handles all of that.
-	 */
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (priv->master) /* eg, device is a slave */
-		method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-	else if (s_ip4)
-		method = nm_setting_ip4_config_get_method (s_ip4);
-	else
-		method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-
-	/* Start IPv4 addressing based on the method requested */
-	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0)
-		ret = dhcp4_start (self, connection, reason);
-	else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0)
-		ret = aipd_start (self, reason);
-	else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
-		/* Use only IPv4 config from the connection data */
-		*out_config = nm_ip4_config_new ();
-		g_assert (*out_config);
-		ret = NM_ACT_STAGE_RETURN_SUCCESS;
-	} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
-		*out_config = shared4_new_config (self, reason);
-		if (*out_config) {
-			priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self));
-			ret = NM_ACT_STAGE_RETURN_SUCCESS;
-		} else
-			ret = NM_ACT_STAGE_RETURN_FAILURE;
-	} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) {
-		/* Nothing to do... */
-		ret = NM_ACT_STAGE_RETURN_STOP;
-	} else {
-		nm_log_warn (LOGD_IP4, "(%s): unhandled IPv4 config method '%s'; will fail",
-		             nm_device_get_ip_iface (self), method);
-	}
-
-	return ret;
-}
-
-/*********************************************/
-/* DHCPv6 stuff */
-
-static void
-dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data)
-{
-	nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data),
-	                            (const char *) key,
-	                            (const char *) value);
-}
-
-static void
-merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src)
-{
-	guint32 i;
-
-	g_return_if_fail (src != NULL);
-	g_return_if_fail (dst != NULL);
-
-	/* addresses */
-	for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++)
-		nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
-
-	/* ptp address; only replace if src doesn't have one */
-	if (!nm_ip6_config_get_ptp_address (dst))
-		nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src));
-
-	/* nameservers */
-	for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
-		nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
-
-	/* default gateway */
-	if (!nm_ip6_config_get_gateway (dst))
-		nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src));
-
-	/* routes */
-	for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
-		nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
-
-	/* domains */
-	for (i = 0; i < nm_ip6_config_get_num_domains (src); i++)
-		nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i));
-
-	/* dns searches */
-	for (i = 0; i < nm_ip6_config_get_num_searches (src); i++)
-		nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i));
-
-	if (!nm_ip6_config_get_mss (dst))
-		nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src));
-}
-
-static gboolean
-ip6_config_merge_and_apply (NMDevice *self,
-                            NMIP6Config *src_config,
-                            NMDeviceStateReason *out_reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMConnection *connection;
-	gboolean success;
-	NMIP6Config *composite;
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	/* If no config was passed in, create a new one */
-	composite = nm_ip6_config_new ();
-	g_assert (composite);
-
-	/* Merge in the given config first, if any */
-	if (src_config)
-		merge_ip6_configs (composite, src_config);
-
-	/* Merge RA and DHCPv6 configs into the composite config */
-	if (priv->ac_ip6_config && (src_config != priv->ac_ip6_config))
-		merge_ip6_configs (composite, priv->ac_ip6_config);
-	if (priv->dhcp6_ip6_config && (src_config != priv->dhcp6_ip6_config))
-		merge_ip6_configs (composite, priv->dhcp6_ip6_config);
-
-	/* Merge user overrides into the composite config */
-	nm_utils_merge_ip6_config (composite, nm_connection_get_setting_ip6_config (connection));
-
-	success = nm_device_set_ip6_config (self, composite, out_reason);
-	g_object_unref (composite);
-	return success;
-}
-
-static void
-dhcp6_lease_change (NMDevice *device)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMConnection *connection;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	if (priv->dhcp6_ip6_config == NULL) {
-		nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind",
-		             nm_device_get_ip_iface (device));
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
-		return;
-	}
-
-	g_assert (priv->dhcp6_client);  /* sanity check */
-
-	connection = nm_device_get_connection (device);
-	g_assert (connection);
-
-	/* Apply the updated config */
-	if (ip6_config_merge_and_apply (device, NULL, &reason) == FALSE) {
-		nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.",
-		             nm_device_get_ip_iface (device));
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
-	} else {
-		/* Notify dispatcher scripts of new DHCPv6 config */
-		nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, connection, device, NULL, NULL);
-	}
-}
-
-static void
-dhcp6_fail (NMDevice *device, gboolean timeout)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-
-	nm_dhcp6_config_reset (priv->dhcp6_config);
-
-	if (timeout || (priv->ip6_state == IP_CONF))
-		nm_device_activate_schedule_ip6_config_timeout (device);
-	else if (priv->ip6_state == IP_DONE)
-		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
-}
-
-static void
-dhcp6_state_changed (NMDHCPClient *client,
-                     NMDHCPState state,
-                     gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMDeviceState dev_state;
-
-	g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE);
-
-	nm_log_dbg (LOGD_DHCP6, "(%s): new DHCPv6 client state %d",
-	            nm_device_get_iface (device), state);
-
-	dev_state = nm_device_get_state (device);
-
-	switch (state) {
-	case DHC_BOUND6:
-	case DHC_RENEW6:     /* lease renewed */
-	case DHC_REBOOT:     /* have valid lease, but now obtained a different one */
-	case DHC_REBIND6:    /* new, different lease */
-		if (priv->dhcp6_ip6_config)
-			g_object_unref (priv->dhcp6_ip6_config);
-		priv->dhcp6_ip6_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE);
-
-		/* Update the DHCP6 config object with new DHCP options */
-		nm_dhcp6_config_reset (priv->dhcp6_config);
-		if (priv->dhcp6_ip6_config) {
-			nm_dhcp_client_foreach_option (priv->dhcp6_client,
-			                               dhcp6_add_option_cb,
-			                               priv->dhcp6_config);
-		}
-		g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG);
-
-		if (priv->ip6_state == IP_CONF)
-			nm_device_activate_schedule_ip6_config_result (device, priv->dhcp6_ip6_config);
-		else if (priv->ip6_state == IP_DONE)
-			dhcp6_lease_change (device);
-		break;
-	case DHC_TIMEOUT: /* timed out contacting DHCP server */
-		dhcp6_fail (device, TRUE);
-		break;
-	case DHC_END: /* dhclient exited normally */
-		/* In IPv6 info-only mode, the client doesn't handle leases so it
-		 * may exit right after getting a response from the server.  That's
-		 * normal.  In that case we just ignore the exit.
-		 */
-		if (priv->dhcp6_mode == IP6_DHCP_OPT_OTHERCONF)
-			break;
-		/* Otherwise, fall through */
-	case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
-	case DHC_ABEND: /* dhclient exited abnormally */
-		/* dhclient quit and can't get/renew a lease; so kill the connection */
-		dhcp6_fail (device, FALSE);
-		break;
-	default:
-		break;
-	}
-}
-
-static void
-dhcp6_timeout (NMDHCPClient *client, gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-
-	g_return_if_fail (nm_device_get_act_request (device) != NULL);
-	g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE);
-
-	nm_dhcp_client_stop (client, FALSE);
-	dhcp6_fail (device, TRUE);
-}
-
-static NMActStageReturn
-dhcp6_start (NMDevice *self,
-             NMConnection *connection,
-             guint32 dhcp_opt,
-             NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
-	guint8 *anycast = NULL;
-	GByteArray *tmp = NULL;
-	guint hwaddr_len = 0;
-	const guint8 *hwaddr;
-
-	if (!connection) {
-		connection = nm_device_get_connection (self);
-		g_assert (connection);
-	}
-
-	/* Begin a DHCP transaction on the interface */
-
-	if (priv->dhcp_anycast_address)
-		anycast = priv->dhcp_anycast_address->data;
-
-	/* Clear old exported DHCP options */
-	if (priv->dhcp6_config)
-		g_object_unref (priv->dhcp6_config);
-	priv->dhcp6_config = nm_dhcp6_config_new ();
-
-	g_warn_if_fail (priv->dhcp6_ip6_config == NULL);
-	if (priv->dhcp6_ip6_config) {
-		g_object_unref (priv->dhcp6_ip6_config);
-		priv->dhcp6_ip6_config = NULL;
-	}
-
-	hwaddr = nm_device_get_hw_address (self, &hwaddr_len);
-	if (hwaddr) {
-		tmp = g_byte_array_sized_new (hwaddr_len);
-		g_byte_array_append (tmp, hwaddr, hwaddr_len);
-	}
-
-	priv->dhcp6_client = nm_dhcp_manager_start_ip6 (priv->dhcp_manager,
-	                                                nm_device_get_ip_iface (self),
-	                                                tmp,
-	                                                nm_connection_get_uuid (connection),
-	                                                nm_connection_get_setting_ip6_config (connection),
-	                                                priv->dhcp_timeout,
-	                                                anycast,
-	                                                (dhcp_opt == IP6_DHCP_OPT_OTHERCONF) ? TRUE : FALSE);
-	if (tmp)
-		g_byte_array_free (tmp, TRUE);
-
-	if (priv->dhcp6_client) {
-		priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client,
-		                                            "state-changed",
-		                                            G_CALLBACK (dhcp6_state_changed),
-		                                            self);
-		priv->dhcp6_timeout_sigid = g_signal_connect (priv->dhcp6_client,
-		                                              "timeout",
-		                                              G_CALLBACK (dhcp6_timeout),
-		                                              self);
-
-		/* DHCP devices will be notified by the DHCP manager when stuff happens */
-		ret = NM_ACT_STAGE_RETURN_POSTPONE;
-	} else {
-		*reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
-		ret = NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	return ret;
-}
-
-/******************************************/
-
-static void
-ip6_addrconf_complete (NMIP6Manager *ip6_manager,
-                       int ifindex,
-                       guint dhcp_opts,
-                       gboolean success,
-                       gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMConnection *connection;
-	NMActStageReturn ret;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	if (ifindex != nm_device_get_ip_ifindex (self))
-		return;
-	g_return_if_fail (priv->act_request != NULL);
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	if (!priv->ip6_waiting_for_config)
-		return;
-
-	priv->ip6_waiting_for_config = FALSE;
-
-	if (!success) {
-		nm_device_activate_schedule_ip6_config_timeout (self);
-		return;
-	}
-
-	priv->dhcp6_mode = dhcp_opts;
-
-	/* If addrconf is all that's required, we're done */
-	if (priv->dhcp6_mode == IP6_DHCP_OPT_NONE) {
-		priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
-		nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config);
-		return;
-	}
-
-	/* If the router said to use DHCP for managed or otherconf, do it */
-
-	/* Don't re-start DHCPv6 if it's already in progress */
-	if (priv->ip6_state != IP_CONF)
-		return;
-
-	nm_log_info (LOGD_DEVICE | LOGD_DHCP6,
-	             "Activation (%s) Stage 3 of 5 (IP Configure Start) starting DHCPv6"
-	             " as requested by IPv6 router...",
-	             priv->iface);
-
-	ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason);
-	switch (ret) {
-	case NM_ACT_STAGE_RETURN_SUCCESS:
-		/* Shouldn't get this, but handle it anyway */
-		g_warn_if_reached ();
-		priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
-		nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config);
-		break;
-	case NM_ACT_STAGE_RETURN_POSTPONE:
-		/* Cache acquired autoconf config and wait for DHCPv6 to complete */
-		priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
-		break;
-	default:
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		break;
-	}
-}
-
-static void
-ip6_config_changed (NMIP6Manager *ip6_manager,
-                    int ifindex,
-                    guint dhcp_opts,
-                    gboolean success,
-                    gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	if (ifindex != nm_device_get_ip_ifindex (self))
-		return;
-	g_return_if_fail (priv->act_request != NULL);
-
-	/* If autoconf failed and IPv6 previously succeeded, fail */
-	if (!success && (priv->ip6_state == IP_DONE)) {
-		nm_device_state_changed (self,
-		                         NM_DEVICE_STATE_FAILED,
-		                         NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-		return;
-	}
-
-	/* FIXME: re-run DHCPv6 here to get any new nameservers or whatever */
-
-	if (priv->ac_ip6_config)
-		g_object_unref (priv->ac_ip6_config);
-	priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
-
-	if (ip6_config_merge_and_apply (self, NULL, &reason) == FALSE) {
-		nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to Router Advertisement.",
-		             nm_device_get_ip_iface (self));
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-	}
-}
-
-static gboolean
-addrconf6_start (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMConnection *connection;
-	gboolean success;
-	const guint8 *hwaddr;
-	guint hwaddr_len = 0;
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	g_warn_if_fail (priv->ac_ip6_config == NULL);
-	if (priv->ac_ip6_config) {
-		g_object_unref (priv->ac_ip6_config);
-		priv->ac_ip6_config = NULL;
-	}
-
-	if (!priv->ip6_manager) {
-		priv->ip6_manager = nm_ip6_manager_get ();
-		priv->ip6_addrconf_sigid = g_signal_connect (priv->ip6_manager,
-		                                             "addrconf-complete",
-		                                             G_CALLBACK (ip6_addrconf_complete),
-		                                             self);
-		priv->ip6_config_changed_sigid = g_signal_connect (priv->ip6_manager,
-		                                                   "config-changed",
-		                                                   G_CALLBACK (ip6_config_changed),
-		                                                   self);
-	}
-
-	hwaddr = nm_device_get_hw_address (self, &hwaddr_len);
-	g_warn_if_fail (hwaddr != NULL);
-	success = nm_ip6_manager_prepare_interface (priv->ip6_manager,
-	                                            nm_device_get_ip_ifindex (self),
-	                                            hwaddr,
-	                                            hwaddr_len,
-	                                            nm_connection_get_setting_ip6_config (connection),
-	                                            priv->ip6_accept_ra_path);
-	if (success) {
-		priv->ip6_waiting_for_config = TRUE;
-		nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
-	}
-
-	return success;
-}
-
-static void
-addrconf6_cleanup (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->ac_ip6_config) {
-		g_object_unref (priv->ac_ip6_config);
-		priv->ac_ip6_config = NULL;
-	}
-
-	if (!priv->ip6_manager)
-		return;
-
-	if (priv->ip6_addrconf_sigid) {
-		g_signal_handler_disconnect (priv->ip6_manager,
-		                             priv->ip6_addrconf_sigid);
-		priv->ip6_addrconf_sigid = 0;
-	}
-	if (priv->ip6_config_changed_sigid) {
-		g_signal_handler_disconnect (priv->ip6_manager,
-		                             priv->ip6_config_changed_sigid);
-		priv->ip6_config_changed_sigid = 0;
-	}
-
-	nm_ip6_manager_cancel_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
-	g_object_unref (priv->ip6_manager);
-	priv->ip6_manager = NULL;
-}
-
-/******************************************/
-
-/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or
- * /lib/sysctl.d/sysctl.conf
- */
-static int
-ip6_use_tempaddr (void)
-{
-	char *contents = NULL;
-	gsize len = 0;
-	const char *group_name = "[forged_group]\n";
-	char *sysctl_data = NULL;
-	GKeyFile *keyfile;
-	GError *error = NULL;
-	int tmp, ret = -1;
-
-	/* Read file contents to a string. */
-	if (!g_file_get_contents ("/etc/sysctl.conf", &contents, &len, NULL))
-		if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, &len, NULL))
-			return -1;
-
-	/* Prepend a group so that we can use GKeyFile parser. */
-	sysctl_data = g_strdup_printf ("%s%s", group_name, contents);
-
-	keyfile = g_key_file_new ();
-	if (keyfile == NULL)
-		goto done;
-
-	if (!g_key_file_load_from_data (keyfile, sysctl_data, len + strlen (group_name), G_KEY_FILE_NONE, NULL))
-		goto done;
-
-	tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error);
-	if (error == NULL)
-		ret = tmp;
-
-done:
-	g_free (contents);
-	g_free (sysctl_data);
-	g_clear_error (&error);
-	g_key_file_free (keyfile);
-
-	return ret;
-}
-
-static gboolean
-ip6_requires_slaves (NMConnection *connection)
-{
-	NMSettingIP6Config *s_ip6;
-	const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
-
-	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	if (s_ip6)
-		method = nm_setting_ip6_config_get_method (s_ip6);
-
-	/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
-	 * to complete addressing.  SLAAC and DHCP obviously need a peer to
-	 * provide a prefix, while Link-Local must perform DAD on the local link.
-	 */
-	return    g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
-	       || g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0
-	       || g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0;
-}
-
-static NMActStageReturn
-act_stage3_ip6_config_start (NMDevice *self,
-                             NMIP6Config **out_config,
-                             NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *ip_iface;
-	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
-	NMConnection *connection;
-	NMSettingIP6Config *s_ip6;
-	const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
-	int conf_use_tempaddr;
-	NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
-	const char *ip6_privacy_str = "0\n";
-	GSList *slaves;
-	gboolean ready_slaves;
-
-	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-
-	ip_iface = nm_device_get_ip_iface (self);
-
-	if (priv->is_master && ip6_requires_slaves (connection)) {
-		/* If the master has no ready slaves, and depends on slaves for
-		 * a successful IPv6 attempt, then postpone IPv6 addressing.
-		 */
-		slaves = nm_device_master_get_slaves (self);
-		ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves);
-		g_slist_free (slaves);
-
-		if (ready_slaves == FALSE) {
-			nm_log_info (LOGD_DEVICE | LOGD_IP6,
-			             "(%s): IPv6 config waiting until slaves are ready",
-			             ip_iface);
-			return NM_ACT_STAGE_RETURN_WAIT;
-		}
-	}
-
-	update_accept_ra_save (self);
-	update_ip6_privacy_save (self);
-
-	priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
-
-	/* If we did not receive IP6 configuration information, default to AUTO.
-	 * Slaves, on the other hand, never have any IP configuration themselves,
-	 * since the master handles all of that.
-	 */
-	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	if (priv->master) /* eg, device is a slave */
-		method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
-	else if (s_ip6)
-		method = nm_setting_ip6_config_get_method (s_ip6);
-	else
-		method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
-
-	if (   strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
-	    || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
-		if (!addrconf6_start (self)) {
-			*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
-			ret = NM_ACT_STAGE_RETURN_FAILURE;
-		} else
-			ret = NM_ACT_STAGE_RETURN_POSTPONE;
-	} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
-		/* Router advertisements shouldn't be used in pure DHCP mode */
-		if (priv->ip6_accept_ra_path)
-			nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0");
-
-		priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED;
-		ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
-	} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
-		/* reset the saved RA value when ipv6 is ignored */
-		if (priv->ip6_accept_ra_path) {
-			nm_utils_do_sysctl (priv->ip6_accept_ra_path,
-			                    priv->ip6_accept_ra_save ? "1" : "0");
-		}
-		ret = NM_ACT_STAGE_RETURN_STOP;
-	} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
-		/* New blank config */
-		*out_config = nm_ip6_config_new ();
-		g_assert (*out_config);
-
-		/* Router advertisements shouldn't be used in manual mode */
-		if (priv->ip6_accept_ra_path)
-			nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0");
-		ret = NM_ACT_STAGE_RETURN_SUCCESS;
-	} else {
-		nm_log_warn (LOGD_IP6, "(%s): unhandled IPv6 config method '%s'; will fail",
-		             nm_device_get_ip_iface (self), method);
-	}
-
-	/* Other methods (shared) aren't implemented yet */
-
-	/* Enable/disable IPv6 Privacy Extensions.
-	 * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf),
-	 * use that value instead of per-connection value.
-	 */
-	conf_use_tempaddr = ip6_use_tempaddr ();
-	if (conf_use_tempaddr >= 0)
-		ip6_privacy = conf_use_tempaddr;
-	else if (s_ip6)
-		ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
-	ip6_privacy = CLAMP (ip6_privacy, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
-
-	switch (ip6_privacy) {
-	case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
-	case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
-		ip6_privacy_str = "0";
-	break;
-	case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
-		ip6_privacy_str = "1";
-	break;
-	case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
-		ip6_privacy_str = "2";
-	break;
-	}
-	if (priv->ip6_privacy_tempaddr_path)
-		nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, ip6_privacy_str);
-
-	return ret;
-}
-
-/**
- * nm_device_activate_stage3_ip4_start:
- * @self: the device
- *
- * Try starting IPv4 configuration.
- */
-gboolean
-nm_device_activate_stage3_ip4_start (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	NMIP4Config *ip4_config = NULL;
-
-	g_assert (priv->ip4_state == IP_WAIT);
-
-	priv->ip4_state = IP_CONF;
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
-		g_assert (ip4_config);
-		nm_device_activate_schedule_ip4_config_result (self, ip4_config);
-		g_object_unref (ip4_config);
-	} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		return FALSE;
-	} else if (ret == NM_ACT_STAGE_RETURN_STOP) {
-		/* Early finish */
-		priv->ip4_state = IP_DONE;
-	} else if (ret == NM_ACT_STAGE_RETURN_WAIT) {
-		/* Wait for something to try IP config again */
-		priv->ip4_state = IP_WAIT;
-	} else
-		g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
-
-	return TRUE;
-}
-
-/**
- * nm_device_activate_stage3_ip6_start:
- * @self: the device
- *
- * Try starting IPv6 configuration.
- */
-gboolean
-nm_device_activate_stage3_ip6_start (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	NMIP6Config *ip6_config = NULL;
-
-	g_assert (priv->ip6_state == IP_WAIT);
-
-	priv->ip6_state = IP_CONF;
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
-		g_assert (ip6_config);
-		nm_device_activate_schedule_ip6_config_result (self, ip6_config);
-		g_object_unref (ip6_config);
-	} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		return FALSE;
-	} else if (ret == NM_ACT_STAGE_RETURN_STOP) {
-		/* Early finish */
-		priv->ip6_state = IP_DONE;
-	} else if (ret == NM_ACT_STAGE_RETURN_WAIT) {
-		/* Wait for something to try IP config again */
-		priv->ip6_state = IP_WAIT;
-	} else
-		g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
-
-	return TRUE;
-}
-
-/*
- * nm_device_activate_stage3_ip_config_start
- *
- * Begin automatic/manual IP configuration
- *
- */
-static gboolean
-nm_device_activate_stage3_ip_config_start (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *iface;
-	int ifindex;
-	NMDevice *master;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, 0);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface);
-	nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-
-	/* Make sure the interface is up before trying to do anything with it */
-	ifindex = nm_device_get_ip_ifindex (self);
-	if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
-		nm_system_iface_set_up (ifindex, TRUE, NULL);
-
-	priv->ip4_state = priv->ip6_state = IP_WAIT;
-
-	/* If the device is a slave, then we don't do any IP configuration but we
-	 * use the IP config stage to indicate to the master we're ready for
-	 * enslavement.  Either the master has already enslaved us, in which case
-	 * our state transition to SECONDARIES is already queued courtesy of
-	 * nm_device_slave_notify_enslaved(), or the master is still activating,
-	 * in which case we postpone activation here until the master enslaves us,
-	 * which calls nm_device_slave_notify_enslaved().
-	 */
-	master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request));
-	if (master) {
-		if (priv->enslaved == FALSE) {
-			nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on master '%s'",
-						 nm_device_get_iface (self),
-						 nm_connection_get_id (nm_device_get_connection (self)),
-						 nm_device_get_iface (master));
-		}
-		goto out;
-	}
-
-	/* IPv4 */
-	if (!nm_device_activate_stage3_ip4_start (self))
-		goto out;
-
-	/* IPv6 */
-	if (!nm_device_activate_stage3_ip6_start (self))
-		goto out;
-
-out:
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);
-	return FALSE;
-}
-
-
-static void
-fw_add_to_zone_cb (GError *error, gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	priv->fw_call = NULL;
-
-	if (error) {
-		/* FIXME: fail the device activation? */
-	}
-
-	activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0);
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.",
-	             nm_device_get_iface (self));
-}
-
-/*
- * nm_device_activate_schedule_stage3_ip_config_start
- *
- * Schedule IP configuration start
- */
-void
-nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-	NMConnection *connection;
-	NMSettingConnection *s_con = NULL;
-	NMDeviceState state;
-	const char *zone;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	state = nm_device_get_state (self);
-	if (nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request)) == FALSE)
-		g_warn_if_fail (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_NEED_AUTH);
-
-	/* Add the interface to the specified firewall zone */
-	connection = nm_device_get_connection (self);
-	g_assert (connection);
-	s_con = nm_connection_get_setting_connection (connection);
-
-	zone = nm_setting_connection_get_zone (s_con);
-	nm_log_dbg (LOGD_DEVICE, "Activation (%s) setting firewall zone '%s'",
-	            nm_device_get_iface (self), zone ? zone : "default");
-	priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_manager,
-	                                                        nm_device_get_ip_iface (self),
-	                                                        zone,
-	                                                        TRUE,
-	                                                        fw_add_to_zone_cb,
-	                                                        self);
-}
-
-static NMActStageReturn
-act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason)
-{
-	if (nm_device_ip_config_should_fail (self, FALSE)) {
-		*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-	return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-
-/*
- * nm_device_activate_stage4_ip4_config_timeout
- *
- * Time out on retrieving the IPv4 config.
- *
- */
-static gboolean
-nm_device_activate_ip4_config_timeout (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *iface;
-	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, AF_INET);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE | LOGD_IP4,
-	             "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) started...",
-	             iface);
-
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
-		goto out;
-	else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		goto out;
-	}
-	g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);	
-
-	priv->ip4_state = IP_DONE;
-
-	/* If IPv4 failed and IPv6 failed, the activation fails */
-	if ((priv->ip6_state == IP_DONE) && (priv->ip6_config == NULL)) {
-		nm_device_state_changed (self,
-				                 NM_DEVICE_STATE_FAILED,
-				                 NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-	}
-
-out:
-	nm_log_info (LOGD_DEVICE | LOGD_IP4,
-	             "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) complete.",
-	             iface);
-	return FALSE;
-}
-
-
-/*
- * nm_device_activate_schedule_ip4_config_timeout
- *
- * Deal with a timeout of the IPv4 configuration
- *
- */
-void
-nm_device_activate_schedule_ip4_config_timeout (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET);
-
-	nm_log_info (LOGD_DEVICE | LOGD_IP4,
-	             "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) scheduled...",
-	             nm_device_get_iface (self));
-}
-
-
-static NMActStageReturn
-act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason)
-{
-	if (nm_device_ip_config_should_fail (self, TRUE)) {
-		*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-
-/*
- * nm_device_activate_ip6_config_timeout
- *
- * Time out on retrieving the IPv6 config.
- *
- */
-static gboolean
-nm_device_activate_ip6_config_timeout (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *iface;
-	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, AF_INET6);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE | LOGD_IP6,
-	             "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) started...",
-	             iface);
-
-	ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason);
-	if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
-		goto out;
-	else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		goto out;
-	}
-	g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
-
-	priv->ip6_state = IP_DONE;
-
-	/* If IPv6 failed and IPv4 failed, the activation fails */
-	if ((priv->ip4_state == IP_DONE) && (priv->ip4_config == NULL)) {
-		nm_device_state_changed (self,
-				                 NM_DEVICE_STATE_FAILED,
-				                 NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-	}
-
-out:
-	nm_log_info (LOGD_DEVICE | LOGD_IP6,
-	             "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) complete.",
-	             iface);
-	return FALSE;
-}
-
-
-/*
- * nm_device_activate_schedule_ip6_config_timeout
- *
- * Deal with a timeout of the IPv6 configuration
- *
- */
-void
-nm_device_activate_schedule_ip6_config_timeout (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6);
-
-	nm_log_info (LOGD_DEVICE | LOGD_IP6,
-	             "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) scheduled...",
-	             nm_device_get_iface (self));
-}
-
-static void
-share_child_setup (gpointer user_data G_GNUC_UNUSED)
-{
-	/* We are in the child process at this point */
-	pid_t pid = getpid ();
-	setpgid (pid, pid);
-
-	nm_unblock_posix_signals (NULL);
-}
-
-static gboolean
-share_init (void)
-{
-	int status;
-	char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc",
-	                    "nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323",
-	                    NULL };
-	char **iter;
-
-	if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_forward", "1")) {
-		nm_log_err (LOGD_SHARING, "Error starting IP forwarding: (%d) %s",
-					errno, strerror (errno));
-		return FALSE;
-	}
-
-	if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_dynaddr", "1")) {
-		nm_log_err (LOGD_SHARING, "error starting IP forwarding: (%d) %s",
-					errno, strerror (errno));
-	}
-
-	for (iter = modules; *iter; iter++) {
-		char *argv[3] = { "/sbin/modprobe", *iter, NULL };
-		char *envp[1] = { NULL };
-		GError *error = NULL;
-
-		if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
-		                   share_child_setup, NULL, NULL, NULL, &status, &error)) {
-			nm_log_err (LOGD_SHARING, "error loading NAT module %s: (%d) %s",
-			            *iter, error ? error->code : 0,
-			            (error && error->message) ? error->message : "unknown");
-			if (error)
-				g_error_free (error);
-		}
-	}
-
-	return TRUE;
-}
-
-static void
-add_share_rule (NMActRequest *req, const char *table, const char *fmt, ...)
-{
-	va_list args;
-	char *cmd;
-
-	va_start (args, fmt);
-	cmd = g_strdup_vprintf (fmt, args);
-	va_end (args);
-
-	nm_act_request_add_share_rule (req, table, cmd);
-	g_free (cmd);
-}
-
-static gboolean
-start_sharing (NMDevice *self, NMIP4Config *config)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActRequest *req;
-	GError *error = NULL;
-	char str_addr[INET_ADDRSTRLEN + 1];
-	char str_mask[INET_ADDRSTRLEN + 1];
-	guint32 netmask, network;
-	NMIP4Address *ip4_addr;
-	const char *ip_iface;
-
-	g_return_val_if_fail (config != NULL, FALSE);
-
-	ip_iface = nm_device_get_ip_iface (self);
-
-	ip4_addr = nm_ip4_config_get_address (config, 0);
-	if (!ip4_addr || !nm_ip4_address_get_address (ip4_addr))
-		return FALSE;
-
-	netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (ip4_addr));
-	if (!inet_ntop (AF_INET, &netmask, str_mask, sizeof (str_mask)))
-		return FALSE;
-
-	network = nm_ip4_address_get_address (ip4_addr) & netmask;
-	if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr)))
-		return FALSE;
-
-	if (!share_init ())
-		return FALSE;
-
-	req = nm_device_get_act_request (self);
-	g_assert (req);
-
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface);
-	add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface);
-	add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface);
-	add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask);
-
-	nm_act_request_set_shared (req, TRUE);
-
-	if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) {
-		nm_log_err (LOGD_SHARING, "(%s/%s): failed to start dnsmasq: %s",
-		            nm_device_get_iface (self), ip_iface,
-		            (error && error->message) ? error->message : "(unknown)");
-		g_error_free (error);
-		nm_act_request_set_shared (req, FALSE);
-		return FALSE;
-	}
-
-	priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, "state-changed",
-	                                           G_CALLBACK (dnsmasq_state_changed_cb),
-	                                           self);
-	return TRUE;
-}
-
-static gboolean
-nm_device_activate_ip4_config_commit (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActRequest *req;
-	NMIP4Config *config = NULL;
-	const char *iface, *method = NULL;
-	NMConnection *connection;
-	NMSettingIP4Config *s_ip4;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	gboolean assumed;
-	int ifindex;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, AF_INET);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) started...",
-	             iface);
-
-	req = nm_device_get_act_request (self);
-	g_assert (req);
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
-
-	config = g_object_get_data (G_OBJECT (req), PENDING_IP4_CONFIG);
-	g_assert (config);
-
-	/* Make sure the interface is up again just because */
-	ifindex = nm_device_get_ip_ifindex (self);
-	if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
-		nm_system_iface_set_up (ifindex, TRUE, NULL);
-
-	/* Allow setting MTU etc */
-	if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
-		NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, config);
-
-	/* Merge with user overrides */
-	nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection));
-
-	assumed = nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request));
-	if (!nm_device_set_ip4_config (self, config, assumed, &reason)) {
-		nm_log_info (LOGD_DEVICE | LOGD_IP4,
-			         "Activation (%s) Stage 5 of 5 (IPv4 Commit) failed",
-					 iface);
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-		goto out;
-	}
-
-	/* Start IPv4 sharing if we need it */
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (s_ip4)
-		method = nm_setting_ip4_config_get_method (s_ip4);
-
-	if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
-		if (!start_sharing (self, config)) {
-			nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IPv4 Commit) start sharing failed.", iface);
-			nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
-			goto out;
-		}
-	}
-
-	/* Enter the SECONDARIES state if this is the first method to complete */
-	priv->ip4_state = IP_DONE;
-	if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
-		nm_device_state_changed (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
-
-out:
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) complete.",
-	             iface);
-
-	/* Balance IP config creation; nm_device_set_ip4_config() takes a reference */
-	g_object_set_data (G_OBJECT (req), PENDING_IP4_CONFIG, NULL);
-
-	return FALSE;
-}
-
-void
-nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	if (config == NULL) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-		return;
-	}
-
-	g_object_set_data_full (G_OBJECT (priv->act_request),
-	                        PENDING_IP4_CONFIG,
-	                        g_object_ref (config),
-	                        g_object_unref);
-
-	activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET);
-
-	nm_log_info (LOGD_DEVICE | LOGD_IP4,
-		         "Activation (%s) Stage 5 of 5 (IPv4 Configure Commit) scheduled...",
-		         nm_device_get_iface (self));
-}
-
-gboolean
-nm_device_activate_ip4_state_in_conf (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_CONF;
-}
-
-gboolean
-nm_device_activate_ip4_state_in_wait (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT;
-}
-
-static gboolean
-nm_device_activate_ip6_config_commit (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActRequest *req;
-	NMIP6Config *config = NULL;
-	const char *iface;
-	NMConnection *connection;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	int ifindex;
-
-	/* Clear the activation source ID now that this stage has run */
-	activation_source_clear (self, FALSE, AF_INET6);
-
-	iface = nm_device_get_iface (self);
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...",
-	             iface);
-
-	req = nm_device_get_act_request (self);
-	g_assert (req);
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
-
-	config = g_object_get_data (G_OBJECT (req), PENDING_IP6_CONFIG);
-	g_assert (config);
-
-	/* Make sure the interface is up again just because */
-	ifindex = nm_device_get_ip_ifindex (self);
-	if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
-		nm_system_iface_set_up (ifindex, TRUE, NULL);
-
-	/* Allow setting MTU etc */
-	if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit)
-		NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, config);
-
-	if (ip6_config_merge_and_apply (self, config, &reason)) {
-		/* Enter the SECONDARIES state if this is the first method to complete */
-		priv->ip6_state = IP_DONE;
-		if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
-			nm_device_state_changed (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
-	} else {
-		nm_log_info (LOGD_DEVICE | LOGD_IP6,
-			         "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed",
-					 iface);
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
-	}
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.",
-	             iface);
-
-	/* Balance IP config creation; nm_device_set_ip6_config() takes a reference */
-	g_object_set_data (G_OBJECT (req), PENDING_IP6_CONFIG, NULL);
-
-	return FALSE;
-}
-
-void
-nm_device_activate_schedule_ip6_config_result (NMDevice *self, NMIP6Config *config)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->act_request);
-
-	if (config == NULL) {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-		return;
-	}
-
-	/* Save the pending config */
-	g_object_set_data_full (G_OBJECT (priv->act_request),
-	                        PENDING_IP6_CONFIG,
-	                        g_object_ref (config),
-	                        g_object_unref);
-
-	activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6);
-
-	nm_log_info (LOGD_DEVICE | LOGD_IP4,
-		         "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...",
-		         nm_device_get_iface (self));
-}
-
-gboolean
-nm_device_activate_ip6_state_in_conf (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_CONF;
-}
-
-gboolean
-nm_device_activate_ip6_state_in_wait (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, FALSE);
-	return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT;
-}
-
-static void
-clear_act_request (NMDevice *self)
-{
-	NMDevicePrivate * priv;
-
-	g_return_if_fail (self != NULL);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (!priv->act_request)
-		return;
-
-	if (priv->secrets_updated_id) {
-		g_signal_handler_disconnect (priv->act_request,
-		                             priv->secrets_updated_id);
-		priv->secrets_updated_id = 0;
-	}
-
-	if (priv->secrets_failed_id) {
-		g_signal_handler_disconnect (priv->act_request,
-		                             priv->secrets_failed_id);
-		priv->secrets_failed_id = 0;
-	}
-
-	nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
-
-	g_clear_object (&priv->act_request);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
-}
-
-static void
-dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->dhcp4_config) {
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
-		g_object_unref (priv->dhcp4_config);
-		priv->dhcp4_config = NULL;
-	}
-
-	if (priv->dhcp4_client) {
-		/* Stop any ongoing DHCP transaction on this device */
-		if (priv->dhcp4_state_sigid) {
-			g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_state_sigid);
-			priv->dhcp4_state_sigid = 0;
-		}
-
-		if (priv->dhcp4_timeout_sigid) {
-			g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_timeout_sigid);
-			priv->dhcp4_timeout_sigid = 0;
-		}
-
-		if (stop)
-			nm_dhcp_client_stop (priv->dhcp4_client, release);
-
-		g_object_unref (priv->dhcp4_client);
-		priv->dhcp4_client = NULL;
-	}
-}
-
-static void
-dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
-
-	if (priv->dhcp6_ip6_config) {
-		g_object_unref (priv->dhcp6_ip6_config);
-		priv->dhcp6_ip6_config = NULL;
-	}
-
-	if (priv->dhcp6_config) {
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
-		g_object_unref (priv->dhcp6_config);
-		priv->dhcp6_config = NULL;
-	}
-
-	if (priv->dhcp6_client) {
-		if (priv->dhcp6_state_sigid) {
-			g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_state_sigid);
-			priv->dhcp6_state_sigid = 0;
-		}
-
-		if (priv->dhcp6_timeout_sigid) {
-			g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_timeout_sigid);
-			priv->dhcp6_timeout_sigid = 0;
-		}
-
-		if (stop)
-			nm_dhcp_client_stop (priv->dhcp6_client, release);
-
-		g_object_unref (priv->dhcp6_client);
-		priv->dhcp6_client = NULL;
-	}
-}
-
-static void
-dnsmasq_cleanup (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (!priv->dnsmasq_manager)
-		return;
-
-	if (priv->dnsmasq_state_id) {
-		g_signal_handler_disconnect (priv->dnsmasq_manager, priv->dnsmasq_state_id);
-		priv->dnsmasq_state_id = 0;
-	}
-
-	nm_dnsmasq_manager_stop (priv->dnsmasq_manager);
-	g_object_unref (priv->dnsmasq_manager);
-	priv->dnsmasq_manager = NULL;
-}
-
-static void
-_update_ip4_address (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	struct ifreq req;
-	guint32 new_address;
-	int fd;
-
-	g_return_if_fail (self  != NULL);
-
-	fd = socket (PF_INET, SOCK_DGRAM, 0);
-	if (fd < 0) {
-		nm_log_err (LOGD_IP4, "couldn't open control socket.");
-		return;
-	}
-
-	memset (&req, 0, sizeof (struct ifreq));
-	strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ);
-	if (ioctl (fd, SIOCGIFADDR, &req) == 0) {
-		new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr;
-		if (new_address != priv->ip4_address)
-			priv->ip4_address = new_address;
-	}
-	close (fd);
-}
-
-/*
- * nm_device_deactivate
- *
- * Remove a device's routing table entries and IP address.
- *
- */
-static void
-nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
-{
-	NMDevicePrivate *priv;
-	NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
-	NMConnection *connection = NULL;
-	NMSettingConnection *s_con = NULL;
-	gboolean tried_ipv6 = FALSE;
-	int ifindex, family;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason '%s') [%d]",
-	             nm_device_get_iface (self), reason_to_string (reason), reason);
-
-	/* Save whether or not we tried IPv6 for later */
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	if (priv->ip6_manager || priv->ip6_config)
-		tried_ipv6 = TRUE;
-
-	/* Clean up when device was deactivated during call to firewall */
-	if (priv->fw_call) {
-		nm_firewall_manager_cancel_call (priv->fw_manager, priv->fw_call);
-		priv->fw_call = NULL;
-	}
-
-	if (priv->act_request)
-		connection = nm_act_request_get_connection (priv->act_request);
-	if (connection) {
-		s_con = nm_connection_get_setting_connection (connection);
-		nm_firewall_manager_remove_from_zone (priv->fw_manager,
-		                                      nm_device_get_ip_iface (self),
-		                                      nm_setting_connection_get_zone (s_con));
-	}
-
-	/* Break the activation chain */
-	activation_source_clear (self, TRUE, AF_INET);
-	activation_source_clear (self, TRUE, AF_INET6);
-
-	/* Clear any queued transitions */
-	nm_device_queued_state_clear (self);
-
-	priv->ip4_state = priv->ip6_state = IP_NONE;
-
-	dhcp4_cleanup (self, TRUE, FALSE);
-	dhcp6_cleanup (self, TRUE, FALSE);
-	addrconf6_cleanup (self);
-	dnsmasq_cleanup (self);
-	aipd_cleanup (self);
-
-	/* Turn off router advertisements until they are needed */
-	if (priv->ip6_accept_ra_path)
-		nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0");
-
-	/* Turn off IPv6 privacy extensions */
-	if (priv->ip6_privacy_tempaddr_path)
-		nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, "0");
-
-	/* Call device type-specific deactivation */
-	if (NM_DEVICE_GET_CLASS (self)->deactivate)
-		NM_DEVICE_GET_CLASS (self)->deactivate (self);
-
-	/* master: release slaves */
-	nm_device_master_release_slaves (self, FALSE);
-
-	/* slave: mark no longer enslaved */
-	g_clear_object (&priv->master);
-	priv->enslaved = FALSE;
-
-	/* Tear down an existing activation request */
-	clear_act_request (self);
-
-	/* Take out any entries in the routing table and any IP address the device had. */
-	ifindex = nm_device_get_ip_ifindex (self);
-	family = tried_ipv6 ? AF_UNSPEC : AF_INET;
-	if (ifindex > 0) {
-		nm_system_iface_flush_routes (ifindex, family);
-		nm_system_iface_flush_addresses (ifindex, family);
-	}
-
-	/* Clean up nameservers and addresses */
-	nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
-	nm_device_set_ip6_config (self, NULL, &ignored);
-
-	/* Clear legacy IPv4 address property */
-	priv->ip4_address = 0;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS);
-
-	/* Only clear ip_iface after flushing all routes and addreses, since
-	 * those are identified by ip_iface, not by iface (which might be a tty
-	 * or ATM device).
-	 */
-	nm_device_set_ip_iface (self, NULL);
-}
-
-static void
-disconnect_cb (NMDevice *device,
-               DBusGMethodInvocation *context,
-               GError *error,
-               gpointer user_data)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	GError *local = NULL;
-
-	if (error)
-		dbus_g_method_return_error (context, error);
-	else {
-		/* Authorized */
-		if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) {
-			local = g_error_new_literal (NM_DEVICE_ERROR,
-			                             NM_DEVICE_ERROR_NOT_ACTIVE,
-			                             "Device is not active");
-			dbus_g_method_return_error (context, local);
-			g_error_free (local);
-		} else {
-			priv->autoconnect = FALSE;
-			nm_device_state_changed (device,
-			                         NM_DEVICE_STATE_DISCONNECTED,
-			                         NM_DEVICE_STATE_REASON_USER_REQUESTED);
-			dbus_g_method_return (context);
-		}
-	}
-}
-
-static void
-impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context)
-{
-	NMConnection *connection;
-	GError *error = NULL;
-
-	if (NM_DEVICE_GET_PRIVATE (device)->act_request == NULL) {
-		error = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ACTIVE,
-		                             "This device is not active");
-		dbus_g_method_return_error (context, error);
-		g_error_free (error);
-		return;
-	}
-
-	connection = nm_device_get_connection (device);
-	g_assert (connection);
-
-	/* Ask the manager to authenticate this request for us */
-	g_signal_emit (device, signals[AUTH_REQUEST], 0,
-	               context,
-	               connection,
-	               NM_AUTH_PERMISSION_NETWORK_CONTROL,
-	               TRUE,
-	               disconnect_cb,
-	               NULL);
-}
-
-void
-nm_device_activate (NMDevice *self, NMActRequest *req)
-{
-	NMDevicePrivate *priv;
-	NMConnection *connection;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-	g_return_if_fail (req != NULL);
-	g_return_if_fail (NM_IS_ACT_REQUEST (req));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
-
-	nm_log_info (LOGD_DEVICE, "Activation (%s) starting connection '%s'",
-	             nm_device_get_iface (self),
-	             nm_connection_get_id (connection));
-
-	g_warn_if_fail (priv->state == NM_DEVICE_STATE_DISCONNECTED);
-
-	priv->act_request = g_object_ref (req);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
-
-	if (nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (req))) {
-		/* If it's an assumed connection, let the device subclass short-circuit
-		 * the normal connection process and just copy its IP configs from the
-		 * interface.
-		 */
-		nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-		nm_device_activate_schedule_stage3_ip_config_start (self);
-	} else {
-		NMDevice *master;
-
-		/* HACK: update the state a bit early to avoid a race between the 
-		 * scheduled stage1 handler and nm_policy_device_change_check() thinking
-		 * that the activation request isn't deferred because the deferred bit
-		 * gets cleared a bit too early, when the connection becomes valid.
-		 */
-		nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
-
-		/* Handle any dependencies this connection might have */
-		master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (req));
-		if (master) {
-			/* Master should at least already be activating */
-			g_assert (nm_device_get_state (master) > NM_DEVICE_STATE_DISCONNECTED);
-
-			g_assert (priv->master == NULL);
-			priv->master = g_object_ref (master);
-			nm_device_master_add_slave (master, self);
-		}
-
-		nm_device_activate_schedule_stage1_device_prepare (self);
-	}
-}
-
-/*
- * nm_device_is_activating
- *
- * Return whether or not the device is currently activating itself.
- *
- */
-gboolean
-nm_device_is_activating (NMDevice *device)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMDeviceState state;
-
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-
-	state = nm_device_get_state (device);
-	if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
-		return TRUE;
-
-	/* There's a small race between the time when stage 1 is scheduled
-	 * and when the device actually sets STATE_PREPARE when the activation
-	 * handler is actually run.  If there's an activation handler scheduled
-	 * we're activating anyway.
-	 */
-	return priv->act_source_id ? TRUE : FALSE;
-}
-
-
-gboolean
-nm_device_can_interrupt_activation (NMDevice *self)
-{
-	gboolean	interrupt = FALSE;
-
-	g_return_val_if_fail (self != NULL, FALSE);
-
-	if (NM_DEVICE_GET_CLASS (self)->can_interrupt_activation)
-		interrupt = NM_DEVICE_GET_CLASS (self)->can_interrupt_activation (self);
-	return interrupt;
-}
-
-/* IP Configuration stuff */
-
-NMDHCP4Config *
-nm_device_get_dhcp4_config (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config;
-}
-
-NMIP4Config *
-nm_device_get_ip4_config (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->ip4_config;
-}
-
-
-static gboolean
-nm_device_set_ip4_config (NMDevice *self,
-                          NMIP4Config *new_config,
-                          gboolean assumed,
-                          NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv;
-	const char *ip_iface;
-	NMIP4Config *old_config = NULL;
-	gboolean success = TRUE;
-	NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL;
-	int ip_ifindex;
-
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-	g_return_val_if_fail (reason != NULL, FALSE);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
-	ip_ifindex = nm_device_get_ip_ifindex (self);
-
-	old_config = priv->ip4_config;
-
-	if (new_config && old_config) {
-		diff = nm_ip4_config_diff (new_config, old_config);
-		if (diff == NM_IP4_COMPARE_FLAG_NONE)
-			return TRUE;  /* no actual change */
-	} else if (!new_config && !old_config)
-		return TRUE;
-
-	priv->ip4_config = NULL;
-
-	if (new_config) {
-		priv->ip4_config = g_object_ref (new_config);
-
-		/* Don't touch the device's actual IP config if the connection is
-		 * assumed when NM starts.
-		 */
-		if (!assumed)
-			success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self), diff);
-
-		if (success || assumed) {
-			/* Export over D-Bus */
-			if (!nm_ip4_config_get_dbus_path (new_config))
-				nm_ip4_config_export (new_config);
-			_update_ip4_address (self);
-		}
-
-		if (!success && reason)
-			*reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
-	}
-
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
-	g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
-
-	if (old_config)
-		g_object_unref (old_config);
-
-	return success;
-}
-
-static gboolean
-nm_device_set_ip6_config (NMDevice *self,
-                          NMIP6Config *new_config,
-                          NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv;
-	const char *ip_iface;
-	NMIP6Config *old_config = NULL;
-	gboolean success = TRUE;
-	NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL;
-	int ip_ifindex;
-
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-	g_return_val_if_fail (reason != NULL, FALSE);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
-	ip_ifindex = nm_device_get_ip_ifindex (self);
-
-	old_config = priv->ip6_config;
-
-	if (new_config && old_config) {
-		diff = nm_ip6_config_diff (new_config, old_config);
-		if (diff == NM_IP6_COMPARE_FLAG_NONE)
-			return TRUE;  /* no actual change */
-	} else if (!new_config && !old_config)
-		return TRUE;
-
-	priv->ip6_config = NULL;
-
-	if (new_config) {
-		priv->ip6_config = g_object_ref (new_config);
-
-		success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff);
-
-		if (success) {
-			/* Export over D-Bus */
-			if (!nm_ip6_config_get_dbus_path (new_config))
-				nm_ip6_config_export (new_config);
-		}
-
-		if (!success && reason)
-			*reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
-	}
-
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
-	g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
-
-	if (old_config)
-		g_object_unref (old_config);
-
-	return success;
-}
-
-NMDHCP6Config *
-nm_device_get_dhcp6_config (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->dhcp6_config;
-}
-
-NMIP6Config *
-nm_device_get_ip6_config (NMDevice *self)
-{
-	g_return_val_if_fail (self != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
-
-	return NM_DEVICE_GET_PRIVATE (self)->ip6_config;
-}
-
-static gboolean
-nm_device_is_up (NMDevice *self)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	if (NM_DEVICE_GET_CLASS (self)->is_up)
-		return NM_DEVICE_GET_CLASS (self)->is_up (self);
-
-	return TRUE;
-}
-
-gboolean
-nm_device_hw_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
-{
-	gboolean success;
-	guint32 tries = 0;
-
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	if (nm_device_hw_is_up (self))
-		goto out;
-
-	nm_log_info (LOGD_HW, "(%s): bringing up device.", nm_device_get_iface (self));
-
-	if (NM_DEVICE_GET_CLASS (self)->hw_bring_up) {
-		success = NM_DEVICE_GET_CLASS (self)->hw_bring_up (self, no_firmware);
-		if (!success)
-			return FALSE;
-	}
-
-	/* Wait for the device to come up if requested */
-	while (block && !nm_device_hw_is_up (self) && (tries++ < 50))
-		g_usleep (200);
-
-	if (!nm_device_hw_is_up (self)) {
-		nm_log_warn (LOGD_HW, "(%s): device not up after timeout!", nm_device_get_iface (self));
-		return FALSE;
-	}
-
-out:
-	/* Can only get HW address of some devices when they are up */
-	if (NM_DEVICE_GET_CLASS (self)->update_hw_address)
-		NM_DEVICE_GET_CLASS (self)->update_hw_address (self);
-
-	_update_ip4_address (self);
-	return TRUE;
-}
-
-static gboolean
-hw_bring_up (NMDevice *device, gboolean *no_firmware)
-{
-	int ifindex = nm_device_get_ip_ifindex (device);
-
-	return ifindex > 0 ? nm_system_iface_set_up (ifindex, TRUE, no_firmware) : TRUE;
-}
-
-void
-nm_device_hw_take_down (NMDevice *self, gboolean block)
-{
-	guint32 tries = 0;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	if (!nm_device_hw_is_up (self))
-		return;
-
-	nm_log_info (LOGD_HW, "(%s): taking down device.", nm_device_get_iface (self));
-
-	if (NM_DEVICE_GET_CLASS (self)->hw_take_down)
-		NM_DEVICE_GET_CLASS (self)->hw_take_down (self);
-
-	/* Wait for the device to come up if requested */
-	while (block && nm_device_hw_is_up (self) && (tries++ < 50))
-		g_usleep (200);
-}
-
-static void
-hw_take_down (NMDevice *device)
-{
-	int ifindex = nm_device_get_ip_ifindex (device);
-
-	if (ifindex > 0)
-		nm_system_iface_set_up (ifindex, FALSE, NULL);
-}
-
-static gboolean
-nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
-{
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
-
-	if (!nm_device_hw_bring_up (self, block, no_firmware))
-		return FALSE;
-
-	if (nm_device_is_up (self))
-		return TRUE;
-
-	nm_log_info (LOGD_HW, "(%s): preparing device.", nm_device_get_iface (self));
-
-	if (NM_DEVICE_GET_CLASS (self)->bring_up)
-		success = NM_DEVICE_GET_CLASS (self)->bring_up (self);
-
-	return success;
-}
-
-static void
-nm_device_take_down (NMDevice *self, gboolean block, NMDeviceStateReason reason)
-{
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	if (nm_device_get_act_request (self))
-		nm_device_deactivate (self, reason);
-
-	if (nm_device_is_up (self)) {
-		nm_log_info (LOGD_HW, "(%s): cleaning up...", nm_device_get_iface (self));
-
-		if (NM_DEVICE_GET_CLASS (self)->take_down)
-			NM_DEVICE_GET_CLASS (self)->take_down (self);
-	}
-
-	nm_device_hw_take_down (self, block);
-}
-
-static void
-dispose (GObject *object)
-{
-	NMDevice *self = NM_DEVICE (object);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	gboolean take_down = TRUE;
-
-	if (priv->disposed || !priv->initialized)
-		goto out;
-
-	priv->disposed = TRUE;
-
-	/* Don't down can-assume-connection capable devices that are activated with
-	 * a connection that can be assumed.
-	 */
-	if (nm_device_can_assume_connections (self) && (priv->state == NM_DEVICE_STATE_ACTIVATED)) {
-		NMConnection *connection;
-	    NMSettingIP4Config *s_ip4 = NULL;
-		const char *method = NULL;
-
-		connection = nm_device_get_connection (self);
-		if (connection) {
-			/* Only static or DHCP IPv4 connections can be left up.
-			 * All IPv6 connections can be left up, so we don't have
-			 * to check that.
-			 */
-			s_ip4 = nm_connection_get_setting_ip4_config (connection);
-			if (s_ip4)
-				method = nm_setting_ip4_config_get_method (s_ip4);
-			if (   !method
-			    || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)
-			    || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)
-			    || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
-				take_down = FALSE;
-		}
-	}
-
-	/* Clear any queued transitions */
-	nm_device_queued_state_clear (self);
-
-	/* Clean up and stop DHCP */
-	dhcp4_cleanup (self, take_down, FALSE);
-	dhcp6_cleanup (self, take_down, FALSE);
-	addrconf6_cleanup (self);
-	dnsmasq_cleanup (self);
-
-	g_warn_if_fail (priv->slaves == NULL);
-
-	/* Take the device itself down and clear its IPv4 configuration */
-	if (priv->managed && take_down) {
-		NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
-
-		nm_device_take_down (self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
-		nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
-	}
-
-	/* reset the saved RA value */
-	if (   priv->ip6_accept_ra_path
-	    && g_file_test (priv->ip6_accept_ra_path, G_FILE_TEST_EXISTS)) {
-		nm_utils_do_sysctl (priv->ip6_accept_ra_path,
-		                    priv->ip6_accept_ra_save ? "1" : "0");
-	}
-	g_free (priv->ip6_accept_ra_path);
-
-	/* reset the saved use_tempaddr value */
-	if (   priv->ip6_privacy_tempaddr_path
-	    && g_file_test (priv->ip6_privacy_tempaddr_path, G_FILE_TEST_EXISTS)) {
-		char tmp[16];
-
-		snprintf (tmp, sizeof (tmp), "%d", priv->ip6_privacy_tempaddr_save);
-		nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, tmp);
-	}
-	g_free (priv->ip6_privacy_tempaddr_path);
-
-	if (priv->cp_added_id) {
-	    g_signal_handler_disconnect (priv->con_provider, priv->cp_added_id);
-	    priv->cp_added_id = 0;
-	}
-
-	if (priv->cp_loaded_id) {
-	    g_signal_handler_disconnect (priv->con_provider, priv->cp_loaded_id);
-	    priv->cp_loaded_id = 0;
-	}
-
-	if (priv->cp_removed_id) {
-	    g_signal_handler_disconnect (priv->con_provider, priv->cp_removed_id);
-	    priv->cp_removed_id = 0;
-	}
-
-	if (priv->cp_updated_id) {
-	    g_signal_handler_disconnect (priv->con_provider, priv->cp_updated_id);
-	    priv->cp_updated_id = 0;
-	}
-
-	g_hash_table_unref (priv->available_connections);
-
-	activation_source_clear (self, TRUE, AF_INET);
-	activation_source_clear (self, TRUE, AF_INET6);
-
-	clear_act_request (self);
-
-out:
-	G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
-	NMDevice *self = NM_DEVICE (object);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->dhcp_manager)
-		g_object_unref (priv->dhcp_manager);
-
-	if (priv->fw_manager)
-		g_object_unref (priv->fw_manager);
-
-	g_free (priv->udi);
-	g_free (priv->path);
-	g_free (priv->iface);
-	g_free (priv->ip_iface);
-	g_free (priv->driver);
-	g_free (priv->driver_version);
-	g_free (priv->firmware_version);
-	g_free (priv->type_desc);
-	if (priv->dhcp_anycast_address)
-		g_byte_array_free (priv->dhcp_anycast_address, TRUE);
-
-	G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
-}
-
-
-static void
-set_property (GObject *object, guint prop_id,
-			  const GValue *value, GParamSpec *pspec)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
- 
-	switch (prop_id) {
-	case PROP_UDI:
-		/* Only virtual interfaces can set UDI post-construction */
-		if (priv->initialized)
-			g_return_if_fail (nm_system_get_iface_type (priv->ifindex, NULL) != NM_IFACE_TYPE_UNSPEC);
-
-		g_free (priv->udi);
-		priv->udi = g_strdup (g_value_get_string (value));
-		break;
-	case PROP_IFACE:
-		g_free (priv->iface);
-		priv->ifindex = 0;
-		priv->iface = g_value_dup_string (value);
-
-		/* Only look up the ifindex if it appears to be an actual kernel
-		 * interface name.  eg Bluetooth devices won't have one until we know
-		 * the IP interface.
-		 */
-		if (priv->iface && !strchr (priv->iface, ':')) {
-			priv->ifindex = nm_netlink_iface_to_index (priv->iface);
-			if (priv->ifindex <= 0)
-				nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface);
-		}
-		break;
-	case PROP_IP_IFACE:
-		break;
-	case PROP_DRIVER:
-		g_free (priv->driver);
-		priv->driver = g_strdup (g_value_get_string (value));
-		break;
-	case PROP_DRIVER_VERSION:
-		g_free (priv->driver_version);
-		priv->driver_version = g_strdup (g_value_get_string (value));
-		break;
-	case PROP_FIRMWARE_VERSION:
-		g_free (priv->firmware_version);
-		priv->firmware_version = g_strdup (g_value_get_string (value));
-		break;
-	case PROP_CAPABILITIES:
-		priv->capabilities = g_value_get_uint (value);
-		break;
-	case PROP_IP4_ADDRESS:
-		priv->ip4_address = g_value_get_uint (value);
-		break;
-	case PROP_MANAGED:
-		priv->managed = g_value_get_boolean (value);
-		break;
-	case PROP_AUTOCONNECT:
-		priv->autoconnect = g_value_get_boolean (value);
-		break;
-	case PROP_FIRMWARE_MISSING:
-		priv->firmware_missing = g_value_get_boolean (value);
-		break;
-	case PROP_DEVICE_TYPE:
-		g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN);
-		priv->type = g_value_get_uint (value);
-		break;
-	case PROP_TYPE_DESC:
-		g_free (priv->type_desc);
-		priv->type_desc = g_value_dup_string (value);
-		break;
-	case PROP_RFKILL_TYPE:
-		priv->rfkill_type = g_value_get_uint (value);
-		break;
-	case PROP_IS_MASTER:
-		priv->is_master = g_value_get_boolean (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static gboolean
-_is_connected (NMDeviceState state)
-{
-	return (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING);
-}
-
-static void
-get_property (GObject *object, guint prop_id,
-			  GValue *value, GParamSpec *pspec)
-{
-	NMDevice *self = NM_DEVICE (object);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMDeviceState state;
-	const char *ac_path = NULL;
-	GPtrArray *array;
-	GHashTableIter iter;
-	NMConnection *connection;
-
-	state = nm_device_get_state (self);
-
-	switch (prop_id) {
-	case PROP_UDI:
-		g_value_set_string (value, priv->udi);
-		break;
-	case PROP_IFACE:
-		g_value_set_string (value, priv->iface);
-		break;
-	case PROP_IP_IFACE:
-		if (_is_connected (state))
-			g_value_set_string (value, nm_device_get_ip_iface (self));
-		else
-			g_value_set_string (value, NULL);
-		break;
-	case PROP_IFINDEX:
-		g_value_set_int (value, priv->ifindex);
-		break;
-	case PROP_DRIVER:
-		g_value_set_string (value, priv->driver);
-		break;
-	case PROP_DRIVER_VERSION:
-		g_value_set_string (value, priv->driver_version);
-		break;
-	case PROP_FIRMWARE_VERSION:
-		g_value_set_string (value, priv->firmware_version);
-		break;
-	case PROP_CAPABILITIES:
-		g_value_set_uint (value, priv->capabilities);
-		break;
-	case PROP_IP4_ADDRESS:
-		g_value_set_uint (value, priv->ip4_address);
-		break;
-	case PROP_IP4_CONFIG:
-		if (_is_connected (state) && priv->ip4_config)
-			g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config));
-		else
-			g_value_set_boxed (value, "/");
-		break;
-	case PROP_DHCP4_CONFIG:
-		if (_is_connected (state) && priv->dhcp4_client)
-			g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config));
-		else
-			g_value_set_boxed (value, "/");
-		break;
-	case PROP_IP6_CONFIG:
-		if (_is_connected (state) && priv->ip6_config)
-			g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config));
-		else
-			g_value_set_boxed (value, "/");
-		break;
-	case PROP_DHCP6_CONFIG:
-		if (_is_connected (state) && priv->dhcp6_client)
-			g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config));
-		else
-			g_value_set_boxed (value, "/");
-		break;
-	case PROP_STATE:
-		g_value_set_uint (value, priv->state);
-		break;
-	case PROP_STATE_REASON:
-		g_value_take_boxed (value, dbus_g_type_specialized_construct (DBUS_G_TYPE_UINT_STRUCT));
-		dbus_g_type_struct_set (value,
-		                        0, priv->state,
-		                        1, priv->state_reason,
-		                        G_MAXUINT);
-		break;
-	case PROP_ACTIVE_CONNECTION:
-		if (priv->act_request)
-			ac_path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (priv->act_request));
-		g_value_set_boxed (value, ac_path ? ac_path : "/");
-		break;
-	case PROP_DEVICE_TYPE:
-		g_value_set_uint (value, priv->type);
-		break;
-	case PROP_MANAGED:
-		g_value_set_boolean (value, priv->managed);
-		break;
-	case PROP_AUTOCONNECT:
-		g_value_set_boolean (value, priv->autoconnect);
-		break;
-	case PROP_FIRMWARE_MISSING:
-		g_value_set_boolean (value, priv->firmware_missing);
-		break;
-	case PROP_TYPE_DESC:
-		g_value_set_string (value, priv->type_desc);
-		break;
-	case PROP_RFKILL_TYPE:
-		g_value_set_uint (value, priv->rfkill_type);
-		break;
-	case PROP_AVAILABLE_CONNECTIONS:
-		array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections));
-		g_hash_table_iter_init (&iter, priv->available_connections);
-		while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL))
-			g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection)));
-		g_value_take_boxed (value, array);
-		break;
-	case PROP_IS_MASTER:
-		g_value_set_boolean (value, priv->is_master);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-
-static void
-nm_device_class_init (NMDeviceClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	g_type_class_add_private (object_class, sizeof (NMDevicePrivate));
-
-	/* Virtual methods */
-	object_class->dispose = dispose;
-	object_class->finalize = finalize;
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-	object_class->constructor = constructor;
-	object_class->constructed = constructed;
-
-	klass->get_type_capabilities = get_type_capabilities;
-	klass->get_generic_capabilities = get_generic_capabilities;
-	klass->act_stage1_prepare = act_stage1_prepare;
-	klass->act_stage2_config = act_stage2_config;
-	klass->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
-	klass->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
-	klass->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
-	klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
-	klass->have_any_ready_slaves = have_any_ready_slaves;
-
-	klass->check_connection_available = check_connection_available;
-	klass->hw_is_up = hw_is_up;
-	klass->hw_bring_up = hw_bring_up;
-	klass->hw_take_down = hw_take_down;
-
-	/* Properties */
-	g_object_class_install_property
-		(object_class, PROP_UDI,
-		 g_param_spec_string (NM_DEVICE_UDI,
-		                      "UDI",
-		                      "Unique Device Identifier",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-	g_object_class_install_property
-		(object_class, PROP_IFACE,
-		 g_param_spec_string (NM_DEVICE_IFACE,
-		                      "Interface",
-		                      "Interface",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_IP_IFACE,
-		 g_param_spec_string (NM_DEVICE_IP_IFACE,
-		                      "IP Interface",
-		                      "IP Interface",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_DRIVER,
-		 g_param_spec_string (NM_DEVICE_DRIVER,
-		                      "Driver",
-		                      "Driver",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_DRIVER_VERSION,
-		 g_param_spec_string (NM_DEVICE_DRIVER_VERSION,
-		                      "Driver Version",
-		                      "Driver Version",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_FIRMWARE_VERSION,
-		 g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION,
-		                      "Firmware Version",
-		                      "Firmware Version",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_CAPABILITIES,
-		 g_param_spec_uint (NM_DEVICE_CAPABILITIES,
-		                    "Capabilities",
-		                    "Capabilities",
-		                    0, G_MAXUINT32, NM_DEVICE_CAP_NONE,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_IP4_ADDRESS,
-		 g_param_spec_uint (NM_DEVICE_IP4_ADDRESS,
-		                    "IP4 address",
-		                    "IP4 address",
-		                    0, G_MAXUINT32, 0, /* FIXME */
-		                    G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_IP4_CONFIG,
-		 g_param_spec_boxed (NM_DEVICE_IP4_CONFIG,
-		                     "IP4 Config",
-		                     "IP4 Config",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_DHCP4_CONFIG,
-		 g_param_spec_boxed (NM_DEVICE_DHCP4_CONFIG,
-		                     "DHCP4 Config",
-		                     "DHCP4 Config",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_IP6_CONFIG,
-		 g_param_spec_boxed (NM_DEVICE_IP6_CONFIG,
-		                     "IP6 Config",
-		                     "IP6 Config",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_DHCP6_CONFIG,
-		 g_param_spec_boxed (NM_DEVICE_DHCP6_CONFIG,
-		                     "DHCP6 Config",
-		                     "DHCP6 Config",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_STATE,
-		 g_param_spec_uint (NM_DEVICE_STATE,
-		                    "State",
-		                    "State",
-		                    0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN,
-		                    G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_STATE_REASON,
-		 g_param_spec_boxed (NM_DEVICE_STATE_REASON,
-		                     "StateReason",
-		                     "StateReason",
-		                     DBUS_G_TYPE_UINT_STRUCT,
-		                     G_PARAM_READABLE));
-
-	g_object_class_install_property
-		(object_class, PROP_ACTIVE_CONNECTION,
-		 g_param_spec_boxed (NM_DEVICE_ACTIVE_CONNECTION,
-		                     "ActiveConnection",
-		                     "ActiveConnection",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READABLE));
-
-	g_object_class_install_property
-		(object_class, PROP_DEVICE_TYPE,
-		 g_param_spec_uint (NM_DEVICE_DEVICE_TYPE,
-		                    "DeviceType",
-		                    "DeviceType",
-		                    0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
-
-	g_object_class_install_property
-		(object_class, PROP_MANAGED,
-		 g_param_spec_boolean (NM_DEVICE_MANAGED,
-		                       "Managed",
-		                       "Managed",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_AUTOCONNECT,
-		 g_param_spec_boolean (NM_DEVICE_AUTOCONNECT,
-		                       "Autoconnect",
-		                       "Autoconnect",
-		                       DEFAULT_AUTOCONNECT,
-		                       G_PARAM_READWRITE));
-
-	g_object_class_install_property
-		(object_class, PROP_FIRMWARE_MISSING,
-		 g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING,
-		                       "FirmwareMissing",
-		                       "Firmware missing",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property
-		(object_class, PROP_TYPE_DESC,
-		 g_param_spec_string (NM_DEVICE_TYPE_DESC,
-		                      "Type Description",
-		                      "Device type description",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
-
-	g_object_class_install_property
-		(object_class, PROP_RFKILL_TYPE,
-		 g_param_spec_uint (NM_DEVICE_RFKILL_TYPE,
-		                    "Rfkill Type",
-		                    "Type of rfkill switch (if any) supported by this device",
-		                    RFKILL_TYPE_WLAN,
-		                    RFKILL_TYPE_MAX,
-		                    RFKILL_TYPE_UNKNOWN,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
-
-	g_object_class_install_property
-		(object_class, PROP_IFINDEX,
-		 g_param_spec_int (NM_DEVICE_IFINDEX,
-		                   "Ifindex",
-		                   "Ifindex",
-		                   0, G_MAXINT, 0,
-		                   G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
-
-	g_object_class_install_property
-		(object_class, PROP_AVAILABLE_CONNECTIONS,
-		 g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS,
-		                     "AvailableConnections",
-		                     "AvailableConnections",
-		                     DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-		                     G_PARAM_READABLE));
-
-	g_object_class_install_property
-		(object_class, PROP_IS_MASTER,
-		 g_param_spec_boolean (NM_DEVICE_IS_MASTER,
-		                       "IsMaster",
-		                       "IsMaster",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
-
-	/* Signals */
-	signals[STATE_CHANGED] =
-		g_signal_new ("state-changed",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMDeviceClass, state_changed),
-		              NULL, NULL,
-		              _nm_marshal_VOID__UINT_UINT_UINT,
-		              G_TYPE_NONE, 3,
-		              G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
-
-	signals[AUTOCONNECT_ALLOWED] =
-		g_signal_new ("autoconnect-allowed",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              0,
-		              autoconnect_allowed_accumulator, NULL,
-		              _nm_marshal_BOOLEAN__VOID,
-		              G_TYPE_BOOLEAN, 0);
-
-	signals[AUTH_REQUEST] =
-		g_signal_new (NM_DEVICE_AUTH_REQUEST,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL,
-		              /* dbus-glib context, connection, permission, allow_interaction, callback, user_data */
-		              _nm_marshal_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER,
-		              G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
-
-	signals[IP4_CONFIG_CHANGED] =
-		g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL,
-		              _nm_marshal_VOID__OBJECT_OBJECT,
-		              G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
-
-	signals[IP6_CONFIG_CHANGED] =
-		g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL,
-		              _nm_marshal_VOID__OBJECT_OBJECT,
-		              G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
-
-	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
-	                                 &dbus_glib_nm_device_interface_object_info);
-
-	dbus_g_error_domain_register (NM_DEVICE_ERROR, NULL, NM_TYPE_DEVICE_ERROR);
-}
-
-void
-nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	if (priv->firmware_missing != new_missing) {
-		priv->firmware_missing = new_missing;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_MISSING);
-	}
-}
-
-gboolean
-nm_device_get_firmware_missing (NMDevice *self)
-{
-	return NM_DEVICE_GET_PRIVATE (self)->firmware_missing;
-}
-
-static const char *
-state_to_string (NMDeviceState state)
-{
-	switch (state) {
-	case NM_DEVICE_STATE_UNMANAGED:
-		return "unmanaged";
-	case NM_DEVICE_STATE_UNAVAILABLE:
-		return "unavailable";
-	case NM_DEVICE_STATE_DISCONNECTED:
-		return "disconnected";
-	case NM_DEVICE_STATE_PREPARE:
-		return "prepare";
-	case NM_DEVICE_STATE_CONFIG:
-		return "config";
-	case NM_DEVICE_STATE_NEED_AUTH:
-		return "need-auth";
-	case NM_DEVICE_STATE_IP_CONFIG:
-		return "ip-config";
-	case NM_DEVICE_STATE_IP_CHECK:
-		return "ip-check";
-	case NM_DEVICE_STATE_SECONDARIES:
-		return "secondaries";
-	case NM_DEVICE_STATE_ACTIVATED:
-		return "activated";
-	case NM_DEVICE_STATE_DEACTIVATING:
-		return "deactivating";
-	case NM_DEVICE_STATE_FAILED:
-		return "failed";
-	default:
-		break;
-	}
-	return "unknown";
-}
-
-static const char *
-reason_to_string (NMDeviceStateReason reason)
-{
-	switch (reason) {
-	case NM_DEVICE_STATE_REASON_NONE:
-		return "none";
-	case NM_DEVICE_STATE_REASON_NOW_MANAGED:
-		return "managed";
-	case NM_DEVICE_STATE_REASON_NOW_UNMANAGED:
-		return "unmanaged";
-	case NM_DEVICE_STATE_REASON_CONFIG_FAILED:
-		return "config-failed";
-	case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE:
-		return "ip-config-unavailable";
-	case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED:
-		return "ip-config-expired";
-	case NM_DEVICE_STATE_REASON_NO_SECRETS:
-		return "no-secrets";
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT:
-		return "supplicant-disconnect";
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED:
-		return "supplicant-config-failed";
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED:
-		return "supplicant-failed";
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT:
-		return "supplicant-timeout";
-	case NM_DEVICE_STATE_REASON_PPP_START_FAILED:
-		return "ppp-start-failed";
-	case NM_DEVICE_STATE_REASON_PPP_DISCONNECT:
-		return "ppp-disconnect";
-	case NM_DEVICE_STATE_REASON_PPP_FAILED:
-		return "ppp-failed";
-	case NM_DEVICE_STATE_REASON_DHCP_START_FAILED:
-		return "dhcp-start-failed";
-	case NM_DEVICE_STATE_REASON_DHCP_ERROR:
-		return "dhcp-error";
-	case NM_DEVICE_STATE_REASON_DHCP_FAILED:
-		return "dhcp-failed";
-	case NM_DEVICE_STATE_REASON_SHARED_START_FAILED:
-		return "sharing-start-failed";
-	case NM_DEVICE_STATE_REASON_SHARED_FAILED:
-		return "sharing-failed";
-	case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED:
-		return "autoip-start-failed";
-	case NM_DEVICE_STATE_REASON_AUTOIP_ERROR:
-		return "autoip-error";
-	case NM_DEVICE_STATE_REASON_AUTOIP_FAILED:
-		return "autoip-failed";
-	case NM_DEVICE_STATE_REASON_MODEM_BUSY:
-		return "modem-busy";
-	case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE:
-		return "modem-no-dialtone";
-	case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER:
-		return "modem-no-carrier";
-	case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT:
-		return "modem-dial-timeout";
-	case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED:
-		return "modem-dial-failed";
-	case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED:
-		return "modem-init-failed";
-	case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
-		return "gsm-apn-failed";
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING:
-		return "gsm-registration-idle";
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED:
-		return "gsm-registration-denied";
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT:
-		return "gsm-registration-timeout";
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED:
-		return "gsm-registration-failed";
-	case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED:
-		return "gsm-pin-check-failed";
-	case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING:
-		return "firmware-missing";
-	case NM_DEVICE_STATE_REASON_REMOVED:
-		return "removed";
-	case NM_DEVICE_STATE_REASON_SLEEPING:
-		return "sleeping";
-	case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED:
-		return "connection-removed";
-	case NM_DEVICE_STATE_REASON_USER_REQUESTED:
-		return "user-requested";
-	case NM_DEVICE_STATE_REASON_CARRIER:
-		return "carrier-changed";
-	case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED:
-		return "connection-assumed";
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE:
-		return "supplicant-available";
-	case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND:
-		return "modem-not-found";
-	case NM_DEVICE_STATE_REASON_BT_FAILED:
-		return "bluetooth-failed";
-	case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED:
-		return "gsm-sim-not-inserted";
-	case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
-		return "gsm-sim-pin-required";
-	case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
-		return "gsm-sim-puk-required";
-	case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG:
-		return "gsm-sim-wrong";
-	case NM_DEVICE_STATE_REASON_INFINIBAND_MODE:
-		return "infiniband-mode";
-	case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
-		return "dependency-failed";
-	case NM_DEVICE_STATE_REASON_BR2684_FAILED:
-		return "br2684-bridge-failed";
-	case NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE:
-		return "modem-manager-unavailable";
-	case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND:
-		return "SSID not found";
-	case NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED:
-		return "secondary-connection-failed";
-	default:
-		break;
-	}
-	return "unknown";
-}
-
-void
-nm_device_state_changed (NMDevice *device,
-                         NMDeviceState state,
-                         NMDeviceStateReason reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMDeviceState old_state;
-	NMActRequest *req;
-	gboolean no_firmware = FALSE;
-	NMConnection *connection;
-
-	/* Track re-entry */
-	static gboolean in_state_changed = FALSE;
-
-	g_warn_if_fail (in_state_changed == FALSE);
-	in_state_changed = TRUE;
-
-	g_return_if_fail (NM_IS_DEVICE (device));
-
-	/* Do nothing if state isn't changing, but as a special case allow
-	 * re-setting UNAVAILABLE if the device is missing firmware so that we
-	 * can retry device initialization.
-	 */
-	if (   (priv->state == state)
-	    && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) {
-		in_state_changed = FALSE;
-		return;
-	}
-
-	old_state = priv->state;
-	priv->state = state;
-	priv->state_reason = reason;
-
-	nm_log_info (LOGD_DEVICE, "(%s): device state change: %s -> %s (reason '%s') [%d %d %d]",
-	             nm_device_get_iface (device),
-	             state_to_string (old_state),
-	             state_to_string (state),
-	             reason_to_string (reason),
-	             old_state,
-	             state,
-	             reason);
-
-	/* Clear any queued transitions */
-	nm_device_queued_state_clear (device);
-
-	/* Cache the activation request for the dispatcher */
-	req = priv->act_request ? g_object_ref (priv->act_request) : NULL;
-
-	if (state <= NM_DEVICE_STATE_UNAVAILABLE)
-		_clear_available_connections (device, TRUE);
-
-	/* Update the available connections list when a device first becomes available */
-	if (   state >= NM_DEVICE_STATE_DISCONNECTED
-	    && old_state < NM_DEVICE_STATE_DISCONNECTED)
-		nm_device_recheck_available_connections (device);
-
-	/* Handle the new state here; but anything that could trigger
-	 * another state change should be done below.
-	 */
-	switch (state) {
-	case NM_DEVICE_STATE_UNMANAGED:
-		nm_device_set_firmware_missing (device, FALSE);
-		if (old_state > NM_DEVICE_STATE_UNMANAGED)
-			nm_device_take_down (device, TRUE, reason);
-		break;
-	case NM_DEVICE_STATE_UNAVAILABLE:
-		if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) {
-			if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware)
-				nm_log_warn (LOGD_HW, "(%s): firmware may be missing.", nm_device_get_iface (device));
-			nm_device_set_firmware_missing (device, no_firmware ? TRUE : FALSE);
-		}
-		/* Ensure the device gets deactivated in response to stuff like
-		 * carrier changes or rfkill.  But don't deactivate devices that are
-		 * about to assume a connection since that defeats the purpose of
-		 * assuming the device's existing connection.
-		 */
-		if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED)
-			nm_device_deactivate (device, reason);
-		break;
-	case NM_DEVICE_STATE_DISCONNECTED:
-		if (old_state != NM_DEVICE_STATE_UNAVAILABLE)
-			nm_device_deactivate (device, reason);
-		break;
-	default:
-		priv->autoconnect = TRUE;
-		break;
-	}
-
-	g_object_notify (G_OBJECT (device), NM_DEVICE_STATE);
-	g_object_notify (G_OBJECT (device), NM_DEVICE_STATE_REASON);
-	g_signal_emit_by_name (device, "state-changed", state, old_state, reason);
-
-	/* Post-process the event after internal notification */
-
-	switch (state) {
-	case NM_DEVICE_STATE_UNAVAILABLE:
-		/* If the device can activate now (ie, it's got a carrier, the supplicant
-		 * is active, or whatever) schedule a delayed transition to DISCONNECTED
-		 * to get things rolling.  The device can't transition immediately because
-		 * we can't change states again from the state handler for a variety of
-		 * reasons.
-		 */
-		if (nm_device_is_available (device)) {
-			nm_log_dbg (LOGD_DEVICE, "(%s): device is available, will transition to DISCONNECTED",
-			            nm_device_get_iface (device));
-			nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
-		} else {
-			nm_log_dbg (LOGD_DEVICE, "(%s): device not yet available for transition to DISCONNECTED",
-			            nm_device_get_iface (device));
-		}
-		break;
-	case NM_DEVICE_STATE_ACTIVATED:
-		nm_log_info (LOGD_DEVICE, "Activation (%s) successful, device activated.",
-		             nm_device_get_iface (device));
-		nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), device, NULL, NULL);
-		break;
-	case NM_DEVICE_STATE_FAILED:
-		connection = nm_device_get_connection (device);
-		nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
-		             "Activation (%s) failed for connection '%s'",
-		             nm_device_get_iface (device),
-		             connection ? nm_connection_get_id (connection) : "<unknown>");
-
-		/* Notify any slaves of the unexpected failure */
-		nm_device_master_release_slaves (device, TRUE);
-
-		/* If the connection doesn't yet have a timestamp, set it to zero so that
-		 * we can distinguish between connections we've tried to activate and have
-		 * failed (zero timestamp), connections that succeeded (non-zero timestamp),
-		 * and those we haven't tried yet (no timestamp).
-		 */
-		if (connection && !nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), NULL)) {
-			nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection),
-			                                         (guint64) 0,
-			                                         TRUE);
-		}
-
-		/* Schedule the transition to DISCONNECTED.  The device can't transition
-		 * immediately because we can't change states again from the state
-		 * handler for a variety of reasons.
-		 */
-		nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
-		break;
-	case NM_DEVICE_STATE_SECONDARIES:
-		nm_log_dbg (LOGD_DEVICE, "(%s): device entered SECONDARIES state",
-		            nm_device_get_iface (device));
-		break;
-	default:
-		break;
-	}
-
-	if (old_state == NM_DEVICE_STATE_ACTIVATED)
-		nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device, NULL, NULL);
-
-	/* Dispose of the cached activation request */
-	if (req)
-		g_object_unref (req);
-
-	in_state_changed = FALSE;
-}
-
-static gboolean
-queued_set_state (gpointer user_data)
-{
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMDeviceState new_state;
-	NMDeviceStateReason new_reason;
-
-	if (priv->queued_state.id) {
-		nm_log_dbg (LOGD_DEVICE, "(%s): running queued state change to %s (id %d)",
-			        nm_device_get_iface (self),
-			        state_to_string (priv->queued_state.state),
-			        priv->queued_state.id);
-
-		/* Clear queued state struct before triggering state change, since
-		 * the state change may queue another state.
-		 */
-		priv->queued_state.id = 0;
-		new_state = priv->queued_state.state;
-		new_reason = priv->queued_state.reason;
-		nm_device_queued_state_clear (self);
-
-		nm_device_state_changed (self, new_state, new_reason);
-	} else {
-		g_warn_if_fail (priv->queued_state.state == NM_DEVICE_STATE_UNKNOWN);
-		g_warn_if_fail (priv->queued_state.reason == NM_DEVICE_STATE_REASON_NONE);
-	}
-	return FALSE;
-}
-
-void
-nm_device_queue_state (NMDevice *self,
-                       NMDeviceState state,
-                       NMDeviceStateReason reason)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-
-	/* We should only ever have one delayed state transition at a time */
-	if (priv->queued_state.id) {
-		g_warn_if_fail (priv->queued_state.id == 0);
-		nm_device_queued_state_clear (self);
-	}
-
-	priv->queued_state.state = state;
-	priv->queued_state.reason = reason;
-	priv->queued_state.id = g_idle_add (queued_set_state, self);
-
-	nm_log_dbg (LOGD_DEVICE, "(%s): queued state change to %s (id %d)",
-	            nm_device_get_iface (self), state_to_string (state),
-	            priv->queued_state.id);
-}
-
-NMDeviceState
-nm_device_queued_state_peek (NMDevice *self)
-{
-	NMDevicePrivate *priv;
-
-	g_return_val_if_fail (self != NULL, NM_DEVICE_STATE_UNKNOWN);
-	g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_STATE_UNKNOWN);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-
-	return priv->queued_state.id ? priv->queued_state.state : NM_DEVICE_STATE_UNKNOWN;
-}
-
-void
-nm_device_queued_state_clear (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->queued_state.id) {
-		nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued state transition (id %d)",
-		            nm_device_get_iface (self), priv->queued_state.id);
-		g_source_remove (priv->queued_state.id);
-	}
-	memset (&priv->queued_state, 0, sizeof (priv->queued_state));
-}
-
-NMDeviceState
-nm_device_get_state (NMDevice *device)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
-
-	return NM_DEVICE_GET_PRIVATE (device)->state;
-}
-
-gboolean
-nm_device_get_managed (NMDevice *device)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-
-	return NM_DEVICE_GET_PRIVATE (device)->managed;
-}
-
-void
-nm_device_set_managed (NMDevice *device,
-                       gboolean managed,
-                       NMDeviceStateReason reason)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (device));
-
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->managed == managed)
-		return;
-
-	priv->managed = managed;
-	nm_log_dbg (LOGD_DEVICE, "(%s): now %s",
-	            nm_device_get_iface (device),
-	            managed ? "managed" : "unmanaged");
-
-	g_object_notify (G_OBJECT (device), NM_DEVICE_MANAGED);
-
-	/* If now managed, jump to unavailable */
-	if (managed)
-		nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, reason);
-	else
-		nm_device_state_changed (device, NM_DEVICE_STATE_UNMANAGED, reason);
-}
-
-gboolean
-nm_device_spec_match_list (NMDevice *device, const GSList *specs)
-{
-	g_return_val_if_fail (device != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-
-	if (NM_DEVICE_GET_CLASS (device)->spec_match_list)
-		return NM_DEVICE_GET_CLASS (device)->spec_match_list (device, specs);
-	return FALSE;
-}
-
-static gboolean
-ip4_match_config (NMDevice *self, NMConnection *connection)
-{
-	NMSettingIP4Config *s_ip4;
-	int i, num;
-	GSList *leases, *iter;
-	NMDHCPManager *dhcp_mgr;
-	const char *method;
-
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-
-	/* Get any saved leases that apply to this connection */
-	dhcp_mgr = nm_dhcp_manager_get ();
-	leases = nm_dhcp_manager_get_lease_config (dhcp_mgr,
-	                                           nm_device_get_iface (self),
-	                                           nm_connection_get_uuid (connection),
-						   FALSE);
-	g_object_unref (dhcp_mgr);
-
-	method = s_ip4 ? nm_setting_ip4_config_get_method (s_ip4) : NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
-		gboolean found = FALSE;
-
-		/* Find at least one lease's address on the device */
-		for (iter = leases; iter; iter = g_slist_next (iter)) {
-			NMIP4Config *ip4_config = iter->data;
-			NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0);
-			struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
-
-			if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self),
-			                                     AF_INET,
-			                                     &tmp,
-			                                     nm_ip4_address_get_prefix (addr))) {
-				found = TRUE; /* Yay, device has same address as a lease */
-				break;
-			}
-		}
-		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
-		g_slist_free (leases);
-		return found;
-	} else {
-		/* Maybe the connection used to be DHCP and there are stale leases; ignore them */
-		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
-		g_slist_free (leases);
-	}
-
-	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
-		// FIXME: Enforce no ipv4 addresses?
-		return TRUE;
-	}
-
-	/* 'shared' and 'link-local' aren't supported methods because 'shared'
-	 * requires too much iptables and dnsmasq state to be reclaimed, and
-	 * avahi-autoipd isn't smart enough to allow the link-local address to be
-	 * determined at any point other than when it was first assigned.
-	 */
-	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
-		return FALSE;
-
-	/* Everything below for static addressing */
-
-	/* Find all IP4 addresses of this connection on the device */
-	if (s_ip4) {
-		num = nm_setting_ip4_config_get_num_addresses (s_ip4);
-		for (i = 0; i < num; i++) {
-			NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i);
-			struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
-
-			if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self),
-						      AF_INET,
-						      &tmp,
-						      nm_ip4_address_get_prefix (addr)))
-				return FALSE;
-		}
-	}
-
-	/* Success; all the connection's static IP addresses are assigned to the device */
-	return TRUE;
-}
-
-gboolean
-nm_device_match_ip_config (NMDevice *device, NMConnection *connection)
-{
-	if (!ip4_match_config (device, connection))
-		return FALSE;
-
-	/* FIXME: match IPv6 config */
-
-	return TRUE;
-}
-
-NMConnection *
-nm_device_connection_match_config (NMDevice *device, const GSList *connections)
-{
-	g_return_val_if_fail (device != NULL, NULL);
-	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
-
-	if (NM_DEVICE_GET_CLASS (device)->connection_match_config)
-		return NM_DEVICE_GET_CLASS (device)->connection_match_config (NM_DEVICE (device), connections);
-	return NULL;
-}
-
-/**
- * nm_device_hwaddr_matches:
- * @device: the device to use when matching the hardware address
- * @connection: the connection which supplies the hardware address
- * @other_hwaddr: if given, use this address instead of the device's actual
- *   hardware address
- * @other_hwaddr_len: length in bytes of @other_hwaddr
- * @fail_if_no_hwaddr: whether to fail the match if @connection does not contain
- *   a hardware address
- *
- * Matches a the devices hardware address (or @other_hwaddr if given) against
- * the hardware-specific setting in @connection.  Allows for device-agnostic
- * hardware address matching without having to know the internal details of
- * the connection and which settings are used by each device subclass.
- *
- * Returns: %TRUE if the @device 's hardware address or @other_hwaddr matches
- *  a hardware address in a hardware-specific setting in @connection
- */
-gboolean
-nm_device_hwaddr_matches (NMDevice *device,
-                          NMConnection *connection,
-                          const guint8 *other_hwaddr,
-                          guint other_hwaddr_len,
-                          gboolean fail_if_no_hwaddr)
-{
-	g_return_val_if_fail (device != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-	if (other_hwaddr)
-		g_return_val_if_fail (other_hwaddr_len > 0, FALSE);
-
-	if (NM_DEVICE_GET_CLASS (device)->hwaddr_matches) {
-		return NM_DEVICE_GET_CLASS (device)->hwaddr_matches (device,
-		                                                     connection,
-		                                                     other_hwaddr,
-		                                                     other_hwaddr_len,
-		                                                     fail_if_no_hwaddr);
-	}
-	return FALSE;
-}
-
-void
-nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout)
-{
-	g_return_if_fail (NM_IS_DEVICE (device));
-
-	NM_DEVICE_GET_PRIVATE (device)->dhcp_timeout = timeout;
-}
-
-void
-nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr)
-{
-	NMDevicePrivate *priv;
-
-	g_return_if_fail (NM_IS_DEVICE (device));
-
-	priv = NM_DEVICE_GET_PRIVATE (device);
-
-	if (priv->dhcp_anycast_address) {
-		g_byte_array_free (priv->dhcp_anycast_address, TRUE);
-		priv->dhcp_anycast_address = NULL;
-	}
-
-	if (addr) {
-		priv->dhcp_anycast_address = g_byte_array_sized_new (ETH_ALEN);
-		g_byte_array_append (priv->dhcp_anycast_address, addr, ETH_ALEN);
-	}
-}
-
-gboolean
-nm_device_get_autoconnect (NMDevice *device)
-{
-	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
-
-	return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
-}
-
-static void
-_signal_available_connections_changed (NMDevice *device)
-{
-	g_object_notify (G_OBJECT (device), NM_DEVICE_AVAILABLE_CONNECTIONS);
-}
-
-static void
-_clear_available_connections (NMDevice *device, gboolean do_signal)
-{
-	g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (device)->available_connections);
-	if (do_signal == TRUE)
-		_signal_available_connections_changed (device);
-}
-
-static gboolean
-_try_add_available_connection (NMDevice *self, NMConnection *connection)
-{
-	if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED)
-		return FALSE;
-
-	if (nm_device_check_connection_compatible (self, connection, NULL)) {
-		/* Let subclasses implement additional checks on the connection */
-		if (   NM_DEVICE_GET_CLASS (self)->check_connection_available
-		    && NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection)) {
-
-			g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections,
-					             g_object_ref (connection),
-					             GUINT_TO_POINTER (1));
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-static gboolean
-_del_available_connection (NMDevice *device, NMConnection *connection)
-{
-	return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (device)->available_connections, connection);
-}
-
-static gboolean
-check_connection_available (NMDevice *device, NMConnection *connection)
-{
-	/* Default is to assume the connection is available unless a subclass
-	 * overrides this with more specific checks.
-	 */
-	return TRUE;
-}
-
-void
-nm_device_recheck_available_connections (NMDevice *device)
-{
-	NMDevicePrivate *priv;
-	const GSList *connections, *iter;
-
-	g_return_if_fail (device != NULL);
-	g_return_if_fail (NM_IS_DEVICE (device));
-
-	priv = NM_DEVICE_GET_PRIVATE(device);
-
-	_clear_available_connections (device, FALSE);
-
-	connections = nm_connection_provider_get_connections (priv->con_provider);
-	for (iter = connections; iter; iter = g_slist_next (iter))
-		_try_add_available_connection (device, NM_CONNECTION (iter->data));
-
-	_signal_available_connections_changed (device);
-}
-
-static void
-cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
-{
-	if (_try_add_available_connection (NM_DEVICE (user_data), connection))
-		_signal_available_connections_changed (NM_DEVICE (user_data));
-}
-
-static void
-cp_connections_loaded (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
-{
-	const GSList *connections, *iter;
-	gboolean added = FALSE;
-
-	connections = nm_connection_provider_get_connections (cp);
-	for (iter = connections; iter; iter = g_slist_next (iter))
-		added |= _try_add_available_connection (NM_DEVICE (user_data), NM_CONNECTION (iter->data));
-
-	if (added)
-		_signal_available_connections_changed (NM_DEVICE (user_data));
-}
-
-static void
-cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
-{
-	if (_del_available_connection (NM_DEVICE (user_data), connection))
-		_signal_available_connections_changed (NM_DEVICE (user_data));
-}
-
-static void
-cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
-{
-	gboolean added, deleted;
-
-	/* FIXME: don't remove it from the hash if it's just going to get re-added */
-	deleted = _del_available_connection (NM_DEVICE (user_data), connection);
-	added = _try_add_available_connection (NM_DEVICE (user_data), connection);
-
-	/* Only signal if the connection was removed OR added, but not both */
-	if (added != deleted)
-		_signal_available_connections_changed (NM_DEVICE (user_data));
-}
-
-gboolean
-nm_device_supports_vlans (NMDevice *device)
-{
-	/* At the moment, NM's VLAN code assumes all VLANs are over ethernet. */
-	return NM_IS_DEVICE_ETHERNET (device);
-}
-
-/**
- * nm_device_read_hwaddr:
- * @dev: the device
- * @buf: an allocated buffer which on success holds the device's hardware
- *   address
- * @buf_len: the size of @buf
- * @out_changed: on success, %TRUE if the contents of @buf are different from
- *   the original contents of @buf when this function was called
- *
- * Reads the device's hardware address from the kernel and copies it into
- * @buf, returning the size of the data copied into @buf.  On failure
- * @buf is not modified.
- *
- * Returns: the size of the hardware address in bytes on success, 0 on failure
- */
-gsize
-nm_device_read_hwaddr (NMDevice *dev,
-                       guint8 *buf,
-                       gsize buf_len,
-                       gboolean *out_changed)
-{
-	struct rtnl_link *rtnl;
-	struct nl_addr *addr;
-	int idx;
-	gsize addrlen = 0;
-	const guint8 *binaddr;
-
-	g_return_val_if_fail (dev != NULL, 0);
-	g_return_val_if_fail (buf != NULL, 0);
-	g_return_val_if_fail (buf_len > 0, 0);
-
-	idx = nm_device_get_ip_ifindex (dev);
-	g_return_val_if_fail (idx > 0, 0);
-
-	rtnl = nm_netlink_index_to_rtnl_link (idx);
-	if (!rtnl) {
-		nm_log_err (LOGD_HW | LOGD_DEVICE,
-		            "(%s): failed to read hardware address (error %d)",
-		            nm_device_get_iface (dev), errno);
-		return 0;
-	}
-
-	addr = rtnl_link_get_addr (rtnl);
-	if (!addr) {
-		nm_log_err (LOGD_HW | LOGD_DEVICE,
-		            "(%s): no hardware address?",
-		            nm_device_get_iface (dev));
-		goto out;
-	}
-
-	addrlen = nl_addr_get_len (addr);
-	if (addrlen > buf_len) {
-		nm_log_err (LOGD_HW | LOGD_DEVICE,
-		            "(%s): hardware address is wrong length (got %zd max %zd)",
-		            nm_device_get_iface (dev), addrlen, buf_len);
-		addrlen = 0;
-	} else {
-		binaddr = nl_addr_get_binary_addr (addr);
-		if (out_changed)
-			*out_changed = memcmp (buf, binaddr, addrlen) ? TRUE : FALSE;
-		memcpy (buf, binaddr, addrlen);
-	}
-
-out:
-	rtnl_link_put (rtnl);
-	return addrlen;
-}