about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in7
-rw-r--r--src/NetworkManagerUtils.c32
-rw-r--r--src/backends/Makefile.am4
-rw-r--r--src/backends/Makefile.in25
-rw-r--r--src/backends/NetworkManagerExherbo.c64
-rw-r--r--src/backends/NetworkManagerGentoo.c34
-rw-r--r--src/bluez-manager/Makefile.in5
-rw-r--r--src/dhcp-manager/Makefile.am38
-rw-r--r--src/dhcp-manager/Makefile.in308
-rw-r--r--src/dhcp-manager/nm-dhcp-client.c12
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient-utils.c217
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient-utils.h35
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient.c97
-rw-r--r--src/dhcp-manager/nm-dhcp-dhcpcd.c2
-rw-r--r--src/dhcp-manager/nm-dhcp-manager.c15
-rw-r--r--src/dhcp-manager/tests/Makefile.am28
-rw-r--r--src/dhcp-manager/tests/Makefile.in610
-rw-r--r--src/dhcp-manager/tests/test-dhcp-dhclient.c249
-rw-r--r--src/dns-manager/Makefile.am4
-rw-r--r--src/dns-manager/Makefile.in21
-rw-r--r--src/dns-manager/nm-dns-dnsmasq.c22
-rw-r--r--src/dns-manager/nm-dns-manager.c9
-rw-r--r--src/dns-manager/nm-dns-utils.c99
-rw-r--r--src/dns-manager/nm-dns-utils.h28
-rw-r--r--src/dnsmasq-manager/Makefile.in5
-rw-r--r--src/dnsmasq-manager/nm-dnsmasq-manager.c12
-rw-r--r--src/ip6-manager/Makefile.in5
-rw-r--r--src/ip6-manager/nm-ip6-manager.c415
-rw-r--r--src/ip6-manager/nm-ip6-manager.h2
-rw-r--r--src/logging/Makefile.in5
-rw-r--r--src/logging/nm-logging.c8
-rw-r--r--src/main.c6
-rw-r--r--src/modem-manager/Makefile.in5
-rw-r--r--src/modem-manager/nm-modem.c6
-rw-r--r--src/nm-activation-request.c73
-rw-r--r--src/nm-active-connection.c78
-rw-r--r--src/nm-active-connection.h12
-rw-r--r--src/nm-device-ethernet.c39
-rw-r--r--src/nm-device-wifi.c9
-rw-r--r--src/nm-device.c32
-rw-r--r--src/nm-manager.c100
-rw-r--r--src/nm-policy-hostname.c56
-rw-r--r--src/nm-policy-hostname.h5
-rw-r--r--src/nm-policy-hosts.c520
-rw-r--r--src/nm-policy-hosts.h20
-rw-r--r--src/nm-policy.c51
-rw-r--r--src/nm-system.c11
-rw-r--r--src/nm-system.h2
-rw-r--r--src/ppp-manager/Makefile.am4
-rw-r--r--src/ppp-manager/Makefile.in49
-rw-r--r--src/ppp-manager/nm-ppp-manager.c14
-rw-r--r--src/supplicant-manager/Makefile.in5
-rw-r--r--src/supplicant-manager/tests/Makefile.in5
-rw-r--r--src/system-settings/Makefile.in5
-rw-r--r--src/system-settings/nm-default-wired-connection.c2
-rw-r--r--src/system-settings/nm-sysconfig-settings.c62
-rw-r--r--src/system-settings/nm-sysconfig-settings.h2
-rw-r--r--src/system-settings/nm-system-config-interface.c3
-rw-r--r--src/system-settings/nm-system-config-interface.h15
-rw-r--r--src/tests/Makefile.in5
-rw-r--r--src/tests/test-policy-hosts.c761
-rw-r--r--src/vpn-manager/Makefile.am18
-rw-r--r--src/vpn-manager/Makefile.in31
-rw-r--r--src/vpn-manager/nm-vpn-connection-base.c199
-rw-r--r--src/vpn-manager/nm-vpn-connection-base.h54
-rw-r--r--src/vpn-manager/nm-vpn-connection.c185
-rw-r--r--src/vpn-manager/nm-vpn-connection.h5
68 files changed, 2938 insertions, 1930 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8c01df0f..d7dccaaf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -275,8 +275,10 @@ EXTRA_DIST = \
 	$(NetworkManager_DATA)
 
 rundir=$(localstatedir)/run/NetworkManager
+statedir=$(localstatedir)/lib/NetworkManager
 install-data-hook:
 	$(mkinstalldirs) -m 0700 $(DESTDIR)$(rundir)
+	$(mkinstalldirs) -m 0700 $(DESTDIR)$(statedir)
 
 CLEANFILES = $(BUILT_SOURCES)
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 17e8158c..bf489591 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -323,6 +323,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -337,6 +341,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -634,6 +639,7 @@ EXTRA_DIST = \
 	$(NetworkManager_DATA)
 
 rundir = $(localstatedir)/run/NetworkManager
+statedir = $(localstatedir)/lib/NetworkManager
 CLEANFILES = $(BUILT_SOURCES)
 all: $(BUILT_SOURCES)
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -1833,6 +1839,7 @@ nm-device-gsm-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_gsm --mode=glib-server --output=$@ $<
 install-data-hook:
 	$(mkinstalldirs) -m 0700 $(DESTDIR)$(rundir)
+	$(mkinstalldirs) -m 0700 $(DESTDIR)$(statedir)
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 10240960..3a28467c 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -370,6 +370,13 @@ nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting)
 		nm_ip6_config_set_never_default (ip6_config, TRUE);
 }
 
+static void
+dispatcher_done_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+	dbus_g_proxy_end_call (proxy, call, NULL, G_TYPE_INVALID);
+	g_object_unref (proxy);
+}
+
 void
 nm_utils_call_dispatcher (const char *action,
                           NMConnection *connection,
@@ -448,18 +455,25 @@ nm_utils_call_dispatcher (const char *action,
 		value_hash_add_object_path (device_props, NMD_DEVICE_PROPS_PATH, nm_device_get_path (device));
 	}
 
-	dbus_g_proxy_call_no_reply (proxy, "Action",
-	                            G_TYPE_STRING, action,
-	                            DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash,
-	                            DBUS_TYPE_G_MAP_OF_VARIANT, connection_props,
-	                            DBUS_TYPE_G_MAP_OF_VARIANT, device_props,
-	                            G_TYPE_INVALID);
-
-	g_object_unref (proxy);
+	/* Do a non-blocking call, but wait for the reply, because dbus-glib
+	 * sometimes needs time to complete internal housekeeping.  If we use
+	 * dbus_g_proxy_call_no_reply(), that housekeeping (specifically the
+	 * GetNameOwner response) doesn't complete and we run into an assert
+	 * on unreffing the proxy.
+	 */
+	dbus_g_proxy_begin_call_with_timeout (proxy, "Action",
+	                                      dispatcher_done_cb,
+	                                      dbus_mgr,
+	                                      g_object_unref,
+	                                      5000,
+	                                      G_TYPE_STRING, action,
+	                                      DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash,
+	                                      DBUS_TYPE_G_MAP_OF_VARIANT, connection_props,
+	                                      DBUS_TYPE_G_MAP_OF_VARIANT, device_props,
+	                                      G_TYPE_INVALID);
 	g_hash_table_destroy (connection_hash);
 	g_hash_table_destroy (connection_props);
 	g_hash_table_destroy (device_props);
-	g_object_unref (dbus_mgr);
 }
 
 gboolean
diff --git a/src/backends/Makefile.am b/src/backends/Makefile.am
index 036dc6de..fbec9aaf 100644
--- a/src/backends/Makefile.am
+++ b/src/backends/Makefile.am
@@ -57,6 +57,10 @@ if TARGET_LINEXA
 libnmbackend_la_SOURCES += NetworkManagerLinexa.c
 endif
 
+if TARGET_EXHERBO
+libnmbackend_la_SOURCES += NetworkManagerExherbo.c
+endif
+
 libnmbackend_la_LIBADD += \
 	$(top_builddir)/src/logging/libnm-logging.la \
 	$(DBUS_LIBS) \
diff --git a/src/backends/Makefile.in b/src/backends/Makefile.in
index 54ad6ce9..3a640dc8 100644
--- a/src/backends/Makefile.in
+++ b/src/backends/Makefile.in
@@ -46,6 +46,7 @@ host_triplet = @host@
 @TARGET_MANDRIVA_TRUE@am__append_10 = NetworkManagerMandriva.c
 @TARGET_PARDUS_TRUE@am__append_11 = NetworkManagerPardus.c
 @TARGET_LINEXA_TRUE@am__append_12 = NetworkManagerLinexa.c
+@TARGET_EXHERBO_TRUE@am__append_13 = NetworkManagerExherbo.c
 subdir = src/backends
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -72,7 +73,8 @@ am__libnmbackend_la_SOURCES_DIST = NetworkManagerGeneric.c \
 	NetworkManagerDebian.c NetworkManagerSlackware.c \
 	NetworkManagerArch.c NetworkManagerPaldo.c \
 	NetworkManagerFrugalware.c NetworkManagerMandriva.c \
-	NetworkManagerPardus.c NetworkManagerLinexa.c
+	NetworkManagerPardus.c NetworkManagerLinexa.c \
+	NetworkManagerExherbo.c
 @TARGET_REDHAT_TRUE@am__objects_1 =  \
 @TARGET_REDHAT_TRUE@	libnmbackend_la-NetworkManagerRedHat.lo
 @TARGET_SUSE_TRUE@am__objects_2 =  \
@@ -92,11 +94,13 @@ am__libnmbackend_la_SOURCES_DIST = NetworkManagerGeneric.c \
 @TARGET_PARDUS_TRUE@	libnmbackend_la-NetworkManagerPardus.lo
 @TARGET_LINEXA_TRUE@am__objects_11 =  \
 @TARGET_LINEXA_TRUE@	libnmbackend_la-NetworkManagerLinexa.lo
+@TARGET_EXHERBO_TRUE@am__objects_12 =  \
+@TARGET_EXHERBO_TRUE@	libnmbackend_la-NetworkManagerExherbo.lo
 am_libnmbackend_la_OBJECTS = libnmbackend_la-NetworkManagerGeneric.lo \
 	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
 	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
 	$(am__objects_7) $(am__objects_8) $(am__objects_9) \
-	$(am__objects_10) $(am__objects_11)
+	$(am__objects_10) $(am__objects_11) $(am__objects_12)
 libnmbackend_la_OBJECTS = $(am_libnmbackend_la_OBJECTS)
 AM_V_lt = $(am__v_lt_$(V))
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@ -224,6 +228,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -238,6 +246,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -325,7 +334,8 @@ libnmbackend_la_SOURCES = NetworkManagerGeneric.c \
 	NetworkManagerGeneric.h $(am__append_1) $(am__append_2) \
 	$(am__append_3) $(am__append_4) $(am__append_5) \
 	$(am__append_6) $(am__append_7) $(am__append_8) \
-	$(am__append_10) $(am__append_11) $(am__append_12)
+	$(am__append_10) $(am__append_11) $(am__append_12) \
+	$(am__append_13)
 libnmbackend_la_LIBADD = $(am__append_9) \
 	$(top_builddir)/src/logging/libnm-logging.la $(DBUS_LIBS) \
 	$(GLIB_LIBS)
@@ -391,6 +401,7 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerArch.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerDebian.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerExherbo.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerFrugalware.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerGeneric.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmbackend_la-NetworkManagerGentoo.Plo@am__quote@
@@ -525,6 +536,14 @@ libnmbackend_la-NetworkManagerLinexa.lo: NetworkManagerLinexa.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnmbackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnmbackend_la-NetworkManagerLinexa.lo `test -f 'NetworkManagerLinexa.c' || echo '$(srcdir)/'`NetworkManagerLinexa.c
 
+libnmbackend_la-NetworkManagerExherbo.lo: NetworkManagerExherbo.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnmbackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnmbackend_la-NetworkManagerExherbo.lo -MD -MP -MF $(DEPDIR)/libnmbackend_la-NetworkManagerExherbo.Tpo -c -o libnmbackend_la-NetworkManagerExherbo.lo `test -f 'NetworkManagerExherbo.c' || echo '$(srcdir)/'`NetworkManagerExherbo.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnmbackend_la-NetworkManagerExherbo.Tpo $(DEPDIR)/libnmbackend_la-NetworkManagerExherbo.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='NetworkManagerExherbo.c' object='libnmbackend_la-NetworkManagerExherbo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnmbackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnmbackend_la-NetworkManagerExherbo.lo `test -f 'NetworkManagerExherbo.c' || echo '$(srcdir)/'`NetworkManagerExherbo.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/src/backends/NetworkManagerExherbo.c b/src/backends/NetworkManagerExherbo.c
new file mode 100644
index 00000000..d7e24cf6
--- /dev/null
+++ b/src/backends/NetworkManagerExherbo.c
@@ -0,0 +1,64 @@
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ * Dan Willemsen <dan@willemsen.us>
+ * Robert Paskowitz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2004 Red Hat, Inc.
+ * (C) Copyright 2004 Dan Willemsen
+ * (C) Copyright 2004 Robert Paskowitz
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "NetworkManagerGeneric.h"
+#include "nm-system.h"
+#include "NetworkManagerUtils.h"
+#include "nm-logging.h"
+
+/*
+ * nm_system_enable_loopback
+ *
+ * Bring up the loopback interface
+ *
+ */
+void nm_system_enable_loopback (void)
+{
+	nm_generic_enable_loopback ();
+}
+
+/*
+ * nm_system_update_dns
+ *
+ * Make glibc/nscd aware of any changes to the resolv.conf file by
+ * restarting nscd. Only restart if already running.
+ *
+ */
+void nm_system_update_dns (void)
+{
+	if (g_file_test ("/usr/sbin/nscd", G_FILE_TEST_IS_EXECUTABLE)) {
+		nm_log_info (LOGD_DNS, "Clearing nscd hosts cache.");
+		nm_spawn_process ("/usr/sbin/nscd -i hosts");
+	}
+}
+
diff --git a/src/backends/NetworkManagerGentoo.c b/src/backends/NetworkManagerGentoo.c
index 8d9e68c5..e5b09384 100644
--- a/src/backends/NetworkManagerGentoo.c
+++ b/src/backends/NetworkManagerGentoo.c
@@ -30,12 +30,22 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <gio/gio.h>
 
 #include "NetworkManagerGeneric.h"
 #include "nm-system.h"
 #include "NetworkManagerUtils.h"
 #include "nm-logging.h"
 
+#define BUFFER_SIZE 512
+
+static void openrc_start_lo_if_necessary() 
+{
+	/* No need to run net.lo if it is already running */
+        if (nm_spawn_process ("/etc/init.d/net.lo status") != 0)
+                nm_spawn_process ("/etc/init.d/net.lo start");
+}
+
 /*
  * nm_system_enable_loopback
  *
@@ -44,9 +54,27 @@
  */
 void nm_system_enable_loopback (void)
 {
-  /* No need to run net.lo if it is already running */
-	if (nm_spawn_process ("/etc/init.d/net.lo status") != 0)
-		nm_spawn_process("/etc/init.d/net.lo start");
+	gchar *comm;
+
+	/* If anything goes wrong trying to open /proc/1/comm, we will assume
+	   OpenRC. */
+	if (!g_file_get_contents ("/proc/1/comm", &comm, NULL, NULL)) {
+		nm_log_info (LOGD_CORE, "NetworkManager is running with OpenRC...");
+		openrc_start_lo_if_necessary ();
+		return;
+	}
+
+	if (g_strstr_len (comm, -1, "systemd")) {
+		/* We use the generic loopback enabler if using systemd. */
+		nm_log_info (LOGD_CORE, "NetworkManager is running with systemd...");
+		nm_generic_enable_loopback ();
+	} else {
+		/* OpenRC otherwise. */
+		nm_log_info (LOGD_CORE, "NetworkManager is running with OpenRC...");
+		openrc_start_lo_if_necessary();
+	}
+
+	g_free (comm);
 }
 
 /*
diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in
index 9edc68b1..f7ca0b4d 100644
--- a/src/bluez-manager/Makefile.in
+++ b/src/bluez-manager/Makefile.in
@@ -186,6 +186,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -200,6 +204,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am
index e29c6718..14ddde0b 100644
--- a/src/dhcp-manager/Makefile.am
+++ b/src/dhcp-manager/Makefile.am
@@ -1,3 +1,5 @@
+SUBDIRS=. tests
+
 INCLUDES = \
 	-I${top_srcdir} \
 	-I${top_srcdir}/include \
@@ -6,15 +8,40 @@ INCLUDES = \
 	-I${top_srcdir}/libnm-util \
 	-I${top_srcdir}/src
 
-noinst_LTLIBRARIES = libdhcp-manager.la
+noinst_LTLIBRARIES = libdhcp-manager.la libdhcp-dhclient.la
+
+################## dhclient ##################
+
+libdhcp_dhclient_la_SOURCES = \
+	nm-dhcp-dhclient-utils.h \
+	nm-dhcp-dhclient-utils.c \
+	nm-dhcp-dhclient.h \
+	nm-dhcp-dhclient.c
+
+libdhcp_dhclient_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DG_DISABLE_DEPRECATED \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-DLIBEXECDIR=\"$(libexecdir)\" \
+	-DLOCALSTATEDIR=\"$(localstatedir)\" \
+	-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
+	-DDHCLIENT_V$(DHCLIENT_VERSION)
+
+libdhcp_dhclient_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+################## main lib ##################
 
 libdhcp_manager_la_SOURCES = \
 	nm-dhcp-client.c \
 	nm-dhcp-client.h \
 	nm-dhcp-manager.c \
 	nm-dhcp-manager.h \
-	nm-dhcp-dhclient.h \
-	nm-dhcp-dhclient.c \
 	nm-dhcp-dhcpcd.h \
 	nm-dhcp-dhcpcd.c
 
@@ -22,18 +49,15 @@ libdhcp_manager_la_CPPFLAGS = \
 	$(DBUS_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	-DG_DISABLE_DEPRECATED \
-	-DBINDIR=\"$(bindir)\" \
-	-DDATADIR=\"$(datadir)\" \
-	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	-DLIBEXECDIR=\"$(libexecdir)\" \
 	-DLOCALSTATEDIR=\"$(localstatedir)\" \
 	-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
-	-DDHCLIENT_V$(DHCLIENT_VERSION) \
 	-DDHCPCD_PATH=\"$(DHCPCD_PATH)\"
 
 libdhcp_manager_la_LIBADD = \
 	$(top_builddir)/marshallers/libmarshallers.la \
 	$(top_builddir)/src/logging/libnm-logging.la \
+	$(builddir)/libdhcp-dhclient.la \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in
index 4a7cc29b..73302319 100644
--- a/src/dhcp-manager/Makefile.in
+++ b/src/dhcp-manager/Makefile.in
@@ -51,18 +51,27 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
+libdhcp_dhclient_la_DEPENDENCIES =  \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_libdhcp_dhclient_la_OBJECTS =  \
+	libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo \
+	libdhcp_dhclient_la-nm-dhcp-dhclient.lo
+libdhcp_dhclient_la_OBJECTS = $(am_libdhcp_dhclient_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
 libdhcp_manager_la_DEPENDENCIES =  \
 	$(top_builddir)/marshallers/libmarshallers.la \
 	$(top_builddir)/src/logging/libnm-logging.la \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+	$(builddir)/libdhcp-dhclient.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am_libdhcp_manager_la_OBJECTS = libdhcp_manager_la-nm-dhcp-client.lo \
 	libdhcp_manager_la-nm-dhcp-manager.lo \
-	libdhcp_manager_la-nm-dhcp-dhclient.lo \
 	libdhcp_manager_la-nm-dhcp-dhcpcd.lo
 libdhcp_manager_la_OBJECTS = $(am_libdhcp_manager_la_OBJECTS)
-AM_V_lt = $(am__v_lt_$(V))
-am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
-am__v_lt_0 = --silent
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -89,11 +98,50 @@ am__v_CCLD_0 = @echo "  CCLD  " $@;
 AM_V_GEN = $(am__v_GEN_$(V))
 am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
 am__v_GEN_0 = @echo "  GEN   " $@;
-SOURCES = $(libdhcp_manager_la_SOURCES)
-DIST_SOURCES = $(libdhcp_manager_la_SOURCES)
+SOURCES = $(libdhcp_dhclient_la_SOURCES) $(libdhcp_manager_la_SOURCES)
+DIST_SOURCES = $(libdhcp_dhclient_la_SOURCES) \
+	$(libdhcp_manager_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+	distdir
 ETAGS = etags
 CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
 ACLOCAL = @ACLOCAL@
 ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
 ALL_LINGUAS = @ALL_LINGUAS@
@@ -186,6 +234,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -200,6 +252,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -275,6 +328,7 @@ target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
+SUBDIRS = . tests
 INCLUDES = \
 	-I${top_srcdir} \
 	-I${top_srcdir}/include \
@@ -283,14 +337,39 @@ INCLUDES = \
 	-I${top_srcdir}/libnm-util \
 	-I${top_srcdir}/src
 
-noinst_LTLIBRARIES = libdhcp-manager.la
+noinst_LTLIBRARIES = libdhcp-manager.la libdhcp-dhclient.la
+
+################## dhclient ##################
+libdhcp_dhclient_la_SOURCES = \
+	nm-dhcp-dhclient-utils.h \
+	nm-dhcp-dhclient-utils.c \
+	nm-dhcp-dhclient.h \
+	nm-dhcp-dhclient.c
+
+libdhcp_dhclient_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DG_DISABLE_DEPRECATED \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-DLIBEXECDIR=\"$(libexecdir)\" \
+	-DLOCALSTATEDIR=\"$(localstatedir)\" \
+	-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
+	-DDHCLIENT_V$(DHCLIENT_VERSION)
+
+libdhcp_dhclient_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+
+################## main lib ##################
 libdhcp_manager_la_SOURCES = \
 	nm-dhcp-client.c \
 	nm-dhcp-client.h \
 	nm-dhcp-manager.c \
 	nm-dhcp-manager.h \
-	nm-dhcp-dhclient.h \
-	nm-dhcp-dhclient.c \
 	nm-dhcp-dhcpcd.h \
 	nm-dhcp-dhcpcd.c
 
@@ -298,22 +377,19 @@ libdhcp_manager_la_CPPFLAGS = \
 	$(DBUS_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	-DG_DISABLE_DEPRECATED \
-	-DBINDIR=\"$(bindir)\" \
-	-DDATADIR=\"$(datadir)\" \
-	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	-DLIBEXECDIR=\"$(libexecdir)\" \
 	-DLOCALSTATEDIR=\"$(localstatedir)\" \
 	-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
-	-DDHCLIENT_V$(DHCLIENT_VERSION) \
 	-DDHCPCD_PATH=\"$(DHCPCD_PATH)\"
 
 libdhcp_manager_la_LIBADD = \
 	$(top_builddir)/marshallers/libmarshallers.la \
 	$(top_builddir)/src/logging/libnm-logging.la \
+	$(builddir)/libdhcp-dhclient.la \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
-all: all-am
+all: all-recursive
 
 .SUFFIXES:
 .SUFFIXES: .c .lo .o .obj
@@ -356,6 +432,8 @@ clean-noinstLTLIBRARIES:
 	  echo "rm -f \"$${dir}/so_locations\""; \
 	  rm -f "$${dir}/so_locations"; \
 	done
+libdhcp-dhclient.la: $(libdhcp_dhclient_la_OBJECTS) $(libdhcp_dhclient_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK)  $(libdhcp_dhclient_la_OBJECTS) $(libdhcp_dhclient_la_LIBADD) $(LIBS)
 libdhcp-manager.la: $(libdhcp_manager_la_OBJECTS) $(libdhcp_manager_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(LINK)  $(libdhcp_manager_la_OBJECTS) $(libdhcp_manager_la_LIBADD) $(LIBS)
 
@@ -365,8 +443,9 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhclient.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-manager.Plo@am__quote@
 
@@ -397,6 +476,22 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
 
+libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo: nm-dhcp-dhclient-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo -MD -MP -MF $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Tpo -c -o libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo `test -f 'nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`nm-dhcp-dhclient-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Tpo $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dhcp-dhclient-utils.c' object='libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo `test -f 'nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`nm-dhcp-dhclient-utils.c
+
+libdhcp_dhclient_la-nm-dhcp-dhclient.lo: nm-dhcp-dhclient.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_dhclient_la-nm-dhcp-dhclient.lo -MD -MP -MF $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Tpo -c -o libdhcp_dhclient_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Tpo $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dhcp-dhclient.c' object='libdhcp_dhclient_la-nm-dhcp-dhclient.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_dhclient_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c
+
 libdhcp_manager_la-nm-dhcp-client.lo: nm-dhcp-client.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-client.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Tpo -c -o libdhcp_manager_la-nm-dhcp-client.lo `test -f 'nm-dhcp-client.c' || echo '$(srcdir)/'`nm-dhcp-client.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Plo
@@ -413,14 +508,6 @@ libdhcp_manager_la-nm-dhcp-manager.lo: nm-dhcp-manager.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_manager_la-nm-dhcp-manager.lo `test -f 'nm-dhcp-manager.c' || echo '$(srcdir)/'`nm-dhcp-manager.c
 
-libdhcp_manager_la-nm-dhcp-dhclient.lo: nm-dhcp-dhclient.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-dhclient.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhclient.Tpo -c -o libdhcp_manager_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhclient.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhclient.Plo
-@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dhcp-dhclient.c' object='libdhcp_manager_la-nm-dhcp-dhclient.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_manager_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c
-
 libdhcp_manager_la-nm-dhcp-dhcpcd.lo: nm-dhcp-dhcpcd.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-dhcpcd.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Tpo -c -o libdhcp_manager_la-nm-dhcp-dhcpcd.lo `test -f 'nm-dhcp-dhcpcd.c' || echo '$(srcdir)/'`nm-dhcp-dhcpcd.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Plo
@@ -435,6 +522,76 @@ mostlyclean-libtool:
 clean-libtool:
 	-rm -rf .libs _libs
 
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
 	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
 	unique=`for i in $$list; do \
@@ -445,10 +602,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
 	mkid -fID $$unique
 tags: TAGS
 
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
 		$(TAGS_FILES) $(LISP)
 	set x; \
 	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
 	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
 	unique=`for i in $$list; do \
 	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
@@ -467,7 +637,7 @@ TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
 	  fi; \
 	fi
 ctags: CTAGS
-CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
 		$(TAGS_FILES) $(LISP)
 	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
 	unique=`for i in $$list; do \
@@ -517,19 +687,48 @@ distdir: $(DISTFILES)
 	    || exit 1; \
 	  fi; \
 	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
 check-am: all-am
-check: check-am
+check: check-recursive
 all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
 
 install-am: all-am
 	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 
-installcheck: installcheck-am
+installcheck: installcheck-recursive
 install-strip:
 	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
 	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
@@ -546,81 +745,83 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
 
 clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
 	mostlyclean-am
 
-distclean: distclean-am
+distclean: distclean-recursive
 	-rm -rf ./$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
 
-dvi: dvi-am
+dvi: dvi-recursive
 
 dvi-am:
 
-html: html-am
+html: html-recursive
 
 html-am:
 
-info: info-am
+info: info-recursive
 
 info-am:
 
 install-data-am:
 
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
 
 install-dvi-am:
 
 install-exec-am:
 
-install-html: install-html-am
+install-html: install-html-recursive
 
 install-html-am:
 
-install-info: install-info-am
+install-info: install-info-recursive
 
 install-info-am:
 
 install-man:
 
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
 
 install-pdf-am:
 
-install-ps: install-ps-am
+install-ps: install-ps-recursive
 
 install-ps-am:
 
 installcheck-am:
 
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
 	-rm -rf ./$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
 
 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
 	mostlyclean-libtool
 
-pdf: pdf-am
+pdf: pdf-recursive
 
 pdf-am:
 
-ps: ps-am
+ps: ps-recursive
 
 ps-am:
 
 uninstall-am:
 
-.MAKE: install-am install-strip
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+	install-am install-strip tags-recursive
 
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES ctags ctags-recursive distclean \
 	distclean-compile distclean-generic distclean-libtool \
 	distclean-tags distdir dvi dvi-am html html-am info info-am \
 	install install-am install-data install-data-am install-dvi \
@@ -628,9 +829,10 @@ uninstall-am:
 	install-html-am install-info install-info-am install-man \
 	install-pdf install-pdf-am install-ps install-ps-am \
 	install-strip installcheck installcheck-am installdirs \
-	maintainer-clean maintainer-clean-generic mostlyclean \
-	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
-	pdf pdf-am ps ps-am tags uninstall uninstall-am
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am
 
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c
index 0c7f3d49..3a8b1940 100644
--- a/src/dhcp-manager/nm-dhcp-client.c
+++ b/src/dhcp-manager/nm-dhcp-client.c
@@ -156,11 +156,15 @@ stop_process (GPid pid, const char *iface)
 
 		if (ret == -1) {
 			/* Child already exited */
-			if (errno == ECHILD)
+			if (errno == ECHILD) {
+				/* Was it really our child and it exited? */
+				if (kill (pid, 0) < 0 && errno == ESRCH)
+					break;
+			} else {
+				/* Took too long; shoot it in the head */
+				i = 0;
 				break;
-			/* Took too long; shoot it in the head */
-			i = 0;
-			break;
+			}
 		}
 		g_usleep (G_USEC_PER_SEC / 5);
 	}
diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
new file mode 100644
index 00000000..cc5255ab
--- /dev/null
+++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
@@ -0,0 +1,217 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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, 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) 2010 Red Hat, Inc.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nm-dhcp-dhclient-utils.h"
+
+#define CLIENTID_TAG            "send dhcp-client-identifier"
+#define CLIENTID_FORMAT         CLIENTID_TAG " \"%s\"; # added by NetworkManager"
+#define CLIENTID_FORMAT_OCTETS  CLIENTID_TAG " %s; # added by NetworkManager"
+
+#define HOSTNAME_TAG     "send host-name"
+#define HOSTNAME_FORMAT  HOSTNAME_TAG " \"%s\"; # added by NetworkManager"
+
+#define ALSOREQ_TAG "also request "
+
+static void
+add_also_request (GPtrArray *array, const char *item)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++) {
+		if (!strcmp (g_ptr_array_index (array, i), item))
+			return;
+	}
+	g_ptr_array_add (array, g_strdup (item));
+}
+
+char *
+nm_dhcp_dhclient_create_config (const char *interface,
+                                NMSettingIP4Config *s_ip4,
+                                guint8 *anycast_addr,
+                                const char *hostname,
+                                const char *orig_path,
+                                const char *orig_contents)
+{
+	GString *new_contents;
+	GPtrArray *alsoreq;
+	int i;
+
+	new_contents = g_string_new (_("# Created by NetworkManager\n"));
+	alsoreq = g_ptr_array_sized_new (5);
+
+	if (orig_contents) {
+		char **lines, **line;
+		gboolean in_alsoreq = FALSE;
+
+		g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path);
+
+		lines = g_strsplit_set (orig_contents, "\n\r", 0);
+		for (line = lines; lines && *line; line++) {
+			char *p = *line;
+
+			if (!strlen (g_strstrip (p)))
+				continue;
+
+			/* Override config file "dhcp-client-id" and use one from the
+			 * connection.
+			 */
+		    if (   s_ip4
+		        && nm_setting_ip4_config_get_dhcp_client_id (s_ip4)
+			    && !strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG)))
+				continue;
+
+			/* Override config file hostname and use one from the connection */
+			if (hostname && !strncmp (p, HOSTNAME_TAG, strlen (HOSTNAME_TAG)))
+				continue;
+
+			/* Check for "also require" */
+			if (!strncmp (p, ALSOREQ_TAG, strlen (ALSOREQ_TAG))) {
+				in_alsoreq = TRUE;
+				p += strlen (ALSOREQ_TAG);
+			}
+
+			if (in_alsoreq) {
+				char **areq, **aiter;
+
+				/* Grab each 'also require' option and save for later */
+				areq = g_strsplit_set (p, "\t ,", -1);
+				for (aiter = areq; aiter && *aiter; aiter++) {
+					if (!strlen (g_strstrip (*aiter)))
+						continue;
+
+					if (*aiter[0] == ';') {
+						/* all done */
+						in_alsoreq = FALSE;
+						break;
+					}
+
+					if (!isalnum ((*aiter)[0]))
+						continue;
+
+					if ((*aiter)[strlen (*aiter) - 1] == ';') {
+						/* Remove the EOL marker */
+						(*aiter)[strlen (*aiter) - 1] = '\0';
+						in_alsoreq = FALSE;
+					}
+
+					add_also_request (alsoreq, *aiter);
+				}
+
+				if (areq)
+					g_strfreev (areq);
+
+				continue;
+			}
+
+			/* Existing configuration line is OK, add it to new configuration */
+			g_string_append (new_contents, *line);
+			g_string_append_c (new_contents, '\n');
+		}
+
+		if (lines)
+			g_strfreev (lines);
+	} else
+		g_string_append_c (new_contents, '\n');
+
+	/* Add NM options from connection */
+	if (s_ip4) {
+		const char *tmp;
+		gboolean added = FALSE;
+
+		tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4);
+		if (tmp) {
+			gboolean is_octets = TRUE;
+			const char *p = tmp;
+
+			while (*p) {
+				if (!isxdigit (*p) && (*p != ':')) {
+					is_octets = FALSE;
+					break;
+				}
+				p++;
+			}
+
+			/* If the client ID is just hex digits and : then don't use quotes,
+			 * because dhclient expects either a quoted ASCII string, or a byte
+			 * array formated as hex octets separated by :
+			 */
+			if (is_octets)
+				g_string_append_printf (new_contents, CLIENTID_FORMAT_OCTETS "\n", tmp);
+			else
+				g_string_append_printf (new_contents, CLIENTID_FORMAT "\n", tmp);
+			added = TRUE;
+		}
+
+		if (hostname) {
+			g_string_append_printf (new_contents, HOSTNAME_FORMAT "\n", hostname);
+			added = TRUE;
+		}
+
+		if (added)
+			g_string_append_c (new_contents, '\n');
+	}
+
+	/* Define options for classless static routes */
+	g_string_append (new_contents,
+	                 "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n");
+	g_string_append (new_contents,
+	                 "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n");
+	/* Web Proxy Auto-Discovery option (bgo #368423) */
+	g_string_append (new_contents, "option wpad code 252 = string;\n");
+
+	g_string_append_c (new_contents, '\n');
+
+	/* Everything we want to request from the DHCP server */
+	add_also_request (alsoreq, "rfc3442-classless-static-routes");
+	add_also_request (alsoreq, "ms-classless-static-routes");
+	add_also_request (alsoreq, "wpad");
+	add_also_request (alsoreq, "ntp-servers");
+
+	/* And add it to the dhclient configuration */
+	for (i = 0; i < alsoreq->len; i++) {
+		char *t = g_ptr_array_index (alsoreq, i);
+
+		g_string_append_printf (new_contents, "also request %s;\n", t);
+		g_free (t);
+	}
+	g_ptr_array_free (alsoreq, TRUE);
+
+	g_string_append_c (new_contents, '\n');
+
+	if (anycast_addr) {
+		g_string_append_printf (new_contents, "interface \"%s\" {\n"
+		                        " initial-interval 1; \n"
+		                        " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n"
+		                        "}\n",
+		                        interface,
+		                        anycast_addr[0], anycast_addr[1],
+		                        anycast_addr[2], anycast_addr[3],
+		                        anycast_addr[4], anycast_addr[5]);
+	}
+
+	return g_string_free (new_contents, FALSE);
+}
+
diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.h b/src/dhcp-manager/nm-dhcp-dhclient-utils.h
new file mode 100644
index 00000000..77def551
--- /dev/null
+++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* 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, 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) 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_DHCP_DHCLIENT_UTILS_H
+#define NM_DHCP_DHCLIENT_UTILS_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <nm-setting-ip4-config.h>
+
+char *nm_dhcp_dhclient_create_config (const char *interface,
+                                      NMSettingIP4Config *s_ip4,
+                                      guint8 *anycast_addr,
+                                      const char *hostname,
+                                      const char *orig_path,
+                                      const char *orig_contents);
+
+#endif /* NM_DHCP_DHCLIENT_UTILS_H */
+
diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c
index d8781524..f6f2a540 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient.c
@@ -39,6 +39,7 @@
 #include "nm-dhcp-dhclient.h"
 #include "nm-utils.h"
 #include "nm-logging.h"
+#include "nm-dhcp-dhclient-utils.h"
 
 G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT)
 
@@ -302,12 +303,6 @@ out:
 }
 
 
-#define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier"
-#define DHCP_CLIENT_ID_FORMAT DHCP_CLIENT_ID_TAG " \"%s\"; # added by NetworkManager"
-#define DHCP_CLIENT_ID_FORMAT_OCTETS DHCP_CLIENT_ID_TAG " %s; # added by NetworkManager"
-
-#define DHCP_HOSTNAME_TAG "send host-name"
-#define DHCP_HOSTNAME_FORMAT DHCP_HOSTNAME_TAG " \"%s\"; # added by NetworkManager"
 
 static gboolean
 merge_dhclient_config (const char *iface,
@@ -318,105 +313,27 @@ merge_dhclient_config (const char *iface,
                        const char *orig_path,
                        GError **error)
 {
-	GString *new_contents;
-	char *orig_contents = NULL;
+	char *orig = NULL, *new;
 	gboolean success = FALSE;
 
 	g_return_val_if_fail (iface != NULL, FALSE);
 	g_return_val_if_fail (conf_file != NULL, FALSE);
 
-	new_contents = g_string_new (_("# Created by NetworkManager\n"));
-
 	if (g_file_test (orig_path, G_FILE_TEST_EXISTS)) {
 		GError *read_error = NULL;
 
-		if (!g_file_get_contents (orig_path, &orig_contents, NULL, &read_error)) {
+		if (!g_file_get_contents (orig_path, &orig, NULL, &read_error)) {
 			nm_log_warn (LOGD_DHCP, "(%s): error reading dhclient configuration %s: %s",
 			             iface, orig_path, read_error->message);
 			g_error_free (read_error);
 		}
 	}
 
-	/* Add existing options, if any, but ignore stuff NM will replace. */
-	if (orig_contents) {
-		char **lines = NULL, **line;
-
-		g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path);
-
-		lines = g_strsplit_set (orig_contents, "\n\r", 0);
-		for (line = lines; lines && *line; line++) {
-			gboolean ignore = FALSE;
-
-			if (!strlen (g_strstrip (*line)))
-				continue;
-
-			if (   s_ip4
-			    && nm_setting_ip4_config_get_dhcp_client_id (s_ip4)
-			    && !strncmp (*line, DHCP_CLIENT_ID_TAG, strlen (DHCP_CLIENT_ID_TAG)))
-				ignore = TRUE;
-
-			if (   s_ip4
-			    && hostname
-			    && !strncmp (*line, DHCP_HOSTNAME_TAG, strlen (DHCP_HOSTNAME_TAG)))
-				ignore = TRUE;
-
-			if (!ignore) {
-				g_string_append (new_contents, *line);
-				g_string_append_c (new_contents, '\n');
-			}
-		}
-
-		if (lines)
-			g_strfreev (lines);
-		g_free (orig_contents);
-	} else
-		g_string_append_c (new_contents, '\n');
-
-	/* Add NM options from connection */
-	if (s_ip4) {
-		const char *tmp;
-
-		tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4);
-		if (tmp) {
-			gboolean is_octets = TRUE;
-			const char *p = tmp;
-
-			while (*p) {
-				if (!isxdigit (*p) && (*p != ':')) {
-					is_octets = FALSE;
-					break;
-				}
-				p++;
-			}
-
-			/* If the client ID is just hex digits and : then don't use quotes,
-			 * because dhclient expects either a quoted ASCII string, or a byte
-			 * array formated as hex octets separated by :
-			 */
-			if (is_octets)
-				g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT_OCTETS "\n", tmp);
-			else
-				g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", tmp);
-		}
-
-		if (hostname)
-			g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", hostname);
-	}
-
-	if (anycast_addr) {
-		g_string_append_printf (new_contents, "interface \"%s\" {\n"
-		                        " initial-interval 1; \n"
-		                        " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n"
-		                        "}\n",
-		                        iface,
-		                        anycast_addr[0], anycast_addr[1],
-		                        anycast_addr[2], anycast_addr[3],
-		                        anycast_addr[4], anycast_addr[5]);
-	}
-
-	success = g_file_set_contents (conf_file, new_contents->str, -1, error);
+	new = nm_dhcp_dhclient_create_config (iface, s_ip4, anycast_addr, hostname, orig_path, orig);
+	g_assert (new);
+	success = g_file_set_contents (conf_file, new, -1, error);
+	g_free (new);
 
-	g_string_free (new_contents, TRUE);
 	return success;
 }
 
diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c
index 378a97b6..4fb703c4 100644
--- a/src/dhcp-manager/nm-dhcp-dhcpcd.c
+++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c
@@ -128,6 +128,8 @@ real_ip4_start (NMDHCPClient *client,
 
 	g_ptr_array_add (argv, (gpointer) "-L");	/* Disable built-in IPv4LL since we use avahi-autoipd */
 
+	g_ptr_array_add (argv, (gpointer) "-G");	/* Let NM handle routing */
+
 	g_ptr_array_add (argv, (gpointer) "-c");	/* Set script file */
 	g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH );
 
diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c
index a1e3e5e2..f3c1e84f 100644
--- a/src/dhcp-manager/nm-dhcp-manager.c
+++ b/src/dhcp-manager/nm-dhcp-manager.c
@@ -317,11 +317,6 @@ nm_dhcp_manager_new (const char *client, GError **error)
 {
 	NMDHCPManagerPrivate *priv;
 	DBusGConnection *g_connection;
-	GType client_type;
-
-	client_type = get_client_type (client, error);
-	if (!client_type)
-		return NULL;
 
 	g_warn_if_fail (singleton == NULL);
 
@@ -329,13 +324,14 @@ nm_dhcp_manager_new (const char *client, GError **error)
 	priv = NM_DHCP_MANAGER_GET_PRIVATE (singleton);
 
 	/* Client-specific setup */
-	priv->client_type = client_type;
+	priv->client_type = get_client_type (client, error);
 	if (priv->client_type == NM_TYPE_DHCP_DHCLIENT)
 		priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config;
 	else if (priv->client_type == NM_TYPE_DHCP_DHCPCD)
 		priv->get_lease_config_func = nm_dhcp_dhcpcd_get_lease_config;
-	else
-		g_assert_not_reached ();
+	else {
+		nm_log_warn (LOGD_DHCP, "No usable DHCP client found! DHCP configurations will fail.");
+	}
 
 	priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal,
 	                                       NULL,
@@ -426,6 +422,9 @@ client_start (NMDHCPManager *self,
 
 	priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
 
+	/* Ensure we have a usable DHCP client */
+	g_return_val_if_fail (priv->client_type != 0, NULL);
+
 	/* Kill any old client instance */
 	client = get_client_for_iface (self, iface, ipv6);
 	if (client) {
diff --git a/src/dhcp-manager/tests/Makefile.am b/src/dhcp-manager/tests/Makefile.am
new file mode 100644
index 00000000..b075fd68
--- /dev/null
+++ b/src/dhcp-manager/tests/Makefile.am
@@ -0,0 +1,28 @@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I${top_srcdir}/libnm-util \
+	-I$(top_srcdir)/src/dhcp-manager
+
+noinst_PROGRAMS = test-dhcp-dhclient
+
+####### policy /etc/hosts test #######
+
+test_dhcp_dhclient_SOURCES = \
+	test-dhcp-dhclient.c
+
+test_dhcp_dhclient_CPPFLAGS = \
+	$(GLIB_CFLAGS)
+
+test_dhcp_dhclient_LDADD = \
+	-ldl \
+	$(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(GLIB_LIBS)
+
+if WITH_TESTS
+
+check-local: test-dhcp-dhclient
+	$(abs_builddir)/test-dhcp-dhclient
+
+endif
+
diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in
new file mode 100644
index 00000000..233cd504
--- /dev/null
+++ b/src/dhcp-manager/tests/Makefile.in
@@ -0,0 +1,610 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = test-dhcp-dhclient$(EXEEXT)
+subdir = src/dhcp-manager/tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_dhcp_dhclient_OBJECTS =  \
+	test_dhcp_dhclient-test-dhcp-dhclient.$(OBJEXT)
+test_dhcp_dhclient_OBJECTS = $(am_test_dhcp_dhclient_OBJECTS)
+am__DEPENDENCIES_1 =
+test_dhcp_dhclient_DEPENDENCIES =  \
+	$(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo "  CC    " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo "  CCLD  " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+SOURCES = $(test_dhcp_dhclient_SOURCES)
+DIST_SOURCES = $(test_dhcp_dhclient_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I${top_srcdir}/libnm-util \
+	-I$(top_srcdir)/src/dhcp-manager
+
+
+####### policy /etc/hosts test #######
+test_dhcp_dhclient_SOURCES = \
+	test-dhcp-dhclient.c
+
+test_dhcp_dhclient_CPPFLAGS = \
+	$(GLIB_CFLAGS)
+
+test_dhcp_dhclient_LDADD = \
+	-ldl \
+	$(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(GLIB_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dhcp-manager/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/dhcp-manager/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+test-dhcp-dhclient$(EXEEXT): $(test_dhcp_dhclient_OBJECTS) $(test_dhcp_dhclient_DEPENDENCIES) 
+	@rm -f test-dhcp-dhclient$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(test_dhcp_dhclient_OBJECTS) $(test_dhcp_dhclient_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+test_dhcp_dhclient-test-dhcp-dhclient.o: test-dhcp-dhclient.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_dhcp_dhclient-test-dhcp-dhclient.o -MD -MP -MF $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo -c -o test_dhcp_dhclient-test-dhcp-dhclient.o `test -f 'test-dhcp-dhclient.c' || echo '$(srcdir)/'`test-dhcp-dhclient.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test-dhcp-dhclient.c' object='test_dhcp_dhclient-test-dhcp-dhclient.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_dhcp_dhclient-test-dhcp-dhclient.o `test -f 'test-dhcp-dhclient.c' || echo '$(srcdir)/'`test-dhcp-dhclient.c
+
+test_dhcp_dhclient-test-dhcp-dhclient.obj: test-dhcp-dhclient.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_dhcp_dhclient-test-dhcp-dhclient.obj -MD -MP -MF $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo -c -o test_dhcp_dhclient-test-dhcp-dhclient.obj `if test -f 'test-dhcp-dhclient.c'; then $(CYGPATH_W) 'test-dhcp-dhclient.c'; else $(CYGPATH_W) '$(srcdir)/test-dhcp-dhclient.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test-dhcp-dhclient.c' object='test_dhcp_dhclient-test-dhcp-dhclient.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_dhcp_dhclient-test-dhcp-dhclient.obj `if test -f 'test-dhcp-dhclient.c'; then $(CYGPATH_W) 'test-dhcp-dhclient.c'; else $(CYGPATH_W) '$(srcdir)/test-dhcp-dhclient.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+@WITH_TESTS_FALSE@check-local:
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
+	clean-generic clean-libtool clean-noinstPROGRAMS ctags \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am
+
+
+@WITH_TESTS_TRUE@check-local: test-dhcp-dhclient
+@WITH_TESTS_TRUE@	$(abs_builddir)/test-dhcp-dhclient
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c
new file mode 100644
index 00000000..c1cd6f80
--- /dev/null
+++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c
@@ -0,0 +1,249 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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, 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) 2010 Red Hat, Inc.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include "nm-dhcp-dhclient-utils.h"
+#include "nm-utils.h"
+
+#define DEBUG 0
+
+static void
+test_config (const char *orig,
+             const char *expected,
+             const char *hostname,
+             const char *dhcp_client_id,
+             const char *iface,
+             guint8 *anycast_addr)
+{
+	NMSettingIP4Config *s_ip4;
+	char *new;
+
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, dhcp_client_id, NULL);
+
+	new = nm_dhcp_dhclient_create_config (iface,
+	                                      s_ip4,
+	                                      anycast_addr,
+	                                      hostname,
+	                                      "/path/to/dhclient.conf",
+	                                      orig);
+	g_assert (new != NULL);
+
+#if DEBUG
+	g_message ("\n- NEW ---------------------------------\n"
+	           "%s"
+	           "+ EXPECTED ++++++++++++++++++++++++++++++\n"
+	           "%s"
+	           "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+	           new, expected);
+#endif
+	g_assert (strlen (new) == strlen (expected));
+	g_assert (strcmp (new, expected) == 0);
+	g_free (new);
+}
+
+/*******************************************/
+
+static const char *orig_missing_expected = \
+	"# Created by NetworkManager\n"
+	"\n"
+	"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
+	"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
+	"option wpad code 252 = string;\n"
+	"\n"
+	"also request rfc3442-classless-static-routes;\n"
+	"also request ms-classless-static-routes;\n"
+	"also request wpad;\n"
+	"also request ntp-servers;\n"
+	"\n";
+
+static void
+test_orig_missing (void)
+{
+	test_config (NULL, orig_missing_expected,
+	             NULL,
+	             NULL,
+	             "eth0",
+	             NULL);
+}
+
+/*******************************************/
+
+static const char *override_client_id_orig = \
+	"send dhcp-client-identifier 00:30:04:20:7A:08;\n";
+
+static const char *override_client_id_expected = \
+	"# Created by NetworkManager\n"
+	"# Merged from /path/to/dhclient.conf\n"
+	"\n"
+	"send dhcp-client-identifier 11:22:33:44:55:66; # added by NetworkManager\n"
+	"\n"
+	"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
+	"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
+	"option wpad code 252 = string;\n"
+	"\n"
+	"also request rfc3442-classless-static-routes;\n"
+	"also request ms-classless-static-routes;\n"
+	"also request wpad;\n"
+	"also request ntp-servers;\n"
+	"\n";
+
+static void
+test_override_client_id (void)
+{
+	test_config (override_client_id_orig, override_client_id_expected,
+	             NULL,
+	             "11:22:33:44:55:66",
+	             "eth0",
+	             NULL);
+}
+
+/*******************************************/
+
+static const char *override_hostname_orig = \
+	"send host-name \"foobar\";\n";
+
+static const char *override_hostname_expected = \
+	"# Created by NetworkManager\n"
+	"# Merged from /path/to/dhclient.conf\n"
+	"\n"
+	"send host-name \"blahblah\"; # added by NetworkManager\n"
+	"\n"
+	"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
+	"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
+	"option wpad code 252 = string;\n"
+	"\n"
+	"also request rfc3442-classless-static-routes;\n"
+	"also request ms-classless-static-routes;\n"
+	"also request wpad;\n"
+	"also request ntp-servers;\n"
+	"\n";
+
+static void
+test_override_hostname (void)
+{
+	test_config (override_hostname_orig, override_hostname_expected,
+	             "blahblah",
+	             NULL,
+	             "eth0",
+	             NULL);
+}
+
+/*******************************************/
+
+static const char *existing_alsoreq_orig = \
+	"also request something;\n"
+	"also request another-thing;\n"
+	;
+
+static const char *existing_alsoreq_expected = \
+	"# Created by NetworkManager\n"
+	"# Merged from /path/to/dhclient.conf\n"
+	"\n"
+	"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
+	"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
+	"option wpad code 252 = string;\n"
+	"\n"
+	"also request something;\n"
+	"also request another-thing;\n"
+	"also request rfc3442-classless-static-routes;\n"
+	"also request ms-classless-static-routes;\n"
+	"also request wpad;\n"
+	"also request ntp-servers;\n"
+	"\n";
+
+static void
+test_existing_alsoreq (void)
+{
+	test_config (existing_alsoreq_orig, existing_alsoreq_expected,
+	             NULL,
+	             NULL,
+	             "eth0",
+	             NULL);
+}
+
+/*******************************************/
+
+static const char *existing_multiline_alsoreq_orig = \
+	"also request something another-thing yet-another-thing\n"
+	"    foobar baz blah;\n"
+	;
+
+static const char *existing_multiline_alsoreq_expected = \
+	"# Created by NetworkManager\n"
+	"# Merged from /path/to/dhclient.conf\n"
+	"\n"
+	"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
+	"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
+	"option wpad code 252 = string;\n"
+	"\n"
+	"also request something;\n"
+	"also request another-thing;\n"
+	"also request yet-another-thing;\n"
+	"also request foobar;\n"
+	"also request baz;\n"
+	"also request blah;\n"
+	"also request rfc3442-classless-static-routes;\n"
+	"also request ms-classless-static-routes;\n"
+	"also request wpad;\n"
+	"also request ntp-servers;\n"
+	"\n";
+
+static void
+test_existing_multiline_alsoreq (void)
+{
+	test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected,
+	             NULL,
+	             NULL,
+	             "eth0",
+	             NULL);
+}
+
+/*******************************************/
+
+#if GLIB_CHECK_VERSION(2,25,12)
+typedef GTestFixtureFunc TCFunc;
+#else
+typedef void (*TCFunc)(void);
+#endif
+
+#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL)
+
+int main (int argc, char **argv)
+{
+	GTestSuite *suite;
+
+	g_test_init (&argc, &argv, NULL);
+
+	g_type_init ();
+
+	suite = g_test_get_root ();
+
+	g_test_suite_add (suite, TESTCASE (test_orig_missing, NULL));
+	g_test_suite_add (suite, TESTCASE (test_override_client_id, NULL));
+	g_test_suite_add (suite, TESTCASE (test_override_hostname, NULL));
+	g_test_suite_add (suite, TESTCASE (test_existing_alsoreq, NULL));
+	g_test_suite_add (suite, TESTCASE (test_existing_multiline_alsoreq, NULL));
+
+	return g_test_run ();
+}
+
diff --git a/src/dns-manager/Makefile.am b/src/dns-manager/Makefile.am
index 1ffe62dc..7b5fc4f8 100644
--- a/src/dns-manager/Makefile.am
+++ b/src/dns-manager/Makefile.am
@@ -14,7 +14,9 @@ libdns_manager_la_SOURCES = \
 	nm-dns-dnsmasq.h \
 	nm-dns-dnsmasq.c \
 	nm-dns-bind.h \
-	nm-dns-bind.c
+	nm-dns-bind.c \
+	nm-dns-utils.h \
+	nm-dns-utils.c
 
 libdns_manager_la_CPPFLAGS = \
 	$(DBUS_CFLAGS) \
diff --git a/src/dns-manager/Makefile.in b/src/dns-manager/Makefile.in
index 496d3756..69b76815 100644
--- a/src/dns-manager/Makefile.in
+++ b/src/dns-manager/Makefile.in
@@ -57,7 +57,8 @@ libdns_manager_la_DEPENDENCIES =  \
 am_libdns_manager_la_OBJECTS = libdns_manager_la-nm-dns-manager.lo \
 	libdns_manager_la-nm-dns-plugin.lo \
 	libdns_manager_la-nm-dns-dnsmasq.lo \
-	libdns_manager_la-nm-dns-bind.lo
+	libdns_manager_la-nm-dns-bind.lo \
+	libdns_manager_la-nm-dns-utils.lo
 libdns_manager_la_OBJECTS = $(am_libdns_manager_la_OBJECTS)
 AM_V_lt = $(am__v_lt_$(V))
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@ -185,6 +186,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -199,6 +204,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -289,7 +295,9 @@ libdns_manager_la_SOURCES = \
 	nm-dns-dnsmasq.h \
 	nm-dns-dnsmasq.c \
 	nm-dns-bind.h \
-	nm-dns-bind.c
+	nm-dns-bind.c \
+	nm-dns-utils.h \
+	nm-dns-utils.c
 
 libdns_manager_la_CPPFLAGS = \
 	$(DBUS_CFLAGS) \
@@ -357,6 +365,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-dnsmasq.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-utils.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -417,6 +426,14 @@ libdns_manager_la-nm-dns-bind.lo: nm-dns-bind.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-bind.lo `test -f 'nm-dns-bind.c' || echo '$(srcdir)/'`nm-dns-bind.c
 
+libdns_manager_la-nm-dns-utils.lo: nm-dns-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdns_manager_la-nm-dns-utils.lo -MD -MP -MF $(DEPDIR)/libdns_manager_la-nm-dns-utils.Tpo -c -o libdns_manager_la-nm-dns-utils.lo `test -f 'nm-dns-utils.c' || echo '$(srcdir)/'`nm-dns-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libdns_manager_la-nm-dns-utils.Tpo $(DEPDIR)/libdns_manager_la-nm-dns-utils.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dns-utils.c' object='libdns_manager_la-nm-dns-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-utils.lo `test -f 'nm-dns-utils.c' || echo '$(srcdir)/'`nm-dns-utils.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c
index 41c8e2a6..9cc01978 100644
--- a/src/dns-manager/nm-dns-dnsmasq.c
+++ b/src/dns-manager/nm-dns-dnsmasq.c
@@ -33,6 +33,7 @@
 #include "nm-logging.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
+#include "nm-dns-utils.h"
 
 G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN)
 
@@ -75,9 +76,11 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split)
 	gboolean added = FALSE;
 
 	if (split) {
+		char **domains, **iter;
+
 		/* FIXME: it appears that dnsmasq can only handle one nameserver
-		 * per domain (at the manpage seems to indicate that) so only use
-		 * the first nameserver here.
+		 * per domain (and the manpage says this too) so only use the first
+		 * nameserver here.
 		 */
 		addr.s_addr = nm_ip4_config_get_nameserver (ip4, 0);
 		memset (&buf[0], 0, sizeof (buf));
@@ -103,6 +106,17 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split)
 				added = TRUE;
 			}
 		}
+
+		/* Ensure reverse-DNS works by directing queries for in-addr.arpa
+		 * domains to the split domain's nameserver.
+		 */
+		domains = nm_dns_utils_get_ip4_rdns_domains (ip4);
+		if (domains) {
+			for (iter = domains; iter && *iter; iter++)
+				g_string_append_printf (str, "server=/%s/%s\n", *iter, buf);
+			g_strfreev (domains);
+			added = TRUE;
+		}
 	}
 
 	/* If no searches or domains, just add the namservers */
@@ -216,7 +230,7 @@ update (NMDnsPlugin *plugin,
 	}
 
 	/* Now add interface configs without split DNS */
-	for (iter = (GSList *) dev_configs; iter;iter = g_slist_next (iter)) {
+	for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) {
 		if (NM_IS_IP4_CONFIG (iter->data))
 			add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
 		else if (NM_IS_IP6_CONFIG (iter->data))
@@ -224,7 +238,7 @@ update (NMDnsPlugin *plugin,
 	}
 
 	/* And any other random configs */
-	for (iter = (GSList *) other_configs; iter;iter = g_slist_next (iter)) {
+	for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) {
 		if (NM_IS_IP4_CONFIG (iter->data))
 			add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
 		else if (NM_IS_IP6_CONFIG (iter->data))
diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c
index 7a6fbbc9..32800d0b 100644
--- a/src/dns-manager/nm-dns-manager.c
+++ b/src/dns-manager/nm-dns-manager.c
@@ -16,7 +16,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com>
- * Copyright (C) 2004 - 2010 Red Hat, Inc.
+ * Copyright (C) 2004 - 2011 Red Hat, Inc.
  * Copyright (C) 2005 - 2008 Novell, Inc.
  *   and others
  */
@@ -583,6 +583,7 @@ update_dns (NMDnsManager *self,
 	rc.nameservers = g_ptr_array_new ();
 	rc.domain = NULL;
 	rc.searches = g_ptr_array_new ();
+	rc.nis_domain = NULL;
 	rc.nis_servers = g_ptr_array_new ();
 
 	if (priv->ip4_vpn_config)
@@ -860,7 +861,7 @@ nm_dns_manager_remove_ip4_config (NMDnsManager *mgr,
 
 	g_object_unref (config);
 
-	if (config_changed (mgr))
+	if (!config_changed (mgr))
 		return TRUE;
 
 	if (!update_dns (mgr, iface, FALSE, &error)) {
@@ -905,7 +906,7 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr,
 	if (!g_slist_find (priv->configs, config))
 		priv->configs = g_slist_append (priv->configs, g_object_ref (config));
 
-	if (config_changed (mgr))
+	if (!config_changed (mgr))
 		return TRUE;
 
 	if (!update_dns (mgr, iface, FALSE, &error)) {
@@ -945,7 +946,7 @@ nm_dns_manager_remove_ip6_config (NMDnsManager *mgr,
 
 	g_object_unref (config);	
 
-	if (config_changed (mgr))
+	if (!config_changed (mgr))
 		return TRUE;
 
 	if (!update_dns (mgr, iface, FALSE, &error)) {
diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c
new file mode 100644
index 00000000..615adfd1
--- /dev/null
+++ b/src/dns-manager/nm-dns-utils.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* 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, 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) 2010 Red Hat, Inc.
+ *
+ */
+
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "nm-dns-utils.h"
+#include "nm-utils.h"
+
+static void
+add_ip4_to_rdns_array (guint32 ip, GPtrArray *domains) /* network byte order */
+{
+	guint32 defprefix;
+	guchar *p;
+	char *str = NULL;
+	int i;
+
+	defprefix = nm_utils_ip4_get_default_prefix (ip);
+
+	/* Convert to host byte order, mask the host bits, and convert back */
+	ip = ntohl (ip);
+	ip &= 0xFFFFFFFF << (32 - defprefix);
+	ip = htonl (ip);
+	p = (guchar *) &ip;
+
+	if (defprefix == 8)
+		str = g_strdup_printf ("%u.in-addr.arpa", p[0] & 0xFF);
+	else if (defprefix == 16)
+		str = g_strdup_printf ("%u.%u.in-addr.arpa", p[1] & 0xFF, p[0] & 0xFF);
+	else if (defprefix == 24)
+		str = g_strdup_printf ("%u.%u.%u.in-addr.arpa", p[2] & 0xFF, p[1] & 0xFF, p[0] & 0xFF);
+
+	g_return_if_fail (str != NULL);
+
+	/* Suppress duplicates */
+	for (i = 0; i < domains->len; i++) {
+		if (strcmp (str, g_ptr_array_index (domains, i)) == 0)
+			break;
+	}
+
+	if (i == domains->len)
+		g_ptr_array_add (domains, str);
+	else
+		g_free (str);
+}
+
+char **
+nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4)
+{
+	GPtrArray *domains = NULL;
+	int i;
+
+	g_return_val_if_fail (ip4 != NULL, NULL);
+
+	domains = g_ptr_array_sized_new (5);
+
+	/* To calculate the reverse DNS domains for this IP4 config, we take
+	 * all the IP addresses and routes in the config, calculate the network
+	 * portion, and convert that to classful, and use the network bits for
+	 * the final domain.  FIXME: better handle classless routing, which might
+	 * require us to add multiple domains for each actual network prefix to
+	 * cover all the separate networks in that block.
+	 */
+
+	for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) {
+		NMIP4Address *addr = nm_ip4_config_get_address (ip4, i);
+
+		add_ip4_to_rdns_array (nm_ip4_address_get_address (addr), domains);
+	}
+
+	for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) {
+		NMIP4Route *route = nm_ip4_config_get_route (ip4, i);
+
+		add_ip4_to_rdns_array (nm_ip4_route_get_dest (route), domains);
+	}
+
+	/* Terminating NULL so we can use g_strfreev() to free it */
+	g_ptr_array_add (domains, NULL);
+
+	/* Free the array and return NULL if the only element was the ending NULL */
+	return (char **) g_ptr_array_free (domains, (domains->len == 1));
+}
+
diff --git a/src/dns-manager/nm-dns-utils.h b/src/dns-manager/nm-dns-utils.h
new file mode 100644
index 00000000..daa6711c
--- /dev/null
+++ b/src/dns-manager/nm-dns-utils.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* 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, 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) 2010 Red Hat, Inc.
+ *
+ */
+
+#ifndef NM_DNS_UTILS_H
+#define NM_DNS_UTILS_H
+
+#include "nm-ip4-config.h"
+
+char **nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4);
+
+#endif  /* NM_DNS_UTILS_H */
+
diff --git a/src/dnsmasq-manager/Makefile.in b/src/dnsmasq-manager/Makefile.in
index 8cb698bc..fb62d61b 100644
--- a/src/dnsmasq-manager/Makefile.in
+++ b/src/dnsmasq-manager/Makefile.in
@@ -183,6 +183,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -197,6 +201,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c
index 701c0782..ca2f9dc4 100644
--- a/src/dnsmasq-manager/nm-dnsmasq-manager.c
+++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c
@@ -254,7 +254,6 @@ create_dm_cmd_line (const char *iface,
 	struct in_addr addr;
 	char buf[INET_ADDRSTRLEN + 15];
 	char localaddr[INET_ADDRSTRLEN + 1];
-	int i;
 
 	dm_binary = nm_find_dnsmasq ();
 	if (!dm_binary) {
@@ -278,17 +277,10 @@ create_dm_cmd_line (const char *iface,
 	/* dnsmasq may read from it's default config file location, which if that
 	 * location is a valid config file, it will combine with the options here
 	 * and cause undesirable side-effects.  Like sending bogus IP addresses
-	 * as the gateway or whatever.  So give dnsmasq a bogus config file
-	 * location to avoid screwing up the configuration we're passing to it.
+	 * as the gateway or whatever.  So tell dnsmasq not to use any config file
+	 * at all.
 	 */
-	memset (buf, 0, sizeof (buf));
-	strcpy (buf, "/tmp/");
-	for (i = 5; i < 15; i++)
-		buf[i] = (char) (g_random_int_range ((guint32) 'a', (guint32) 'z') & 0xFF);
-	strcat (buf, ".conf");
-
 	nm_cmd_line_add_string (cmd, "--conf-file");
-	nm_cmd_line_add_string (cmd, buf);
 
 	nm_cmd_line_add_string (cmd, "--no-hosts");
 	nm_cmd_line_add_string (cmd, "--keep-in-foreground");
diff --git a/src/ip6-manager/Makefile.in b/src/ip6-manager/Makefile.in
index 13a3e0e9..1e8da3da 100644
--- a/src/ip6-manager/Makefile.in
+++ b/src/ip6-manager/Makefile.in
@@ -183,6 +183,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -197,6 +201,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c
index f6f6127c..7ffa2d1f 100644
--- a/src/ip6-manager/nm-ip6-manager.c
+++ b/src/ip6-manager/nm-ip6-manager.c
@@ -76,6 +76,11 @@ typedef struct {
 	time_t expires;
 } NMIP6RDNSS;
 
+typedef struct {
+	char domain[256];
+	time_t expires;
+} NMIP6DNSSL;
+
 /******************************************************************/
 
 typedef struct {
@@ -97,6 +102,9 @@ typedef struct {
 	GArray *rdnss_servers;
 	guint rdnss_timeout_id;
 
+	GArray *dnssl_domains;
+	guint dnssl_timeout_id;
+
 	guint ip6flags_poll_id;
 
 	guint32 ra_flags;
@@ -122,6 +130,10 @@ nm_ip6_device_destroy (NMIP6Device *device)
 		g_array_free (device->rdnss_servers, TRUE);
 	if (device->rdnss_timeout_id)
 		g_source_remove (device->rdnss_timeout_id);
+	if (device->dnssl_domains)
+		g_array_free (device->dnssl_domains, TRUE);
+	if (device->dnssl_timeout_id)
+		g_source_remove (device->dnssl_timeout_id);
 	if (device->ip6flags_poll_id)
 		g_source_remove (device->ip6flags_poll_id);
 
@@ -155,6 +167,8 @@ nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
 
 	device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
 
+	device->dnssl_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL));
+
 	g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device);
 
 	/* and the original value of IPv6 enable/disable */
@@ -285,7 +299,7 @@ set_rdnss_timeout (NMIP6Device *device)
 				nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided nameserver %s",
 				            device->iface, buf);
 			}
-			g_array_remove_index_fast (device->rdnss_servers, i--);
+			g_array_remove_index (device->rdnss_servers, i--);
 			continue;
 		}
 
@@ -300,6 +314,61 @@ set_rdnss_timeout (NMIP6Device *device)
 	}
 }
 
+static void set_dnssl_timeout (NMIP6Device *device);
+
+static gboolean
+dnssl_expired (gpointer user_data)
+{
+	NMIP6Device *device = user_data;
+	CallbackInfo info = { device, IP6_DHCP_OPT_NONE };
+
+	nm_log_dbg (LOGD_IP6, "(%s): IPv6 DNSSL information expired", device->iface);
+
+	set_dnssl_timeout (device);
+	emit_config_changed (&info);
+	return FALSE;
+}
+
+static void
+set_dnssl_timeout (NMIP6Device *device)
+{
+	time_t expires = 0, now = time (NULL);
+	NMIP6DNSSL *dnssl;
+	int i;
+
+	if (device->dnssl_timeout_id) {
+		g_source_remove (device->dnssl_timeout_id);
+		device->dnssl_timeout_id = 0;
+	}
+
+	/* Find the soonest expiration time. */
+	for (i = 0; i < device->dnssl_domains->len; i++) {
+		dnssl = &g_array_index (device->dnssl_domains, NMIP6DNSSL, i);
+		if (dnssl->expires == 0)
+			continue;
+
+		/* If the entry has already expired, remove it; the "+ 1" is
+		 * because g_timeout_add_seconds() might fudge the timing a
+		 * bit.
+		 */
+		if (dnssl->expires <= now + 1) {
+			nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided domain %s",
+			            device->iface, dnssl->domain);
+			g_array_remove_index (device->dnssl_domains, i--);
+			continue;
+		}
+
+		if (!expires || dnssl->expires < expires)
+			expires = dnssl->expires;
+	}
+
+	if (expires) {
+		device->dnssl_timeout_id = g_timeout_add_seconds (expires - now,
+		                                                  dnssl_expired,
+		                                                  device);
+	}
+}
+
 static CallbackInfo *
 callback_info_new (NMIP6Device *device, guint dhcp_opts, gboolean success)
 {
@@ -569,13 +638,258 @@ process_prefix (NMIP6Manager *manager, struct nl_msg *msg)
  */
 
 #define ND_OPT_RDNSS 25
+#define ND_OPT_DNSSL 31
+
 struct nd_opt_rdnss {
 	uint8_t nd_opt_rdnss_type;
 	uint8_t nd_opt_rdnss_len;
 	uint16_t nd_opt_rdnss_reserved1;
 	uint32_t nd_opt_rdnss_lifetime;
 	/* followed by one or more IPv6 addresses */
-};
+} __attribute__ ((packed));
+
+struct nd_opt_dnssl {
+	uint8_t nd_opt_dnssl_type;
+	uint8_t nd_opt_dnssl_len;
+	uint16_t nd_opt_dnssl_reserved1;
+	uint32_t nd_opt_dnssl_lifetime;
+	/* followed by one or more suffixes */
+} __attribute__ ((packed));
+
+static gboolean
+process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt)
+{
+	size_t opt_len;
+	struct nd_opt_rdnss *rdnss_opt;
+	time_t now = time (NULL);
+	struct in6_addr *addr;
+	GArray *new_servers;
+	NMIP6RDNSS server, *cur_server;
+	gboolean changed = FALSE;
+	guint i;
+
+	opt_len = opt->nd_opt_len;
+
+	if (opt_len < 3 || (opt_len & 1) == 0)
+		return FALSE;
+
+	rdnss_opt = (struct nd_opt_rdnss *) opt;
+
+	new_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
+
+	/* Pad the DNS server expiry somewhat to give a bit of slack in cases
+	 * where one RA gets lost or something (which can happen on unreliable
+	 * links like WiFi where certain types of frames are not retransmitted).
+	 * Note that 0 has special meaning and is therefore not adjusted.
+	 */
+	server.expires = ntohl (rdnss_opt->nd_opt_rdnss_lifetime);
+	if (server.expires > 0)
+		server.expires += now + 10;
+
+	for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) {
+		char buf[INET6_ADDRSTRLEN + 1];
+
+		if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf)))
+			strcpy(buf, "[invalid]");
+
+		for (i = 0; i < device->rdnss_servers->len; i++) {
+			cur_server = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i));
+
+			if (!IN6_ARE_ADDR_EQUAL (addr, &cur_server->addr))
+				continue;
+
+			cur_server->expires = server.expires;
+
+			if (server.expires > 0) {
+				nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided nameserver %s (expires in %d seconds)",
+				            device->iface, buf,
+				            server.expires - now);
+				break;
+			}
+
+			nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided nameserver %s on router request",
+			            device->iface, buf);
+
+			g_array_remove_index (device->rdnss_servers, i);
+			changed = TRUE;
+			break;
+		}
+
+		if (server.expires == 0)
+			continue;
+		if (i < device->rdnss_servers->len)
+			continue;
+
+		nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)",
+		            device->iface, buf, server.expires - now);
+
+		server.addr = *addr;
+		g_array_append_val (new_servers, server);
+	}
+
+	/* New servers must be added in the order they are listed in the
+	 * RA option and before any existing servers.
+	 *
+	 * Note: This is the place to remove servers if we want to cap the
+	 *       number of resolvers. The RFC states that the one to expire
+	 *       first of the existing servers should be removed.
+	 */
+	if (new_servers->len) {
+		g_array_prepend_vals (device->rdnss_servers,
+		                      new_servers->data, new_servers->len);
+		changed = TRUE;
+	}
+
+	g_array_free (new_servers, TRUE);
+
+	/* Timeouts may have changed even if IPs didn't */
+	set_rdnss_timeout (device);
+
+	return changed;
+}
+
+static const char *
+parse_dnssl_domain (const unsigned char *buffer, size_t maxlen)
+{
+	static char domain[256];
+	size_t label_len;
+
+	domain[0] = '\0';
+
+	while (maxlen > 0) {
+		label_len = *buffer;
+		buffer++;
+		maxlen--;
+
+		if (label_len == 0)
+			return domain;
+
+		if (label_len > maxlen)
+			return NULL;
+		if ((sizeof (domain) - strlen (domain)) < (label_len + 2))
+			return NULL;
+
+		if (domain[0] != '\0')
+			strcat (domain, ".");
+		strncat (domain, (const char *)buffer, label_len);
+		buffer += label_len;
+		maxlen -= label_len;
+	}
+
+	return NULL;
+}
+
+static gboolean
+process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt)
+{
+	size_t opt_len;
+	struct nd_opt_dnssl *dnssl_opt;
+	unsigned char *opt_ptr;
+	time_t now = time (NULL);
+	GArray *new_domains;
+	NMIP6DNSSL domain, *cur_domain;
+	gboolean changed;
+	guint i;
+
+	opt_len = opt->nd_opt_len;
+
+	if (opt_len < 2)
+		return FALSE;
+
+	dnssl_opt = (struct nd_opt_dnssl *) opt;
+
+	opt_ptr = (unsigned char *)(dnssl_opt + 1);
+	opt_len = (opt_len - 1) * 8; /* prefer bytes for later handling */
+
+	new_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL));
+
+	changed = FALSE;
+
+	/* Pad the DNS server expiry somewhat to give a bit of slack in cases
+	 * where one RA gets lost or something (which can happen on unreliable
+	 * links like wifi where certain types of frames are not retransmitted).
+	 * Note that 0 has special meaning and is therefore not adjusted.
+	 */
+	domain.expires = ntohl (dnssl_opt->nd_opt_dnssl_lifetime);
+	if (domain.expires > 0)
+		domain.expires += now + 10;
+
+	while (opt_len) {
+		const char *domain_str;
+
+		domain_str = parse_dnssl_domain (opt_ptr, opt_len);
+		if (domain_str == NULL) {
+			nm_log_dbg (LOGD_IP6, "(%s): invalid DNSSL option, parsing aborted",
+			            device->iface);
+			break;
+		}
+
+		/* The DNSSL encoding of domains happen to occupy the same size
+		 * as the length of the resulting string, including terminating
+		 * null. */
+		opt_ptr += strlen (domain_str) + 1;
+		opt_len -= strlen (domain_str) + 1;
+
+		/* Ignore empty domains. They're probably just padding... */
+		if (domain_str[0] == '\0')
+			continue;
+
+		for (i = 0; i < device->dnssl_domains->len; i++) {
+			cur_domain = &(g_array_index (device->dnssl_domains, NMIP6DNSSL, i));
+
+			if (strcmp (domain_str, cur_domain->domain) != 0)
+				continue;
+
+			cur_domain->expires = domain.expires;
+
+			if (domain.expires > 0) {
+				nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided domain %s (expires in %d seconds)",
+				            device->iface, domain_str,
+				            domain.expires - now);
+				break;
+			}
+
+			nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided domain %s on router request",
+			            device->iface, domain_str);
+
+			g_array_remove_index (device->dnssl_domains, i);
+			changed = TRUE;
+			break;
+		}
+
+		if (domain.expires == 0)
+			continue;
+		if (i < device->dnssl_domains->len)
+			continue;
+
+		nm_log_dbg (LOGD_IP6, "(%s): found RA-provided domain %s (expires in %d seconds)",
+		            device->iface, domain_str, domain.expires - now);
+
+		g_assert (strlen (domain_str) < sizeof (domain.domain));
+		strcpy (domain.domain, domain_str);
+		g_array_append_val (new_domains, domain);
+	}
+
+	/* New domains must be added in the order they are listed in the
+	 * RA option and before any existing domains.
+	 *
+	 * Note: This is the place to remove domains if we want to cap the
+	 *       number of domains. The RFC states that the one to expire
+	 *       first of the existing domains should be removed.
+	 */
+	if (new_domains->len) {
+		g_array_prepend_vals (device->dnssl_domains,
+		                      new_domains->data, new_domains->len);
+		changed = TRUE;
+	}
+
+	g_array_free (new_domains, TRUE);
+
+	/* Timeouts may have changed even if domains didn't */
+	set_dnssl_timeout (device);
+
+	return changed;
+}
 
 static NMIP6Device *
 process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
@@ -583,13 +897,8 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
 	NMIP6Device *device;
 	struct nduseroptmsg *ndmsg;
 	struct nd_opt_hdr *opt;
-	guint opts_len, i;
-	time_t now = time (NULL);
-	struct nd_opt_rdnss *rdnss_opt;
-	struct in6_addr *addr;
-	GArray *servers;
-	NMIP6RDNSS server, *sa, *sb;
-	gboolean changed;
+	guint opts_len;
+	gboolean changed = FALSE;
 
 	nm_log_dbg (LOGD_IP6, "processing netlink nduseropt message");
 
@@ -608,8 +917,6 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
 		return NULL;
 	}
 
-	servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
-
 	opt = (struct nd_opt_hdr *) (ndmsg + 1);
 	opts_len = ndmsg->nduseropt_opts_len;
 
@@ -619,66 +926,19 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
 		if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3))
 			break;
 
-		if (opt->nd_opt_type != ND_OPT_RDNSS)
-			goto next;
-
-		if (nd_opt_len < 3 || (nd_opt_len & 1) == 0)
-			goto next;
-
-		rdnss_opt = (struct nd_opt_rdnss *) opt;
-
-		/* Pad the DNS server expiry somewhat to give a bit of slack in cases
-		 * where one RA gets lost or something (which can happen on unreliable
-		 * links like wifi where certain types of frames are not retransmitted).
-		 */
-		server.expires = now + ntohl (rdnss_opt->nd_opt_rdnss_lifetime) + 10;
-
-		for (addr = (struct in6_addr *) (rdnss_opt + 1); nd_opt_len >= 2; addr++, nd_opt_len -= 2) {
-			char buf[INET6_ADDRSTRLEN + 1];
-
-			if (inet_ntop (AF_INET6, addr, buf, sizeof (buf))) {
-				nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)",
-				            device->iface, buf,
-				            ntohl (rdnss_opt->nd_opt_rdnss_lifetime));
-			}
-
-			server.addr = *addr;
-			g_array_append_val (servers, server);
+		switch (opt->nd_opt_type) {
+		case ND_OPT_RDNSS:
+			changed = process_nduseropt_rdnss (device, opt);
+			break;
+		case ND_OPT_DNSSL:
+			changed = process_nduseropt_dnssl (device, opt);
+			break;
 		}
 
-	next:
 		opts_len -= opt->nd_opt_len << 3;
 		opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3));
 	}
 
-	/* See if anything (other than expiration time) changed */
-	if (servers->len != device->rdnss_servers->len)
-		changed = TRUE;
-	else {
-		for (i = 0; i < servers->len; i++) {
-			sa = &(g_array_index (servers, NMIP6RDNSS, i));
-			sb = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i));
-			if (IN6_ARE_ADDR_EQUAL (&sa->addr, &sb->addr) == FALSE) {
-				changed = TRUE;
-				break;
-			}
-		}
-		changed = FALSE;
-	}
-
-	if (changed) {
-		nm_log_dbg (LOGD_IP6, "(%s): RA-provided nameservers changed", device->iface);
-	}
-
-	/* Always copy in new servers (even if unchanged) to get their updated
-	 * expiration times.
-	 */
-	g_array_free (device->rdnss_servers, TRUE);
-	device->rdnss_servers = servers;
-
-	/* Timeouts may have changed even if IPs didn't */
-	set_rdnss_timeout (device);
-
 	if (changed)
 		return device;
 	else
@@ -791,7 +1051,7 @@ netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer us
 	}
 }
 
-void
+gboolean
 nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
                                   int ifindex,
                                   NMSettingIP6Config *s_ip6,
@@ -801,16 +1061,17 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
 	NMIP6Device *device;
 	const char *method = NULL;
 
-	g_return_if_fail (NM_IS_IP6_MANAGER (manager));
-	g_return_if_fail (ifindex > 0);
+	g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), FALSE);
+	g_return_val_if_fail (ifindex > 0, FALSE);
 
 	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
 
 	device = nm_ip6_device_new (manager, ifindex);
-	g_return_if_fail (device != NULL);
-	g_return_if_fail (   strchr (device->iface, '/') == NULL
-	                  && strcmp (device->iface, "all") != 0
-	                  && strcmp (device->iface, "default") != 0);
+	g_return_val_if_fail (device != NULL, FALSE);
+	g_return_val_if_fail (   strchr (device->iface, '/') == NULL
+	                      && strcmp (device->iface, "all") != 0
+	                      && strcmp (device->iface, "default") != 0,
+	                      FALSE);
 
 	if (s_ip6)
 		method = nm_setting_ip6_config_get_method (s_ip6);
@@ -825,6 +1086,8 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
 		device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
 		nm_utils_do_sysctl (accept_ra_path, "1\n");
 	}
+
+	return TRUE;
 }
 
 static gboolean
@@ -1014,6 +1277,14 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
 			nm_ip6_config_add_nameserver (config, &rdnss[i].addr);
 	}
 
+	/* Add DNS domains */
+	if (device->dnssl_domains) {
+		NMIP6DNSSL *dnssl = (NMIP6DNSSL *)(device->dnssl_domains->data);
+
+		for (i = 0; i < device->dnssl_domains->len; i++)
+			nm_ip6_config_add_domain (config, dnssl[i].domain);
+	}
+
 	return config;
 }
 
diff --git a/src/ip6-manager/nm-ip6-manager.h b/src/ip6-manager/nm-ip6-manager.h
index 77c11068..2732c63e 100644
--- a/src/ip6-manager/nm-ip6-manager.h
+++ b/src/ip6-manager/nm-ip6-manager.h
@@ -71,7 +71,7 @@ typedef struct {
 GType nm_ip6_manager_get_type (void);
 
 NMIP6Manager *nm_ip6_manager_get               (void);
-void          nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
+gboolean      nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
                                                 int ifindex,
                                                 NMSettingIP6Config *s_ip6,
                                                 const char *accept_ra_path);
diff --git a/src/logging/Makefile.in b/src/logging/Makefile.in
index 36f04548..48a29b8f 100644
--- a/src/logging/Makefile.in
+++ b/src/logging/Makefile.in
@@ -180,6 +180,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -194,6 +198,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c
index 5b5622fd..c5f57a13 100644
--- a/src/logging/nm-logging.c
+++ b/src/logging/nm-logging.c
@@ -235,14 +235,14 @@ void _nm_log (const char *loc,
 
 	if ((log_level & LOGL_DEBUG) && (level == LOGL_DEBUG)) {
 		g_get_current_time (&tv);
-		syslog (LOG_INFO, "<debug> [%ld.%ld] [%s] %s(): %s\n", tv.tv_sec, tv.tv_usec, loc, func, msg);
+		syslog (LOG_INFO, "<debug> [%ld.%ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg);
 	} else if ((log_level & LOGL_INFO) && (level == LOGL_INFO))
-		syslog (LOG_INFO, "<info> %s\n", msg);
+		syslog (LOG_INFO, "<info> %s", msg);
 	else if ((log_level & LOGL_WARN) && (level == LOGL_WARN))
-		syslog (LOG_WARNING, "<warn> %s\n", msg);
+		syslog (LOG_WARNING, "<warn> %s", msg);
 	else if ((log_level & LOGL_ERR) && (level == LOGL_ERR)) {
 		g_get_current_time (&tv);
-		syslog (LOG_ERR, "<error> [%ld.%ld] [%s] %s(): %s\n", tv.tv_sec, tv.tv_usec, loc, func, msg);
+		syslog (LOG_ERR, "<error> [%ld.%ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg);
 	}
 	g_free (msg);
 }
diff --git a/src/main.c b/src/main.c
index 7e75f05e..b22c769d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,6 +49,7 @@
 #include "nm-netlink-monitor.h"
 #include "nm-vpn-manager.h"
 #include "nm-logging.h"
+#include "nm-policy-hosts.h"
 
 #if !defined(NM_DIST_VERSION)
 # define NM_DIST_VERSION VERSION
@@ -466,7 +467,7 @@ main (int argc, char *argv[])
 		{ "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ','", "plugin1,plugin2" },
 		{ "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, "Log level: one of [ERR, WARN, INFO, DEBUG]", "INFO" },
 		{ "log-domains", 0, 0, G_OPTION_ARG_STRING, &log_domains,
-		        "Log domains separated by ',': any combination of [NONE,HW,RKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,WIFI_SCAN,IP4,IP6,AUTOIP4,DNS,VPN,SHARING,SUPPLICANT,USER_SET,SYS_SET,SUSPEND,CORE,DEVICE,OLPC]",
+		        "Log domains separated by ',': any combination of [NONE,HW,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,WIFI_SCAN,IP4,IP6,AUTOIP4,DNS,VPN,SHARING,SUPPLICANT,USER_SET,SYS_SET,SUSPEND,CORE,DEVICE,OLPC]",
 		        "HW,RFKILL,WIFI" },
 		{NULL}
 	};
@@ -713,6 +714,9 @@ main (int argc, char *argv[])
 		goto done;
 	}
 
+	/* Clean leftover "# Added by NetworkManager" entries from /etc/hosts */
+	nm_policy_hosts_clean_etc_hosts ();
+
 	nm_manager_start (manager);
 
 	/* Bring up the loopback interface. */
diff --git a/src/modem-manager/Makefile.in b/src/modem-manager/Makefile.in
index 042b202d..c640df5b 100644
--- a/src/modem-manager/Makefile.in
+++ b/src/modem-manager/Makefile.in
@@ -186,6 +186,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -200,6 +204,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c
index e07b818b..b3f7eaa1 100644
--- a/src/modem-manager/nm-modem.c
+++ b/src/modem-manager/nm-modem.c
@@ -876,6 +876,12 @@ modem_properties_changed (DBusGProxy *proxy,
 		priv->mm_enabled = g_value_get_boolean (value);
 		g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED);
 	}
+
+	value = g_hash_table_lookup (props, "IpMethod");
+	if (value && G_VALUE_HOLDS_UINT (value)) {
+		priv->ip_method = g_value_get_uint (value);
+		g_object_notify (G_OBJECT (self), NM_MODEM_IP_METHOD);
+	}
 }
 
 /*****************************************************************************/
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c
index 2529e77f..7d131401 100644
--- a/src/nm-activation-request.c
+++ b/src/nm-activation-request.c
@@ -35,6 +35,7 @@
 #include "nm-properties-changed-signal.h"
 #include "nm-active-connection.h"
 #include "nm-dbus-glib-types.h"
+#include "nm-active-connection-glue.h"
 
 
 static void secrets_provider_interface_init (NMSecretsProviderInterface *sp_interface_class);
@@ -304,64 +305,15 @@ nm_act_request_class_init (NMActRequestClass *req_class)
 	object_class->finalize = finalize;
 
 	/* properties */
-	g_object_class_install_property
-		(object_class, PROP_SERVICE_NAME,
-		 g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME,
-							  "Service name",
-							  "Service name",
-							  NULL,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_CONNECTION,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_CONNECTION,
-							  "Connection",
-							  "Connection",
-							  DBUS_TYPE_G_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_SPECIFIC_OBJECT,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
-							  "Specific object",
-							  "Specific object",
-							  DBUS_TYPE_G_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEVICES,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
-							  "Devices",
-							  "Devices",
-							  DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_STATE,
-		 g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE,
-							  "State",
-							  "State",
-							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
-							  NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
-							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEFAULT,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
-							   "Default",
-							   "Is the default IPv4 active connection",
-							   FALSE,
-							   G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEFAULT6,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
-							   "Default6",
-							   "Is the default IPv6 active connection",
-							   FALSE,
-							   G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_VPN,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN,
-							   "VPN",
-							   "Is a VPN connection",
-							   FALSE,
-							   G_PARAM_READABLE));
+    nm_active_connection_install_properties (object_class,
+                                             PROP_SERVICE_NAME,
+                                             PROP_CONNECTION,
+                                             PROP_SPECIFIC_OBJECT,
+                                             PROP_DEVICES,
+                                             PROP_STATE,
+                                             PROP_DEFAULT,
+                                             PROP_DEFAULT6,
+                                             PROP_VPN);
 
 	/* Signals */
 	signals[CONNECTION_SECRETS_UPDATED] =
@@ -386,9 +338,10 @@ nm_act_request_class_init (NMActRequestClass *req_class)
 
 	signals[PROPERTIES_CHANGED] = 
 		nm_properties_changed_signal_new (object_class,
-								    G_STRUCT_OFFSET (NMActRequestClass, properties_changed));
+		                                  G_STRUCT_OFFSET (NMActRequestClass, properties_changed));
 
-	nm_active_connection_install_type_info (object_class);
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (req_class),
+	                                 &dbus_glib_nm_active_connection_object_info);
 }
 
 static gboolean
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 4207e145..90495bd2 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -21,8 +21,8 @@
 #include <glib.h>
 #include "nm-active-connection.h"
 #include "NetworkManager.h"
-#include "nm-active-connection-glue.h"
 #include "nm-logging.h"
+#include "nm-dbus-glib-types.h"
 
 char *
 nm_active_connection_get_next_object_path (void)
@@ -33,13 +33,6 @@ nm_active_connection_get_next_object_path (void)
 }
 
 void
-nm_active_connection_install_type_info (GObjectClass *klass)
-{
-	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
-									 &dbus_glib_nm_active_connection_object_info);
-}
-
-void
 nm_active_connection_scope_to_value (NMConnection *connection, GValue *value)
 {
 	if (!connection) {
@@ -60,4 +53,73 @@ nm_active_connection_scope_to_value (NMConnection *connection, GValue *value)
 	}
 }
 
+void
+nm_active_connection_install_properties (GObjectClass *object_class,
+                                         guint prop_service_name,
+                                         guint prop_connection,
+                                         guint prop_specific_object,
+                                         guint prop_devices,
+                                         guint prop_state,
+                                         guint prop_default,
+                                         guint prop_default6,
+                                         guint prop_vpn)
+{
+	g_object_class_install_property (object_class, prop_service_name,
+		g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME,
+		                     "Service name",
+		                     "Service name",
+		                     NULL,
+		                     G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_connection,
+		g_param_spec_boxed (NM_ACTIVE_CONNECTION_CONNECTION,
+		                    "Connection",
+		                    "Connection",
+		                    DBUS_TYPE_G_OBJECT_PATH,
+		                    G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_specific_object,
+		g_param_spec_boxed (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
+		                    "Specific object",
+		                    "Specific object",
+		                    DBUS_TYPE_G_OBJECT_PATH,
+		                    G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_devices,
+		g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
+		                    "Devices",
+		                    "Devices",
+		                    DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
+		                    G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_state,
+		g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE,
+		                   "State",
+		                   "State",
+		                   NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
+		                   NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
+		                   NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
+		                   G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_default,
+		g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
+		                      "Default",
+		                      "Is the default IPv4 active connection",
+		                      FALSE,
+		                      G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_default6,
+		g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
+		                      "Default6",
+		                      "Is the default IPv6 active connection",
+		                      FALSE,
+		                      G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, prop_vpn,
+		g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN,
+		                      "VPN",
+		                      "Is a VPN connection",
+		                      FALSE,
+		                      G_PARAM_READABLE));
+}
 
diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h
index 6a463cb2..5dde3087 100644
--- a/src/nm-active-connection.h
+++ b/src/nm-active-connection.h
@@ -35,8 +35,16 @@
 
 char *nm_active_connection_get_next_object_path (void);
 
-void nm_active_connection_install_type_info (GObjectClass *klass);
-
 void nm_active_connection_scope_to_value (NMConnection *connection, GValue *value);
 
+void nm_active_connection_install_properties (GObjectClass *object_class,
+                                              guint prop_service_name,
+                                              guint prop_connection,
+                                              guint prop_specific_object,
+                                              guint prop_devices,
+                                              guint prop_state,
+                                              guint prop_default,
+                                              guint prop_default6,
+                                              guint prop_vpn);
+
 #endif /* NM_ACTIVE_CONNECTION_H */
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index 08bbc501..49e58887 100644
--- a/src/nm-device-ethernet.c
+++ b/src/nm-device-ethernet.c
@@ -308,7 +308,7 @@ _update_s390_subchannels (NMDeviceEthernet *self)
 	const char *iface;
 	GUdevClient *client;
 	GUdevDevice *dev;
-	GUdevDevice *parent;
+	GUdevDevice *parent = NULL;
 	const char *parent_path, *item, *driver;
 	const char *subsystems[] = { "net", NULL };
 	GDir *dir;
@@ -487,8 +487,42 @@ constructor (GType type,
 }
 
 static void
+clear_secrets_tries (NMDevice *device)
+{
+	NMActRequest *req;
+	NMConnection *connection;
+
+	req = nm_device_get_act_request (device);
+	if (req) {
+		connection = nm_act_request_get_connection (req);
+		/* Clear wired secrets tries on success, failure, or when deactivating */
+		g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL);
+	}
+}
+
+static void
+device_state_changed (NMDevice *device,
+                      NMDeviceState new_state,
+                      NMDeviceState old_state,
+                      NMDeviceStateReason reason,
+                      gpointer user_data)
+{
+
+	switch (new_state) {
+	case NM_DEVICE_STATE_ACTIVATED:
+	case NM_DEVICE_STATE_FAILED:
+	case NM_DEVICE_STATE_DISCONNECTED:
+		clear_secrets_tries (device);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
 nm_device_ethernet_init (NMDeviceEthernet * self)
 {
+	g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), NULL);
 }
 
 static gboolean
@@ -1751,6 +1785,9 @@ real_deactivate_quickly (NMDevice *device)
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
+	/* Clear wired secrets tries when deactivating */
+	clear_secrets_tries (device);
+
 	if (priv->pending_ip4_config) {
 		g_object_unref (priv->pending_ip4_config);
 		priv->pending_ip4_config = NULL;
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
index b09d1125..451284dc 100644
--- a/src/nm-device-wifi.c
+++ b/src/nm-device-wifi.c
@@ -1231,6 +1231,15 @@ real_deactivate_quickly (NMDevice *dev)
 	NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMAccessPoint *orig_ap = nm_device_wifi_get_activation_ap (self);
+	NMActRequest *req;
+	NMConnection *connection;
+
+	req = nm_device_get_act_request (dev);
+	if (req) {
+		connection = nm_act_request_get_connection (req);
+		/* Clear wireless secrets tries when deactivating */
+		g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
+	}
 
 	cleanup_association_attempt (self, TRUE);
 
diff --git a/src/nm-device.c b/src/nm-device.c
index e8f0b206..9c771c2a 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -790,6 +790,7 @@ addrconf6_setup (NMDevice *self)
 	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingIP6Config *s_ip6;
+	gboolean success;
 
 	req = nm_device_get_act_request (self);
 	g_assert (req);
@@ -809,13 +810,14 @@ addrconf6_setup (NMDevice *self)
 	}
 
 	s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
-	nm_ip6_manager_prepare_interface (priv->ip6_manager,
-	                                  nm_device_get_ip_ifindex (self),
-	                                  s_ip6,
-	                                  priv->ip6_accept_ra_path);
-	priv->ip6_waiting_for_config = TRUE;
+	success = nm_ip6_manager_prepare_interface (priv->ip6_manager,
+	                                            nm_device_get_ip_ifindex (self),
+	                                            s_ip6,
+	                                            priv->ip6_accept_ra_path);
+	if (success)
+		priv->ip6_waiting_for_config = TRUE;
 
-	return TRUE;
+	return success;
 }
 
 static void
@@ -1951,7 +1953,9 @@ nm_device_activate_stage4_ip4_config_get (gpointer user_data)
 	g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
 					   NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
 
+nm_log_info (LOGD_DEVICE | LOGD_IP4, "Scheduling stage 5");
 	nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET);
+nm_log_info (LOGD_DEVICE | LOGD_IP4, "Done scheduling stage 5");
 
 out:
 	nm_log_info (LOGD_DEVICE | LOGD_IP4,
@@ -2803,17 +2807,22 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
 {
 	NMDevice *self = NM_DEVICE (device);
 	NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
+	gboolean tried_ipv6 = FALSE;
 
 	g_return_if_fail (self != NULL);
 
 	nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason: %d).",
 	             nm_device_get_iface (self), reason);
 
+	/* Check this before deactivate_quickly is run */
+	if (NM_DEVICE_GET_PRIVATE (self)->ip6_manager)
+		tried_ipv6 = TRUE;
+
 	nm_device_deactivate_quickly (self);
 
 	/* Take out any entries in the routing table and any IP address the device had. */
-	nm_system_device_flush_routes (self, nm_device_get_ip6_config (self) ? AF_UNSPEC : AF_INET);
-	nm_system_device_flush_addresses (self);
+	nm_system_device_flush_routes (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
+	nm_system_device_flush_addresses (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
 	nm_device_update_ip4_address (self);	
 
 	/* Clean up nameservers and addresses */
@@ -3321,7 +3330,7 @@ dispose (GObject *object)
 	if (   nm_device_interface_can_assume_connections (NM_DEVICE_INTERFACE (self))
 	    && (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED)) {
 		NMConnection *connection;
-	    NMSettingIP4Config *s_ip4;
+	    NMSettingIP4Config *s_ip4 = NULL;
 		const char *method = NULL;
 
 		/* Only system connections can be left up */
@@ -3334,9 +3343,8 @@ dispose (GObject *object)
 			 * to check that.
 			 */
 			s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
-			g_assert (s_ip4);
-
-			method = nm_setting_ip4_config_get_method (s_ip4);
+			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))
diff --git a/src/nm-manager.c b/src/nm-manager.c
index eb393fac..8b24aa51 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -16,7 +16,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2009 Novell, Inc.
- * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2011 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -464,18 +464,19 @@ nm_manager_update_state (NMManager *manager)
 }
 
 static void
-ignore_cb (NMSettingsConnectionInterface *connection, GError *error, gpointer user_data)
-{
-}
-
-static void
 update_active_connection_timestamp (NMManager *manager, NMDevice *device)
 {
 	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingsConnectionInterface *connection_interface;
 	NMManagerPrivate *priv;
+	const char *connection_uuid;
+	guint64 timestamp;
+	guint64 *ts_ptr;
+	GKeyFile *timestamps_file;
+	char *data, *tmp;
+	gsize len;
+	GError *error = NULL;
 
 	g_return_if_fail (NM_IS_DEVICE (device));
 
@@ -490,16 +491,38 @@ update_active_connection_timestamp (NMManager *manager, NMDevice *device)
 	if (nm_connection_get_scope (connection) != NM_CONNECTION_SCOPE_SYSTEM)
 		return;
 
+	/* Update timestamp in connection's object data */
+	timestamp = (guint64) time (NULL);
+	ts_ptr = g_new (guint64, 1);
+	*ts_ptr = timestamp;
+	g_object_set_data_full (G_OBJECT (connection), NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG, ts_ptr, g_free);
+
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
-	g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL), NULL);
+	connection_uuid = nm_setting_connection_get_uuid (s_con);
 
-	if (nm_setting_connection_get_read_only (s_con))
-		return;
+	/* Save timestamp to timestamps database file */
+	timestamps_file = g_key_file_new ();
+	if (!g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
+		if (!(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT))
+			nm_log_warn (LOGD_SYS_SET, "error parsing timestamps file '%s': %s", NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, error->message);
+		g_clear_error (&error);
+	}
+
+	tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
+	g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp);
+	g_free (tmp);
 
-	connection_interface = nm_settings_interface_get_connection_by_path (NM_SETTINGS_INTERFACE (priv->sys_settings),
-	                                                                     nm_connection_get_path (connection));
-	nm_settings_connection_interface_update (connection_interface, ignore_cb, NULL);
+	data = g_key_file_to_data (timestamps_file, &len, &error);
+	if (data) {
+		g_file_set_contents (NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, data, len, &error);
+		g_free (data);
+	}
+	if (error) {
+		nm_log_warn (LOGD_SYS_SET, "error saving timestamp: %s", error->message);
+		g_error_free (error);
+	}
+	g_key_file_free (timestamps_file);
 }
 
 static void
@@ -1356,6 +1379,12 @@ user_proxy_init (NMManager *self)
 	g_return_if_fail (self != NULL);
 	g_return_if_fail (priv->user_proxy == NULL);
 
+	/* Don't try to initialize the user settings proxy if the user
+	 * settings service doesn't actually exist.
+	 */
+	if (!nm_dbus_manager_name_has_owner (priv->dbus_mgr, NM_DBUS_SERVICE_USER_SETTINGS))
+		return;
+
 	bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
 	priv->user_proxy = dbus_g_proxy_new_for_name_owner (bus,
 	                                                    NM_DBUS_SERVICE_USER_SETTINGS,
@@ -2426,6 +2455,14 @@ udev_device_removed_cb (NMUdevManager *manager,
 
 	ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX");
 	device = find_device_by_ifindex (self, ifindex);
+	if (!device) {
+		/* On removal we won't always be able to read properties anymore, as
+		 * they may have already been removed from sysfs.  Instead, we just
+		 * have to fall back to the device's interface name.
+		 */
+		device = find_device_by_iface (self, g_udev_device_get_name (udev_device));
+	}
+
 	if (device)
 		priv->devices = remove_one_device (self, priv->devices, device, FALSE);
 }
@@ -3845,6 +3882,23 @@ nm_manager_auto_user_connections_allowed (NMManager *self)
 	       && priv->user_con_perm == NM_AUTH_CALL_RESULT_YES;
 }
 
+static guint64
+get_connection_timestamp (NMConnection *connection)
+{
+	if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
+		guint64 *ts_p;
+
+		ts_p = (guint64 *) g_object_get_data (G_OBJECT (connection), NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG);
+		return ts_p != NULL ? *ts_p : 0;
+	} else {
+		NMSettingConnection *s_con;
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+		g_assert (s_con);
+		return nm_setting_connection_get_timestamp (s_con);
+	}
+}
+
 static int
 connection_sort (gconstpointer pa, gconstpointer pb)
 {
@@ -3852,6 +3906,7 @@ connection_sort (gconstpointer pa, gconstpointer pb)
 	NMSettingConnection *con_a;
 	NMConnection *b = NM_CONNECTION (pb);
 	NMSettingConnection *con_b;
+	guint64 ts_a, ts_b;
 
 	con_a = (NMSettingConnection *) nm_connection_get_setting (a, NM_TYPE_SETTING_CONNECTION);
 	g_assert (con_a);
@@ -3864,10 +3919,13 @@ connection_sort (gconstpointer pa, gconstpointer pb)
 		return 1;
 	}
 
-	if (nm_setting_connection_get_timestamp (con_a) > nm_setting_connection_get_timestamp (con_b))
+	ts_a = get_connection_timestamp (a);
+	ts_b = get_connection_timestamp (b);
+	if (ts_a > ts_b)
 		return -1;
-	else if (nm_setting_connection_get_timestamp (con_a) == nm_setting_connection_get_timestamp (con_b))
+	else if (ts_a == ts_b)
 		return 0;
+
 	return 1;
 }
 
@@ -3967,8 +4025,7 @@ nm_manager_start (NMManager *self)
 	 * they will be queried when the user settings service shows up on the
 	 * bus in nm_manager_name_owner_changed().
 	 */
-	if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, NM_DBUS_SERVICE_USER_SETTINGS))
-		user_proxy_init (self);
+	user_proxy_init (self);
 
 	nm_udev_manager_query_devices (priv->udev_mgr);
 	bluez_manager_resync_devices (self);
@@ -4351,10 +4408,11 @@ dispose (GObject *object)
 
 	/* Unregister property filter */
 	bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
-	g_assert (bus);
-	dbus_connection = dbus_g_connection_get_connection (bus);
-	g_assert (dbus_connection);
-	dbus_connection_remove_filter (dbus_connection, prop_filter, manager);
+	if (bus) {
+		dbus_connection = dbus_g_connection_get_connection (bus);
+		g_assert (dbus_connection);
+		dbus_connection_remove_filter (dbus_connection, prop_filter, manager);
+	}
 	g_object_unref (priv->dbus_mgr);
 
 	if (priv->bluez_mgr)
diff --git a/src/nm-policy-hostname.c b/src/nm-policy-hostname.c
index 42a2e0f9..4fe69c5a 100644
--- a/src/nm-policy-hostname.c
+++ b/src/nm-policy-hostname.c
@@ -30,7 +30,6 @@
 
 #include "nm-logging.h"
 #include "nm-policy-hostname.h"
-#include "nm-policy-hosts.h"
 
 /************************************************************************/
 
@@ -206,74 +205,39 @@ hostname_thread_is_dead (HostnameThread *ht)
 /************************************************************************/
 
 #define FALLBACK_HOSTNAME4 "localhost.localdomain"
-#define FALLBACK_HOSTNAME6 "localhost6.localdomain6"
 
 gboolean
-nm_policy_set_system_hostname (const char *new_hostname,
-                               const char *ip4_addr,
-                               const char *ip6_addr,
-                               const char *msg)
+nm_policy_set_system_hostname (const char *new_hostname, const char *msg)
 {
 	char old_hostname[HOST_NAME_MAX + 1];
-	int ret = 0;
 	const char *name;
-	gboolean set_hostname = TRUE, changed = FALSE, old_valid = TRUE;
+	int ret;
 
 	if (new_hostname)
 		g_warn_if_fail (strlen (new_hostname));
 
-	name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4;
-
 	old_hostname[HOST_NAME_MAX] = '\0';
 	errno = 0;
 	ret = gethostname (old_hostname, HOST_NAME_MAX);
 	if (ret != 0) {
 		nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s",
 		             errno, strerror (errno));
-		old_valid = FALSE;
 	} else {
 		/* Don't set the hostname if it isn't actually changing */
 		if (   (new_hostname && !strcmp (old_hostname, new_hostname))
 		    || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4)))
-			set_hostname = FALSE;
-
-		if (old_hostname[0] == '\0')
-			old_valid = FALSE;
-	}
-
-	if (set_hostname) {
-		nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg);
-		ret = sethostname (name, strlen (name));
-		if (ret != 0) {
-			nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
-			             name, errno, strerror (errno));
 			return FALSE;
-		}
 	}
 
-	/* But even if the hostname isn't changing, always try updating /etc/hosts
-	 * just in case the hostname changed while NM wasn't running; we need to
-	 * make sure that /etc/hosts has valid mappings for '127.0.0.1' and the
-	 * current system hostname.  If those exist,
-	 * nm_policy_hosts_update_etc_hosts() will just return and won't touch
-	 * /etc/hosts at all.
-	 */
-	if (!nm_policy_hosts_update_etc_hosts (name,
-	                                       old_valid ? old_hostname : NULL,
-	                                       FALLBACK_HOSTNAME4,
-	                                       FALLBACK_HOSTNAME6,
-	                                       ip4_addr,
-	                                       ip6_addr,
-	                                       &changed)) {
-		/* error updating /etc/hosts; fallback to localhost.localdomain */
-		nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME4 "' (error updating /etc/hosts)");
-		ret = sethostname (FALLBACK_HOSTNAME4, strlen (FALLBACK_HOSTNAME4));
-		if (ret != 0) {
-			nm_log_warn (LOGD_DNS, "couldn't set the fallback system hostname (%s): (%d) %s",
-			             FALLBACK_HOSTNAME4, errno, strerror (errno));
-		}
+	name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4;
+
+	nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg);
+	ret = sethostname (name, strlen (name));
+	if (ret != 0) {
+		nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
+		             name, errno, strerror (errno));
 	}
 
-	return changed;
+	return (ret == 0);
 }
 
diff --git a/src/nm-policy-hostname.h b/src/nm-policy-hostname.h
index 9c768847..e76713f1 100644
--- a/src/nm-policy-hostname.h
+++ b/src/nm-policy-hostname.h
@@ -24,10 +24,7 @@
 
 #include <glib.h>
 
-gboolean nm_policy_set_system_hostname (const char *new_hostname,
-                                        const char *ip4_addr,
-                                        const char *ip6_addr,
-                                        const char *msg);
+gboolean nm_policy_set_system_hostname (const char *new_hostname, const char *msg);
 
 
 typedef struct HostnameThread HostnameThread;
diff --git a/src/nm-policy-hosts.c b/src/nm-policy-hosts.c
index 7f9cff80..8bbd1d3b 100644
--- a/src/nm-policy-hosts.c
+++ b/src/nm-policy-hosts.c
@@ -20,526 +20,74 @@
 
 #include <config.h>
 #include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <arpa/inet.h>
 
 #include "nm-policy-hosts.h"
 #include "nm-logging.h"
 
-#define IP4_LH "127.0.0.1"
-#define IP6_LH "::1"
-
-gboolean
-nm_policy_hosts_find_token (const char *line, const char *token)
-{
-	const char *start = line, *p = line;
-
-	g_return_val_if_fail (line != NULL, FALSE);
-	g_return_val_if_fail (token != NULL, FALSE);
-	g_return_val_if_fail (strlen (token) > 0, FALSE);
-
-	/* Walk through the line to find the next whitespace character */
-	while (p <= line + strlen (line)) {
-		if (isblank (*p) || (*p == '\0')) {
-			/* Token starts with 'start' and ends with 'end' */
-			if ((p > start) && *start && (p - start == strlen (token)) && !strncmp (start, token, (p - start)))
-				return TRUE; /* found */
-
-			/* not found; advance start and continue looking */
-			start = p + 1;
-		}
-		p++;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-is_local_mapping (const char *str, gboolean ip6, const char *hostname)
-{
-	const char *addr = ip6 ? IP6_LH : IP4_LH;
-	const char *fallback = ip6 ? "localhost6" : "localhost";
-
-	return (   !strncmp (str, addr, strlen (addr))
-	        && nm_policy_hosts_find_token (str, hostname ? hostname : fallback));
-}
-
-static gboolean
-is_ip4_addr (const char *str)
-{
-	struct in_addr found;
-	char buf[INET_ADDRSTRLEN + 2];
-	const char *p = str;
-	guint32 i = 0;
-
-	memset (buf, 0, sizeof (buf));
-	while (*p && !isblank (*p) && (i < sizeof (buf)))
-		buf[i++] = *p++;
-
-	return inet_pton (AF_INET, buf, &found) == 1 ? TRUE : FALSE;
-}
-
-static gboolean
-ip4_addr_matches (const char *str, const char *ip4_addr)
-{
-	struct in_addr found, given;
-	char buf[INET_ADDRSTRLEN + 2];
-	const char *p = str;
-	guint32 i = 0;
-
-	g_return_val_if_fail (ip4_addr != NULL, FALSE);
-
-	memset (buf, 0, sizeof (buf));
-	while (*p && !isblank (*p) && (i < sizeof (buf)))
-		buf[i++] = *p++;
-
-	if (inet_pton (AF_INET, buf, &found) != 1)
-		return FALSE;
-	if (inet_pton (AF_INET, ip4_addr, &given) != 1)
-		return FALSE;
-
-	return memcmp (&found, &given, sizeof (found)) == 0;
-}
-
-static gboolean
-is_ip6_addr (const char *str)
-{
-	struct in6_addr found;
-	char buf[INET6_ADDRSTRLEN + 2];
-	const char *p = str;
-	guint32 i = 0;
-
-	memset (buf, 0, sizeof (buf));
-	while (*p && !isblank (*p) && (i < sizeof (buf)))
-		buf[i++] = *p++;
-
-	return inet_pton (AF_INET6, buf, &found) == 1 ? TRUE : FALSE;
-}
-
-static gboolean
-ip6_addr_matches (const char *str, const char *ip6_addr)
-{
-	struct in6_addr found, given;
-	char buf[INET6_ADDRSTRLEN + 2];
-	const char *p = str;
-	guint32 i = 0;
-
-	g_return_val_if_fail (ip6_addr != NULL, FALSE);
-
-	memset (buf, 0, sizeof (buf));
-	while (*p && !isblank (*p) && (i < sizeof (buf)))
-		buf[i++] = *p++;
-
-	if (inet_pton (AF_INET6, buf, &found) != 1)
-		return FALSE;
-	if (inet_pton (AF_INET6, ip6_addr, &given) != 1)
-		return FALSE;
-
-	return memcmp (&found, &given, sizeof (found)) == 0;
-}
-
-static char *
-get_custom_hostnames (const char *line,
-                      const char *hostname,
-                      const char *old_hostname,
-                      const char *short_hostname,
-                      const char *fallback_hostname)
-{
-	char **items = NULL, **iter;
-	guint start = 0;
-	GString *str = NULL;
-	char *custom = NULL;
-
-	g_return_val_if_fail (line != NULL, NULL);
-
-	if (!strncmp (line, IP4_LH, strlen (IP4_LH)))
-		start = strlen (IP4_LH);
-	else if (!strncmp (line, IP6_LH, strlen (IP6_LH)))
-		start = strlen (IP6_LH);
-
-	g_return_val_if_fail (start > 0, NULL);
-
-	/* Split the line into tokens */
-	items = g_strsplit_set (line + start, " \t", -1);
-	if (!items)
-		return NULL;
-
-	str = g_string_sized_new (50);
-	/* Ignore current & old hostnames, and localhost-anything */
-	for (iter = items; iter && *iter; iter++) {
-		if (*iter[0] == '\0')
-			continue;
-		if (hostname && !strcmp (*iter, hostname))
-			continue;
-		if (old_hostname && !strcmp (*iter, old_hostname))
-			continue;
-		if (short_hostname && !strcmp (*iter, short_hostname))
-			continue;
-		if (fallback_hostname && !strcmp (*iter, fallback_hostname))
-			continue;
-		if (!strcmp (*iter, "localhost"))
-			continue;
-		if (!strcmp (*iter, "localhost6"))
-			continue;
-		if (!strcmp (*iter, "localhost.localdomain"))
-			continue;
-		if (!strcmp (*iter, "localhost4.localdomain4"))
-			continue;
-		if (!strcmp (*iter, "localhost6.localdomain6"))
-			continue;
-
-		/* Found a custom hostname */
-		g_string_append_c (str, '\t');
-		g_string_append (str, *iter);
-	}
-
-	if (str->len)
-		custom = g_string_free (str, FALSE);
-	else
-		g_string_free (str, TRUE);
-
-	g_strfreev (items);
-	return custom;
-}
-
 #define ADDED_TAG "# Added by NetworkManager"
 
 GString *
-nm_policy_get_etc_hosts (const char **lines,
-                         gsize existing_len,
-                         const char *hostname,
-                         const char *old_hostname,
-                         const char *fallback_hostname4,
-                         const char *fallback_hostname6,
-                         const char *ip4_addr,
-                         const char *ip6_addr,
-                         GError **error)
+nm_policy_get_etc_hosts (const char *contents, gsize contents_len)
 {
-	GString *contents = NULL;
-	const char **line;
-	gboolean found_localhost4 = FALSE;
-	gboolean found_localhost6 = FALSE;
-	gboolean found_host4 = FALSE;
-	gboolean found_host6 = FALSE;
-	gboolean found_user_host4 = FALSE;
-	gboolean found_user_host6 = FALSE;
-	gboolean initial_comments = TRUE;
-	gboolean added = FALSE;
-	gboolean hostname4_is_fallback;
-	gboolean hostname6_is_fallback;
-	gboolean host4_before = FALSE;
-	gboolean host6_before = FALSE;
-	gboolean no_stale = TRUE;
-	char *short_hostname = NULL;
-	char *custom4 = NULL;
-	char *custom6 = NULL;
-
-	g_return_val_if_fail (lines != NULL, FALSE);
-	g_return_val_if_fail (hostname != NULL, FALSE);
-
-	hostname4_is_fallback = !strcmp (hostname, fallback_hostname4);
-	hostname6_is_fallback = !strcmp (hostname, fallback_hostname6);
-
-	/* Find the short hostname, like 'foo' from 'foo.bar.baz'; we want to
-	 * make sure that the entries we add for this host also include the short
-	 * hostname too so that if the resolver does not answer queries for the
-	 * machine's actual hostname/domain, that stuff like 'ping foo' still works.
-	 */
-	if (!hostname4_is_fallback || !hostname6_is_fallback) {
-		char *dot;
-
-		short_hostname = g_strdup (hostname);
-		dot = strchr (short_hostname, '.');
-		if (dot && *(dot+1))
-			*dot = '\0';
-		else {
-			g_free (short_hostname);
-			short_hostname = NULL;
-		}
-	}
-
-	/* We need the following in /etc/hosts:
-	 *
-	 * 1) current hostname mapped to current IPv4 addresses if IPv4 is active
-	 * 2) current hostname mapped to current IPv6 addresses if IPv6 is active
-	 * 3) 'localhost' mapped to 127.0.0.1
-	 * 4) 'localhost6' mapped to ::1
-	 *
-	 * If all these things exist we don't need to bother updating the file.
-	 */
-
-	if (!ip4_addr)
-		host4_before = TRUE;
-	if (!ip6_addr)
-		host6_before = TRUE;
-
-	/* Look for the four cases from above */
-	for (line = lines; lines && *line; line++) {
-		gboolean found_hostname = FALSE;
-
-		if ((*line[0] == '\0') || (*line[0] == '#'))
-			continue;
+	char **lines = NULL, **iter;
+	GString *new_contents = NULL;
 
-		found_hostname = nm_policy_hosts_find_token (*line, hostname);
-		if (found_hostname) {
-			/* Found the current hostname on this line */
-			if (ip4_addr && ip4_addr_matches (*line, ip4_addr)) {
-				found_host4 = TRUE;
-				if (strstr (*line, ADDED_TAG)) {
-					if (!host4_before)
-						host4_before = !found_localhost4;
-				} else {
-					found_user_host4 = TRUE;
-					host4_before = TRUE;  /* Ignore if user added mapping manually */
-				}
-			} else if (!ip4_addr && strstr (*line, ADDED_TAG)) {
-				/* If this is a stale NM-added IPv4 entry we need to remove it,
-				 * so make sure we update /etc/hosts.
-				 */
-				if (is_ip4_addr (*line))
-					no_stale = FALSE;
-			}
+	if (contents_len == 0 || !strstr (contents, ADDED_TAG))
+		return NULL;
 
-			if (ip6_addr && ip6_addr_matches (*line, ip6_addr)) {
-				found_host6 = TRUE;
-				if (strstr (*line, ADDED_TAG)) {
-					if (!host6_before)
-						host6_before = !found_localhost6;
-				} else {
-					found_user_host6 = TRUE;
-					host6_before = TRUE;  /* Ignore if user added mapping manually */
-				}
-			} else if (!ip6_addr && strstr (*line, ADDED_TAG)) {
-				/* If this is a stale NM-added IPv6 entry we need to remove it,
-				 * so make sure we update /etc/hosts.
-				 */
-				if (is_ip6_addr (*line))
-					no_stale = FALSE;
-			}
-		}
+	new_contents = g_string_sized_new (contents_len);
 
-		if (is_local_mapping (*line, FALSE, "localhost")) {
-			/* a 127.0.0.1 line containing 'localhost' */
-			found_localhost4 = TRUE;
-			custom4 = get_custom_hostnames (*line, hostname, old_hostname, short_hostname, fallback_hostname4);
-			if (!ip4_addr) {
-				/* If there's no IP-specific mapping for the current hostname
-				 * but that hostname is present on in the local mapping line,
-				 * we've found our IPv4 hostname mapping.  If the hostname is
-				 * the fallback *IPv6* hostname it's not going to show up in
-				 * the IPv4 local mapping though, so fake it.
-				 */
-				if (hostname6_is_fallback || found_hostname)
-					found_host4 = TRUE;
-			}
-		} else if (is_local_mapping (*line, TRUE, "localhost6")) {
-			/* a ::1 line containing 'localhost6' */
-			found_localhost6 = TRUE;
-			custom6 = get_custom_hostnames (*line, hostname, old_hostname, short_hostname, fallback_hostname6);
-			if (!ip6_addr) {
-				/* If there's no IP-specific mapping for the current hostname
-				 * but that hostname is present on in the local mapping line,
-				 * we've found our IPv6 hostname mapping.  If the hostname is
-				 * the fallback *IPv4* hostname it's not going to show up in
-				 * the IPv6 local mapping though, so fake it.
-				 */
-				if (hostname4_is_fallback || found_hostname)
-					found_host6 = TRUE;
-			}
+	/* Remove "# Added ..." lines */
+	lines = g_strsplit_set (contents, "\n\r", -1);
+	for (iter = lines; iter && *iter; iter++) {
+		if (!strstr (*iter, ADDED_TAG)) {
+			g_string_append (new_contents, *iter);
+			g_string_append_c (new_contents, '\n');
 		}
-
-		if (   found_localhost4
-		    && found_host4
-		    && found_localhost6
-		    && found_host6
-		    && host4_before
-		    && host6_before
-		    && no_stale)
-			goto out;  /* No update required */
-	}
-
-	contents = g_string_sized_new (existing_len ? existing_len + 100 : 200);
-	if (!contents) {
-		g_set_error_literal (error, 0, 0, "not enough memory");
-		goto out;
 	}
+	g_strfreev (lines);
 
-	/* Construct the new hosts file; replace any 127.0.0.1/::1 entry that is
-	 * at the beginning of the file or right after initial comments and contains
-	 * the string 'localhost' (for IPv4) or 'localhost6' (for IPv6).  If there
-	 * is no 127.0.0.1 or ::1 entry at the beginning or after initial comments
-	 * that contains 'localhost' or 'localhost6', add one there
-	 * and ignore any other 127.0.0.1/::1 entries that contain 'localhost' or
-	 * 'localhost6'.
+	/* Remove last blank line at end of file, if one exists; this is
+	 * an artifact of how g_strsplit_set() works.
 	 */
-	for (line = lines, initial_comments = TRUE; lines && *line; line++) {
-		/* This is the first line after the initial comments */
-		if (strlen (*line) && initial_comments && (*line[0] != '#')) {
-			initial_comments = FALSE;
-
-			/* If the user added their own mapping for the hostname, just make
-			 * a simple 'localhost' mapping and assume the user knows what they
-			 * are doing with their manual hostname entry.  Otherwise if the
-			 * hostname wasn't found somewhere else, add it to the localhost
-			 * mapping line to make sure it's mapped to something.
-			 */
-
-			/* Add the address mappings first so they take precedence */
-			if (!hostname4_is_fallback && ip4_addr && !found_user_host4) {
-				g_string_append_printf (contents, "%s\t%s", ip4_addr, hostname);
-				if (short_hostname)
-					g_string_append_printf (contents, "\t%s", short_hostname);
-				g_string_append_printf (contents, "\t%s\n", ADDED_TAG);
-			}
-			if (!hostname6_is_fallback && ip6_addr && !found_user_host6) {
-				g_string_append_printf (contents, "%s\t%s", ip6_addr, hostname);
-				if (short_hostname)
-					g_string_append_printf (contents, "\t%s", short_hostname);
-				g_string_append_printf (contents, "\t%s\n", ADDED_TAG);
-			}
+	if (   (new_contents->len > 2)
+	    && (new_contents->str[new_contents->len - 1] == '\n'))
+		g_string_truncate (new_contents, new_contents->len - 1);
 
-			/* IPv4 localhost line */
-			g_string_append (contents, "127.0.0.1");
-			if (!hostname4_is_fallback && !ip4_addr && !found_user_host4) {
-				g_string_append_printf (contents, "\t%s", hostname);
-				if (short_hostname)
-					g_string_append_printf (contents, "\t%s", short_hostname);
-			}
-			g_string_append_printf (contents, "\t%s\tlocalhost", fallback_hostname4);
-			if (custom4)
-				g_string_append (contents, custom4);
-			g_string_append_c (contents, '\n');
-
-			/* IPv6 localhost line */
-			g_string_append (contents, "::1");
-			if (!hostname6_is_fallback && !hostname4_is_fallback && !ip6_addr && !found_user_host6) {
-				g_string_append_printf (contents, "\t%s", hostname);
-				if (short_hostname)
-					g_string_append_printf (contents, "\t%s", short_hostname);
-			}
-			g_string_append_printf (contents, "\t%s\tlocalhost6", fallback_hostname6);
-			if (custom6)
-				g_string_append (contents, custom6);
-			g_string_append_c (contents, '\n');
-
-			added = TRUE;
-		}
-
-		/* Don't add the original line if it is a localhost mapping */
-		if (   !is_local_mapping (*line, FALSE, "localhost")
-		    && !is_local_mapping (*line, FALSE, fallback_hostname4)
-		    && !is_local_mapping (*line, FALSE, hostname)
-		    && !is_local_mapping (*line, TRUE, "localhost6")
-		    && !is_local_mapping (*line, TRUE, fallback_hostname6)
-		    && !is_local_mapping (*line, TRUE, hostname)
-			&& !strstr (*line, ADDED_TAG)) {
-
-			g_string_append (contents, *line);
-			/* Only append the new line if this isn't the last line in the file */
-			if (*(line+1))
-				g_string_append_c (contents, '\n');
-		}
-	}
-
-	/* Hmm, /etc/hosts was empty for some reason */
-	if (!added) {
-		g_string_append (contents, "# Do not remove the following lines, or various programs\n");
-		g_string_append (contents, "# that require network functionality will fail.\n");
-
-		/* Add the address mappings first so they take precedence */
-		if (!hostname4_is_fallback && ip4_addr) {
-			g_string_append_printf (contents, "%s\t%s", ip4_addr, hostname);
-			if (short_hostname)
-				g_string_append_printf (contents, "\t%s", short_hostname);
-			g_string_append_printf (contents, "\t%s\n", ADDED_TAG);
-		}
-		if (!hostname6_is_fallback && ip6_addr) {
-			g_string_append_printf (contents, "%s\t%s", ip6_addr, hostname);
-			if (short_hostname)
-				g_string_append_printf (contents, "\t%s", short_hostname);
-			g_string_append_printf (contents, "\t%s\n", ADDED_TAG);
-		}
-
-		g_string_append_printf (contents, "127.0.0.1\t%s\tlocalhost\n", fallback_hostname4);
-		g_string_append_printf (contents, "::1\t%s\tlocalhost6\n", fallback_hostname6);
-	}
-
-out:
-	g_free (custom4);
-	g_free (custom6);
-	g_free (short_hostname);
-	return contents;
+	return new_contents;
 }
 
-gboolean
-nm_policy_hosts_update_etc_hosts (const char *hostname,
-                                  const char *old_hostname,
-                                  const char *fallback_hostname4,
-                                  const char *fallback_hostname6,
-                                  const char *ip4_addr,
-                                  const char *ip6_addr,
-                                  gboolean *out_changed)
+/* remove any leftover "# Added by NetworkManager" lines */
+void
+nm_policy_hosts_clean_etc_hosts (void)
 {
 	char *contents = NULL;
-	char **lines = NULL;
-	GError *error = NULL;
-	GString *new_contents = NULL;
 	gsize contents_len = 0;
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (hostname != NULL, FALSE);
-	g_return_val_if_fail (out_changed != NULL, FALSE);
+	GError *error = NULL;
+	GString *new;
 
 	if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
 		nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
 		             error ? error->code : 0,
 		             (error && error->message) ? error->message : "(unknown)");
 		g_clear_error (&error);
-		return FALSE;
+		return;
 	}
 
-	/* Get the new /etc/hosts contents */
-	lines = g_strsplit_set (contents, "\n\r", 0);
-	new_contents = nm_policy_get_etc_hosts ((const char **) lines,
-	                                        contents_len,
-	                                        hostname,
-	                                        old_hostname,
-	                                        fallback_hostname4,
-	                                        fallback_hostname6,
-	                                        ip4_addr,
-	                                        ip6_addr,
-	                                        &error);
-	g_strfreev (lines);
-	g_free (contents);
-
-	if (new_contents) {
-		nm_log_info (LOGD_DNS, "Updating /etc/hosts with new system hostname");
+	new = nm_policy_get_etc_hosts (contents, contents_len);
+	if (new && new->len) {
+		nm_log_info (LOGD_DNS, "Cleaning leftovers from /etc/hosts");
 
 		g_clear_error (&error);
-		/* And actually update /etc/hosts */
-		if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
-			nm_log_warn (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s",
-			             error ? error->code : 0,
-			             (error && error->message) ? error->message : "(unknown)");
+		if (!g_file_set_contents (SYSCONFDIR "/hosts", new->str, -1, &error)) {
+			nm_log_dbg (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s",
+			            error ? error->code : 0,
+			            (error && error->message) ? error->message : "(unknown)");
 			g_clear_error (&error);
-		} else {
-			success = TRUE;
-			*out_changed = TRUE;
 		}
-
-		g_string_free (new_contents, TRUE);
-	} else if (!error) {
-		/* No change required */
-		success = TRUE;
-	} else {
-		nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
-		             error->code, error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
 	}
 
-	return success;
+	if (new)
+		g_string_free (new, TRUE);
 }
 
diff --git a/src/nm-policy-hosts.h b/src/nm-policy-hosts.h
index ebaaf0fd..9f4bf9a9 100644
--- a/src/nm-policy-hosts.h
+++ b/src/nm-policy-hosts.h
@@ -23,26 +23,10 @@
 
 #include <glib.h>
 
-gboolean nm_policy_hosts_update_etc_hosts (const char *hostname,
-                                           const char *old_hostname,
-                                           const char *fallback_hostname4,
-                                           const char *fallback_hostname6,
-                                           const char *ip4_addr,
-                                           const char *ip6_addr,
-                                           gboolean *out_changed);
+void nm_policy_hosts_clean_etc_hosts (void);
 
 /* Only for testcases; don't use outside of nm-policy-hosts.c */
-gboolean nm_policy_hosts_find_token (const char *line, const char *token);
-
-GString *nm_policy_get_etc_hosts (const char **lines,
-                                  gsize existing_len,
-                                  const char *hostname,
-                                  const char *old_hostname,
-                                  const char *fallback_hostname4,
-                                  const char *fallback_hostname6,
-                                  const char *ip4_addr,
-                                  const char *ip6_addr,
-                                  GError **error);
+GString *nm_policy_get_etc_hosts (const char *contents, gsize contents_len);
 
 #endif /* NM_POLICY_HOSTS_H */
 
diff --git a/src/nm-policy.c b/src/nm-policy.c
index e8a18d02..aed2f897 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -42,7 +42,6 @@
 #include "nm-system.h"
 #include "nm-dns-manager.h"
 #include "nm-vpn-manager.h"
-#include "nm-policy-hosts.h"
 #include "nm-policy-hostname.h"
 
 struct NMPolicy {
@@ -233,9 +232,6 @@ _set_hostname (NMPolicy *policy,
                const char *new_hostname,
                const char *msg)
 {
-	char ip4_addr[INET_ADDRSTRLEN + 1];
-	char ip6_addr[INET6_ADDRSTRLEN + 1];
-
 	if (change_hostname) {
 		NMDnsManager *dns_mgr;
 
@@ -247,43 +243,7 @@ _set_hostname (NMPolicy *policy,
 		g_object_unref (dns_mgr);
 	}
 
-	/* Get the default IPv4 and IPv6 addresses so we can assign
-	 * the hostname to them in /etc/hosts.
-	 */
-	memset (ip4_addr, 0, sizeof (ip4_addr));
-	if (policy->default_device4) {
-		NMIP4Config *config = NULL;
-		NMIP4Address *addr = NULL;
-
-		config = nm_device_get_ip4_config (policy->default_device4);
-		if (config)
-			addr = nm_ip4_config_get_address (config, 0);
-
-		if (addr) {
-			struct in_addr tmp;
-
-			tmp.s_addr = nm_ip4_address_get_address (addr);
-			inet_ntop (AF_INET, &tmp, ip4_addr, sizeof (ip4_addr));
-		}
-	}
-
-	memset (ip6_addr, 0, sizeof (ip6_addr));
-	if (policy->default_device6) {
-		NMIP6Config *config = NULL;
-		NMIP6Address *addr = NULL;
-
-		config = nm_device_get_ip6_config (policy->default_device6);
-		if (config)
-			addr = nm_ip6_config_get_address (config, 0);
-
-		if (addr)
-			inet_ntop (AF_INET6, nm_ip6_address_get_address (addr), ip6_addr, sizeof (ip6_addr));
-	}
-
-	if (nm_policy_set_system_hostname (policy->cur_hostname,
-	                                   strlen (ip4_addr) ? ip4_addr : NULL,
-	                                   strlen (ip6_addr) ? ip6_addr : NULL,
-	                                   msg))
+	if (nm_policy_set_system_hostname (policy->cur_hostname, msg))
 		nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL);
 }
 
@@ -1235,15 +1195,6 @@ nm_policy_destroy (NMPolicy *policy)
 	}
 	g_slist_free (policy->dev_signal_ids);
 
-	/* Rewrite /etc/hosts on exit to ensure we don't leave stale IP addresses
-	 * lying around.  FIXME: this will take out a valid IP address of an
-	 * ethernet device we're leaving active (ie, a connection we can "assume"
-	 * when NM starts again).
-	 */
-	policy->default_device4 = NULL;
-	policy->default_device6 = NULL;
-	update_system_hostname (policy, NULL, NULL);
-
 	g_free (policy->orig_hostname);
 	g_free (policy->cur_hostname);
 
diff --git a/src/nm-system.c b/src/nm-system.c
index 7921fec6..e8b8fec1 100644
--- a/src/nm-system.c
+++ b/src/nm-system.c
@@ -1187,14 +1187,14 @@ nm_system_replace_default_ip6_route (const char *iface, const struct in6_addr *g
 	return success;
 }
 
-static void flush_addresses (const char *iface, gboolean ipv4_only)
+static void flush_addresses (const char *iface, int family)
 {
 	int iface_idx;
 
 	g_return_if_fail (iface != NULL);
 	iface_idx = nm_netlink_iface_to_index (iface);
 	if (iface_idx >= 0)
-		sync_addresses (iface, iface_idx, ipv4_only ? AF_INET : AF_UNSPEC, NULL, 0);
+		sync_addresses (iface, iface_idx, family, NULL, 0);
 }
 
 /*
@@ -1203,12 +1203,11 @@ static void flush_addresses (const char *iface, gboolean ipv4_only)
  * Flush all network addresses associated with a network device
  *
  */
-void nm_system_device_flush_addresses (NMDevice *dev)
+void nm_system_device_flush_addresses (NMDevice *dev, int family)
 {
 	g_return_if_fail (dev != NULL);
 
-	flush_addresses (nm_device_get_ip_iface (dev),
-					 nm_device_get_ip6_config (dev) == NULL);
+	flush_addresses (nm_device_get_ip_iface (dev), family);
 }
 
 
@@ -1220,7 +1219,7 @@ void nm_system_device_flush_addresses (NMDevice *dev)
  */
 void nm_system_device_flush_addresses_with_iface (const char *iface)
 {
-	flush_addresses (iface, FALSE);
+	flush_addresses (iface, AF_UNSPEC);
 }
 
 
diff --git a/src/nm-system.h b/src/nm-system.h
index 8cb22d74..094f40ef 100644
--- a/src/nm-system.h
+++ b/src/nm-system.h
@@ -55,7 +55,7 @@ gboolean		nm_system_replace_default_ip4_route_vpn (const char *iface,
 struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config);
 
 
-void			nm_system_device_flush_addresses			(NMDevice *dev);
+void			nm_system_device_flush_addresses			(NMDevice *dev, int family);
 void			nm_system_device_flush_addresses_with_iface	(const char *iface);
 
 void			nm_system_enable_loopback				(void);
diff --git a/src/ppp-manager/Makefile.am b/src/ppp-manager/Makefile.am
index f213dd2e..540e5855 100644
--- a/src/ppp-manager/Makefile.am
+++ b/src/ppp-manager/Makefile.am
@@ -33,6 +33,8 @@ libppp_manager_la_LIBADD = \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
+if WITH_PPP
+
 pppd_plugindir = $(PPPD_PLUGIN_DIR)
 pppd_plugin_LTLIBRARIES = nm-pppd-plugin.la
 
@@ -52,6 +54,8 @@ nm_pppd_plugin_la_LIBADD = \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
+endif
+
 BUILT_SOURCES = nm-ppp-manager-glue.h
 
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in
index 1013c2c2..20cfb0ba 100644
--- a/src/ppp-manager/Makefile.in
+++ b/src/ppp-manager/Makefile.in
@@ -82,15 +82,19 @@ libppp_manager_la_OBJECTS = $(am_libppp_manager_la_OBJECTS)
 AM_V_lt = $(am__v_lt_$(V))
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
 am__v_lt_0 = --silent
-nm_pppd_plugin_la_DEPENDENCIES =  \
-	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
-am_nm_pppd_plugin_la_OBJECTS = nm_pppd_plugin_la-nm-pppd-plugin.lo
+@WITH_PPP_TRUE@nm_pppd_plugin_la_DEPENDENCIES =  \
+@WITH_PPP_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@WITH_PPP_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__nm_pppd_plugin_la_SOURCES_DIST = nm-pppd-plugin.c nm-pppd-plugin.h \
+	nm-ppp-status.h
+@WITH_PPP_TRUE@am_nm_pppd_plugin_la_OBJECTS =  \
+@WITH_PPP_TRUE@	nm_pppd_plugin_la-nm-pppd-plugin.lo
 nm_pppd_plugin_la_OBJECTS = $(am_nm_pppd_plugin_la_OBJECTS)
 nm_pppd_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(AM_CFLAGS) $(CFLAGS) $(nm_pppd_plugin_la_LDFLAGS) $(LDFLAGS) \
 	-o $@
+@WITH_PPP_TRUE@am_nm_pppd_plugin_la_rpath = -rpath $(pppd_plugindir)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -119,7 +123,7 @@ am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
 am__v_GEN_0 = @echo "  GEN   " $@;
 SOURCES = $(libppp_manager_la_SOURCES) $(nm_pppd_plugin_la_SOURCES)
 DIST_SOURCES = $(libppp_manager_la_SOURCES) \
-	$(nm_pppd_plugin_la_SOURCES)
+	$(am__nm_pppd_plugin_la_SOURCES_DIST)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -215,6 +219,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -229,6 +237,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -332,22 +341,22 @@ libppp_manager_la_LIBADD = \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
-pppd_plugindir = $(PPPD_PLUGIN_DIR)
-pppd_plugin_LTLIBRARIES = nm-pppd-plugin.la
-nm_pppd_plugin_la_SOURCES = \
-	nm-pppd-plugin.c \
-	nm-pppd-plugin.h \
-	nm-ppp-status.h
+@WITH_PPP_TRUE@pppd_plugindir = $(PPPD_PLUGIN_DIR)
+@WITH_PPP_TRUE@pppd_plugin_LTLIBRARIES = nm-pppd-plugin.la
+@WITH_PPP_TRUE@nm_pppd_plugin_la_SOURCES = \
+@WITH_PPP_TRUE@	nm-pppd-plugin.c \
+@WITH_PPP_TRUE@	nm-pppd-plugin.h \
+@WITH_PPP_TRUE@	nm-ppp-status.h
 
-nm_pppd_plugin_la_CPPFLAGS = \
-	$(DBUS_CFLAGS) \
-	$(GLIB_CFLAGS)
+@WITH_PPP_TRUE@nm_pppd_plugin_la_CPPFLAGS = \
+@WITH_PPP_TRUE@	$(DBUS_CFLAGS) \
+@WITH_PPP_TRUE@	$(GLIB_CFLAGS)
 
-nm_pppd_plugin_la_LDFLAGS = -module -avoid-version
-nm_pppd_plugin_la_LIBADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(DBUS_LIBS) \
-	$(GLIB_LIBS)
+@WITH_PPP_TRUE@nm_pppd_plugin_la_LDFLAGS = -module -avoid-version
+@WITH_PPP_TRUE@nm_pppd_plugin_la_LIBADD = \
+@WITH_PPP_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@WITH_PPP_TRUE@	$(DBUS_LIBS) \
+@WITH_PPP_TRUE@	$(GLIB_LIBS)
 
 BUILT_SOURCES = nm-ppp-manager-glue.h
 CLEANFILES = $(BUILT_SOURCES)
@@ -429,7 +438,7 @@ clean-pppd_pluginLTLIBRARIES:
 libppp-manager.la: $(libppp_manager_la_OBJECTS) $(libppp_manager_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(LINK)  $(libppp_manager_la_OBJECTS) $(libppp_manager_la_LIBADD) $(LIBS)
 nm-pppd-plugin.la: $(nm_pppd_plugin_la_OBJECTS) $(nm_pppd_plugin_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(nm_pppd_plugin_la_LINK) -rpath $(pppd_plugindir) $(nm_pppd_plugin_la_OBJECTS) $(nm_pppd_plugin_la_LIBADD) $(LIBS)
+	$(AM_V_CCLD)$(nm_pppd_plugin_la_LINK) $(am_nm_pppd_plugin_la_rpath) $(nm_pppd_plugin_la_OBJECTS) $(nm_pppd_plugin_la_LIBADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index efa660b0..31a5e57a 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -165,7 +165,8 @@ dispose (GObject *object)
 
 	nm_ppp_manager_stop (NM_PPP_MANAGER (object));
 
-	g_object_unref (priv->act_req);
+	if (priv->act_req)
+		g_object_unref (priv->act_req);
 	g_object_unref (priv->dbus_manager);
 
 	G_OBJECT_CLASS (nm_ppp_manager_parent_class)->dispose (object);
@@ -724,6 +725,8 @@ create_pppd_cmd_line (NMPPPManager *self,
 	NMCmdLine *cmd;
 	const char *ppp_debug;
 
+	g_return_val_if_fail (setting != NULL, NULL);
+
 	ppp_binary = nm_find_pppd ();
 	if (!ppp_binary) {
 		g_set_error (err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR,
@@ -897,6 +900,15 @@ nm_ppp_manager_start (NMPPPManager *manager,
 
 	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
 
+#if !WITH_PPP
+	/* PPP support disabled */
+	g_set_error_literal (err,
+	                     NM_PPP_MANAGER_ERROR,
+	                     NM_PPP_MANAGER_ERROR_UNKOWN,
+	                     "PPP support is not enabled.");
+	return FALSE;
+#endif
+
 	priv->pid = 0;
 
 	/* Make sure /dev/ppp exists (bgo #533064) */
diff --git a/src/supplicant-manager/Makefile.in b/src/supplicant-manager/Makefile.in
index 0bc3ebcf..03b05e5d 100644
--- a/src/supplicant-manager/Makefile.in
+++ b/src/supplicant-manager/Makefile.in
@@ -226,6 +226,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -240,6 +244,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in
index 1403a3f1..17113522 100644
--- a/src/supplicant-manager/tests/Makefile.in
+++ b/src/supplicant-manager/tests/Makefile.in
@@ -185,6 +185,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -199,6 +203,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/system-settings/Makefile.in b/src/system-settings/Makefile.in
index 1bc66bac..45f4a414 100644
--- a/src/system-settings/Makefile.in
+++ b/src/system-settings/Makefile.in
@@ -196,6 +196,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -210,6 +214,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/system-settings/nm-default-wired-connection.c b/src/system-settings/nm-default-wired-connection.c
index 1cda3d9e..0d19dea0 100644
--- a/src/system-settings/nm-default-wired-connection.c
+++ b/src/system-settings/nm-default-wired-connection.c
@@ -163,7 +163,7 @@ constructor (GType type,
 		      NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
 		      NM_SETTING_CONNECTION_UUID, uuid,
 		      NM_SETTING_CONNECTION_READ_ONLY, priv->read_only,
-		      NM_SETTING_CONNECTION_TIMESTAMP, time (NULL),
+		      NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
 		      NULL);
 
 	g_free (id);
diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c
index d929813f..75ac9879 100644
--- a/src/system-settings/nm-sysconfig-settings.c
+++ b/src/system-settings/nm-sysconfig-settings.c
@@ -19,7 +19,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ * (C) Copyright 2007 - 2011 Red Hat, Inc.
  * (C) Copyright 2008 Novell, Inc.
  */
 
@@ -480,8 +480,35 @@ connection_removed (NMSettingsConnectionInterface *connection,
                     gpointer user_data)
 {
 	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data);
+	NMSettingConnection *s_con;
+	GKeyFile *timestamps_file;
+	const char *connection_uuid;
+	char *data;
+	gsize len;
+	GError *error = NULL;
 
+	/* Remove connection from the table */
 	g_hash_table_remove (priv->connections, connection);
+
+	/* Remove timestamp from timestamps database file */
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+	connection_uuid = nm_setting_connection_get_uuid (s_con);
+
+	timestamps_file = g_key_file_new ();
+	if (g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
+		g_key_file_remove_key (timestamps_file, "timestamps", connection_uuid, NULL);
+		data = g_key_file_to_data (timestamps_file, &len, &error);
+		if (data) {
+			g_file_set_contents (NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, data, len, &error);
+			g_free (data);
+		}
+		if (error) {
+			nm_log_warn (LOGD_SYS_SET, "error writing timestamps file '%s': %s", NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, error->message);
+			g_error_free (error);
+		}
+	}
+	g_key_file_free (timestamps_file);
 }
 
 static void
@@ -491,6 +518,13 @@ claim_connection (NMSysconfigSettings *self,
 {
 	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
 
+	NMSettingConnection *s_con;
+	const char *connection_uuid;
+	guint64 timestamp = 0;
+	GKeyFile *timestamps_file;
+	GError *err = NULL;
+	char *tmp_str;
+
 	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
 	g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
 
@@ -498,6 +532,32 @@ claim_connection (NMSysconfigSettings *self,
 		/* A plugin is lying to us. */
 		return;
 
+	/* Read timestamp from database file and store it into connection's object data */
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+	connection_uuid = nm_setting_connection_get_uuid (s_con);
+
+	timestamps_file = g_key_file_new ();
+	g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL);
+	tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &err);
+	if (tmp_str) {
+		timestamp = g_ascii_strtoull (tmp_str, NULL, 10);
+		g_free (tmp_str);
+	}
+
+	/* Update connection's timestamp */
+	if (!err) {
+		guint64 *ts_ptr = g_new (guint64, 1);
+
+		*ts_ptr = timestamp;
+		g_object_set_data_full (G_OBJECT (connection), NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG, ts_ptr, g_free);
+	} else {
+		nm_log_dbg (LOGD_SYS_SET, "failed to read connection timestamp for '%s': (%d) %s",
+		            connection_uuid, err->code, err->message);
+		g_clear_error (&err);
+	}
+	g_key_file_free (timestamps_file);
+
 	g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1));
 	g_signal_connect (connection,
 	                  NM_SETTINGS_CONNECTION_INTERFACE_REMOVED,
diff --git a/src/system-settings/nm-sysconfig-settings.h b/src/system-settings/nm-sysconfig-settings.h
index ae2ba683..8b2622a7 100644
--- a/src/system-settings/nm-sysconfig-settings.h
+++ b/src/system-settings/nm-sysconfig-settings.h
@@ -41,6 +41,8 @@
 #define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
 
 #define NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS "unmanaged-specs"
+#define NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE LOCALSTATEDIR"/lib/NetworkManager/timestamps"
+#define NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG   "timestamp-tag"
 
 typedef struct {
 	NMSettingsService parent_instance;
diff --git a/src/system-settings/nm-system-config-interface.c b/src/system-settings/nm-system-config-interface.c
index 90fd93ba..9fb34278 100644
--- a/src/system-settings/nm-system-config-interface.c
+++ b/src/system-settings/nm-system-config-interface.c
@@ -53,7 +53,8 @@ interface_init (gpointer g_iface)
 							  "Capabilities",
 							  "Plugin capabilties",
 							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
-							  NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST - 1,
+							  (  NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS
+							   | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME),
 							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
 							  G_PARAM_READABLE));
 
diff --git a/src/system-settings/nm-system-config-interface.h b/src/system-settings/nm-system-config-interface.h
index 3daceb89..d5634aa6 100644
--- a/src/system-settings/nm-system-config-interface.h
+++ b/src/system-settings/nm-system-config-interface.h
@@ -41,15 +41,6 @@ G_BEGIN_DECLS
  */
 GObject * nm_system_config_factory (void);
 
-/* NOTE:
- *   When passing NMConnection objects to NetworkManager, any properties
- * of that NMConnection's NMSetting objects that are secrets must be set as
- * GObject data items on the NMSetting object, _not_ inside the NMSetting
- * object itself.  This is to ensure that the secrets are only given to
- * NetworkManager itself and not exposed to clients like nm-applet that need
- * connection details, but not secrets.
- */
-
 #define NM_TYPE_SYSTEM_CONFIG_INTERFACE      (nm_system_config_interface_get_type ())
 #define NM_SYSTEM_CONFIG_INTERFACE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE, NMSystemConfigInterface))
 #define NM_IS_SYSTEM_CONFIG_INTERFACE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE))
@@ -67,9 +58,11 @@ GObject * nm_system_config_factory (void);
 typedef enum {
 	NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE = 0x00000000,
 	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS = 0x00000001,
-	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME = 0x00000002,
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME = 0x00000002
 
-	NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST = NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME
+	/* When adding more capabilities, be sure to update the "Capabilities"
+	 * property max value in nm-system-config-interface.c.
+	 */
 } NMSystemConfigInterfaceCapabilities;
 
 typedef enum {
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 40d1d6ab..46a75b25 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -194,6 +194,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -208,6 +212,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff --git a/src/tests/test-policy-hosts.c b/src/tests/test-policy-hosts.c
index 8865c426..62862e75 100644
--- a/src/tests/test-policy-hosts.c
+++ b/src/tests/test-policy-hosts.c
@@ -23,41 +23,17 @@
 
 #include "nm-policy-hosts.h"
 
-#define FALLBACK_HOSTNAME4 "localhost.localdomain"
-#define FALLBACK_HOSTNAME6 "localhost6.localdomain6"
-
-#define DEBUG 0
+#define DEBUG 1
 
 static void
-test_generic (const char *before,
-              const char *after,
-              const char *hostname,
-              const char *ip4_addr,
-              const char *ip6_addr,
-              gboolean expect_error)
+test_generic (const char *before, const char *after)
 {
-	char **lines;
 	GString *newc;
-	GError *error = NULL;
 
 	/* Get the new /etc/hosts contents */
-	lines = g_strsplit_set (before, "\n\r", 0);
-	newc = nm_policy_get_etc_hosts ((const char **) lines,
-	                                strlen (before),
-	                                hostname,
-	                                NULL,
-	                                FALLBACK_HOSTNAME4,
-	                                FALLBACK_HOSTNAME6,
-	                                ip4_addr,
-	                                ip6_addr,
-	                                &error);
-	g_strfreev (lines);
+	newc = nm_policy_get_etc_hosts (before, strlen (before));
 
-	if (expect_error) {
-		g_assert (newc == NULL);
-		g_assert (error != NULL);
-		g_clear_error (&error);
-	} else if (after == NULL) {
+	if (after == NULL) {
 		/* No change to /etc/hosts required */
 #if DEBUG
 		if (newc != NULL) {
@@ -68,10 +44,8 @@ test_generic (const char *before,
 		}
 #endif
 		g_assert (newc == NULL);
-		g_assert (error == NULL);
 	} else {
 		g_assert (newc != NULL);
-		g_assert (error == NULL);
 
 #if DEBUG
 		g_message ("\n- NEW ---------------------------------\n"
@@ -81,7 +55,6 @@ test_generic (const char *before,
 		           "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
 		           newc->str, after);
 #endif
-		g_assert (strlen (newc->str) == strlen (after));
 		g_assert (strcmp (newc->str, after) == 0);
 		g_string_free (newc, TRUE);
 	}
@@ -99,7 +72,7 @@ static const char *generic_before = \
 static void
 test_hosts_generic (void)
 {
-	test_generic (generic_before, NULL, "localhost.localdomain", NULL, NULL, FALSE);
+	test_generic (generic_before, NULL);
 }
 
 /*******************************************/
@@ -112,311 +85,25 @@ static const char *generic_no_boilerplate_before = \
 static void
 test_hosts_generic_no_boilerplate (void)
 {
-	test_generic (generic_no_boilerplate_before, NULL, "localhost.localdomain", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *generic_no_boilerplate_no_lh_before = \
-	"127.0.0.1	localhost.localdomain\n"
-	"::1		localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *generic_no_boilerplate_no_lh_after = \
-	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_generic_no_boilerplate_no_lh (void)
-{
-	test_generic (generic_no_boilerplate_no_lh_before,
-	              generic_no_boilerplate_no_lh_after,
-	              "localhost.localdomain",
-	              NULL,
-	              NULL,
-	              FALSE);
-}
-
-/*******************************************/
-
-
-static const char *generic_no_boilerplate_no_lh_no_host_before = \
-	"127.0.0.1	localhost.localdomain\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *generic_no_boilerplate_no_lh_no_host_after = \
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_generic_no_boilerplate_no_lh_no_host (void)
-{
-	test_generic (generic_no_boilerplate_no_lh_no_host_before,
-	              generic_no_boilerplate_no_lh_no_host_after,
-	              "comet",
-	              NULL,
-	              NULL,
-	              FALSE);
-}
-
-/*******************************************/
-static const char *named_generic_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	playboy localhost\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *named_generic_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	playboy	localhost.localdomain	localhost\n"
-	"::1	playboy	localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named_generic (void)
-{
-	test_generic (named_generic_before, named_generic_after, "playboy", NULL, NULL, FALSE);
+	test_generic (generic_no_boilerplate_before, NULL);
 }
 
 /*******************************************/
 
-static const char *named4_non127_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	tomcat	localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"192.168.1.2	tomcat\n";
-
-static void
-test_hosts_named4_non127 (void)
-{
-	test_generic (named4_non127_before, NULL, "tomcat", "192.168.1.2", NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *named6_non127_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	tomcat localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"3001:abba::3234 tomcat\n";
-
-static void
-test_hosts_named6_non127 (void)
-{
-	test_generic (named6_non127_before, NULL, "tomcat", NULL, "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named4_non127_more_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	tomcat	localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"192.168.1.2	tomcat\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	srx.main.ebayrtm.com\n"
-	"127.0.0.1	cdn5.tribalfusion.com\n";
-
-static void
-test_hosts_named4_non127_more (void)
-{
-	test_generic (named4_non127_more_before, NULL, "tomcat", "192.168.1.2", NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *named6_non127_more_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	tomcat localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"3001:abba::3234	tomcat\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	srx.main.ebayrtm.com\n"
-	"127.0.0.1	cdn5.tribalfusion.com\n";
-
-static void
-test_hosts_named6_non127_more (void)
-{
-	test_generic (named6_non127_more_before, NULL, "tomcat", NULL, "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named_no_lh_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"192.168.1.2	tomcat\n";
-
-static const char *named_no_lh_after = \
+static const char *leftover_before = \
 	"# Do not remove the following line, or various programs\n"
 	"# that require network functionality will fail.\n"
+	"192.168.1.2	comet	# Added by NetworkManager\n"
 	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	tomcat	localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"192.168.1.2	tomcat\n";
-
-static void
-test_hosts_named_no_localhost (void)
-{
-	test_generic (named_no_lh_before, named_no_lh_after, "tomcat", "192.168.1.2", NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *no_lh_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	tomcat\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *no_lh_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	tomcat	localhost.localdomain	localhost\n"
-	"::1	tomcat	localhost6.localdomain6	localhost6\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_no_localhost (void)
-{
-	test_generic (no_lh_before, no_lh_after, "tomcat", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *named_last_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 sparcbook.ausil.us\n"
-	"::1         localhost localhost.localdomain localhost6 localhost6.localdomain6 sparcbook.ausil.us\n";
-
-static void
-test_hosts_named_last (void)
-{
-	test_generic (named_last_before, NULL, "sparcbook.ausil.us", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *no_host4_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	srx.main.ebayrtm.com\n"
-	"127.0.0.1	cdn5.tribalfusion.com\n"
-	"127.0.0.1	a.tribalfusion.com\n";
-
-static const char *no_host4_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	srx.main.ebayrtm.com\n"
-	"127.0.0.1	cdn5.tribalfusion.com\n"
-	"127.0.0.1	a.tribalfusion.com\n";
-
-static void
-test_hosts_no_host4 (void)
-{
-	test_generic (no_host4_before, no_host4_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *no_host6_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *no_host6_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_no_host6 (void)
-{
-	test_generic (no_host6_before, no_host6_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2 comet\n"
-	"3001:abba::3234 comet\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127 (void)
-{
-	test_generic (named46_non127_before, NULL, "comet", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_long_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2 comet.space	comet\n"
-	"3001:abba::3234 comet.space	comet\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127_long (void)
-{
-	test_generic (named46_non127_long_before, NULL, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_other4_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
 	"::1	localhost6.localdomain6	localhost6\n"
 	"192.168.1.3	comet\n"
 	"3001:abba::3234	comet\n"
 	"\n"
 	"127.0.0.1	lcmd.us.intellitxt.com\n";
 
-static const char *named46_non127_other4_after = \
+static const char *leftover_after = \
 	"# Do not remove the following line, or various programs\n"
 	"# that require network functionality will fail.\n"
-	"192.168.1.2	comet	# Added by NetworkManager\n"
 	"127.0.0.1	localhost.localdomain	localhost\n"
 	"::1	localhost6.localdomain6	localhost6\n"
 	"192.168.1.3	comet\n"
@@ -425,416 +112,44 @@ static const char *named46_non127_other4_after = \
 	"127.0.0.1	lcmd.us.intellitxt.com\n";
 
 static void
-test_hosts_named46_non127_other4 (void)
+test_hosts_leftover (void)
 {
-	test_generic (named46_non127_other4_before, named46_non127_other4_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE);
+	test_generic (leftover_before, leftover_after);
 }
 
 /*******************************************/
 
-static const char *named46_non127_other4_long_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.3	comet.space\n"
-	"3001:abba::3234	comet.space\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *named46_non127_other4_long_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"192.168.1.2	comet.space	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.3	comet.space\n"
-	"3001:abba::3234	comet.space\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127_other4_long (void)
-{
-	test_generic (named46_non127_other4_long_before, named46_non127_other4_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_other6_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2	comet\n"
-	"3001:abba::9675	comet\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *named46_non127_other6_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"3001:abba::3234	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2	comet\n"
-	"3001:abba::9675	comet\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127_other6 (void)
-{
-	test_generic (named46_non127_other6_before, named46_non127_other6_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_other6_long_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2	comet.space\n"
-	"3001:abba::9675	comet.space\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *named46_non127_other6_long_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"3001:abba::3234	comet.space	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.2	comet.space\n"
-	"3001:abba::9675	comet.space\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127_other6_long (void)
-{
-	test_generic (named46_non127_other6_long_before, named46_non127_other6_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *unnamed46_non127_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *unnamed46_non127_after = \
+static const char *leftover_double_newline_before = \
 	"# Do not remove the following line, or various programs\n"
 	"# that require network functionality will fail.\n"
 	"192.168.1.2	comet	# Added by NetworkManager\n"
-	"3001:abba::3234	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain	localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_unnamed46_non127 (void)
-{
-	test_generic (unnamed46_non127_before, unnamed46_non127_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *unnamed46_non127_long_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static const char *unnamed46_non127_long_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"192.168.1.2	comet.space	comet	# Added by NetworkManager\n"
-	"3001:abba::3234	comet.space	comet	# Added by NetworkManager\n"
 	"127.0.0.1	localhost.localdomain	localhost\n"
 	"::1	localhost6.localdomain6	localhost6\n"
+	"192.168.1.3	comet\n"
+	"3001:abba::3234	comet\n"
 	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_unnamed46_non127_long (void)
-{
-	test_generic (unnamed46_non127_long_before, unnamed46_non127_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *named46_non127_wrong_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n"
-	"192.168.1.3	comet	# Added by NetworkManager\n"
-	"3001:abba::9876	comet	# Added by NetworkManager\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
+	"127.0.0.1	lcmd.us.intellitxt.com\n"
+	"\n";
 
-static const char *named46_non127_wrong_after = \
+static const char *leftover_double_newline_after = \
 	"# Do not remove the following line, or various programs\n"
 	"# that require network functionality will fail.\n"
-	"192.168.1.2	comet	# Added by NetworkManager\n"
-	"3001:abba::3234	comet	# Added by NetworkManager\n"
 	"127.0.0.1	localhost.localdomain	localhost\n"
 	"::1	localhost6.localdomain6	localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n";
-
-static void
-test_hosts_named46_non127_wrong (void)
-{
-	test_generic (named46_non127_wrong_before, named46_non127_wrong_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE);
-}
-
-/*******************************************/
-
-static const char *long_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain	localhost	comet\n"
-	"::1		localhost6.localdomain6 localhost6\n"
-	"\n"
-	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	adserver.adtech.de\n"
-	"127.0.0.1	a.as-us.falkag.net\n"
-	"127.0.0.1	a.as-eu.falkag.net\n"
-	"127.0.0.1	ads.doubleclick.com\n"
-	"\n"
-	"# random comment\n"
-	"127.0.0.1	m1.2mdn.net\n"
-	"127.0.0.1	ds.serving-sys.com\n"
-	"127.0.0.1	pagead2.googlesyndication.com\n"
-	"127.0.0.1	ad.doubleclick.com\n"
-	"127.0.0.1	ad.doubleclick.net\n"
-	"127.0.0.1	oascentral.movietickets.com\n"
-	"127.0.0.1	view.atdmt.com\n"
-	"127.0.0.1	ads.chumcity.com\n";
-
-static const char *long_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n"
+	"192.168.1.3	comet\n"
+	"3001:abba::3234	comet\n"
 	"\n"
 	"127.0.0.1	lcmd.us.intellitxt.com\n"
-	"127.0.0.1	adserver.adtech.de\n"
-	"127.0.0.1	a.as-us.falkag.net\n"
-	"127.0.0.1	a.as-eu.falkag.net\n"
-	"127.0.0.1	ads.doubleclick.com\n"
-	"\n"
-	"# random comment\n"
-	"127.0.0.1	m1.2mdn.net\n"
-	"127.0.0.1	ds.serving-sys.com\n"
-	"127.0.0.1	pagead2.googlesyndication.com\n"
-	"127.0.0.1	ad.doubleclick.com\n"
-	"127.0.0.1	ad.doubleclick.net\n"
-	"127.0.0.1	oascentral.movietickets.com\n"
-	"127.0.0.1	view.atdmt.com\n"
-	"127.0.0.1	ads.chumcity.com\n";
-
-static void
-test_hosts_long (void)
-{
-	test_generic (long_before, long_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *custom4_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost pintglass\n"
-	"::1	localhost6.localdomain6	localhost6\n";
-
-static const char *custom4_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost	pintglass\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n";
-
-static void
-test_hosts_custom4 (void)
-{
-	test_generic (custom4_before, custom4_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *custom6_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6	pintglass\n";
-
-static const char *custom6_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6	pintglass\n";
-
-static void
-test_hosts_custom6 (void)
-{
-	test_generic (custom6_before, custom6_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *custom46_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost shotglass\n"
-	"::1	localhost6.localdomain6	localhost6 pintglass\n";
-
-static const char *custom46_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost	shotglass\n"
-	"::1	comet	localhost6.localdomain6	localhost6	pintglass\n";
-
-static void
-test_hosts_custom46 (void)
-{
-	test_generic (custom46_before, custom46_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *custom46_mixed_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	localhost.localdomain localhost shotglass\n"
-	"::1	localhost6.localdomain6	localhost6 pintglass\n";
-
-static const char *custom46_mixed_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost	shotglass\n"
-	"::1	comet	localhost6.localdomain6	localhost6	pintglass\n";
-
-static void
-test_hosts_custom46_mixed (void)
-{
-	test_generic (custom46_mixed_before, custom46_mixed_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *stale4_removed_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"1.2.3.4	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n";
-
-static const char *stale4_removed_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n";
+	"\n";
 
 static void
-test_hosts_stale4_removed (void)
+test_hosts_leftover_double_newline (void)
 {
-	test_generic (stale4_removed_before, stale4_removed_after, "comet", NULL, NULL, FALSE);
+	test_generic (leftover_double_newline_before, leftover_double_newline_after);
 }
 
 /*******************************************/
 
-static const char *stale6_removed_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"3001:abba::3234	comet	# Added by NetworkManager\n"
-	"127.0.0.1	comet	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n";
-
-static const char *stale6_removed_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n";
-
-static void
-test_hosts_stale6_removed (void)
-{
-	test_generic (stale6_removed_before, stale6_removed_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-static const char *stale46_removed_before = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"1.2.3.4	comet	# Added by NetworkManager\n"
-	"3001:abba::3234	comet	# Added by NetworkManager\n"
-	"127.0.0.1	localhost.localdomain localhost\n"
-	"::1	localhost6.localdomain6	localhost6\n";
-
-static const char *stale46_removed_after = \
-	"# Do not remove the following line, or various programs\n"
-	"# that require network functionality will fail.\n"
-	"127.0.0.1	comet	localhost.localdomain	localhost\n"
-	"::1	comet	localhost6.localdomain6	localhost6\n";
-
-static void
-test_hosts_stale46_removed (void)
-{
-	test_generic (stale46_removed_before, stale46_removed_after, "comet", NULL, NULL, FALSE);
-}
-
-/*******************************************/
-
-typedef struct {
-	const char *line;
-	const char *token;
-	gboolean expected;
-} Foo;
-
-static Foo foo[] = {
-	/* Using \t here to easily differentiate tabs vs. spaces for testing */
-	{ "127.0.0.1\tfoobar\tblah", "blah", TRUE },
-	{ "", "blah", FALSE },
-	{ "1.1.1.1\tbork\tfoo", "blah", FALSE },
-	{ "127.0.0.1 foobar\tblah", "blah", TRUE },
-	{ "127.0.0.1 foobar blah", "blah", TRUE },
-	{ "127.0.0.1 localhost", "localhost.localdomain", FALSE },
-	{ "192.168.1.1 blah borkbork", "blah", TRUE },
-	{ "192.168.1.1 foobar\tblah borkbork", "blah", TRUE },
-	{ "192.168.1.1\tfoobar\tblah\tborkbork", "blah", TRUE },
-	{ "192.168.1.1 \tfoobar \tblah \tborkbork\t ", "blah", TRUE },
-	{ "\t\t\t\t   \t\t\tasdfadf  a\t\t\t\t\t   \t\t\t\t\t ", "blah", FALSE },
-	{ NULL, NULL, FALSE }
-};
-
-static void
-test_find_token (void)
-{
-	Foo *iter = &foo[0];
-
-	while (iter->line) {
-		gboolean found;
-
-		found = nm_policy_hosts_find_token (iter->line, iter->token);
-		if (found != iter->expected) {
-			g_warning ("find-token: unexpected token result %d for '%s' <= '%s' (expected %d)",
-			           found, iter->line, iter->token, iter->expected);
-		}
-		g_assert (found == iter->expected);
-		iter++;
-	}
-}
-
 #if GLIB_CHECK_VERSION(2,25,12)
 typedef GTestFixtureFunc TCFunc;
 #else
@@ -851,38 +166,10 @@ int main (int argc, char **argv)
 
 	suite = g_test_get_root ();
 
-	g_test_suite_add (suite, TESTCASE (test_find_token, NULL));
 	g_test_suite_add (suite, TESTCASE (test_hosts_generic, NULL));
 	g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate_no_lh, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate_no_lh_no_host, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named_generic, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named4_non127, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named6_non127, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named4_non127_more, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named6_non127_more, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_long, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other4, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other4_long, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other6, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other6_long, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_wrong, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_unnamed46_non127, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_unnamed46_non127_long, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named_no_localhost, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_no_localhost, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_named_last, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_no_host4, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_no_host6, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_long, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_custom4, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_custom6, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_custom46, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_custom46_mixed, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_stale4_removed, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_stale6_removed, NULL));
-	g_test_suite_add (suite, TESTCASE (test_hosts_stale46_removed, NULL));
+	g_test_suite_add (suite, TESTCASE (test_hosts_leftover, NULL));
+	g_test_suite_add (suite, TESTCASE (test_hosts_leftover_double_newline, NULL));
 
 	return g_test_run ();
 }
diff --git a/src/vpn-manager/Makefile.am b/src/vpn-manager/Makefile.am
index b0692d70..3b206617 100644
--- a/src/vpn-manager/Makefile.am
+++ b/src/vpn-manager/Makefile.am
@@ -11,12 +11,14 @@ INCLUDES = \
 
 noinst_LTLIBRARIES = libvpn-manager.la
 
-libvpn_manager_la_SOURCES =	\
-	nm-vpn-manager.c	\
-	nm-vpn-manager.h	\
-	nm-vpn-service.c	\
-	nm-vpn-service.h	\
-	nm-vpn-connection.c	\
+libvpn_manager_la_SOURCES = \
+	nm-vpn-manager.c \
+	nm-vpn-manager.h \
+	nm-vpn-service.c \
+	nm-vpn-service.h \
+	nm-vpn-connection-base.c \
+	nm-vpn-connection-base.h \
+	nm-vpn-connection.c \
 	nm-vpn-connection.h
 
 libvpn_manager_la_CPPFLAGS =	\
@@ -31,6 +33,9 @@ libvpn_manager_la_LIBADD = \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
 
+nm-vpn-connection-base-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection_base --mode=glib-server --output=$@ $<
+
 nm-vpn-connection-glue.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-server --output=$@ $<
 
@@ -39,6 +44,7 @@ nm-vpn-plugin-bindings.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
 
 
 BUILT_SOURCES = \
+	nm-vpn-connection-base-glue.h \
 	nm-vpn-connection-glue.h \
 	nm-vpn-plugin-bindings.h
 
diff --git a/src/vpn-manager/Makefile.in b/src/vpn-manager/Makefile.in
index e0a4f4ed..a1d72bbe 100644
--- a/src/vpn-manager/Makefile.in
+++ b/src/vpn-manager/Makefile.in
@@ -58,6 +58,7 @@ libvpn_manager_la_DEPENDENCIES =  \
 	$(am__DEPENDENCIES_1)
 am_libvpn_manager_la_OBJECTS = libvpn_manager_la-nm-vpn-manager.lo \
 	libvpn_manager_la-nm-vpn-service.lo \
+	libvpn_manager_la-nm-vpn-connection-base.lo \
 	libvpn_manager_la-nm-vpn-connection.lo
 libvpn_manager_la_OBJECTS = $(am_libvpn_manager_la_OBJECTS)
 AM_V_lt = $(am__v_lt_$(V))
@@ -186,6 +187,10 @@ MSGFMT_OPTS = @MSGFMT_OPTS@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
 NSS_CFLAGS = @NSS_CFLAGS@
 NSS_LIBS = @NSS_LIBS@
 OBJDUMP = @OBJDUMP@
@@ -200,6 +205,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -287,11 +293,13 @@ INCLUDES = \
 
 noinst_LTLIBRARIES = libvpn-manager.la
 libvpn_manager_la_SOURCES = \
-	nm-vpn-manager.c	\
-	nm-vpn-manager.h	\
-	nm-vpn-service.c	\
-	nm-vpn-service.h	\
-	nm-vpn-connection.c	\
+	nm-vpn-manager.c \
+	nm-vpn-manager.h \
+	nm-vpn-service.c \
+	nm-vpn-service.h \
+	nm-vpn-connection-base.c \
+	nm-vpn-connection-base.h \
+	nm-vpn-connection.c \
 	nm-vpn-connection.h
 
 libvpn_manager_la_CPPFLAGS = \
@@ -307,6 +315,7 @@ libvpn_manager_la_LIBADD = \
 	$(GLIB_LIBS)
 
 BUILT_SOURCES = \
+	nm-vpn-connection-base-glue.h \
 	nm-vpn-connection-glue.h \
 	nm-vpn-plugin-bindings.h
 
@@ -364,6 +373,7 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-connection-base.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-service.Plo@am__quote@
@@ -411,6 +421,14 @@ libvpn_manager_la-nm-vpn-service.lo: nm-vpn-service.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvpn_manager_la-nm-vpn-service.lo `test -f 'nm-vpn-service.c' || echo '$(srcdir)/'`nm-vpn-service.c
 
+libvpn_manager_la-nm-vpn-connection-base.lo: nm-vpn-connection-base.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvpn_manager_la-nm-vpn-connection-base.lo -MD -MP -MF $(DEPDIR)/libvpn_manager_la-nm-vpn-connection-base.Tpo -c -o libvpn_manager_la-nm-vpn-connection-base.lo `test -f 'nm-vpn-connection-base.c' || echo '$(srcdir)/'`nm-vpn-connection-base.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvpn_manager_la-nm-vpn-connection-base.Tpo $(DEPDIR)/libvpn_manager_la-nm-vpn-connection-base.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-vpn-connection-base.c' object='libvpn_manager_la-nm-vpn-connection-base.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvpn_manager_la-nm-vpn-connection-base.lo `test -f 'nm-vpn-connection-base.c' || echo '$(srcdir)/'`nm-vpn-connection-base.c
+
 libvpn_manager_la-nm-vpn-connection.lo: nm-vpn-connection.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvpn_manager_la-nm-vpn-connection.lo -MD -MP -MF $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Tpo -c -o libvpn_manager_la-nm-vpn-connection.lo `test -f 'nm-vpn-connection.c' || echo '$(srcdir)/'`nm-vpn-connection.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Tpo $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Plo
@@ -627,6 +645,9 @@ uninstall-am:
 	pdf pdf-am ps ps-am tags uninstall uninstall-am
 
 
+nm-vpn-connection-base-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection_base --mode=glib-server --output=$@ $<
+
 nm-vpn-connection-glue.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-server --output=$@ $<
 
diff --git a/src/vpn-manager/nm-vpn-connection-base.c b/src/vpn-manager/nm-vpn-connection-base.c
new file mode 100644
index 00000000..8a6fb2be
--- /dev/null
+++ b/src/vpn-manager/nm-vpn-connection-base.c
@@ -0,0 +1,199 @@
+/* -*- 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 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#include "NetworkManager.h"
+#include "nm-vpn-connection-base.h"
+#include "nm-active-connection.h"
+#include "nm-vpn-connection-base-glue.h"
+#include "nm-dbus-manager.h"
+
+G_DEFINE_ABSTRACT_TYPE (NMVpnConnectionBase, nm_vpn_connection_base, G_TYPE_OBJECT)
+
+#define NM_VPN_CONNECTION_BASE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                               NM_TYPE_VPN_CONNECTION_BASE, \
+                                               NMVpnConnectionBasePrivate))
+
+typedef struct {
+	gboolean disposed;
+
+	NMConnection *connection;
+	char *ac_path;
+	gboolean is_default;
+	gboolean is_default6;
+	NMActiveConnectionState state;
+} NMVpnConnectionBasePrivate;
+
+enum {
+	PROP_0,
+	PROP_SERVICE_NAME,
+	PROP_CONNECTION,
+	PROP_SPECIFIC_OBJECT,
+	PROP_DEVICES,
+	PROP_STATE,
+	PROP_DEFAULT,
+	PROP_DEFAULT6,
+	PROP_VPN,
+
+	LAST_PROP
+};
+
+/****************************************************************/
+
+void
+nm_vpn_connection_base_set_state (NMVpnConnectionBase *self,
+                                  NMVPNConnectionState vpn_state)
+{
+	NMVpnConnectionBasePrivate *priv = NM_VPN_CONNECTION_BASE_GET_PRIVATE (self);
+	NMActiveConnectionState new_ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
+
+	/* Set the NMActiveConnection state based on VPN state */
+	switch (vpn_state) {
+	case NM_VPN_CONNECTION_STATE_PREPARE:
+	case NM_VPN_CONNECTION_STATE_NEED_AUTH:
+	case NM_VPN_CONNECTION_STATE_CONNECT:
+	case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET:
+		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
+		break;
+	case NM_VPN_CONNECTION_STATE_ACTIVATED:
+		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
+		break;
+	default:
+		break;
+	}
+
+	if (new_ac_state != priv->state) {
+		priv->state = new_ac_state;
+		g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE);
+	}
+}
+
+const char *
+nm_vpn_connection_base_get_ac_path (NMVpnConnectionBase *self)
+{
+	return NM_VPN_CONNECTION_BASE_GET_PRIVATE (self)->ac_path;
+}
+
+void
+nm_vpn_connection_base_export (NMVpnConnectionBase *self,
+                               NMConnection *connection)
+{
+	NMVpnConnectionBasePrivate *priv = NM_VPN_CONNECTION_BASE_GET_PRIVATE (self);
+	NMDBusManager *dbus_mgr;
+
+	g_return_if_fail (priv->connection == NULL);
+
+	priv->connection = g_object_ref (connection);
+
+	dbus_mgr = nm_dbus_manager_get ();
+	dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr),
+	                                     priv->ac_path, G_OBJECT (self));
+	g_object_unref (dbus_mgr);
+}
+
+/****************************************************************/
+
+static void
+nm_vpn_connection_base_init (NMVpnConnectionBase *self)
+{
+	NMVpnConnectionBasePrivate *priv = NM_VPN_CONNECTION_BASE_GET_PRIVATE (self);
+
+	priv->state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
+	priv->ac_path = nm_active_connection_get_next_object_path ();
+}
+
+static void
+dispose (GObject *object)
+{
+	NMVpnConnectionBasePrivate *priv = NM_VPN_CONNECTION_BASE_GET_PRIVATE (object);
+
+	if (!priv->disposed) {
+		priv->disposed = TRUE;
+
+		g_free (priv->ac_path);
+		g_object_unref (priv->connection);
+	}
+
+	G_OBJECT_CLASS (nm_vpn_connection_base_parent_class)->dispose (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMVpnConnectionBasePrivate *priv = NM_VPN_CONNECTION_BASE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_SERVICE_NAME:
+		nm_active_connection_scope_to_value (priv->connection, value);
+		break;
+	case PROP_CONNECTION:
+		g_value_set_boxed (value, nm_connection_get_path (priv->connection));
+		break;
+	case PROP_SPECIFIC_OBJECT:
+		g_value_set_boxed (value, priv->ac_path);
+		break;
+	case PROP_DEVICES:
+		g_value_take_boxed (value, g_ptr_array_new ());
+		break;
+	case PROP_STATE:
+		g_value_set_uint (value, priv->state);
+		break;
+	case PROP_DEFAULT:
+		g_value_set_boolean (value, priv->is_default);
+		break;
+	case PROP_DEFAULT6:
+		g_value_set_boolean (value, priv->is_default6);
+		break;
+	case PROP_VPN:
+		g_value_set_boolean (value, TRUE);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_vpn_connection_base_class_init (NMVpnConnectionBaseClass *vpn_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (vpn_class);
+
+	g_type_class_add_private (vpn_class, sizeof (NMVpnConnectionBasePrivate));
+
+	/* virtual methods */
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* properties */
+    nm_active_connection_install_properties (object_class,
+                                             PROP_SERVICE_NAME,
+                                             PROP_CONNECTION,
+                                             PROP_SPECIFIC_OBJECT,
+                                             PROP_DEVICES,
+                                             PROP_STATE,
+                                             PROP_DEFAULT,
+                                             PROP_DEFAULT6,
+                                             PROP_VPN);
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (vpn_class),
+									 &dbus_glib_nm_vpn_connection_base_object_info);
+}
+
diff --git a/src/vpn-manager/nm-vpn-connection-base.h b/src/vpn-manager/nm-vpn-connection-base.h
new file mode 100644
index 00000000..0c17d9e8
--- /dev/null
+++ b/src/vpn-manager/nm-vpn-connection-base.h
@@ -0,0 +1,54 @@
+/* -*- 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.
+ *
+ * (C) Copyright 2005 - 2011 Red Hat, Inc.
+ */
+
+#ifndef NM_VPN_CONNECTION_BASE_H
+#define NM_VPN_CONNECTION_BASE_H
+
+#include <glib-object.h>
+#include "NetworkManagerVPN.h"
+#include "nm-connection.h"
+
+#define NM_TYPE_VPN_CONNECTION_BASE            (nm_vpn_connection_base_get_type ())
+#define NM_VPN_CONNECTION_BASE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION_BASE, NMVpnConnectionBase))
+#define NM_VPN_CONNECTION_BASE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_CONNECTION_BASE, NMVpnConnectionBaseClass))
+#define NM_IS_VPN_CONNECTION_BASE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_CONNECTION_BASE))
+#define NM_IS_VPN_CONNECTION_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_CONNECTION_BASE))
+#define NM_VPN_CONNECTION_BASE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION_BASE, NMVpnConnectionBaseClass))
+
+typedef struct {
+	GObject parent;
+} NMVpnConnectionBase;
+
+typedef struct {
+	GObjectClass parent;
+} NMVpnConnectionBaseClass;
+
+GType nm_vpn_connection_base_get_type (void);
+
+const char *nm_vpn_connection_base_get_ac_path (NMVpnConnectionBase *self);
+
+void nm_vpn_connection_base_export (NMVpnConnectionBase *self,
+                                    NMConnection *connection);
+
+void nm_vpn_connection_base_set_state (NMVpnConnectionBase *self,
+                                       NMVPNConnectionState vpn_state);
+
+#endif /* NM_VPN_CONNECTION_BASE_H */
+
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index cf844992..03e213ff 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -52,7 +52,7 @@
 
 static void secrets_provider_interface_init (NMSecretsProviderInterface *sp_interface_class);
 
-G_DEFINE_TYPE_EXTENDED (NMVPNConnection, nm_vpn_connection, G_TYPE_OBJECT, 0,
+G_DEFINE_TYPE_EXTENDED (NMVPNConnection, nm_vpn_connection, NM_TYPE_VPN_CONNECTION_BASE, 0,
                         G_IMPLEMENT_INTERFACE (NM_TYPE_SECRETS_PROVIDER_INTERFACE,
                                                secrets_provider_interface_init))
 
@@ -62,16 +62,11 @@ typedef struct {
 	NMConnection *connection;
 
 	NMActRequest *act_request;
-	char *ac_path;
 
 	NMDevice *parent_dev;
 	gulong device_monitor;
 	gulong device_ip4;
 
-	gboolean is_default;
-	gboolean is_default6;
-	NMActiveConnectionState state;
-
 	NMVPNConnectionState vpn_state;
 	NMVPNConnectionStateReason failure_reason;
 	DBusGProxy *proxy;
@@ -97,14 +92,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 enum {
 	PROP_0,
-	PROP_SERVICE_NAME,
-	PROP_CONNECTION,
-	PROP_SPECIFIC_OBJECT,
-	PROP_DEVICES,
-	PROP_STATE,
-	PROP_DEFAULT,
-	PROP_DEFAULT6,
-	PROP_VPN,
 	PROP_VPN_STATE,
 	PROP_BANNER,
 
@@ -117,7 +104,6 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
                                  NMVPNConnectionStateReason reason)
 {
 	NMVPNConnectionPrivate *priv;
-	NMActiveConnectionState new_ac_state;
 	NMVPNConnectionState old_vpn_state;
 	char *ip_iface;
 
@@ -131,32 +117,14 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
 	old_vpn_state = priv->vpn_state;
 	priv->vpn_state = vpn_state;
 
+	/* Update active connection base class state */
+	nm_vpn_connection_base_set_state (NM_VPN_CONNECTION_BASE (connection), vpn_state);
+
 	/* Save ip_iface since when the VPN goes down it may get freed
 	 * before we're done with it.
 	 */
 	ip_iface = g_strdup (priv->ip_iface);
 
-	/* Set the NMActiveConnection state based on VPN state */
-	switch (vpn_state) {
-	case NM_VPN_CONNECTION_STATE_PREPARE:
-	case NM_VPN_CONNECTION_STATE_NEED_AUTH:
-	case NM_VPN_CONNECTION_STATE_CONNECT:
-	case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET:
-		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
-		break;
-	case NM_VPN_CONNECTION_STATE_ACTIVATED:
-		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
-		break;
-	default:
-		new_ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-		break;
-	}
-
-	if (new_ac_state != priv->state) {
-		priv->state = new_ac_state;
-		g_object_notify (G_OBJECT (connection), NM_ACTIVE_CONNECTION_STATE);
-	}
-
 	/* The connection gets destroyed by the VPN manager when it enters the
 	 * disconnected/failed state, but we need to keep it around for a bit
 	 * to send out signals and handle the dispatcher.  So ref it.
@@ -259,6 +227,9 @@ nm_vpn_connection_new (NMConnection *connection,
 	priv->device_ip4 = g_signal_connect (parent_device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG,
 	                                     G_CALLBACK (device_ip4_config_changed),
 	                                     self);
+
+	nm_vpn_connection_base_export (NM_VPN_CONNECTION_BASE (self), connection);
+
 	return self;
 }
 
@@ -623,6 +594,7 @@ static void
 really_activate (NMVPNConnection *connection)
 {
 	NMVPNConnectionPrivate *priv;
+	GHashTable *hash;
 
 	g_return_if_fail (NM_IS_VPN_CONNECTION (connection));
 	g_return_if_fail (nm_vpn_connection_get_vpn_state (connection) == NM_VPN_CONNECTION_STATE_NEED_AUTH);
@@ -639,10 +611,12 @@ really_activate (NMVPNConnection *connection)
 						    G_CALLBACK (nm_vpn_connection_ip4_config_get),
 						    connection, NULL);
 
+	hash = nm_connection_to_hash (priv->connection);
 	org_freedesktop_NetworkManager_VPN_Plugin_connect_async (priv->proxy,
-												  nm_connection_to_hash (priv->connection),
-												  nm_vpn_connection_connect_cb,
-												  connection);
+	                                                         hash,
+	                                                         nm_vpn_connection_connect_cb,
+	                                                         connection);
+	g_hash_table_destroy (hash);
 
 	nm_vpn_connection_set_vpn_state (connection,
 	                                 NM_VPN_CONNECTION_STATE_CONNECT,
@@ -688,7 +662,7 @@ nm_vpn_connection_get_active_connection_path (NMVPNConnection *connection)
 {
 	g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL);
 
-	return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ac_path;
+	return nm_vpn_connection_base_get_ac_path (NM_VPN_CONNECTION_BASE (connection));
 }
 
 const char *
@@ -979,20 +953,9 @@ connection_state_changed (NMVPNConnection *connection,
 }
 
 static void
-nm_vpn_connection_init (NMVPNConnection *connection)
+nm_vpn_connection_init (NMVPNConnection *self)
 {
-	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
-	NMDBusManager *dbus_mgr;
-
-	priv->state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-	priv->vpn_state = NM_VPN_CONNECTION_STATE_PREPARE;
-	priv->ac_path = nm_active_connection_get_next_object_path ();
-
-	dbus_mgr = nm_dbus_manager_get ();
-	dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr),
-								  priv->ac_path,
-								  G_OBJECT (connection));
-	g_object_unref (dbus_mgr);
+	NM_VPN_CONNECTION_GET_PRIVATE (self)->vpn_state = NM_VPN_CONNECTION_STATE_PREPARE;
 }
 
 static void
@@ -1039,7 +1002,6 @@ finalize (GObject *object)
 
 	g_free (priv->banner);
 	g_free (priv->ip_iface);
-	g_free (priv->ac_path);
 
 	G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object);
 }
@@ -1051,30 +1013,6 @@ get_property (GObject *object, guint prop_id,
 	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
 
 	switch (prop_id) {
-	case PROP_SERVICE_NAME:
-		nm_active_connection_scope_to_value (priv->connection, value);
-		break;
-	case PROP_CONNECTION:
-		g_value_set_boxed (value, nm_connection_get_path (priv->connection));
-		break;
-	case PROP_SPECIFIC_OBJECT:
-		g_value_set_boxed (value, nm_act_request_get_active_connection_path (priv->act_request));
-		break;
-	case PROP_DEVICES:
-		g_value_take_boxed (value, g_ptr_array_new ());
-		break;
-	case PROP_STATE:
-		g_value_set_uint (value, priv->state);
-		break;
-	case PROP_DEFAULT:
-		g_value_set_boolean (value, priv->is_default);
-		break;
-	case PROP_DEFAULT6:
-		g_value_set_boolean (value, priv->is_default6);
-		break;
-	case PROP_VPN:
-		g_value_set_boolean (value, TRUE);
-		break;
 	case PROP_VPN_STATE:
 		g_value_set_uint (value, priv->vpn_state);
 		break;
@@ -1101,82 +1039,21 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
 	object_class->finalize = finalize;
 
 	/* properties */
-	g_object_class_install_property
-		(object_class, PROP_SERVICE_NAME,
-		 g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME,
-							  "Service name",
-							  "Service name",
-							  NULL,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_CONNECTION,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_CONNECTION,
-							  "Connection",
-							  "Connection",
-							  DBUS_TYPE_G_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_SPECIFIC_OBJECT,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
-							  "Specific object",
-							  "Specific object",
-							  DBUS_TYPE_G_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEVICES,
-		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
-							  "Devices",
-							  "Devices",
-							  DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_STATE,
-		 g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE,
-							  "State",
-							  "State",
-							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
-							  NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
-							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEFAULT,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
-							   "Default",
-							   "Is the default IPv4 active connection",
-							   FALSE,
-							   G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_DEFAULT6,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
-							   "Default6",
-							   "Is the default IPv6 active connection",
-							   FALSE,
-							   G_PARAM_READABLE));
-	g_object_class_install_property
-		(object_class, PROP_VPN,
-		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN,
-							   "VPN",
-							   "Is a VPN connection",
-							   TRUE,
-							   G_PARAM_READABLE));
-
-	g_object_class_install_property
-		(object_class, PROP_VPN_STATE,
-		 g_param_spec_uint (NM_VPN_CONNECTION_VPN_STATE,
-						"VpnState",
-						"Current VPN state",
-						NM_VPN_CONNECTION_STATE_UNKNOWN,
-						NM_VPN_CONNECTION_STATE_DISCONNECTED,
-						NM_VPN_CONNECTION_STATE_UNKNOWN,
-						G_PARAM_READABLE));
-
-	g_object_class_install_property
-		(object_class, PROP_BANNER,
-		 g_param_spec_string (NM_VPN_CONNECTION_BANNER,
-						  "Banner",
-						  "Login Banner",
-						  NULL,
-						  G_PARAM_READABLE));
+	g_object_class_install_property (object_class, PROP_VPN_STATE,
+		g_param_spec_uint (NM_VPN_CONNECTION_VPN_STATE,
+		                   "VpnState",
+		                   "Current VPN state",
+		                   NM_VPN_CONNECTION_STATE_UNKNOWN,
+		                   NM_VPN_CONNECTION_STATE_DISCONNECTED,
+		                   NM_VPN_CONNECTION_STATE_UNKNOWN,
+		                   G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class, PROP_BANNER,
+		g_param_spec_string (NM_VPN_CONNECTION_BANNER,
+		                     "Banner",
+		                     "Login Banner",
+		                     NULL,
+		                     G_PARAM_READABLE));
 
 	/* signals */
 	signals[VPN_STATE_CHANGED] =
diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h
index d69674db..ab880b17 100644
--- a/src/vpn-manager/nm-vpn-connection.h
+++ b/src/vpn-manager/nm-vpn-connection.h
@@ -28,6 +28,7 @@
 #include "nm-device.h"
 #include "nm-activation-request.h"
 #include "nm-secrets-provider-interface.h"
+#include "nm-vpn-connection-base.h"
 
 #define NM_TYPE_VPN_CONNECTION            (nm_vpn_connection_get_type ())
 #define NM_VPN_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnection))
@@ -40,11 +41,11 @@
 #define NM_VPN_CONNECTION_BANNER "banner"
 
 typedef struct {
-	GObject parent;
+	NMVpnConnectionBase parent;
 } NMVPNConnection;
 
 typedef struct {
-	GObjectClass parent;
+	NMVpnConnectionBaseClass parent;
 
 	/* Signals */
 	void (*vpn_state_changed) (NMVPNConnection *connection,