summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am56
-rw-r--r--src/Makefile.in236
-rw-r--r--src/NetworkManagerUtils.c2989
-rw-r--r--src/NetworkManagerUtils.h371
-rw-r--r--src/devices/adsl/nm-atm-manager.c3
-rw-r--r--src/devices/adsl/nm-device-adsl.c10
-rw-r--r--src/devices/bluetooth/nm-bluez-common.h2
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c17
-rw-r--r--src/devices/bluetooth/nm-bluez-device.h3
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c10
-rw-r--r--src/devices/bluetooth/nm-bluez4-adapter.c3
-rw-r--r--src/devices/bluetooth/nm-bluez4-manager.c3
-rw-r--r--src/devices/bluetooth/nm-bluez5-dun.c3
-rw-r--r--src/devices/bluetooth/nm-bluez5-manager.c3
-rw-r--r--src/devices/bluetooth/nm-bt-error.c3
-rw-r--r--src/devices/bluetooth/nm-device-bt.c3
-rw-r--r--src/devices/nm-arping-manager.c449
-rw-r--r--src/devices/nm-arping-manager.h53
-rw-r--r--src/devices/nm-device-bond.c11
-rw-r--r--src/devices/nm-device-bridge.c11
-rw-r--r--src/devices/nm-device-ethernet-utils.c6
-rw-r--r--src/devices/nm-device-ethernet.c113
-rw-r--r--src/devices/nm-device-factory.c62
-rw-r--r--src/devices/nm-device-factory.h19
-rw-r--r--src/devices/nm-device-generic.c4
-rw-r--r--src/devices/nm-device-infiniband.c22
-rw-r--r--src/devices/nm-device-ip-tunnel.c25
-rw-r--r--src/devices/nm-device-macvlan.c57
-rw-r--r--src/devices/nm-device-private.h1
-rw-r--r--src/devices/nm-device-tun.c18
-rw-r--r--src/devices/nm-device-veth.c5
-rw-r--r--src/devices/nm-device-vlan.c53
-rw-r--r--src/devices/nm-device-vxlan.c34
-rw-r--r--src/devices/nm-device.c2399
-rw-r--r--src/devices/nm-device.h86
-rw-r--r--src/devices/nm-lldp-listener.c105
-rw-r--r--src/devices/nm-lldp-listener.h3
-rw-r--r--src/devices/team/nm-device-team.c17
-rw-r--r--src/devices/team/nm-team-factory.c3
-rw-r--r--src/devices/tests/Makefile.am18
-rw-r--r--src/devices/tests/Makefile.in88
-rw-r--r--src/devices/tests/test-arping.c139
-rw-r--r--src/devices/tests/test-lldp.c44
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c3
-rw-r--r--src/devices/wifi/nm-device-wifi.c109
-rw-r--r--src/devices/wifi/nm-wifi-ap-utils.c11
-rw-r--r--src/devices/wifi/nm-wifi-ap.c3
-rw-r--r--src/devices/wifi/nm-wifi-factory.c13
-rw-r--r--src/devices/wifi/tests/test-wifi-ap-utils.c5
-rw-r--r--src/devices/wwan/nm-device-modem.c3
-rw-r--r--src/devices/wwan/nm-modem-broadband.c25
-rw-r--r--src/devices/wwan/nm-modem-manager.c3
-rw-r--r--src/devices/wwan/nm-modem.c7
-rw-r--r--src/devices/wwan/nm-wwan-factory.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-client.c35
-rw-r--r--src/dhcp-manager/nm-dhcp-client.h2
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient-utils.c13
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-dhcpcd.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-helper.c4
-rw-r--r--src/dhcp-manager/nm-dhcp-listener.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-manager.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-systemd.c203
-rw-r--r--src/dhcp-manager/nm-dhcp-utils.c3
-rw-r--r--src/dhcp-manager/tests/test-dhcp-dhclient.c8
-rw-r--r--src/dhcp-manager/tests/test-dhcp-utils.c5
-rw-r--r--src/dns-manager/nm-dns-dnsmasq.c15
-rw-r--r--src/dns-manager/nm-dns-manager.c224
-rw-r--r--src/dns-manager/nm-dns-plugin.c6
-rw-r--r--src/dns-manager/nm-dns-unbound.c2
-rw-r--r--src/dns-manager/nm-dns-utils.c2
-rw-r--r--src/dnsmasq-manager/nm-dnsmasq-manager.c77
-rw-r--r--src/dnsmasq-manager/nm-dnsmasq-utils.c2
-rw-r--r--src/dnsmasq-manager/tests/test-dnsmasq-utils.c3
-rw-r--r--src/main-utils.c3
-rw-r--r--src/main.c15
-rw-r--r--src/nm-activation-request.c6
-rw-r--r--src/nm-active-connection.c57
-rw-r--r--src/nm-active-connection.h3
-rw-r--r--src/nm-audit-manager.c9
-rw-r--r--src/nm-auth-manager.c3
-rw-r--r--src/nm-auth-subject.c3
-rw-r--r--src/nm-auth-subject.h4
-rw-r--r--src/nm-auth-utils.c3
-rw-r--r--src/nm-bus-manager.c3
-rw-r--r--src/nm-bus-manager.h6
-rw-r--r--src/nm-config-data.c16
-rw-r--r--src/nm-config.c13
-rw-r--r--src/nm-connection-provider.c2
-rw-r--r--src/nm-connectivity.c41
-rw-r--r--src/nm-core-utils.c2944
-rw-r--r--src/nm-core-utils.h415
-rw-r--r--src/nm-dcb.c3
-rw-r--r--src/nm-default-route-manager.c3
-rw-r--r--src/nm-dhcp4-config.c3
-rw-r--r--src/nm-dhcp6-config.c3
-rw-r--r--src/nm-dispatcher.c5
-rw-r--r--src/nm-enum-types.c22
-rw-r--r--src/nm-enum-types.h2
-rw-r--r--src/nm-exported-object.c15
-rw-r--r--src/nm-firewall-manager.c7
-rw-r--r--src/nm-iface-helper.c11
-rw-r--r--src/nm-ip4-config.c158
-rw-r--r--src/nm-ip4-config.h1
-rw-r--r--src/nm-ip6-config.c143
-rw-r--r--src/nm-ip6-config.h3
-rw-r--r--src/nm-logging.c168
-rw-r--r--src/nm-logging.h45
-rw-r--r--src/nm-manager.c226
-rw-r--r--src/nm-manager.h6
-rw-r--r--src/nm-multi-index.c7
-rw-r--r--src/nm-policy.c4
-rw-r--r--src/nm-rfkill-manager.c3
-rw-r--r--src/nm-route-manager.c7
-rw-r--r--src/nm-session-monitor.c3
-rw-r--r--src/nm-sleep-monitor-systemd.c3
-rw-r--r--src/nm-sleep-monitor-upower.c4
-rw-r--r--src/nm-types.h1
-rw-r--r--src/platform/nm-fake-platform.c35
-rw-r--r--src/platform/nm-linux-platform.c295
-rw-r--r--src/platform/nm-linux-platform.h2
-rw-r--r--src/platform/nm-platform-utils.c27
-rw-r--r--src/platform/nm-platform-utils.h4
-rw-r--r--src/platform/nm-platform.c128
-rw-r--r--src/platform/nm-platform.h84
-rw-r--r--src/platform/nmp-object.c13
-rw-r--r--src/platform/nmp-object.h8
-rw-r--r--src/platform/tests/monitor.c23
-rw-r--r--src/platform/tests/test-address.c28
-rw-r--r--src/platform/tests/test-cleanup.c24
-rw-r--r--src/platform/tests/test-common.c30
-rw-r--r--src/platform/tests/test-link.c36
-rw-r--r--src/platform/tests/test-nmp-object.c4
-rw-r--r--src/platform/tests/test-route.c25
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.c3
-rw-r--r--src/platform/wifi/wifi-utils-wext.c6
-rw-r--r--src/platform/wifi/wifi-utils.c3
-rw-r--r--src/ppp-manager/nm-ppp-manager.c7
-rw-r--r--src/ppp-manager/nm-pppd-plugin.c1
-rw-r--r--src/rdisc/nm-fake-rdisc.c4
-rw-r--r--src/rdisc/nm-lndp-rdisc.c3
-rw-r--r--src/rdisc/nm-rdisc.c3
-rw-r--r--src/rdisc/tests/test-rdisc-fake.c3
-rw-r--r--src/rdisc/tests/test-rdisc-linux.c3
-rw-r--r--src/settings/nm-agent-manager.c3
-rw-r--r--src/settings/nm-inotify-helper.c3
-rw-r--r--src/settings/nm-secret-agent.c3
-rw-r--r--src/settings/nm-settings-connection.c17
-rw-r--r--src/settings/nm-settings-plugin.c2
-rw-r--r--src/settings/nm-settings.c61
-rw-r--r--src/settings/plugins/ibft/nm-ibft-connection.c2
-rw-r--r--src/settings/plugins/ibft/plugin.c5
-rw-r--r--src/settings/plugins/ibft/reader.c7
-rw-r--r--src/settings/plugins/ibft/tests/test-ibft.c3
-rw-r--r--src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c25
-rw-r--r--src/settings/plugins/ifcfg-rh/plugin.c3
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c117
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.c3
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-21
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface1
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-13
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-26
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip5
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c40
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c7267
-rw-r--r--src/settings/plugins/ifcfg-rh/utils.c16
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c92
-rw-r--r--src/settings/plugins/ifnet/connection_parser.c3
-rw-r--r--src/settings/plugins/ifnet/net_parser.c5
-rw-r--r--src/settings/plugins/ifnet/net_utils.c10
-rw-r--r--src/settings/plugins/ifnet/nm-ifnet-connection.c14
-rw-r--r--src/settings/plugins/ifnet/plugin.c6
-rw-r--r--src/settings/plugins/ifnet/tests/test-ifnet.c6
-rw-r--r--src/settings/plugins/ifnet/wpa_parser.c6
-rw-r--r--src/settings/plugins/ifupdown/interface_parser.c5
-rw-r--r--src/settings/plugins/ifupdown/nm-ifupdown-connection.c14
-rw-r--r--src/settings/plugins/ifupdown/parser.c3
-rw-r--r--src/settings/plugins/ifupdown/plugin.c13
-rw-r--r--src/settings/plugins/ifupdown/tests/test-ifupdown.c323
-rw-r--r--src/settings/plugins/keyfile/nm-keyfile-connection.c11
-rw-r--r--src/settings/plugins/keyfile/plugin.c11
-rw-r--r--src/settings/plugins/keyfile/reader.c3
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c918
-rw-r--r--src/settings/plugins/keyfile/utils.c10
-rw-r--r--src/settings/plugins/keyfile/writer.c42
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c3
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c279
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.h10
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.c180
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.h9
-rw-r--r--src/supplicant-manager/nm-supplicant-settings-verify.c3
-rw-r--r--src/supplicant-manager/tests/test-supplicant-config.c3
-rw-r--r--src/systemd/nm-sd-adapt.c5
-rw-r--r--src/systemd/nm-sd-adapt.h10
-rw-r--r--src/systemd/src/basic/alloc-util.c2
-rw-r--r--src/systemd/src/basic/alloc-util.h4
-rw-r--r--src/systemd/src/basic/async.h4
-rw-r--r--src/systemd/src/basic/escape.c59
-rw-r--r--src/systemd/src/basic/escape.h12
-rw-r--r--src/systemd/src/basic/fd-util.c2
-rw-r--r--src/systemd/src/basic/fd-util.h8
-rw-r--r--src/systemd/src/basic/fileio.c35
-rw-r--r--src/systemd/src/basic/fileio.h6
-rw-r--r--src/systemd/src/basic/fs-util.c7
-rw-r--r--src/systemd/src/basic/fs-util.h4
-rw-r--r--src/systemd/src/basic/hash-funcs.c83
-rw-r--r--src/systemd/src/basic/hash-funcs.h65
-rw-r--r--src/systemd/src/basic/hashmap.c62
-rw-r--r--src/systemd/src/basic/hashmap.h47
-rw-r--r--src/systemd/src/basic/hexdecoct.c63
-rw-r--r--src/systemd/src/basic/hexdecoct.h9
-rw-r--r--src/systemd/src/basic/hostname-util.c2
-rw-r--r--src/systemd/src/basic/hostname-util.h4
-rw-r--r--src/systemd/src/basic/in-addr-util.c6
-rw-r--r--src/systemd/src/basic/in-addr-util.h9
-rw-r--r--src/systemd/src/basic/io-util.c2
-rw-r--r--src/systemd/src/basic/io-util.h22
-rw-r--r--src/systemd/src/basic/list.h4
-rw-r--r--src/systemd/src/basic/log.h14
-rw-r--r--src/systemd/src/basic/macro.h57
-rw-r--r--src/systemd/src/basic/mempool.c2
-rw-r--r--src/systemd/src/basic/mempool.h4
-rw-r--r--src/systemd/src/basic/parse-util.c24
-rw-r--r--src/systemd/src/basic/parse-util.h4
-rw-r--r--src/systemd/src/basic/path-util.c4
-rw-r--r--src/systemd/src/basic/path-util.h4
-rw-r--r--src/systemd/src/basic/prioq.c2
-rw-r--r--src/systemd/src/basic/prioq.h4
-rw-r--r--src/systemd/src/basic/random-util.c15
-rw-r--r--src/systemd/src/basic/random-util.h2
-rw-r--r--src/systemd/src/basic/refcnt.h4
-rw-r--r--src/systemd/src/basic/set.h4
-rw-r--r--src/systemd/src/basic/siphash24.h4
-rw-r--r--src/systemd/src/basic/socket-util.h8
-rw-r--r--src/systemd/src/basic/sparse-endian.h2
-rw-r--r--src/systemd/src/basic/stdio-util.h76
-rw-r--r--src/systemd/src/basic/string-table.c2
-rw-r--r--src/systemd/src/basic/string-table.h22
-rw-r--r--src/systemd/src/basic/string-util.c68
-rw-r--r--src/systemd/src/basic/string-util.h11
-rw-r--r--src/systemd/src/basic/strv.c22
-rw-r--r--src/systemd/src/basic/strv.h6
-rw-r--r--src/systemd/src/basic/time-util.c82
-rw-r--r--src/systemd/src/basic/time-util.h34
-rw-r--r--src/systemd/src/basic/umask-util.h4
-rw-r--r--src/systemd/src/basic/unaligned.h4
-rw-r--r--src/systemd/src/basic/utf8.c50
-rw-r--r--src/systemd/src/basic/utf8.h22
-rw-r--r--src/systemd/src/basic/util.c4
-rw-r--r--src/systemd/src/basic/util.h4
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-option.c22
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-packet.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-protocol.h46
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c18
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-protocol.h39
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.c2
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.c2
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.h4
-rw-r--r--src/systemd/src/libsystemd-network/lldp-port.c2
-rw-r--r--src/systemd/src/libsystemd-network/lldp-port.h4
-rw-r--r--src/systemd/src/libsystemd-network/lldp-tlv.c2
-rw-r--r--src/systemd/src/libsystemd-network/lldp-tlv.h4
-rw-r--r--src/systemd/src/libsystemd-network/lldp.h4
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c17
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h8
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c75
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c163
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c50
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c4
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c2
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c2
-rw-r--r--src/systemd/src/shared/dns-domain.c349
-rw-r--r--src/systemd/src/shared/dns-domain.h9
-rw-r--r--src/systemd/src/systemd/_sd-common.h4
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h46
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h12
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h39
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-lease.h4
-rw-r--r--src/systemd/src/systemd/sd-event.h4
-rw-r--r--src/systemd/src/systemd/sd-id128.h4
-rw-r--r--src/systemd/src/systemd/sd-ipv4acd.h4
-rw-r--r--src/systemd/src/systemd/sd-ipv4ll.h4
-rw-r--r--src/systemd/src/systemd/sd-lldp.h4
-rw-r--r--src/systemd/src/systemd/sd-ndisc.h4
-rw-r--r--src/tests/Makefile.am16
-rw-r--r--src/tests/Makefile.in64
-rw-r--r--src/tests/config/nm-test-device.c2
-rw-r--r--src/tests/config/test-config.c4
-rw-r--r--src/tests/test-dcb.c3
-rw-r--r--src/tests/test-general-with-expect.c57
-rw-r--r--src/tests/test-general.c155
-rw-r--r--src/tests/test-ip4-config.c3
-rw-r--r--src/tests/test-ip6-config.c3
-rw-r--r--src/tests/test-resolvconf-capture.c3
-rw-r--r--src/tests/test-route-manager.c3
-rw-r--r--src/tests/test-systemd.c53
-rw-r--r--src/tests/test-utils.c4
-rw-r--r--src/tests/test-wired-defname.c8
-rw-r--r--src/vpn-manager/nm-vpn-connection.c146
-rw-r--r--src/vpn-manager/nm-vpn-manager.c3
310 files changed, 11583 insertions, 14182 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7e858310..eea646a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,6 +77,8 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/basic/fileio.h \
 	systemd/src/basic/fs-util.c \
 	systemd/src/basic/fs-util.h \
+	systemd/src/basic/hash-funcs.c \
+	systemd/src/basic/hash-funcs.h \
 	systemd/src/basic/hashmap.c \
 	systemd/src/basic/hashmap.h \
 	systemd/src/basic/hexdecoct.c \
@@ -101,11 +103,12 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/basic/random-util.c \
 	systemd/src/basic/random-util.h \
 	systemd/src/basic/refcnt.h \
+	systemd/src/basic/set.h \
 	systemd/src/basic/siphash24.c \
 	systemd/src/basic/siphash24.h \
-	systemd/src/basic/set.h \
 	systemd/src/basic/socket-util.h \
 	systemd/src/basic/sparse-endian.h \
+	systemd/src/basic/stdio-util.h \
 	systemd/src/basic/string-table.c \
 	systemd/src/basic/string-table.h \
 	systemd/src/basic/string-util.c \
@@ -135,15 +138,15 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/libsystemd-network/dhcp6-network.c \
 	systemd/src/libsystemd-network/dhcp6-option.c \
 	systemd/src/libsystemd-network/dhcp6-protocol.h \
-	systemd/src/libsystemd-network/lldp.h \
-	systemd/src/libsystemd-network/lldp-network.h \
+	systemd/src/libsystemd-network/lldp-internal.c \
+	systemd/src/libsystemd-network/lldp-internal.h \
 	systemd/src/libsystemd-network/lldp-network.c \
-	systemd/src/libsystemd-network/lldp-tlv.c \
-	systemd/src/libsystemd-network/lldp-tlv.h \
+	systemd/src/libsystemd-network/lldp-network.h \
 	systemd/src/libsystemd-network/lldp-port.c \
 	systemd/src/libsystemd-network/lldp-port.h \
-	systemd/src/libsystemd-network/lldp-internal.h \
-	systemd/src/libsystemd-network/lldp-internal.c \
+	systemd/src/libsystemd-network/lldp-tlv.c \
+	systemd/src/libsystemd-network/lldp-tlv.h \
+	systemd/src/libsystemd-network/lldp.h \
 	systemd/src/libsystemd-network/network-internal.c \
 	systemd/src/libsystemd-network/network-internal.h \
 	systemd/src/libsystemd-network/sd-dhcp-client.c \
@@ -161,11 +164,11 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/systemd/sd-dhcp-lease.h \
 	systemd/src/systemd/sd-dhcp6-client.h \
 	systemd/src/systemd/sd-dhcp6-lease.h \
-	systemd/src/systemd/sd-lldp.h \
 	systemd/src/systemd/sd-event.h \
 	systemd/src/systemd/sd-id128.h \
 	systemd/src/systemd/sd-ipv4acd.h \
 	systemd/src/systemd/sd-ipv4ll.h \
+	systemd/src/systemd/sd-lldp.h \
 	systemd/src/systemd/sd-ndisc.h
 
 libsystemd_nm_la_CPPFLAGS = \
@@ -181,6 +184,37 @@ libsystemd_nm_la_CPPFLAGS = \
 libsystemd_nm_la_LIBADD = \
 	$(GLIB_LIBS)
 
+######################
+# libsystemd-nm-base
+######################
+
+if ENABLE_TESTS
+noinst_LTLIBRARIES += \
+	libNetworkManager-base.la
+
+libNetworkManager_base_la_SOURCES = \
+	nm-core-utils.c \
+	nm-core-utils.h \
+	nm-logging.c \
+	nm-logging.h
+
+libNetworkManager_base_la_CPPFLAGS = \
+	-I$(top_srcdir)/shared \
+	-I$(top_builddir)/shared \
+	-I$(top_srcdir)/libnm-core \
+	-I$(top_builddir)/libnm-core \
+	-I$(top_srcdir)/src/platform \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
+	-DNO_SYSTEMD_JOURNAL \
+	-DPREFIX=\"$(prefix)\" \
+	-DNMSTATEDIR=\"$(nmstatedir)\" \
+	$(GLIB_CFLAGS)
+
+libNetworkManager_base_la_LIBADD = \
+	$(top_builddir)/libnm-core/libnm-core.la \
+	$(GLIB_LIBS)
+endif
+
 ###########################################
 # NetworkManager
 ###########################################
@@ -240,6 +274,8 @@ libNetworkManager_la_SOURCES = \
 	devices/nm-device.h \
 	devices/nm-lldp-listener.c \
 	devices/nm-lldp-listener.h \
+	devices/nm-arping-manager.c \
+	devices/nm-arping-manager.h \
 	devices/nm-device-ethernet-utils.c \
 	devices/nm-device-ethernet-utils.h \
 	devices/nm-device-factory.c \
@@ -399,6 +435,8 @@ libNetworkManager_la_SOURCES = \
 	nm-session-monitor.c \
 	nm-sleep-monitor.h \
 	nm-types.h \
+	nm-core-utils.c \
+	nm-core-utils.h \
 	NetworkManagerUtils.c \
 	NetworkManagerUtils.h
 
@@ -530,6 +568,8 @@ libnm_iface_helper_la_SOURCES = \
 	nm-logging.h \
 	nm-multi-index.c \
 	nm-multi-index.h \
+	nm-core-utils.c \
+	nm-core-utils.h \
 	NetworkManagerUtils.c \
 	NetworkManagerUtils.h
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 9a91cfba..14ef31f7 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -102,16 +102,23 @@ host_triplet = @host@
 @ENABLE_TESTS_TRUE@	supplicant-manager/tests \
 @ENABLE_TESTS_TRUE@	tests
 
+
+######################
+# libsystemd-nm-base
+######################
+@ENABLE_TESTS_TRUE@am__append_5 = \
+@ENABLE_TESTS_TRUE@	libNetworkManager-base.la
+
 sbin_PROGRAMS = NetworkManager$(EXEEXT)
-@SUSPEND_RESUME_UPOWER_TRUE@am__append_5 = nm-sleep-monitor-upower.c
+@SUSPEND_RESUME_UPOWER_TRUE@am__append_6 = nm-sleep-monitor-upower.c
 # systemd/consolekit suspend/resume used whenever upower is not enabled
-@SUSPEND_RESUME_UPOWER_FALSE@am__append_6 = nm-sleep-monitor-systemd.c
-@WITH_WEXT_TRUE@am__append_7 = \
+@SUSPEND_RESUME_UPOWER_FALSE@am__append_7 = nm-sleep-monitor-systemd.c
+@WITH_WEXT_TRUE@am__append_8 = \
 @WITH_WEXT_TRUE@	platform/wifi/wifi-utils-wext.c \
 @WITH_WEXT_TRUE@	platform/wifi/wifi-utils-wext.h
 
-@WITH_LIBSOUP_TRUE@am__append_8 = $(LIBSOUP_LIBS)
-@WITH_WEXT_TRUE@am__append_9 = \
+@WITH_LIBSOUP_TRUE@am__append_9 = $(LIBSOUP_LIBS)
+@WITH_WEXT_TRUE@am__append_10 = \
 @WITH_WEXT_TRUE@	platform/wifi/wifi-utils-wext.c \
 @WITH_WEXT_TRUE@	platform/wifi/wifi-utils-wext.h
 
@@ -140,6 +147,21 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
+@ENABLE_TESTS_TRUE@libNetworkManager_base_la_DEPENDENCIES =  \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1)
+am__libNetworkManager_base_la_SOURCES_DIST = nm-core-utils.c \
+	nm-core-utils.h nm-logging.c nm-logging.h
+@ENABLE_TESTS_TRUE@am_libNetworkManager_base_la_OBJECTS =  \
+@ENABLE_TESTS_TRUE@	libNetworkManager_base_la-nm-core-utils.lo \
+@ENABLE_TESTS_TRUE@	libNetworkManager_base_la-nm-logging.lo
+libNetworkManager_base_la_OBJECTS =  \
+	$(am_libNetworkManager_base_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+@ENABLE_TESTS_TRUE@am_libNetworkManager_base_la_rpath =
 @WITH_LIBSOUP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
 libNetworkManager_la_DEPENDENCIES =  \
 	$(top_builddir)/libnm-core/libnm-core.la \
@@ -160,6 +182,7 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \
 	dhcp-manager/nm-dhcp-dhcpcd.h dhcp-manager/nm-dhcp-systemd.h \
 	devices/nm-device.c devices/nm-device.h \
 	devices/nm-lldp-listener.c devices/nm-lldp-listener.h \
+	devices/nm-arping-manager.c devices/nm-arping-manager.h \
 	devices/nm-device-ethernet-utils.c \
 	devices/nm-device-ethernet-utils.h devices/nm-device-factory.c \
 	devices/nm-device-factory.h devices/nm-device-generic.c \
@@ -237,7 +260,8 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \
 	nm-manager.h nm-multi-index.c nm-multi-index.h nm-policy.c \
 	nm-policy.h nm-rfkill-manager.c nm-rfkill-manager.h \
 	nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.h \
-	nm-types.h NetworkManagerUtils.c NetworkManagerUtils.h \
+	nm-types.h nm-core-utils.c nm-core-utils.h \
+	NetworkManagerUtils.c NetworkManagerUtils.h \
 	nm-sleep-monitor-upower.c nm-sleep-monitor-systemd.c \
 	platform/wifi/wifi-utils-wext.c \
 	platform/wifi/wifi-utils-wext.h
@@ -248,38 +272,34 @@ am__objects_1 =
 @SUSPEND_RESUME_UPOWER_FALSE@	nm-sleep-monitor-systemd.lo
 @WITH_WEXT_TRUE@am__objects_4 = wifi-utils-wext.lo
 am_libNetworkManager_la_OBJECTS = $(am__objects_1) $(am__objects_1) \
-	nm-device.lo nm-lldp-listener.lo nm-device-ethernet-utils.lo \
-	nm-device-factory.lo nm-device-generic.lo nm-dhcp-client.lo \
-	nm-dhcp-utils.lo nm-dhcp-listener.lo nm-dhcp-manager.lo \
-	nm-dns-dnsmasq.lo nm-dns-unbound.lo nm-dns-manager.lo \
-	nm-dns-plugin.lo nm-dns-utils.lo nm-dnsmasq-manager.lo \
-	nm-dnsmasq-utils.lo nm-fake-platform.lo nm-linux-platform.lo \
-	nm-platform.lo nm-platform-utils.lo nmp-object.lo \
-	wifi-utils-nl80211.lo wifi-utils.lo nm-fake-rdisc.lo \
-	nm-lndp-rdisc.lo nm-rdisc.lo nm-ppp-manager.lo \
-	nm-agent-manager.lo nm-inotify-helper.lo nm-secret-agent.lo \
-	nm-settings-connection.lo nm-settings-plugin.lo nm-settings.lo \
-	nm-keyfile-connection.lo plugin.lo reader.lo utils.lo \
-	writer.lo nm-supplicant-config.lo nm-supplicant-interface.lo \
-	nm-supplicant-manager.lo nm-supplicant-settings-verify.lo \
-	nm-vpn-connection.lo nm-vpn-manager.lo \
-	nm-activation-request.lo nm-active-connection.lo \
-	nm-audit-manager.lo nm-bus-manager.lo nm-config.lo \
-	nm-config-data.lo nm-connection-provider.lo nm-connectivity.lo \
-	nm-dcb.lo nm-route-manager.lo nm-default-route-manager.lo \
-	nm-dhcp4-config.lo nm-dhcp6-config.lo nm-dispatcher.lo \
-	nm-enum-types.lo nm-exported-object.lo nm-firewall-manager.lo \
-	nm-ip4-config.lo nm-ip6-config.lo nm-logging.lo \
-	nm-auth-manager.lo nm-auth-subject.lo nm-auth-utils.lo \
-	nm-manager.lo nm-multi-index.lo nm-policy.lo \
-	nm-rfkill-manager.lo nm-session-monitor.lo \
-	NetworkManagerUtils.lo $(am__objects_2) $(am__objects_3) \
-	$(am__objects_4)
+	nm-device.lo nm-lldp-listener.lo nm-arping-manager.lo \
+	nm-device-ethernet-utils.lo nm-device-factory.lo \
+	nm-device-generic.lo nm-dhcp-client.lo nm-dhcp-utils.lo \
+	nm-dhcp-listener.lo nm-dhcp-manager.lo nm-dns-dnsmasq.lo \
+	nm-dns-unbound.lo nm-dns-manager.lo nm-dns-plugin.lo \
+	nm-dns-utils.lo nm-dnsmasq-manager.lo nm-dnsmasq-utils.lo \
+	nm-fake-platform.lo nm-linux-platform.lo nm-platform.lo \
+	nm-platform-utils.lo nmp-object.lo wifi-utils-nl80211.lo \
+	wifi-utils.lo nm-fake-rdisc.lo nm-lndp-rdisc.lo nm-rdisc.lo \
+	nm-ppp-manager.lo nm-agent-manager.lo nm-inotify-helper.lo \
+	nm-secret-agent.lo nm-settings-connection.lo \
+	nm-settings-plugin.lo nm-settings.lo nm-keyfile-connection.lo \
+	plugin.lo reader.lo utils.lo writer.lo nm-supplicant-config.lo \
+	nm-supplicant-interface.lo nm-supplicant-manager.lo \
+	nm-supplicant-settings-verify.lo nm-vpn-connection.lo \
+	nm-vpn-manager.lo nm-activation-request.lo \
+	nm-active-connection.lo nm-audit-manager.lo nm-bus-manager.lo \
+	nm-config.lo nm-config-data.lo nm-connection-provider.lo \
+	nm-connectivity.lo nm-dcb.lo nm-route-manager.lo \
+	nm-default-route-manager.lo nm-dhcp4-config.lo \
+	nm-dhcp6-config.lo nm-dispatcher.lo nm-enum-types.lo \
+	nm-exported-object.lo nm-firewall-manager.lo nm-ip4-config.lo \
+	nm-ip6-config.lo nm-logging.lo nm-auth-manager.lo \
+	nm-auth-subject.lo nm-auth-utils.lo nm-manager.lo \
+	nm-multi-index.lo nm-policy.lo nm-rfkill-manager.lo \
+	nm-session-monitor.lo nm-core-utils.lo NetworkManagerUtils.lo \
+	$(am__objects_2) $(am__objects_3) $(am__objects_4)
 libNetworkManager_la_OBJECTS = $(am_libNetworkManager_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
 libnm_iface_helper_la_DEPENDENCIES =  \
 	$(top_builddir)/libnm-core/libnm-core.la \
 	$(top_builddir)/introspection/libnmdbus.la libsystemd-nm.la \
@@ -304,7 +324,8 @@ am__libnm_iface_helper_la_SOURCES_DIST =  \
 	nm-exported-object.h nm-ip4-config.c nm-ip4-config.h \
 	nm-ip6-config.c nm-ip6-config.h nm-enum-types.c \
 	nm-enum-types.h nm-logging.c nm-logging.h nm-multi-index.c \
-	nm-multi-index.h NetworkManagerUtils.c NetworkManagerUtils.h \
+	nm-multi-index.h nm-core-utils.c nm-core-utils.h \
+	NetworkManagerUtils.c NetworkManagerUtils.h \
 	platform/wifi/wifi-utils-wext.c \
 	platform/wifi/wifi-utils-wext.h
 am_libnm_iface_helper_la_OBJECTS = nm-dhcp-client.lo nm-dhcp-utils.lo \
@@ -313,14 +334,15 @@ am_libnm_iface_helper_la_OBJECTS = nm-dhcp-client.lo nm-dhcp-utils.lo \
 	wifi-utils.lo nm-fake-rdisc.lo nm-lndp-rdisc.lo nm-rdisc.lo \
 	nm-route-manager.lo nm-exported-object.lo nm-ip4-config.lo \
 	nm-ip6-config.lo nm-enum-types.lo nm-logging.lo \
-	nm-multi-index.lo NetworkManagerUtils.lo $(am__objects_4)
+	nm-multi-index.lo nm-core-utils.lo NetworkManagerUtils.lo \
+	$(am__objects_4)
 libnm_iface_helper_la_OBJECTS = $(am_libnm_iface_helper_la_OBJECTS)
 libsystemd_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
 am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd-adapt.lo \
 	libsystemd_nm_la-alloc-util.lo libsystemd_nm_la-escape.lo \
 	libsystemd_nm_la-fd-util.lo libsystemd_nm_la-fileio.lo \
-	libsystemd_nm_la-fs-util.lo libsystemd_nm_la-hashmap.lo \
-	libsystemd_nm_la-hexdecoct.lo \
+	libsystemd_nm_la-fs-util.lo libsystemd_nm_la-hash-funcs.lo \
+	libsystemd_nm_la-hashmap.lo libsystemd_nm_la-hexdecoct.lo \
 	libsystemd_nm_la-hostname-util.lo \
 	libsystemd_nm_la-in-addr-util.lo libsystemd_nm_la-io-util.lo \
 	libsystemd_nm_la-mempool.lo libsystemd_nm_la-parse-util.lo \
@@ -336,9 +358,9 @@ am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd-adapt.lo \
 	libsystemd_nm_la-dhcp-packet.lo \
 	libsystemd_nm_la-dhcp6-network.lo \
 	libsystemd_nm_la-dhcp6-option.lo \
-	libsystemd_nm_la-lldp-network.lo libsystemd_nm_la-lldp-tlv.lo \
-	libsystemd_nm_la-lldp-port.lo \
 	libsystemd_nm_la-lldp-internal.lo \
+	libsystemd_nm_la-lldp-network.lo libsystemd_nm_la-lldp-port.lo \
+	libsystemd_nm_la-lldp-tlv.lo \
 	libsystemd_nm_la-network-internal.lo \
 	libsystemd_nm_la-sd-dhcp-client.lo \
 	libsystemd_nm_la-sd-dhcp-lease.lo \
@@ -415,10 +437,12 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(libNetworkManager_la_SOURCES) \
+SOURCES = $(libNetworkManager_base_la_SOURCES) \
+	$(libNetworkManager_la_SOURCES) \
 	$(libnm_iface_helper_la_SOURCES) $(libsystemd_nm_la_SOURCES) \
 	$(NetworkManager_SOURCES) $(nm_iface_helper_SOURCES)
-DIST_SOURCES = $(am__libNetworkManager_la_SOURCES_DIST) \
+DIST_SOURCES = $(am__libNetworkManager_base_la_SOURCES_DIST) \
+	$(am__libNetworkManager_la_SOURCES_DIST) \
 	$(am__libnm_iface_helper_la_SOURCES_DIST) \
 	$(libsystemd_nm_la_SOURCES) $(NetworkManager_SOURCES) \
 	$(nm_iface_helper_SOURCES)
@@ -815,11 +839,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/shared -I$(top_builddir)/shared \
 	-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
 	-DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \
 	-DPPPD_PLUGIN_DIR=\"$(PPPD_PLUGIN_DIR)\" $(NULL)
-noinst_LTLIBRARIES = \
-	libNetworkManager.la \
-	libnm-iface-helper.la \
-	libsystemd-nm.la
-
+noinst_LTLIBRARIES = libNetworkManager.la libnm-iface-helper.la \
+	libsystemd-nm.la $(am__append_5)
 
 ######################
 # libsystemd-nm
@@ -844,6 +865,8 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/basic/fileio.h \
 	systemd/src/basic/fs-util.c \
 	systemd/src/basic/fs-util.h \
+	systemd/src/basic/hash-funcs.c \
+	systemd/src/basic/hash-funcs.h \
 	systemd/src/basic/hashmap.c \
 	systemd/src/basic/hashmap.h \
 	systemd/src/basic/hexdecoct.c \
@@ -868,11 +891,12 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/basic/random-util.c \
 	systemd/src/basic/random-util.h \
 	systemd/src/basic/refcnt.h \
+	systemd/src/basic/set.h \
 	systemd/src/basic/siphash24.c \
 	systemd/src/basic/siphash24.h \
-	systemd/src/basic/set.h \
 	systemd/src/basic/socket-util.h \
 	systemd/src/basic/sparse-endian.h \
+	systemd/src/basic/stdio-util.h \
 	systemd/src/basic/string-table.c \
 	systemd/src/basic/string-table.h \
 	systemd/src/basic/string-util.c \
@@ -902,15 +926,15 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/libsystemd-network/dhcp6-network.c \
 	systemd/src/libsystemd-network/dhcp6-option.c \
 	systemd/src/libsystemd-network/dhcp6-protocol.h \
-	systemd/src/libsystemd-network/lldp.h \
-	systemd/src/libsystemd-network/lldp-network.h \
+	systemd/src/libsystemd-network/lldp-internal.c \
+	systemd/src/libsystemd-network/lldp-internal.h \
 	systemd/src/libsystemd-network/lldp-network.c \
-	systemd/src/libsystemd-network/lldp-tlv.c \
-	systemd/src/libsystemd-network/lldp-tlv.h \
+	systemd/src/libsystemd-network/lldp-network.h \
 	systemd/src/libsystemd-network/lldp-port.c \
 	systemd/src/libsystemd-network/lldp-port.h \
-	systemd/src/libsystemd-network/lldp-internal.h \
-	systemd/src/libsystemd-network/lldp-internal.c \
+	systemd/src/libsystemd-network/lldp-tlv.c \
+	systemd/src/libsystemd-network/lldp-tlv.h \
+	systemd/src/libsystemd-network/lldp.h \
 	systemd/src/libsystemd-network/network-internal.c \
 	systemd/src/libsystemd-network/network-internal.h \
 	systemd/src/libsystemd-network/sd-dhcp-client.c \
@@ -928,11 +952,11 @@ libsystemd_nm_la_SOURCES = \
 	systemd/src/systemd/sd-dhcp-lease.h \
 	systemd/src/systemd/sd-dhcp6-client.h \
 	systemd/src/systemd/sd-dhcp6-lease.h \
-	systemd/src/systemd/sd-lldp.h \
 	systemd/src/systemd/sd-event.h \
 	systemd/src/systemd/sd-id128.h \
 	systemd/src/systemd/sd-ipv4acd.h \
 	systemd/src/systemd/sd-ipv4ll.h \
+	systemd/src/systemd/sd-lldp.h \
 	systemd/src/systemd/sd-ndisc.h
 
 libsystemd_nm_la_CPPFLAGS = \
@@ -948,6 +972,28 @@ libsystemd_nm_la_CPPFLAGS = \
 libsystemd_nm_la_LIBADD = \
 	$(GLIB_LIBS)
 
+@ENABLE_TESTS_TRUE@libNetworkManager_base_la_SOURCES = \
+@ENABLE_TESTS_TRUE@	nm-core-utils.c \
+@ENABLE_TESTS_TRUE@	nm-core-utils.h \
+@ENABLE_TESTS_TRUE@	nm-logging.c \
+@ENABLE_TESTS_TRUE@	nm-logging.h
+
+@ENABLE_TESTS_TRUE@libNetworkManager_base_la_CPPFLAGS = \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/shared \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/shared \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/platform \
+@ENABLE_TESTS_TRUE@	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
+@ENABLE_TESTS_TRUE@	-DNO_SYSTEMD_JOURNAL \
+@ENABLE_TESTS_TRUE@	-DPREFIX=\"$(prefix)\" \
+@ENABLE_TESTS_TRUE@	-DNMSTATEDIR=\"$(nmstatedir)\" \
+@ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS)
+
+@ENABLE_TESTS_TRUE@libNetworkManager_base_la_LIBADD = \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@	$(GLIB_LIBS)
+
 NetworkManager_SOURCES = \
 	$(nm_device_sources) $(nm_device_headers) \
 	$(nm_dhcp_client_sources) $(nm_dhcp_client_headers) \
@@ -996,7 +1042,8 @@ nm_dhcp_client_headers = \
 libNetworkManager_la_SOURCES = $(nm_device_headers) \
 	$(nm_dhcp_client_headers) devices/nm-device.c \
 	devices/nm-device.h devices/nm-lldp-listener.c \
-	devices/nm-lldp-listener.h devices/nm-device-ethernet-utils.c \
+	devices/nm-lldp-listener.h devices/nm-arping-manager.c \
+	devices/nm-arping-manager.h devices/nm-device-ethernet-utils.c \
 	devices/nm-device-ethernet-utils.h devices/nm-device-factory.c \
 	devices/nm-device-factory.h devices/nm-device-generic.c \
 	devices/nm-device-generic.h devices/nm-device-logging.h \
@@ -1073,8 +1120,9 @@ libNetworkManager_la_SOURCES = $(nm_device_headers) \
 	nm-manager.h nm-multi-index.c nm-multi-index.h nm-policy.c \
 	nm-policy.h nm-rfkill-manager.c nm-rfkill-manager.h \
 	nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.h \
-	nm-types.h NetworkManagerUtils.c NetworkManagerUtils.h \
-	$(am__append_5) $(am__append_6) $(am__append_7)
+	nm-types.h nm-core-utils.c nm-core-utils.h \
+	NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_6) \
+	$(am__append_7) $(am__append_8)
 GLIB_GENERATED = nm-enum-types.h nm-enum-types.c
 GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM --fhead '\#include <nm-core-enum-types.h>\n'
 GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
@@ -1090,7 +1138,7 @@ libNetworkManager_la_LIBADD =  \
 	$(top_builddir)/introspection/libnmdbus.la libsystemd-nm.la \
 	$(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(SYSTEMD_LOGIN_LIBS) \
 	$(SYSTEMD_JOURNAL_LIBS) $(LIBNDP_LIBS) $(LIBDL) $(LIBM) \
-	$(SELINUX_LIBS) $(LIBAUDIT_LIBS) $(am__append_8)
+	$(SELINUX_LIBS) $(LIBAUDIT_LIBS) $(am__append_9)
 NetworkManager_LDFLAGS = -rdynamic
 
 ######################
@@ -1111,8 +1159,8 @@ libnm_iface_helper_la_SOURCES = dhcp-manager/nm-dhcp-client.c \
 	nm-exported-object.h nm-ip4-config.c nm-ip4-config.h \
 	nm-ip6-config.c nm-ip6-config.h nm-enum-types.c \
 	nm-enum-types.h nm-logging.c nm-logging.h nm-multi-index.c \
-	nm-multi-index.h NetworkManagerUtils.c NetworkManagerUtils.h \
-	$(am__append_9)
+	nm-multi-index.h nm-core-utils.c nm-core-utils.h \
+	NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_10)
 libnm_iface_helper_la_LIBADD = \
 	$(top_builddir)/libnm-core/libnm-core.la \
 	$(top_builddir)/introspection/libnmdbus.la \
@@ -1202,6 +1250,9 @@ clean-noinstLTLIBRARIES:
 	  rm -f $${locs}; \
 	}
 
+libNetworkManager-base.la: $(libNetworkManager_base_la_OBJECTS) $(libNetworkManager_base_la_DEPENDENCIES) $(EXTRA_libNetworkManager_base_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK) $(am_libNetworkManager_base_la_rpath) $(libNetworkManager_base_la_OBJECTS) $(libNetworkManager_base_la_LIBADD) $(LIBS)
+
 libNetworkManager.la: $(libNetworkManager_la_OBJECTS) $(libNetworkManager_la_DEPENDENCIES) $(EXTRA_libNetworkManager_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(LINK)  $(libNetworkManager_la_OBJECTS) $(libNetworkManager_la_LIBADD) $(LIBS)
 
@@ -1324,6 +1375,8 @@ distclean-compile:
 	-rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManagerUtils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libNetworkManager_base_la-nm-core-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libNetworkManager_base_la-nm-logging.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-alloc-util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-arp-util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-dhcp-identifier.Plo@am__quote@
@@ -1337,6 +1390,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fd-util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fileio.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fs-util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-hash-funcs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-hashmap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-hexdecoct.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-hostname-util.Plo@am__quote@
@@ -1373,6 +1427,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-activation-request.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-active-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-agent-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-arping-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-audit-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-auth-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-auth-subject.Plo@am__quote@
@@ -1382,6 +1437,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connection-provider.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connectivity.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-core-utils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dcb.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-default-route-manager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bond.Po@am__quote@
@@ -1482,6 +1538,20 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+libNetworkManager_base_la-nm-core-utils.lo: nm-core-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libNetworkManager_base_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libNetworkManager_base_la-nm-core-utils.lo -MD -MP -MF $(DEPDIR)/libNetworkManager_base_la-nm-core-utils.Tpo -c -o libNetworkManager_base_la-nm-core-utils.lo `test -f 'nm-core-utils.c' || echo '$(srcdir)/'`nm-core-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libNetworkManager_base_la-nm-core-utils.Tpo $(DEPDIR)/libNetworkManager_base_la-nm-core-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-core-utils.c' object='libNetworkManager_base_la-nm-core-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libNetworkManager_base_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libNetworkManager_base_la-nm-core-utils.lo `test -f 'nm-core-utils.c' || echo '$(srcdir)/'`nm-core-utils.c
+
+libNetworkManager_base_la-nm-logging.lo: nm-logging.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libNetworkManager_base_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libNetworkManager_base_la-nm-logging.lo -MD -MP -MF $(DEPDIR)/libNetworkManager_base_la-nm-logging.Tpo -c -o libNetworkManager_base_la-nm-logging.lo `test -f 'nm-logging.c' || echo '$(srcdir)/'`nm-logging.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libNetworkManager_base_la-nm-logging.Tpo $(DEPDIR)/libNetworkManager_base_la-nm-logging.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-logging.c' object='libNetworkManager_base_la-nm-logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libNetworkManager_base_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libNetworkManager_base_la-nm-logging.lo `test -f 'nm-logging.c' || echo '$(srcdir)/'`nm-logging.c
+
 nm-device.lo: devices/nm-device.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device.lo -MD -MP -MF $(DEPDIR)/nm-device.Tpo -c -o nm-device.lo `test -f 'devices/nm-device.c' || echo '$(srcdir)/'`devices/nm-device.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-device.Tpo $(DEPDIR)/nm-device.Plo
@@ -1496,6 +1566,13 @@ nm-lldp-listener.lo: devices/nm-lldp-listener.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-lldp-listener.lo `test -f 'devices/nm-lldp-listener.c' || echo '$(srcdir)/'`devices/nm-lldp-listener.c
 
+nm-arping-manager.lo: devices/nm-arping-manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-arping-manager.lo -MD -MP -MF $(DEPDIR)/nm-arping-manager.Tpo -c -o nm-arping-manager.lo `test -f 'devices/nm-arping-manager.c' || echo '$(srcdir)/'`devices/nm-arping-manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-arping-manager.Tpo $(DEPDIR)/nm-arping-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='devices/nm-arping-manager.c' object='nm-arping-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-arping-manager.lo `test -f 'devices/nm-arping-manager.c' || echo '$(srcdir)/'`devices/nm-arping-manager.c
+
 nm-device-ethernet-utils.lo: devices/nm-device-ethernet-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-ethernet-utils.lo -MD -MP -MF $(DEPDIR)/nm-device-ethernet-utils.Tpo -c -o nm-device-ethernet-utils.lo `test -f 'devices/nm-device-ethernet-utils.c' || echo '$(srcdir)/'`devices/nm-device-ethernet-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-ethernet-utils.Tpo $(DEPDIR)/nm-device-ethernet-utils.Plo
@@ -1839,6 +1916,13 @@ libsystemd_nm_la-fs-util.lo: systemd/src/basic/fs-util.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-fs-util.lo `test -f 'systemd/src/basic/fs-util.c' || echo '$(srcdir)/'`systemd/src/basic/fs-util.c
 
+libsystemd_nm_la-hash-funcs.lo: systemd/src/basic/hash-funcs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-hash-funcs.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-hash-funcs.Tpo -c -o libsystemd_nm_la-hash-funcs.lo `test -f 'systemd/src/basic/hash-funcs.c' || echo '$(srcdir)/'`systemd/src/basic/hash-funcs.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-hash-funcs.Tpo $(DEPDIR)/libsystemd_nm_la-hash-funcs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='systemd/src/basic/hash-funcs.c' object='libsystemd_nm_la-hash-funcs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-hash-funcs.lo `test -f 'systemd/src/basic/hash-funcs.c' || echo '$(srcdir)/'`systemd/src/basic/hash-funcs.c
+
 libsystemd_nm_la-hashmap.lo: systemd/src/basic/hashmap.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-hashmap.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-hashmap.Tpo -c -o libsystemd_nm_la-hashmap.lo `test -f 'systemd/src/basic/hashmap.c' || echo '$(srcdir)/'`systemd/src/basic/hashmap.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-hashmap.Tpo $(DEPDIR)/libsystemd_nm_la-hashmap.Plo
@@ -2007,6 +2091,13 @@ libsystemd_nm_la-dhcp6-option.lo: systemd/src/libsystemd-network/dhcp6-option.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-dhcp6-option.lo `test -f 'systemd/src/libsystemd-network/dhcp6-option.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/dhcp6-option.c
 
+libsystemd_nm_la-lldp-internal.lo: systemd/src/libsystemd-network/lldp-internal.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-internal.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-internal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='systemd/src/libsystemd-network/lldp-internal.c' object='libsystemd_nm_la-lldp-internal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c
+
 libsystemd_nm_la-lldp-network.lo: systemd/src/libsystemd-network/lldp-network.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-network.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-network.Tpo -c -o libsystemd_nm_la-lldp-network.lo `test -f 'systemd/src/libsystemd-network/lldp-network.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-network.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-network.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-network.Plo
@@ -2014,13 +2105,6 @@ libsystemd_nm_la-lldp-network.lo: systemd/src/libsystemd-network/lldp-network.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-network.lo `test -f 'systemd/src/libsystemd-network/lldp-network.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-network.c
 
-libsystemd_nm_la-lldp-tlv.lo: systemd/src/libsystemd-network/lldp-tlv.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-tlv.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='systemd/src/libsystemd-network/lldp-tlv.c' object='libsystemd_nm_la-lldp-tlv.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c
-
 libsystemd_nm_la-lldp-port.lo: systemd/src/libsystemd-network/lldp-port.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-port.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-port.Tpo -c -o libsystemd_nm_la-lldp-port.lo `test -f 'systemd/src/libsystemd-network/lldp-port.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-port.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-port.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-port.Plo
@@ -2028,12 +2112,12 @@ libsystemd_nm_la-lldp-port.lo: systemd/src/libsystemd-network/lldp-port.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-port.lo `test -f 'systemd/src/libsystemd-network/lldp-port.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-port.c
 
-libsystemd_nm_la-lldp-internal.lo: systemd/src/libsystemd-network/lldp-internal.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-internal.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-internal.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='systemd/src/libsystemd-network/lldp-internal.c' object='libsystemd_nm_la-lldp-internal.lo' libtool=yes @AMDEPBACKSLASH@
+libsystemd_nm_la-lldp-tlv.lo: systemd/src/libsystemd-network/lldp-tlv.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-tlv.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='systemd/src/libsystemd-network/lldp-tlv.c' object='libsystemd_nm_la-lldp-tlv.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c
 
 libsystemd_nm_la-network-internal.lo: systemd/src/libsystemd-network/network-internal.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-network-internal.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-network-internal.Tpo -c -o libsystemd_nm_la-network-internal.lo `test -f 'systemd/src/libsystemd-network/network-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/network-internal.c
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index fb680d96..50fe4efd 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -15,1909 +15,25 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2004 - 2014 Red Hat, Inc.
+ * Copyright 2004 - 2016 Red Hat, Inc.
  * Copyright 2005 - 2008 Novell, Inc.
  */
 
-#include "config.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <resolv.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <linux/if.h>
-#include <linux/if_infiniband.h>
-
 #include "nm-default.h"
+
 #include "NetworkManagerUtils.h"
-#include "nm-platform.h"
+
 #include "nm-utils.h"
-#include "nm-core-internal.h"
-#include "nm-device.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-ip6-config.h"
-#include "nm-setting-wireless.h"
-#include "nm-setting-wireless-security.h"
-#include "nm-auth-utils.h"
-
-/*
- * Some toolchains (E.G. uClibc 0.9.33 and earlier) don't export
- * CLOCK_BOOTTIME even though the kernel supports it, so provide a
- * local definition
- */
-#ifndef CLOCK_BOOTTIME
-#define CLOCK_BOOTTIME 7
-#endif
-
-G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int));
-int _nm_utils_testing = 0;
-
-gboolean
-nm_utils_get_testing_initialized ()
-{
-	NMUtilsTestFlags flags;
-
-	flags = (NMUtilsTestFlags) _nm_utils_testing;
-	if (flags == NM_UTILS_TEST_NONE)
-		flags = (NMUtilsTestFlags) g_atomic_int_get (&_nm_utils_testing);
-	return flags != NM_UTILS_TEST_NONE;
-}
-
-NMUtilsTestFlags
-nm_utils_get_testing ()
-{
-	NMUtilsTestFlags flags;
-
-	flags = (NMUtilsTestFlags) _nm_utils_testing;
-	if (flags != NM_UTILS_TEST_NONE) {
-		/* Flags already initialized. Return them. */
-		return flags & NM_UTILS_TEST_ALL;
-	}
-
-	/* Accessing nm_utils_get_testing() causes us to set the flags to initialized.
-	 * Detecting running tests also based on g_test_initialized(). */
-	flags = _NM_UTILS_TEST_INITIALIZED;
-	if (g_test_initialized ())
-		flags |= _NM_UTILS_TEST_GENERAL;
-
-	if (g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
-		/* Done. We set it. */
-		return flags & NM_UTILS_TEST_ALL;
-	}
-	/* It changed in the meantime (??). Re-read the value. */
-	return ((NMUtilsTestFlags) _nm_utils_testing) & NM_UTILS_TEST_ALL;
-}
-
-void
-_nm_utils_set_testing (NMUtilsTestFlags flags)
-{
-	g_assert (!NM_FLAGS_ANY (flags, ~NM_UTILS_TEST_ALL));
-
-	/* mask out everything except ALL, and always set GENERAL. */
-	flags = (flags & NM_UTILS_TEST_ALL) | (_NM_UTILS_TEST_GENERAL | _NM_UTILS_TEST_INITIALIZED);
-
-	if (!g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
-		/* We only allow setting _nm_utils_set_testing() once, before fetching the
-		 * value with nm_utils_get_testing(). */
-		g_return_if_reached ();
-	}
-}
-
-/*****************************************************************************/
-
-G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error)
-
-void
-nm_utils_error_set_cancelled (GError **error,
-                              gboolean is_disposing,
-                              const char *instance_name)
-{
-	if (is_disposing) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING,
-		             "Disposing %s instance",
-		             instance_name && *instance_name ? instance_name : "source");
-	} else {
-		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
-		                     "Request cancelled");
-	}
-}
-
-gboolean
-nm_utils_error_is_cancelled (GError *error,
-                             gboolean consider_is_disposing)
-{
-	if (error) {
-		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-			return TRUE;
-		if (   consider_is_disposing
-		    && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-/*****************************************************************************/
-
-static GSList *_singletons = NULL;
-static gboolean _singletons_shutdown = FALSE;
-
-static void
-_nm_singleton_instance_weak_cb (gpointer data,
-                                GObject *where_the_object_was)
-{
-	_singletons = g_slist_remove (_singletons, where_the_object_was);
-}
-
-static void __attribute__((destructor))
-_nm_singleton_instance_destroy (void)
-{
-	_singletons_shutdown = TRUE;
-
-	while (_singletons) {
-		GObject *instance = _singletons->data;
-
-		_singletons = g_slist_delete_link (_singletons, _singletons);
-
-		g_object_weak_unref (instance, _nm_singleton_instance_weak_cb, NULL);
-
-		if (instance->ref_count > 1)
-			nm_log_dbg (LOGD_CORE, "disown %s singleton (%p)", G_OBJECT_TYPE_NAME (instance), instance);
-
-		g_object_unref (instance);
-	}
-}
-
-void
-_nm_singleton_instance_register_destruction (GObject *instance)
-{
-	g_return_if_fail (G_IS_OBJECT (instance));
-
-	/* Don't allow registration after shutdown. We only destroy the singletons
-	 * once. */
-	g_return_if_fail (!_singletons_shutdown);
-
-	g_object_weak_ref (instance, _nm_singleton_instance_weak_cb, NULL);
-
-	_singletons = g_slist_prepend (_singletons, instance);
-}
-
-/*****************************************************************************/
-
-gint
-nm_utils_ascii_str_to_bool (const char *str,
-                            gint default_value)
-{
-	gsize len;
-	char *s = NULL;
-
-	if (!str)
-		return default_value;
-
-	while (str[0] && g_ascii_isspace (str[0]))
-		str++;
-
-	if (!str[0])
-		return default_value;
-
-	len = strlen (str);
-	if (g_ascii_isspace (str[len - 1])) {
-		s = g_strdup (str);
-		g_strchomp (s);
-		str = s;
-	}
-
-	if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
-		default_value = TRUE;
-	else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
-		default_value = FALSE;
-	if (s)
-		g_free (s);
-	return default_value;
-}
-
-/*****************************************************************************/
-
-/*
- * nm_ethernet_address_is_valid:
- * @addr: pointer to a binary or ASCII Ethernet address
- * @len: length of @addr, or -1 if @addr is ASCII
- *
- * Compares an Ethernet address against known invalid addresses.
-
- * Returns: %TRUE if @addr is a valid Ethernet address, %FALSE if it is not.
- */
-gboolean
-nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
-{
-	guint8 invalid_addr[4][ETH_ALEN] = {
-	    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-	    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	    {0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
-	    {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}, /* prism54 dummy MAC */
-	};
-	guint8 addr_bin[ETH_ALEN];
-	guint i;
-
-	if (!addr) {
-		g_return_val_if_fail (len == -1 || len == ETH_ALEN, FALSE);
-		return FALSE;
-	}
-
-	if (len == -1) {
-		if (!nm_utils_hwaddr_aton (addr, addr_bin, ETH_ALEN))
-			return FALSE;
-		addr = addr_bin;
-	} else if (len != ETH_ALEN)
-		g_return_val_if_reached (FALSE);
-
-	/* Check for multicast address */
-	if ((((guint8 *) addr)[0]) & 0x01)
-		return FALSE;
-
-	for (i = 0; i < G_N_ELEMENTS (invalid_addr); i++) {
-		if (nm_utils_hwaddr_matches (addr, ETH_ALEN, invalid_addr[i], ETH_ALEN))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-/* nm_utils_ip4_address_clear_host_address:
- * @addr: source ip6 address
- * @plen: prefix length of network
- *
- * returns: the input address, with the host address set to 0.
- */
-in_addr_t
-nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen)
-{
-	return addr & nm_utils_ip4_prefix_to_netmask (plen);
-}
-
-/* nm_utils_ip6_address_clear_host_address:
- * @dst: destination output buffer, will contain the network part of the @src address
- * @src: source ip6 address
- * @plen: prefix length of network
- *
- * Note: this function is self assignment safe, to update @src inplace, set both
- * @dst and @src to the same destination.
- */
-const struct in6_addr *
-nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen)
-{
-	g_return_val_if_fail (plen <= 128, NULL);
-	g_return_val_if_fail (src, NULL);
-	g_return_val_if_fail (dst, NULL);
-
-	if (plen < 128) {
-		guint nbytes = plen / 8;
-		guint nbits = plen % 8;
-
-		if (nbytes && dst != src)
-			memcpy (dst, src, nbytes);
-		if (nbits) {
-			dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
-			nbytes++;
-		}
-		if (nbytes <= 15)
-			memset (&dst->s6_addr[nbytes], 0, 16 - nbytes);
-	} else if (src != dst)
-		*dst = *src;
-
-	return dst;
-}
-
-void
-nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
-{
-	gsize elt_size;
-	guint index_to_delete;
-	guint i_src;
-	guint mm_src, mm_dst, mm_len;
-	gsize i_itd;
-	guint res_length;
-
-	g_return_if_fail (array);
-	if (!len)
-		return;
-	g_return_if_fail (indexes_to_delete);
-
-	elt_size = g_array_get_element_size (array);
-
-	i_itd = 0;
-	index_to_delete = indexes_to_delete[0];
-	if (index_to_delete >= array->len)
-		g_return_if_reached ();
-
-	res_length = array->len - 1;
-
-	mm_dst = index_to_delete;
-	mm_src = index_to_delete;
-	mm_len = 0;
-
-	for (i_src = index_to_delete; i_src < array->len; i_src++) {
-		if (i_src < index_to_delete)
-			mm_len++;
-		else {
-			/* we require indexes_to_delete to contain non-repeated, ascending
-			 * indexes. Otherwise we would need to presort the indexes. */
-			while (TRUE) {
-				guint dd;
-
-				if (i_itd + 1 >= len) {
-					index_to_delete = G_MAXUINT;
-					break;
-				}
-
-				dd = indexes_to_delete[++i_itd];
-				if (dd > index_to_delete) {
-					if (dd >= array->len)
-						g_warn_if_reached ();
-					else {
-						g_assert (res_length > 0);
-						res_length--;
-					}
-					index_to_delete = dd;
-					break;
-				}
-				g_warn_if_reached ();
-			}
-
-			if (mm_len) {
-				memmove (&array->data[mm_dst * elt_size],
-				         &array->data[mm_src * elt_size],
-				         mm_len * elt_size);
-				mm_dst += mm_len;
-				mm_src += mm_len + 1;
-				mm_len = 0;
-			} else
-				mm_src++;
-		}
-	}
-	if (mm_len) {
-		memmove (&array->data[mm_dst * elt_size],
-		         &array->data[mm_src * elt_size],
-		         mm_len * elt_size);
-	}
-	g_array_set_size (array, res_length);
-}
-
-int
-nm_spawn_process (const char *args, GError **error)
-{
-	GError *local = NULL;
-	gint num_args;
-	char **argv = NULL;
-	int status = -1;
-
-	g_return_val_if_fail (args != NULL, -1);
-	g_return_val_if_fail (!error || !*error, -1);
-
-	if (g_shell_parse_argv (args, &num_args, &argv, &local)) {
-		g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local);
-		g_strfreev (argv);
-	}
-
-	if (local) {
-		nm_log_warn (LOGD_CORE, "could not spawn process '%s': %s", args, local->message);
-		g_propagate_error (error, local);
-	}
-
-	return status;
-}
-
-static const char *
-_trunk_first_line (char *str)
-{
-	char *s;
-
-	s = strchr (str, '\n');
-	if (s)
-		s[0] = '\0';
-	return str;
-}
-
-int
-nm_utils_modprobe (GError **error, gboolean suppress_error_logging, const char *arg1, ...)
-{
-	gs_unref_ptrarray GPtrArray *argv = NULL;
-	int exit_status;
-	gs_free char *_log_str = NULL;
-#define ARGV_TO_STR(argv)   (_log_str ? _log_str : (_log_str = g_strjoinv (" ", (char **) argv->pdata)))
-	GError *local = NULL;
-	va_list ap;
-	NMLogLevel llevel = suppress_error_logging ? LOGL_DEBUG : LOGL_ERR;
-	gs_free char *std_out = NULL, *std_err = NULL;
-
-	g_return_val_if_fail (!error || !*error, -1);
-	g_return_val_if_fail (arg1, -1);
-
-	/* construct the argument list */
-	argv = g_ptr_array_sized_new (4);
-	g_ptr_array_add (argv, "/sbin/modprobe");
-	g_ptr_array_add (argv, (char *) arg1);
-
-	va_start (ap, arg1);
-	while ((arg1 = va_arg (ap, const char *)))
-		g_ptr_array_add (argv, (char *) arg1);
-	va_end (ap);
-
-	g_ptr_array_add (argv, NULL);
-
-	nm_log_dbg (LOGD_CORE, "modprobe: '%s'", ARGV_TO_STR (argv));
-	if (!g_spawn_sync (NULL, (char **) argv->pdata, NULL, 0, NULL, NULL, &std_out, &std_err, &exit_status, &local)) {
-		nm_log (llevel, LOGD_CORE, "modprobe: '%s' failed: %s", ARGV_TO_STR (argv), local->message);
-		g_propagate_error (error, local);
-		return -1;
-	} else if (exit_status != 0)
-		nm_log (llevel, LOGD_CORE, "modprobe: '%s' exited with error %d%s%s%s%s%s%s", ARGV_TO_STR (argv), exit_status,
-		        std_out&&*std_out ? " (" : "", std_out&&*std_out ? _trunk_first_line (std_out) : "", std_out&&*std_out ? ")" : "",
-		        std_err&&*std_err ? " (" : "", std_err&&*std_err ? _trunk_first_line (std_err) : "", std_err&&*std_err ? ")" : "");
-
-	return exit_status;
-}
-
-/**
- * nm_utils_get_start_time_for_pid:
- * @pid: the process identifier
- * @out_state: return the state character, like R, S, Z. See `man 5 proc`.
- * @out_ppid: parent process id
- *
- * Originally copied from polkit source (src/polkit/polkitunixprocess.c)
- * and adjusted.
- *
- * Returns: the timestamp when the process started (by parsing /proc/$PID/stat).
- * If an error occurs (e.g. the process does not exist), 0 is returned.
- *
- * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds)
- **/
-guint64
-nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid)
-{
-	guint64 start_time;
-	gs_free gchar *filename = NULL;
-	gs_free gchar *contents = NULL;
-	size_t length;
-	gs_strfreev gchar **tokens = NULL;
-	guint num_tokens;
-	gchar *p;
-	gchar *endp;
-	char state = '\0';
-	gint64 ppid = 0;
-
-	start_time = 0;
-	contents = NULL;
-
-	g_return_val_if_fail (pid > 0, 0);
-
-	filename = g_strdup_printf ("/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid);
-
-	if (!g_file_get_contents (filename, &contents, &length, NULL))
-		goto out;
-
-	/* start time is the token at index 19 after the '(process name)' entry - since only this
-	 * field can contain the ')' character, search backwards for this to avoid malicious
-	 * processes trying to fool us
-	 */
-	p = strrchr (contents, ')');
-	if (p == NULL)
-		goto out;
-	p += 2; /* skip ') ' */
-	if (p - contents >= (int) length)
-		goto out;
-
-	state = p[0];
-
-	tokens = g_strsplit (p, " ", 0);
-
-	num_tokens = g_strv_length (tokens);
-
-	if (num_tokens < 20)
-		goto out;
-
-	if (out_ppid)
-		ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0);
-
-	errno = 0;
-	start_time = strtoull (tokens[19], &endp, 10);
-	if (*endp != '\0' || errno != 0)
-		start_time = 0;
-
-out:
-	if (out_state)
-		*out_state = state;
-	if (out_ppid)
-		*out_ppid = ppid;
-
-	return start_time;
-}
-
-/******************************************************************************************/
-
-typedef struct {
-	pid_t pid;
-	NMLogDomain log_domain;
-	union {
-		struct {
-			gint64 wait_start_us;
-			guint source_timeout_kill_id;
-		} async;
-		struct {
-			gboolean success;
-			int child_status;
-		} sync;
-	};
-	NMUtilsKillChildAsyncCb callback;
-	void *user_data;
-
-	char log_name[1]; /* variable-length object, must be last element!! */
-} KillChildAsyncData;
-
-#define LOG_NAME_FMT "kill child process '%s' (%ld)"
-#define LOG_NAME_PROCESS_FMT "kill process '%s' (%ld)"
-#define LOG_NAME_ARGS log_name,(long)pid
-
-static KillChildAsyncData *
-_kc_async_data_alloc (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data)
-{
-	KillChildAsyncData *data;
-	size_t log_name_len;
-
-	/* append the name at the end of our KillChildAsyncData. */
-	log_name_len = strlen (LOG_NAME_FMT) + 20 + strlen (log_name);
-	data = g_malloc (sizeof (KillChildAsyncData) - 1 + log_name_len);
-	g_snprintf (data->log_name, log_name_len, LOG_NAME_FMT, LOG_NAME_ARGS);
-
-	data->pid = pid;
-	data->user_data = user_data;
-	data->callback = callback;
-	data->log_domain = log_domain;
-
-	return data;
-}
-
-#define KC_EXIT_TO_STRING_BUF_SIZE 128
-static const char *
-_kc_exit_to_string (char *buf, int exit)
-#define _kc_exit_to_string(buf, exit) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_EXIT_TO_STRING_BUF_SIZE && sizeof ((buf)[0]) == 1), _kc_exit_to_string (buf, exit) )
-{
-	if (WIFEXITED (exit))
-		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "normally with status %d", WEXITSTATUS (exit));
-	else if (WIFSIGNALED (exit))
-		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "by signal %d", WTERMSIG (exit));
-	else
-		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "with unexpected status %d", exit);
-	return buf;
-}
-
-static const char *
-_kc_signal_to_string (int sig)
-{
-	switch (sig) {
-	case 0:  return "no signal (0)";
-	case SIGKILL:  return "SIGKILL (" G_STRINGIFY (SIGKILL) ")";
-	case SIGTERM:  return "SIGTERM (" G_STRINGIFY (SIGTERM) ")";
-	default:
-		return "Unexpected signal";
-	}
-}
-
-#define KC_WAITED_TO_STRING 100
-static const char *
-_kc_waited_to_string (char *buf, gint64 wait_start_us)
-#define _kc_waited_to_string(buf, wait_start_us) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_WAITED_TO_STRING && sizeof ((buf)[0]) == 1), _kc_waited_to_string (buf, wait_start_us) )
-{
-	g_snprintf (buf, KC_WAITED_TO_STRING, " (%ld usec elapsed)", (long) (nm_utils_get_monotonic_timestamp_us () - wait_start_us));
-	return buf;
-}
-
-static void
-_kc_cb_watch_child (GPid pid, gint status, gpointer user_data)
-{
-	KillChildAsyncData *data = user_data;
-	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE], buf_wait[KC_WAITED_TO_STRING];
-
-	if (data->async.source_timeout_kill_id)
-		g_source_remove (data->async.source_timeout_kill_id);
-
-	nm_log_dbg (data->log_domain, "%s: terminated %s%s",
-	            data->log_name, _kc_exit_to_string (buf_exit, status),
-	            _kc_waited_to_string (buf_wait, data->async.wait_start_us));
-
-	if (data->callback)
-		data->callback (pid, TRUE, status, data->user_data);
-
-	g_free (data);
-}
-
-static gboolean
-_kc_cb_timeout_grace_period (void *user_data)
-{
-	KillChildAsyncData *data = user_data;
-	int ret, errsv;
-
-	data->async.source_timeout_kill_id = 0;
-
-	if ((ret = kill (data->pid, SIGKILL)) != 0) {
-		errsv = errno;
-		/* ESRCH means, process does not exist or is already a zombie. */
-		if (errsv != ESRCH) {
-			nm_log_err (LOGD_CORE | data->log_domain, "%s: kill(SIGKILL) returned unexpected return value %d: (%s, %d)",
-			            data->log_name, ret, strerror (errsv), errsv);
-		}
-	} else {
-		nm_log_dbg (data->log_domain, "%s: process not terminated after %ld usec. Sending SIGKILL signal",
-		            data->log_name, (long) (nm_utils_get_monotonic_timestamp_us () - data->async.wait_start_us));
-	}
-
-	return G_SOURCE_REMOVE;
-}
-
-static gboolean
-_kc_invoke_callback_idle (gpointer user_data)
-{
-	KillChildAsyncData *data = user_data;
-
-	if (data->sync.success) {
-		char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
-
-		nm_log_dbg (data->log_domain, "%s: invoke callback: terminated %s",
-		            data->log_name, _kc_exit_to_string (buf_exit, data->sync.child_status));
-	} else
-		nm_log_dbg (data->log_domain, "%s: invoke callback: killing child failed", data->log_name);
-
-	data->callback (data->pid, data->sync.success, data->sync.child_status, data->user_data);
-	g_free (data);
-
-	return G_SOURCE_REMOVE;
-}
-
-static void
-_kc_invoke_callback (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data, gboolean success, int child_status)
-{
-	KillChildAsyncData *data;
-
-	if (!callback)
-		return;
-
-	data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
-	data->sync.success = success;
-	data->sync.child_status = child_status;
-
-	g_idle_add (_kc_invoke_callback_idle, data);
-}
-
-/* nm_utils_kill_child_async:
- * @pid: the process id of the process to kill
- * @sig: signal to send initially. Set to 0 to send not signal.
- * @log_domain: the logging domain used for logging (LOGD_NONE to suppress logging)
- * @log_name: for logging, the name of the processes to kill
- * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
- * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter is ignored.
- * @callback: (allow-none): callback after the child terminated. This function will always
- *   be invoked asynchronously.
- * @user_data: passed on to callback
- *
- * Uses g_child_watch_add(), so note the glib comment: if you obtain pid from g_spawn_async() or
- * g_spawn_async_with_pipes() you will need to pass %G_SPAWN_DO_NOT_REAP_CHILD as flag to the spawn
- * function for the child watching to work.
- * Also note, that you must g_source_remove() any other child watchers for @pid because glib
- * supports only one watcher per child.
- **/
-void
-nm_utils_kill_child_async (pid_t pid, int sig, NMLogDomain log_domain,
-                           const char *log_name, guint32 wait_before_kill_msec,
-                           NMUtilsKillChildAsyncCb callback, void *user_data)
-{
-	int status = 0, errsv;
-	pid_t ret;
-	KillChildAsyncData *data;
-	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
-
-	g_return_if_fail (pid > 0);
-	g_return_if_fail (log_name != NULL);
-
-	/* let's see if the child already terminated... */
-	ret = waitpid (pid, &status, WNOHANG);
-	if (ret > 0) {
-		nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
-		            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
-		_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
-		return;
-	} else if (ret != 0) {
-		errsv = errno;
-		/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
-		if (errsv != ECHILD) {
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
-			            LOG_NAME_ARGS, strerror (errsv), errsv);
-			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
-			return;
-		}
-	}
-
-	/* send the first signal. */
-	if (kill (pid, sig) != 0) {
-		errsv = errno;
-		/* ESRCH means, process does not exist or is already a zombie. */
-		if (errsv != ESRCH) {
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error sending %s: %s (%d)",
-			            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
-			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
-			return;
-		}
-
-		/* let's try again with waitpid, probably there was a race... */
-		ret = waitpid (pid, &status, 0);
-		if (ret > 0) {
-			nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
-			            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
-			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
-		} else {
-			errsv = errno;
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
-			            LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
-			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
-		}
-		return;
-	}
-
-	data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
-	data->async.wait_start_us = nm_utils_get_monotonic_timestamp_us ();
-
-	if (sig != SIGKILL && wait_before_kill_msec > 0) {
-		data->async.source_timeout_kill_id = g_timeout_add (wait_before_kill_msec, _kc_cb_timeout_grace_period, data);
-		nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s (send SIGKILL in %ld milliseconds)...",
-		            data->log_name,  _kc_signal_to_string (sig), (long) wait_before_kill_msec);
-	} else {
-		data->async.source_timeout_kill_id = 0;
-		nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s...",
-		            data->log_name, _kc_signal_to_string (sig));
-	}
-
-	g_child_watch_add (pid, _kc_cb_watch_child, data);
-}
-
-static inline gulong
-_sleep_duration_convert_ms_to_us (guint32 sleep_duration_msec)
-{
-	if (sleep_duration_msec > 0) {
-		guint64 x = (gint64) sleep_duration_msec * (guint64) 1000L;
-
-		return x < G_MAXULONG ? (gulong) x : G_MAXULONG;
-	}
-	return G_USEC_PER_SEC / 20;
-}
-
-/* nm_utils_kill_child_sync:
- * @pid: process id to kill
- * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
- * second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
- * @log_domain: log debug information for this domain. Errors and warnings are logged both
- * as %LOGD_CORE and @log_domain.
- * @log_name: name of the process to kill for logging.
- * @child_status: (out) (allow-none): return the exit status of the child, if no error occured.
- * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
- * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has not effect.
- * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
- * Set to zero, to use the default (meaning 20 wakeups per seconds).
- *
- * Kill a child process synchronously and wait. The function first checks if the child already terminated
- * and if it did, return the exit status. Otherwise send one @sig signal. @sig  will always be
- * sent unless the child already exited. If the child does not exit within @wait_before_kill_msec milliseconds,
- * the function will send %SIGKILL and waits for the child indefinitly. If @wait_before_kill_msec is zero, no
- * %SIGKILL signal will be sent.
- *
- * In case of error, errno is preserved to contain the last reason of failure.
- **/
-gboolean
-nm_utils_kill_child_sync (pid_t pid, int sig, NMLogDomain log_domain, const char *log_name,
-                          int *child_status, guint32 wait_before_kill_msec,
-                          guint32 sleep_duration_msec)
-{
-	int status = 0, errsv = 0;
-	pid_t ret;
-	gboolean success = FALSE;
-	gboolean was_waiting = FALSE, send_kill = FALSE;
-	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
-	char buf_wait[KC_WAITED_TO_STRING];
-	gint64 wait_start_us;
-
-	g_return_val_if_fail (pid > 0, FALSE);
-	g_return_val_if_fail (log_name != NULL, FALSE);
-
-	/* check if the child process already terminated... */
-	ret = waitpid (pid, &status, WNOHANG);
-	if (ret > 0) {
-		nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
-		            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
-		success = TRUE;
-		goto out;
-	} else if (ret != 0) {
-		errsv = errno;
-		/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
-		if (errsv != ECHILD) {
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
-			            LOG_NAME_ARGS, strerror (errsv), errsv);
-			goto out;
-		}
-	}
-
-	/* send first signal @sig */
-	if (kill (pid, sig) != 0) {
-		errsv = errno;
-		/* ESRCH means, process does not exist or is already a zombie. */
-		if (errsv != ESRCH) {
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send %s: %s (%d)",
-			            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
-		} else {
-			/* let's try again with waitpid, probably there was a race... */
-			ret = waitpid (pid, &status, 0);
-			if (ret > 0) {
-				nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
-				            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
-				success = TRUE;
-			} else {
-				errsv = errno;
-				nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
-				            LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
-			}
-		}
-		goto out;
-	}
-
-	wait_start_us = nm_utils_get_monotonic_timestamp_us ();
-
-	/* wait for the process to terminated... */
-	if (sig != SIGKILL) {
-		gint64 wait_until, now;
-		gulong sleep_time, sleep_duration_usec;
-		int loop_count = 0;
-
-		sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
-		wait_until = wait_before_kill_msec <= 0 ? 0 : wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
-
-		while (TRUE) {
-			ret = waitpid (pid, &status, WNOHANG);
-			if (ret > 0) {
-				nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s, process %ld exited %s%s",
-				            LOG_NAME_ARGS, _kc_signal_to_string (sig), (long) ret, _kc_exit_to_string (buf_exit, status),
-				            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-				success = TRUE;
-				goto out;
-			}
-			if (ret == -1) {
-				errsv = errno;
-				/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
-				if (errsv != ECHILD) {
-					nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s, waitpid failed with %s (%d)%s",
-					            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
-					           was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-					goto out;
-				}
-			}
-
-			if (!wait_until)
-				break;
-
-			now = nm_utils_get_monotonic_timestamp_us ();
-			if (now >= wait_until)
-				break;
-
-			if (!was_waiting) {
-				nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting up to %ld milliseconds for process to terminate normally after sending %s...",
-				            LOG_NAME_ARGS, (long) MAX (wait_before_kill_msec, 0), _kc_signal_to_string (sig));
-				was_waiting = TRUE;
-			}
-
-			sleep_time = MIN (wait_until - now, sleep_duration_usec);
-			if (loop_count < 20) {
-				/* At the beginning we expect the process to die fast.
-				 * Limit the sleep time, the limit doubles with every iteration. */
-				sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
-				loop_count++;
-			}
-			g_usleep (sleep_time);
-		}
-
-		/* send SIGKILL, if called with @wait_before_kill_msec > 0 */
-		if (wait_until) {
-			nm_log_dbg (log_domain, LOG_NAME_FMT ": sending SIGKILL...", LOG_NAME_ARGS);
-
-			send_kill = TRUE;
-			if (kill (pid, SIGKILL) != 0) {
-				errsv = errno;
-				/* ESRCH means, process does not exist or is already a zombie. */
-				if (errsv != ESRCH) {
-					nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send SIGKILL (after sending %s), %s (%d)",
-								LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
-					goto out;
-				}
-			}
-		}
-	}
-
-	if (!was_waiting) {
-		nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting for process to terminate after sending %s%s...",
-		            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "");
-	}
-
-	/* block until the child terminates. */
-	while ((ret = waitpid (pid, &status, 0)) <= 0) {
-		errsv = errno;
-
-		if (errsv != EINTR) {
-			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s%s, waitpid failed with %s (%d)%s",
-			            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", strerror (errsv), errsv,
-			            _kc_waited_to_string (buf_wait, wait_start_us));
-			goto out;
-		}
-	}
-
-	nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s%s, process %ld exited %s%s",
-	            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", (long) ret,
-	            _kc_exit_to_string (buf_exit, status), _kc_waited_to_string (buf_wait, wait_start_us));
-	success = TRUE;
-out:
-	if (child_status)
-		*child_status = success ? status : -1;
-	errno = success ? 0 : errsv;
-	return success;
-}
-
-/* nm_utils_kill_process_sync:
- * @pid: process id to kill
- * @start_time: the start time of the process to kill (as obtained by nm_utils_get_start_time_for_pid()).
- *   This is an optional argument, to avoid (somewhat) killing the wrong process as @pid
- *   might get recycled. You can pass 0, to not provide this parameter.
- * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
- *   second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
- * @log_domain: log debug information for this domain. Errors and warnings are logged both
- *   as %LOGD_CORE and @log_domain.
- * @log_name: name of the process to kill for logging.
- * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
- *   to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has no effect.
- *   If @max_wait_msec is set but less then @wait_before_kill_msec, the final %SIGKILL will also
- *   not be send.
- * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
- *   Set to zero, to use the default (meaning 20 wakeups per seconds).
- * @max_wait_msec: if 0, waits indefinitely until the process is gone (or a zombie). Otherwise, this
- *   is the maxium wait time until returning. If @max_wait_msec is non-zero but smaller then @wait_before_kill_msec,
- *   we will not send a final %SIGKILL.
- *
- * Kill a non-child process synchronously and wait. This function will not return before the
- * process with PID @pid is gone, the process is a zombie, or @max_wait_msec expires.
- **/
-void
-nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain log_domain,
-                            const char *log_name, guint32 wait_before_kill_msec,
-                            guint32 sleep_duration_msec, guint32 max_wait_msec)
-{
-	int errsv;
-	guint64 start_time0;
-	gint64 wait_until_sigkill, now, wait_start_us, max_wait_until;
-	gulong sleep_time, sleep_duration_usec;
-	int loop_count = 0;
-	gboolean was_waiting = FALSE;
-	char buf_wait[KC_WAITED_TO_STRING];
-	char p_state;
-
-	g_return_if_fail (pid > 0);
-	g_return_if_fail (log_name != NULL);
-	g_return_if_fail (wait_before_kill_msec > 0);
-
-	start_time0 = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
-	if (start_time0 == 0) {
-		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it seems already gone",
-		            LOG_NAME_ARGS, (long int) pid);
-		return;
-	}
-	if (start_time != 0 && start_time != start_time0) {
-		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": don't kill process %ld because the start_time is unexpectedly %lu instead of %ld",
-		            LOG_NAME_ARGS, (long int) pid, (long unsigned) start_time0, (long unsigned) start_time);
-		return;
-	}
-
-	switch (p_state) {
-	case 'Z':
-	case 'x':
-	case 'X':
-		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it is already a zombie (%c)",
-		            LOG_NAME_ARGS, (long int) pid, p_state);
-		return;
-	default:
-		break;
-	}
-
-	if (kill (pid, sig) != 0) {
-		errsv = errno;
-		/* ESRCH means, process does not exist or is already a zombie. */
-		if (errsv == ESRCH) {
-			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s because process seems gone",
-			            LOG_NAME_ARGS, _kc_signal_to_string (sig));
-		} else {
-			nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s: %s (%d)",
-			             LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
-		}
-		return;
-	}
-
-	/* wait for the process to terminated... */
-
-	wait_start_us = nm_utils_get_monotonic_timestamp_us ();
-
-	sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
-	if (sig != SIGKILL)
-		wait_until_sigkill = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
-	else
-		wait_until_sigkill = 0;
-	if (max_wait_msec > 0) {
-		max_wait_until = wait_start_us + (((gint64) max_wait_msec) * 1000L);
-		if (wait_until_sigkill > 0 && wait_until_sigkill > max_wait_msec)
-			wait_until_sigkill = 0;
-	} else
-		max_wait_until = 0;
-
-	while (TRUE) {
-		start_time = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
-
-		if (start_time != start_time0) {
-			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone after sending signal %s%s",
-			            LOG_NAME_ARGS, _kc_signal_to_string (sig),
-			            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-			return;
-		}
-		switch (p_state) {
-		case 'Z':
-		case 'x':
-		case 'X':
-			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is a zombie (%c) after sending signal %s%s",
-			            LOG_NAME_ARGS, p_state, _kc_signal_to_string (sig),
-			            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-			return;
-		default:
-			break;
-		}
-
-		if (kill (pid, 0) != 0) {
-			errsv = errno;
-			/* ESRCH means, process does not exist or is already a zombie. */
-			if (errsv == ESRCH) {
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie after sending signal %s%s",
-				            LOG_NAME_ARGS, _kc_signal_to_string (sig),
-				            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-			} else {
-				nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to kill(%ld, 0): %s (%d)%s",
-				             LOG_NAME_ARGS, (long int) pid, strerror (errsv), errsv,
-				             was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-			}
-			return;
-		}
-
-		sleep_time = sleep_duration_usec;
-		now = nm_utils_get_monotonic_timestamp_us ();
-
-		if (   max_wait_until != 0
-		    && now >= max_wait_until) {
-			if (wait_until_sigkill != 0) {
-				/* wait_before_kill_msec is not larger then max_wait_until but we did not yet send
-				 * SIGKILL. Although we already reached our timeout, we don't want to skip sending
-				 * the signal. Even if we don't wait for the process to disappear. */
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
-				kill (pid, SIGKILL);
-			}
-			nm_log_warn (log_domain, LOG_NAME_PROCESS_FMT ": timeout %u msec waiting for process to disappear (after sending %s)%s",
-			             LOG_NAME_ARGS, (unsigned) max_wait_until, _kc_signal_to_string (sig),
-			             was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
-			return;
-		}
-
-		if (wait_until_sigkill != 0) {
-			if (now >= wait_until_sigkill) {
-				/* Still not dead. SIGKILL now... */
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
-				if (kill (pid, SIGKILL) != 0) {
-					errsv = errno;
-					/* ESRCH means, process does not exist or is already a zombie. */
-					if (errsv != ESRCH) {
-						nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie%s",
-						            LOG_NAME_ARGS, _kc_waited_to_string (buf_wait, wait_start_us));
-					} else {
-						nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send SIGKILL (after sending %s), %s (%d)%s",
-						             LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
-						             _kc_waited_to_string (buf_wait, wait_start_us));
-					}
-					return;
-				}
-				sig = SIGKILL;
-				wait_until_sigkill = 0;
-				loop_count = 0; /* reset the loop_count. Now we really expect the process to die quickly. */
-			} else
-				sleep_time = MIN (wait_until_sigkill - now, sleep_duration_usec);
-		}
-
-		if (!was_waiting) {
-			if (wait_until_sigkill != 0) {
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear before sending KILL signal after sending %s...",
-				            LOG_NAME_ARGS, (long) wait_before_kill_msec, _kc_signal_to_string (sig));
-			} else if (max_wait_until != 0) {
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear after sending %s...",
-				            LOG_NAME_ARGS, (long) max_wait_msec, _kc_signal_to_string (sig));
-			} else {
-				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting for process to disappear after sending %s...",
-				            LOG_NAME_ARGS, _kc_signal_to_string (sig));
-			}
-			was_waiting = TRUE;
-		}
-
-		if (loop_count < 20) {
-			/* At the beginning we expect the process to die fast.
-			 * Limit the sleep time, the limit doubles with every iteration. */
-			sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
-			loop_count++;
-		}
-		g_usleep (sleep_time);
-	}
-}
-#undef LOG_NAME_FMT
-#undef LOG_NAME_PROCESS_FMT
-#undef LOG_NAME_ARGS
-
-const char *const NM_PATHS_DEFAULT[] = {
-	PREFIX "/sbin/",
-	PREFIX "/bin/",
-	"/sbin/",
-	"/usr/sbin/",
-	"/usr/local/sbin/",
-	"/bin/",
-	"/usr/bin/",
-	"/usr/local/bin/",
-	NULL,
-};
-
-const char *
-nm_utils_find_helper(const char *progname, const char *try_first, GError **error)
-{
-	return nm_utils_file_search_in_paths (progname, try_first, NM_PATHS_DEFAULT, G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error);
-}
-
-/******************************************************************************************/
-
-#define MAC_TAG "mac:"
-#define INTERFACE_NAME_TAG "interface-name:"
-#define DEVICE_TYPE_TAG "type:"
-#define SUBCHAN_TAG "s390-subchannels:"
-#define EXCEPT_TAG "except:"
-#define MATCH_TAG_CONFIG_NM_VERSION             "nm-version:"
-#define MATCH_TAG_CONFIG_NM_VERSION_MIN         "nm-version-min:"
-#define MATCH_TAG_CONFIG_NM_VERSION_MAX         "nm-version-max:"
-#define MATCH_TAG_CONFIG_ENV                    "env:"
-
-#define _spec_has_prefix(pspec, tag) \
-	({ \
-		const char **_spec = (pspec); \
-		gboolean _has = FALSE; \
-		\
-		if (!g_ascii_strncasecmp (*_spec, (""tag), STRLEN (tag))) { \
-			*_spec += STRLEN (tag); \
-			_has = TRUE; \
-		} \
-		_has; \
-	})
-
-static const char *
-_match_except (const char *spec_str, gboolean *out_except)
-{
-	if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, STRLEN (EXCEPT_TAG))) {
-		spec_str += STRLEN (EXCEPT_TAG);
-		*out_except = TRUE;
-	} else
-		*out_except = FALSE;
-	return spec_str;
-}
-
-NMMatchSpecMatchType
-nm_match_spec_device_type (const GSList *specs, const char *device_type)
-{
-	const GSList *iter;
-	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
-
-	if (!device_type || !*device_type)
-		return NM_MATCH_SPEC_NO_MATCH;
-
-	for (iter = specs; iter; iter = g_slist_next (iter)) {
-		const char *spec_str = iter->data;
-		gboolean except;
-
-		if (!spec_str || !*spec_str)
-			continue;
-
-		spec_str = _match_except (spec_str, &except);
-
-		if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)) != 0)
-			continue;
-
-		spec_str += STRLEN (DEVICE_TYPE_TAG);
-		if (strcmp (spec_str, device_type) == 0) {
-			if (except)
-				return NM_MATCH_SPEC_NEG_MATCH;
-			match = NM_MATCH_SPEC_MATCH;
-		}
-	}
-	return match;
-}
-
-NMMatchSpecMatchType
-nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
-{
-	const GSList *iter;
-	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
-
-	g_return_val_if_fail (hwaddr != NULL, NM_MATCH_SPEC_NO_MATCH);
-
-	for (iter = specs; iter; iter = g_slist_next (iter)) {
-		const char *spec_str = iter->data;
-		gboolean except;
-
-		if (!spec_str || !*spec_str)
-			continue;
-
-		spec_str = _match_except (spec_str, &except);
-
-		if (   !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG))
-		    || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))
-		    || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)))
-			continue;
-
-		if (!g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG)))
-			spec_str += STRLEN (MAC_TAG);
-		else if (except)
-			continue;
-
-		if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) {
-			if (except)
-				return NM_MATCH_SPEC_NEG_MATCH;
-			match = NM_MATCH_SPEC_MATCH;
-		}
-	}
-	return match;
-}
-
-NMMatchSpecMatchType
-nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
-{
-	const GSList *iter;
-	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
-
-	g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH);
-
-	for (iter = specs; iter; iter = g_slist_next (iter)) {
-		const char *spec_str = iter->data;
-		gboolean use_pattern = FALSE;
-		gboolean except;
-
-		if (!spec_str || !*spec_str)
-			continue;
-
-		spec_str = _match_except (spec_str, &except);
-
-		if (   !g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG))
-		    || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))
-		    || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)))
-			continue;
-
-		if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG))) {
-			spec_str += STRLEN (INTERFACE_NAME_TAG);
-			if (spec_str[0] == '=')
-				spec_str += 1;
-			else {
-				if (spec_str[0] == '~')
-					spec_str += 1;
-				use_pattern=TRUE;
-			}
-		} else if (except)
-			continue;
-
-		if (   !strcmp (spec_str, interface_name)
-		    || (use_pattern && g_pattern_match_simple (spec_str, interface_name))) {
-			if (except)
-				return NM_MATCH_SPEC_NEG_MATCH;
-			match = NM_MATCH_SPEC_MATCH;
-		}
-	}
-	return match;
-}
-
-#define BUFSIZE 10
-
-static gboolean
-parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
-{
-	long unsigned int tmp;
-	char buf[BUFSIZE + 1];
-	const char *p = subchannels;
-	int i = 0;
-	char *pa = NULL, *pb = NULL, *pc = NULL;
-
-	g_return_val_if_fail (subchannels != NULL, FALSE);
-	g_return_val_if_fail (a != NULL, FALSE);
-	g_return_val_if_fail (*a == 0, FALSE);
-	g_return_val_if_fail (b != NULL, FALSE);
-	g_return_val_if_fail (*b == 0, FALSE);
-	g_return_val_if_fail (c != NULL, FALSE);
-	g_return_val_if_fail (*c == 0, FALSE);
-
-	/* sanity check */
-	if (!g_ascii_isxdigit (subchannels[0]))
-		return FALSE;
-
-	/* Get the first channel */
-	while (*p && (*p != ',')) {
-		if (!g_ascii_isxdigit (*p) && (*p != '.'))
-			return FALSE;  /* Invalid chars */
-		if (i >= BUFSIZE)
-			return FALSE;  /* Too long to be a subchannel */
-		buf[i++] = *p++;
-	}
-	buf[i] = '\0';
-
-	/* and grab each of its elements, there should be 3 */
-	pa = &buf[0];
-	pb = strchr (buf, '.');
-	if (pb)
-		pc = strchr (pb + 1, '.');
-	if (!pa || !pb || !pc)
-		return FALSE;
-
-	/* Split the string */
-	*pb++ = '\0';
-	*pc++ = '\0';
-
-	errno = 0;
-	tmp = strtoul (pa, NULL, 16);
-	if (errno)
-		return FALSE;
-	*a = (guint32) tmp;
-
-	errno = 0;
-	tmp = strtoul (pb, NULL, 16);
-	if (errno)
-		return FALSE;
-	*b = (guint32) tmp;
-
-	errno = 0;
-	tmp = strtoul (pc, NULL, 16);
-	if (errno)
-		return FALSE;
-	*c = (guint32) tmp;
-
-	return TRUE;
-}
-
-NMMatchSpecMatchType
-nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
-{
-	const GSList *iter;
-	guint32 a = 0, b = 0, c = 0;
-	guint32 spec_a = 0, spec_b = 0, spec_c = 0;
-	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
-
-	g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH);
-
-	if (!specs)
-		return NM_MATCH_SPEC_NO_MATCH;
-
-	if (!parse_subchannels (subchannels, &a, &b, &c))
-		return NM_MATCH_SPEC_NO_MATCH;
-
-	for (iter = specs; iter; iter = g_slist_next (iter)) {
-		const char *spec_str = iter->data;
-		gboolean except;
-
-		if (!spec_str || !*spec_str)
-			continue;
-
-		spec_str = _match_except (spec_str, &except);
-
-		if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))) {
-			spec_str += STRLEN (SUBCHAN_TAG);
-			if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) {
-				if (a == spec_a && b == spec_b && c == spec_c) {
-					if (except)
-						return NM_MATCH_SPEC_NEG_MATCH;
-					match = NM_MATCH_SPEC_MATCH;
-				}
-			}
-		}
-	}
-	return match;
-}
-
-static gboolean
-_match_config_nm_version (const char *str, const char *tag, guint cur_nm_version)
-{
-	gs_free char *s_ver = NULL;
-	gs_strfreev char **s_ver_tokens = NULL;
-	gint v_maj = -1, v_min = -1, v_mic = -1;
-	guint c_maj = -1, c_min = -1, c_mic = -1;
-	guint n_tokens;
-
-	s_ver = g_strdup (str);
-	g_strstrip (s_ver);
-
-	/* Let's be strict with the accepted format here. No funny stuff!! */
-
-	if (s_ver[strspn (s_ver, ".0123456789")] != '\0')
-		return FALSE;
-
-	s_ver_tokens = g_strsplit (s_ver, ".", -1);
-	n_tokens = g_strv_length (s_ver_tokens);
-	if (n_tokens == 0 || n_tokens > 3)
-		return FALSE;
-
-	v_maj = _nm_utils_ascii_str_to_int64 (s_ver_tokens[0], 10, 0, 0xFFFF, -1);
-	if (v_maj < 0)
-		return FALSE;
-	if (n_tokens >= 2) {
-		v_min = _nm_utils_ascii_str_to_int64 (s_ver_tokens[1], 10, 0, 0xFF, -1);
-		if (v_min < 0)
-			return FALSE;
-	}
-	if (n_tokens >= 3) {
-		v_mic = _nm_utils_ascii_str_to_int64 (s_ver_tokens[2], 10, 0, 0xFF, -1);
-		if (v_mic < 0)
-			return FALSE;
-	}
-
-	nm_decode_version (cur_nm_version, &c_maj, &c_min, &c_mic);
-
-#define CHECK_AND_RETURN_FALSE(cur, val, tag, is_last_digit) \
-	G_STMT_START { \
-		if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MIN)) { \
-			if (cur < val) \
-				return FALSE; \
-		} else if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MAX)) { \
-			if (cur > val) \
-				return FALSE; \
-		} else { \
-			if (cur != val) \
-				return FALSE; \
-		} \
-		if (!(is_last_digit)) { \
-			if (cur != val) \
-				return FALSE; \
-		} \
-	} G_STMT_END
-	if (v_mic >= 0)
-		CHECK_AND_RETURN_FALSE (c_mic, v_mic, tag, TRUE);
-	if (v_min >= 0)
-		CHECK_AND_RETURN_FALSE (c_min, v_min, tag, v_mic < 0);
-	CHECK_AND_RETURN_FALSE (c_maj, v_maj, tag, v_min < 0);
-	return TRUE;
-}
-
-NMMatchSpecMatchType
-nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env)
-{
-	const GSList *iter;
-	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
-
-	if (!specs)
-		return NM_MATCH_SPEC_NO_MATCH;
-
-	for (iter = specs; iter; iter = g_slist_next (iter)) {
-		const char *spec_str = iter->data;
-		gboolean except;
-		gboolean v_match;
-
-		if (!spec_str || !*spec_str)
-			continue;
-
-		spec_str = _match_except (spec_str, &except);
-
-		if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION))
-			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
-		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
-			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
-		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
-			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
-		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV))
-			v_match = env && env[0] && !strcmp (spec_str, env);
-		else
-			continue;
-
-		if (v_match) {
-			if (except)
-				return NM_MATCH_SPEC_NEG_MATCH;
-			match = NM_MATCH_SPEC_MATCH;
-		}
-	}
-	return match;
-}
-
-/**
- * nm_match_spec_split:
- * @value: the string of device specs
- *
- * Splits the specs from the string and returns them as individual
- * entires in a #GSList.
- *
- * It does not validate any specs, it basically just does a special
- * strsplit with ',' or ';' as separators and supporting '\\' as
- * escape character.
- *
- * Leading and trailing spaces of each entry are removed. But the user
- * can preserve them by specifying "\\s has 2 leading" or "has 2 trailing \\s".
- *
- * Specs can have a qualifier like "interface-name:". We still don't strip
- * any whitespace after the colon, so "interface-name: X" matches an interface
- * named " X".
- *
- * Returns: (transfer-full): the list of device specs.
- */
-GSList *
-nm_match_spec_split (const char *value)
-{
-	char *string_value, *p, *q0, *q;
-	GSList *pieces = NULL;
-	int trailing_ws;
-
-	if (!value || !*value)
-		return NULL;
-
-	/* Copied from glibs g_key_file_parse_value_as_string() function
-	 * and adjusted. */
-
-	string_value = g_new (gchar, strlen (value) + 1);
-
-	p = (gchar *) value;
-
-	/* skip over leading whitespace */
-	while (g_ascii_isspace (*p))
-		p++;
-
-	q0 = q = string_value;
-	trailing_ws = 0;
-	while (*p) {
-		if (*p == '\\') {
-			p++;
-
-			switch (*p) {
-			case 's':
-				*q = ' ';
-				break;
-			case 'n':
-				*q = '\n';
-				break;
-			case 't':
-				*q = '\t';
-				break;
-			case 'r':
-				*q = '\r';
-				break;
-			case '\\':
-				*q = '\\';
-				break;
-			case '\0':
-				break;
-			default:
-				if (NM_IN_SET (*p, ',', ';'))
-					*q = *p;
-				else {
-					*q++ = '\\';
-					*q = *p;
-				}
-				break;
-			}
-			if (*p == '\0')
-				break;
-			p++;
-			trailing_ws = 0;
-		} else {
-			*q = *p;
-			if (*p == '\0')
-				break;
-			if (g_ascii_isspace (*p)) {
-				trailing_ws++;
-				p++;
-			} else if (NM_IN_SET (*p, ',', ';')) {
-				if (q0 < q - trailing_ws)
-					pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
-				q0 = q + 1;
-				p++;
-				trailing_ws = 0;
-				while (g_ascii_isspace (*p))
-					p++;
-			} else
-				p++;
-		}
-		q++;
-	}
-
-	*q = '\0';
-	if (q0 < q - trailing_ws)
-		pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
-	g_free (string_value);
-	return g_slist_reverse (pieces);
-}
-
-/**
- * nm_match_spec_join:
- * @specs: the device specs to join
- *
- * This is based on g_key_file_parse_string_as_value(), analog to
- * nm_match_spec_split() which is based on g_key_file_parse_value_as_string().
- *
- * Returns: (transfer-full): a joined list of device specs that can be
- *   split again with nm_match_spec_split(). Note that
- *   nm_match_spec_split (nm_match_spec_join (specs)) yields the original
- *   result (which is not true the other way around because there are multiple
- *   ways to encode the same joined specs string).
- */
-char *
-nm_match_spec_join (GSList *specs)
-{
-	const char *p;
-	GString *str;
-
-	str = g_string_new ("");
-
-	for (; specs; specs = specs->next) {
-		p = specs->data;
-
-		if (!p || !*p)
-			continue;
-
-		if (str->len > 0)
-			g_string_append_c (str, ',');
-
-		/* escape leading whitespace */
-		switch (*p) {
-		case ' ':
-			g_string_append (str, "\\s");
-			p++;
-			break;
-		case '\t':
-			g_string_append (str, "\\t");
-			p++;
-			break;
-		}
-
-		for (; *p; p++) {
-			switch (*p) {
-			case '\n':
-				g_string_append (str, "\\n");
-				break;
-			case '\r':
-				g_string_append (str, "\\r");
-				break;
-			case '\\':
-				g_string_append (str, "\\\\");
-				break;
-			case ',':
-				g_string_append (str, "\\,");
-				break;
-			case ';':
-				g_string_append (str, "\\;");
-				break;
-			default:
-				g_string_append_c (str, *p);
-				break;
-			}
-		}
-
-		/* escape trailing whitespaces */
-		switch (str->str[str->len - 1]) {
-		case ' ':
-			g_string_overwrite (str, str->len - 1, "\\s");
-			break;
-		case '\t':
-			g_string_overwrite (str, str->len - 1, "\\t");
-			break;
-		}
-	}
-
-	return g_string_free (str, FALSE);
-}
-
-/*****************************************************************************/
-
-char _nm_utils_to_string_buffer[];
-
-void
-nm_utils_to_string_buffer_init (char **buf, gsize *len)
-{
-	if (!*buf) {
-		*buf = _nm_utils_to_string_buffer;
-		*len = sizeof (_nm_utils_to_string_buffer);
-	}
-}
-
-gboolean
-nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len)
-{
-	nm_utils_to_string_buffer_init (buf, len);
-	if (!obj) {
-		g_strlcpy (*buf, "(null)", *len);
-		return FALSE;
-	}
-	return TRUE;
-}
-
-void
-nm_utils_strbuf_append_c (char **buf, gsize *len, char c)
-{
-	switch (*len) {
-	case 0:
-		return;
-	case 1:
-		(*buf)[0] = '\0';
-		*len = 0;
-		(*buf)++;
-		return;
-	default:
-		(*buf)[0] = c;
-		(*buf)[1] = '\0';
-		(*len)--;
-		(*buf)++;
-		return;
-	}
-}
-
-void
-nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str)
-{
-	gsize src_len;
-
-	switch (*len) {
-	case 0:
-		return;
-	case 1:
-		if (!str || !*str) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		(*buf)[0] = '\0';
-		*len = 0;
-		(*buf)++;
-		return;
-	default:
-		if (!str || !*str) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		src_len = g_strlcpy (*buf, str, *len);
-		if (src_len >= *len) {
-			*buf = &(*buf)[*len];
-			*len = 0;
-		} else {
-			*buf = &(*buf)[src_len];
-			*len -= src_len;
-		}
-		return;
-	}
-}
-
-void
-nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
-{
-	char *p = *buf;
-	va_list args;
-	gint retval;
-
-	if (*len == 0)
-		return;
-
-	va_start (args, format);
-	retval = g_vsnprintf (p, *len, format, args);
-	va_end (args);
-
-	if (retval >= *len) {
-		*buf = &p[*len];
-		*len = 0;
-	} else {
-		*buf = &p[retval];
-		*len -= retval;
-	}
-}
-
-const char *
-nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
-                    gsize n_descs,
-                    unsigned flags,
-                    char *buf,
-                    gsize len)
-{
-	gsize i;
-	char *p;
-
-#if NM_MORE_ASSERTS > 10
-	nm_assert (descs);
-	nm_assert (n_descs > 0);
-	for (i = 0; i < n_descs; i++) {
-		gsize j;
-
-		nm_assert (descs[i].flag && nm_utils_is_power_of_two (descs[i].flag));
-		nm_assert (descs[i].name && descs[i].name[0]);
-		for (j = 0; j < i; j++)
-			nm_assert (descs[j].flag != descs[i].flag);
-	}
-#endif
-
-	nm_utils_to_string_buffer_init (&buf, &len);
-
-	if (!len)
-		return buf;
-
-	buf[0] = '\0';
-	if (!flags) {
-		return buf;
-	}
-
-	p = buf;
-	for (i = 0; flags && i < n_descs; i++) {
-		if (NM_FLAGS_HAS (flags, descs[i].flag)) {
-			flags &= ~descs[i].flag;
-
-			if (buf[0] != '\0')
-				nm_utils_strbuf_append_c (&p, &len, ',');
-			nm_utils_strbuf_append_str (&p, &len, descs[i].name);
-		}
-	}
-	if (flags) {
-		if (buf[0] != '\0')
-			nm_utils_strbuf_append_c (&p, &len, ',');
-		nm_utils_strbuf_append (&p, &len, "0x%x", flags);
-	}
-	return buf;
-};
-
-/*****************************************************************************/
-
-const char *
-nm_utils_enum2str (const NMUtilsEnum2StrDesc *descs,
-                   gsize n_descs,
-                   int val,
-                   char *buf,
-                   gsize len)
-{
-	gsize i;
-
-#if NM_MORE_ASSERTS > 10
-	nm_assert (descs);
-	nm_assert (n_descs > 0);
-	for (i = 0; i < n_descs; i++) {
-		gsize j;
-
-		nm_assert (descs[i].name && descs[i].name[0]);
-		for (j = 0; j < i; j++)
-			nm_assert (descs[j].value != descs[i].value);
-	}
-#endif
-
-	nm_utils_to_string_buffer_init (&buf, &len);
-
-	if (!len)
-		return buf;
-
-	for (i = 0; i < n_descs; i++) {
-		if (val == descs[i].value) {
-			g_strlcpy (buf, descs[i].name, len);
-			return buf;
-		}
-	}
+#include "nm-core-internal.h"
 
-	g_snprintf (buf, len, "(%d)", val);
-	return buf;
-};
+#include "nm-platform.h"
+#include "nm-exported-object.h"
+#include "nm-auth-utils.h"
 
-/*****************************************************************************/
+/******************************************************************************/
 
 /**
  * nm_utils_get_shared_wifi_permission:
@@ -1948,7 +64,7 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection)
 	return NULL;
 }
 
-/*********************************/
+/******************************************************************************/
 
 static char *
 get_new_connection_name (const GSList *existing,
@@ -2138,109 +254,7 @@ nm_utils_complete_generic (NMConnection *connection,
 	g_hash_table_destroy (parameters);
 }
 
-char *
-nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id)
-{
-	/* Basically VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD */
-	return g_strdup_printf ("%s.%d", parent_iface, vlan_id);
-}
-
-/**
- * nm_utils_read_resolv_conf_nameservers():
- * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
- *
- * Reads all nameservers out of @rc_contents or /etc/resolv.conf and returns
- * them.
- *
- * Returns: a #GPtrArray of 'char *' elements of each nameserver line from
- * @contents or resolv.conf
- */
-GPtrArray *
-nm_utils_read_resolv_conf_nameservers (const char *rc_contents)
-{
-	GPtrArray *nameservers = NULL;
-	char *contents = NULL;
-	char **lines, **iter;
-	char *p;
-
-	if (rc_contents)
-		contents = g_strdup (rc_contents);
-	else {
-		if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
-			return NULL;
-	}
-
-	nameservers = g_ptr_array_new_full (3, g_free);
-
-	lines = g_strsplit_set (contents, "\r\n", -1);
-	for (iter = lines; *iter; iter++) {
-		if (!g_str_has_prefix (*iter, "nameserver"))
-			continue;
-		p = *iter + strlen ("nameserver");
-		if (!g_ascii_isspace (*p++))
-			continue;
-		/* Skip intermediate whitespace */
-		while (g_ascii_isspace (*p))
-			p++;
-		g_strchomp (p);
-
-		g_ptr_array_add (nameservers, g_strdup (p));
-	}
-	g_strfreev (lines);
-	g_free (contents);
-
-	return nameservers;
-}
-
-/**
- * nm_utils_read_resolv_conf_dns_options():
- * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
- *
- * Reads all dns options out of @rc_contents or /etc/resolv.conf and returns
- * them.
- *
- * Returns: a #GPtrArray of 'char *' elements of each option
- */
-GPtrArray *
-nm_utils_read_resolv_conf_dns_options (const char *rc_contents)
-{
-	GPtrArray *options = NULL;
-	char *contents = NULL;
-	char **lines, **line_iter;
-	char **tokens, **token_iter;
-	char *p;
-
-	if (rc_contents)
-		contents = g_strdup (rc_contents);
-	else {
-		if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
-			return NULL;
-	}
-
-	options = g_ptr_array_new_full (3, g_free);
-
-	lines = g_strsplit_set (contents, "\r\n", -1);
-	for (line_iter = lines; *line_iter; line_iter++) {
-		if (!g_str_has_prefix (*line_iter, "options"))
-			continue;
-		p = *line_iter + strlen ("options");
-		if (!g_ascii_isspace (*p++))
-			continue;
-
-		tokens = g_strsplit (p, " ", 0);
-		for (token_iter = tokens; token_iter && *token_iter; token_iter++) {
-			g_strstrip (*token_iter);
-			if (!*token_iter[0])
-				continue;
-			g_ptr_array_add (options, g_strdup (*token_iter));
-		}
-		g_strfreev (tokens);
-	}
-	g_strfreev (lines);
-	g_free (contents);
-
-	return options;
-}
+/*****************************************************************************/
 
 static GHashTable *
 check_property_in_hash (GHashTable *hash,
@@ -2321,6 +335,95 @@ check_ip6_method (NMConnection *orig,
 	return allow;
 }
 
+static int
+route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)
+{
+	gint64 r, metric1, metric2;
+
+	r = g_strcmp0 (nm_ip_route_get_dest (route1), nm_ip_route_get_dest (route2));
+	if (r)
+		return r;
+
+	r = nm_ip_route_get_prefix (route1) - nm_ip_route_get_prefix (route2);
+	if (r)
+		return r > 0 ? 1 : -1;
+
+	r = g_strcmp0 (nm_ip_route_get_next_hop (route1), nm_ip_route_get_next_hop (route2));
+	if (r)
+		return r;
+
+	metric1 = nm_ip_route_get_metric (route1) == -1 ? default_metric : nm_ip_route_get_metric (route1);
+	metric2 = nm_ip_route_get_metric (route2) == -1 ? default_metric : nm_ip_route_get_metric (route2);
+
+	r = metric1 - metric2;
+	if (r)
+		return r > 0 ? 1 : -1;
+
+	r = nm_ip_route_get_family (route1) - nm_ip_route_get_family (route2);
+	if (r)
+		return r > 0 ? 1 : -1;
+
+	return 0;
+}
+
+static int
+route_ptr_compare (const void *a, const void *b)
+{
+	return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, -1);
+}
+
+static gboolean
+check_ip_routes (NMConnection *orig,
+                 NMConnection *candidate,
+                 GHashTable *settings,
+                 gint64 default_metric,
+                 gboolean v4)
+{
+	gs_free NMIPRoute **routes1 = NULL, **routes2 = NULL;
+	NMSettingIPConfig *s_ip1, *s_ip2;
+	const char *s_name;
+	GHashTable *props;
+	guint i, num;
+
+	s_name = v4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME :
+	              NM_SETTING_IP6_CONFIG_SETTING_NAME;
+
+	props = check_property_in_hash (settings,
+	                                s_name,
+	                                NM_SETTING_IP_CONFIG_ROUTES);
+	if (!props)
+		return TRUE;
+
+	s_ip1 = (NMSettingIPConfig *) nm_connection_get_setting_by_name (orig, s_name);
+	s_ip2 = (NMSettingIPConfig *) nm_connection_get_setting_by_name (candidate, s_name);
+
+	if (!s_ip1 || !s_ip2)
+		return FALSE;
+
+	num = nm_setting_ip_config_get_num_routes (s_ip1);
+	if (num != nm_setting_ip_config_get_num_routes (s_ip2))
+		return FALSE;
+
+	routes1 = g_new (NMIPRoute *, num);
+	routes2 = g_new (NMIPRoute *, num);
+
+	for (i = 0; i < num; i++) {
+		routes1[i] = nm_setting_ip_config_get_route (s_ip1, i);
+		routes2[i] = nm_setting_ip_config_get_route (s_ip2, i);
+	}
+
+	qsort (routes1, num, sizeof (NMIPRoute *), route_ptr_compare);
+	qsort (routes2, num, sizeof (NMIPRoute *), route_ptr_compare);
+
+	for (i = 0; i < num; i++) {
+		if (route_compare (routes1[i], routes2[i], default_metric))
+			return FALSE;
+	}
+
+	remove_from_hash (settings, props, s_name, NM_SETTING_IP_CONFIG_ROUTES);
+	return TRUE;
+}
+
 static gboolean
 check_ip4_method (NMConnection *orig,
                   NMConnection *candidate,
@@ -2504,7 +607,9 @@ static NMConnection *
 check_possible_match (NMConnection *orig,
                       NMConnection *candidate,
                       GHashTable *settings,
-                      gboolean device_has_carrier)
+                      gboolean device_has_carrier,
+                      gint64 default_v4_metric,
+                      gint64 default_v6_metric)
 {
 	g_return_val_if_fail (settings != NULL, NULL);
 
@@ -2514,6 +619,12 @@ check_possible_match (NMConnection *orig,
 	if (!check_ip4_method (orig, candidate, settings, device_has_carrier))
 		return NULL;
 
+	if (!check_ip_routes (orig, candidate, settings, default_v4_metric, TRUE))
+		return NULL;
+
+	if (!check_ip_routes (orig, candidate, settings, default_v6_metric, FALSE))
+		return NULL;
+
 	if (!check_connection_interface_name (orig, candidate, settings))
 		return NULL;
 
@@ -2557,6 +668,8 @@ NMConnection *
 nm_utils_match_connection (GSList *connections,
                            NMConnection *original,
                            gboolean device_has_carrier,
+                           gint64 default_v4_metric,
+                           gint64 default_v6_metric,
                            NMUtilsMatchFilterFunc match_filter_func,
                            gpointer match_filter_data)
 {
@@ -2573,8 +686,10 @@ nm_utils_match_connection (GSList *connections,
 		}
 
 		if (!nm_connection_diff (original, candidate, NM_SETTING_COMPARE_FLAG_INFERRABLE, &diffs)) {
-			if (!best_match)
-				best_match = check_possible_match (original, candidate, diffs, device_has_carrier);
+			if (!best_match) {
+				best_match = check_possible_match (original, candidate, diffs, device_has_carrier,
+				                                   default_v4_metric, default_v6_metric);
+			}
 
 			if (!best_match && nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
 				GString *diff_string;
@@ -2614,860 +729,7 @@ nm_utils_match_connection (GSList *connections,
 	return best_match;
 }
 
-int
-nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b)
-{
-	NMSettingConnection *a_s_con, *b_s_con;
-	gboolean a_ac, b_ac;
-	gint a_ap, b_ap;
-
-	a_s_con = nm_connection_get_setting_connection (*a);
-	b_s_con = nm_connection_get_setting_connection (*b);
-
-	a_ac = !!nm_setting_connection_get_autoconnect (a_s_con);
-	b_ac = !!nm_setting_connection_get_autoconnect (b_s_con);
-	if (a_ac != b_ac)
-		return ((int) b_ac) - ((int) a_ac);
-	if (!a_ac)
-		return 0;
-
-	a_ap = nm_setting_connection_get_autoconnect_priority (a_s_con);
-	b_ap = nm_setting_connection_get_autoconnect_priority (b_s_con);
-	if (a_ap != b_ap)
-		return (a_ap > b_ap) ? -1 : 1;
-
-	return 0;
-}
-
-/**************************************************************************/
-
-static gint64 monotonic_timestamp_offset_sec;
-static int monotonic_timestamp_clock_mode = 0;
-
-static void
-monotonic_timestamp_get (struct timespec *tp)
-{
-	int clock_mode = 0;
-	int err = 0;
-
-	switch (monotonic_timestamp_clock_mode) {
-	case 0:
-		/* the clock is not yet initialized (first run) */
-		err = clock_gettime (CLOCK_BOOTTIME, tp);
-		if (err == -1 && errno == EINVAL) {
-			clock_mode = 2;
-			err = clock_gettime (CLOCK_MONOTONIC, tp);
-		} else
-			clock_mode = 1;
-		break;
-	case 1:
-		/* default, return CLOCK_BOOTTIME */
-		err = clock_gettime (CLOCK_BOOTTIME, tp);
-		break;
-	case 2:
-		/* fallback, return CLOCK_MONOTONIC. Kernels prior to 2.6.39
-		 * don't support CLOCK_BOOTTIME. */
-		err = clock_gettime (CLOCK_MONOTONIC, tp);
-		break;
-	}
-
-	g_assert (err == 0); (void)err;
-	g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND);
-
-	if (G_LIKELY (clock_mode == 0))
-		return;
-
-	/* Calculate an offset for the time stamp.
-	 *
-	 * We always want positive values, because then we can initialize
-	 * a timestamp with 0 and be sure, that it will be less then any
-	 * value nm_utils_get_monotonic_timestamp_*() might return.
-	 * For this to be true also for nm_utils_get_monotonic_timestamp_s() at
-	 * early boot, we have to shift the timestamp to start counting at
-	 * least from 1 second onward.
-	 *
-	 * Another advantage of shifting is, that this way we make use of the whole 31 bit
-	 * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s()
-	 * wraps (~68 years).
-	 **/
-	monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1;
-	monotonic_timestamp_clock_mode = clock_mode;
-
-	if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
-		time_t now = time (NULL);
-		struct tm tm;
-		char s[255];
-
-		strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
-		nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
-		                       "an offset of %lld.0 seconds to %s (local time is %s)",
-		                       tp->tv_nsec, (long long) -monotonic_timestamp_offset_sec,
-		                       clock_mode == 1 ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", s);
-	}
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_ns:
- *
- * Returns: a monotonically increasing time stamp in nanoseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_ns (void)
-{
-	struct timespec tp = { 0 };
-
-	monotonic_timestamp_get (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * NM_UTILS_NS_PER_SECOND +
-	       tp.tv_nsec;
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_us:
- *
- * Returns: a monotonically increasing time stamp in microseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_us (void)
-{
-	struct timespec tp = { 0 };
-
-	monotonic_timestamp_get (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) G_USEC_PER_SEC) +
-	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_ms:
- *
- * Returns: a monotonically increasing time stamp in milliseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_ms (void)
-{
-	struct timespec tp = { 0 };
-
-	monotonic_timestamp_get (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) 1000) +
-	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_s:
- *
- * Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing
- * away sub second parts). The returned value will always be positive.
- *
- * This value wraps after roughly 68 years which should be fine for any
- * practical purpose.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint32
-nm_utils_get_monotonic_timestamp_s (void)
-{
-	struct timespec tp = { 0 };
-
-	monotonic_timestamp_get (&tp);
-	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec);
-}
-
-typedef struct
-{
-	const char *name;
-	NMSetting *setting;
-	NMSetting *diff_base_setting;
-	GHashTable *setting_diff;
-} LogConnectionSettingData;
-
-typedef struct
-{
-	const char *item_name;
-	NMSettingDiffResult diff_result;
-} LogConnectionSettingItem;
-
-static gint
-_log_connection_sort_hashes_fcn (gconstpointer a, gconstpointer b)
-{
-	const LogConnectionSettingData *v1 = a;
-	const LogConnectionSettingData *v2 = b;
-	guint32 p1, p2;
-	NMSetting *s1, *s2;
-
-	s1 = v1->setting ? v1->setting : v1->diff_base_setting;
-	s2 = v2->setting ? v2->setting : v2->diff_base_setting;
-
-	g_assert (s1 && s2);
-
-	p1 = _nm_setting_get_setting_priority (s1);
-	p2 = _nm_setting_get_setting_priority (s2);
-
-	if (p1 != p2)
-		return p1 > p2 ? 1 : -1;
-
-	return strcmp (v1->name, v2->name);
-}
-
-static GArray *
-_log_connection_sort_hashes (NMConnection *connection, NMConnection *diff_base, GHashTable *connection_diff)
-{
-	GHashTableIter iter;
-	GArray *sorted_hashes;
-	LogConnectionSettingData setting_data;
-
-	sorted_hashes = g_array_sized_new (TRUE, FALSE, sizeof (LogConnectionSettingData), g_hash_table_size (connection_diff));
-
-	g_hash_table_iter_init (&iter, connection_diff);
-	while (g_hash_table_iter_next (&iter, (gpointer) &setting_data.name, (gpointer) &setting_data.setting_diff)) {
-		setting_data.setting = nm_connection_get_setting_by_name (connection, setting_data.name);
-		setting_data.diff_base_setting = diff_base ? nm_connection_get_setting_by_name (diff_base, setting_data.name) : NULL;
-		g_assert (setting_data.setting || setting_data.diff_base_setting);
-		g_array_append_val (sorted_hashes, setting_data);
-	}
-
-	g_array_sort (sorted_hashes, _log_connection_sort_hashes_fcn);
-	return sorted_hashes;
-}
-
-static gint
-_log_connection_sort_names_fcn (gconstpointer a, gconstpointer b)
-{
-	const LogConnectionSettingItem *v1 = a;
-	const LogConnectionSettingItem *v2 = b;
-
-	/* we want to first show the items, that disappeared, then the one that changed and
-	 * then the ones that were added. */
-
-	if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_A))
-		return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) ? -1 : 1;
-	if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_B))
-		return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) ? 1 : -1;
-	return strcmp (v1->item_name, v2->item_name);
-}
-
-static char *
-_log_connection_get_property (NMSetting *setting, const char *name)
-{
-	GValue val = G_VALUE_INIT;
-	char *s;
-
-	g_return_val_if_fail (setting, NULL);
-
-	if (   !NM_IS_SETTING_VPN (setting)
-	    && nm_setting_get_secret_flags (setting, name, NULL, NULL))
-		return g_strdup ("****");
-
-	if (!_nm_setting_get_property (setting, name, &val))
-		g_return_val_if_reached (FALSE);
-
-	if (G_VALUE_HOLDS_STRING (&val)) {
-		const char *val_s;
-
-		val_s = g_value_get_string (&val);
-		if (!val_s) {
-			/* for NULL, we want to return the unquoted string "NULL". */
-			s = g_strdup ("NULL");
-		} else {
-			char *escaped = g_strescape (val_s, "'");
-
-			s = g_strdup_printf ("'%s'", escaped);
-			g_free (escaped);
-		}
-	} else {
-		s = g_strdup_value_contents (&val);
-		if (s == NULL)
-			s = g_strdup ("NULL");
-		else {
-			char *escaped = g_strescape (s, "'");
-
-			g_free (s);
-			s = escaped;
-		}
-	}
-	g_value_unset(&val);
-	return s;
-}
-
-static void
-_log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sorted_names)
-{
-	GHashTableIter iter;
-	LogConnectionSettingItem item;
-	gpointer p;
-
-	g_array_set_size (sorted_names, 0);
-
-	g_hash_table_iter_init (&iter, setting_data->setting_diff);
-	while (g_hash_table_iter_next (&iter, (gpointer) &item.item_name, &p)) {
-		item.diff_result = GPOINTER_TO_UINT (p);
-		g_array_append_val (sorted_names, item);
-	}
-
-	g_array_sort (sorted_names, _log_connection_sort_names_fcn);
-}
-
-void
-nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix)
-{
-	GHashTable *connection_diff = NULL;
-	GArray *sorted_hashes;
-	GArray *sorted_names = NULL;
-	int i, j;
-	gboolean connection_diff_are_same;
-	gboolean print_header = TRUE;
-	gboolean print_setting_header;
-	GString *str1;
-
-	g_return_if_fail (NM_IS_CONNECTION (connection));
-	g_return_if_fail (!diff_base || (NM_IS_CONNECTION (diff_base) && diff_base != connection));
-
-	/* For VPN setting types, this is broken, because we cannot (generically) print the content of data/secrets. Bummer... */
-
-	if (!nm_logging_enabled (level, domain))
-		return;
-
-	if (!prefix)
-		prefix = "";
-	if (!name)
-		name = "";
-
-	connection_diff_are_same = nm_connection_diff (connection, diff_base, NM_SETTING_COMPARE_FLAG_EXACT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, &connection_diff);
-	if (connection_diff_are_same) {
-		if (diff_base)
-			nm_log (level, domain, "%sconnection '%s' (%p/%s and %p/%s): no difference", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base));
-		else
-			nm_log (level, domain, "%sconnection '%s' (%p/%s): no properties set", prefix, name, connection, G_OBJECT_TYPE_NAME (connection));
-		g_assert (!connection_diff);
-		return;
-	}
-
-	/* FIXME: it doesn't nicely show the content of NMSettingVpn, becuase nm_connection_diff() does not
-	 * expand the hash values. */
-
-	sorted_hashes = _log_connection_sort_hashes (connection, diff_base, connection_diff);
-	if (sorted_hashes->len <= 0)
-		goto out;
-
-	sorted_names = g_array_new (FALSE, FALSE, sizeof (LogConnectionSettingItem));
-	str1 = g_string_new (NULL);
-
-	for (i = 0; i < sorted_hashes->len; i++) {
-		LogConnectionSettingData *setting_data = &g_array_index (sorted_hashes, LogConnectionSettingData, i);
-
-		_log_connection_sort_names (setting_data, sorted_names);
-		print_setting_header = TRUE;
-		for (j = 0; j < sorted_names->len; j++) {
-			char *str_conn, *str_diff;
-			LogConnectionSettingItem *item = &g_array_index (sorted_names, LogConnectionSettingItem, j);
-
-			str_conn = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_A)
-			           ? _log_connection_get_property (setting_data->setting, item->item_name)
-			           : NULL;
-			str_diff = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_B)
-			           ? _log_connection_get_property (setting_data->diff_base_setting, item->item_name)
-			           : NULL;
-
-			if (print_header) {
-				GError *err_verify = NULL;
-				const char *path = nm_connection_get_path (connection);
-
-				if (diff_base) {
-					nm_log (level, domain, "%sconnection '%s' (%p/%s < %p/%s)%s%s%s:", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base),
-					        NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
-				} else {
-					nm_log (level, domain, "%sconnection '%s' (%p/%s):%s%s%s", prefix, name, connection, G_OBJECT_TYPE_NAME (connection),
-					        NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
-				}
-				print_header = FALSE;
-
-				if (!nm_connection_verify (connection, &err_verify)) {
-					nm_log (level, domain, "%sconnection %p does not verify: %s", prefix, connection, err_verify->message);
-					g_clear_error (&err_verify);
-				}
-			}
-#define _NM_LOG_ALIGN "-25"
-			if (print_setting_header) {
-				if (diff_base) {
-					if (setting_data->setting && setting_data->diff_base_setting)
-						g_string_printf (str1, "%p < %p", setting_data->setting, setting_data->diff_base_setting);
-					else if (setting_data->diff_base_setting)
-						g_string_printf (str1, "*missing* < %p", setting_data->diff_base_setting);
-					else
-						g_string_printf (str1, "%p < *missing*", setting_data->setting);
-					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %s ]", prefix, setting_data->name, str1->str);
-				} else
-					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %p ]", prefix, setting_data->name, setting_data->setting);
-				print_setting_header = FALSE;
-			}
-			g_string_printf (str1, "%s.%s", setting_data->name, item->item_name);
-			switch (item->diff_result & (NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B)) {
-				case NM_SETTING_DIFF_RESULT_IN_B:
-					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s < %s", prefix, str1->str, str_diff ? str_diff : "NULL");
-					break;
-				case NM_SETTING_DIFF_RESULT_IN_A:
-					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s", prefix, str1->str, str_conn ? str_conn : "NULL");
-					break;
-				default:
-					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s < %s", prefix, str1->str, str_conn ? str_conn : "NULL", str_diff ? str_diff : "NULL");
-					break;
-#undef _NM_LOG_ALIGN
-			}
-			g_free (str_conn);
-			g_free (str_diff);
-		}
-	}
-
-	g_array_free (sorted_names, TRUE);
-	g_string_free (str1, TRUE);
-out:
-	g_hash_table_destroy (connection_diff);
-	g_array_free (sorted_hashes, TRUE);
-}
-
-/**
- * nm_utils_monotonic_timestamp_as_boottime:
- * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME.
- * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if
- * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano
- * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc.
- *
- * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime().
- * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick.
- * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds.
- * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp
- * is always positive.
- *
- * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC.
- **/
-gint64
-nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick)
-{
-	gint64 offset;
-
-	/* only support ns-per-tick being a multiple of 10. */
-	g_return_val_if_fail (timestamp_ns_per_tick == 1
-	                      || (timestamp_ns_per_tick > 0 &&
-	                          timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND &&
-	                          timestamp_ns_per_tick % 10 == 0),
-	                      -1);
-
-	/* Check that the timestamp is in a valid range. */
-	g_return_val_if_fail (timestamp >= 0, -1);
-
-	/* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful
-	 * value (because he has no idea what these timestamps would be). That would be a bug. */
-	g_return_val_if_fail (monotonic_timestamp_clock_mode != 0, -1);
-
-	/* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
-	offset = monotonic_timestamp_offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick);
-
-	/* check for overflow. */
-	g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64);
-
-	return timestamp - offset;
-}
-
-
-#define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/"
-#define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/"
-G_STATIC_ASSERT (sizeof (IPV4_PROPERTY_DIR) == sizeof (IPV6_PROPERTY_DIR));
-
-static const char *
-_get_property_path (const char *ifname,
-                    const char *property,
-                    gboolean ipv6)
-{
-	static char path[sizeof (IPV6_PROPERTY_DIR) + IFNAMSIZ + 32];
-	int len;
-
-	ifname = ASSERT_VALID_PATH_COMPONENT (ifname);
-	property = ASSERT_VALID_PATH_COMPONENT (property);
-
-	len = g_snprintf (path,
-	                  sizeof (path),
-	                  "%s%s/%s",
-	                  ipv6 ? IPV6_PROPERTY_DIR : IPV4_PROPERTY_DIR,
-	                  ifname,
-	                  property);
-	g_assert (len < sizeof (path) - 1);
-
-	return path;
-}
-
-/**
- * nm_utils_ip6_property_path:
- * @ifname: an interface name
- * @property: a property name
- *
- * Returns the path to IPv6 property @property on @ifname. Note that
- * this uses a static buffer.
- */
-const char *
-nm_utils_ip6_property_path (const char *ifname, const char *property)
-{
-	return _get_property_path (ifname, property, TRUE);
-}
-
-/**
- * nm_utils_ip4_property_path:
- * @ifname: an interface name
- * @property: a property name
- *
- * Returns the path to IPv4 property @property on @ifname. Note that
- * this uses a static buffer.
- */
-const char *
-nm_utils_ip4_property_path (const char *ifname, const char *property)
-{
-	return _get_property_path (ifname, property, FALSE);
-}
-
-gboolean
-nm_utils_is_valid_path_component (const char *name)
-{
-	const char *n;
-
-	if (name == NULL || name[0] == '\0')
-		return FALSE;
-
-	if (name[0] == '.') {
-		if (name[1] == '\0')
-			return FALSE;
-		if (name[1] == '.' && name[2] == '\0')
-			return FALSE;
-	}
-	n = name;
-	do {
-		if (*n == '/')
-			return FALSE;
-	} while (*(++n) != '\0');
-
-	return TRUE;
-}
-
-const char *
-ASSERT_VALID_PATH_COMPONENT (const char *name)
-{
-	if (G_LIKELY (nm_utils_is_valid_path_component (name)))
-		return name;
-
-	nm_log_err (LOGD_CORE, "Failed asserting path component: %s%s%s",
-	            NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
-	g_error ("FATAL: Failed asserting path component: %s%s%s",
-	         NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
-	g_assert_not_reached ();
-}
-
-gboolean
-nm_utils_is_specific_hostname (const char *name)
-{
-	if (!name)
-		return FALSE;
-	if (   strcmp (name, "(none)")
-	    && strcmp (name, "localhost")
-	    && strcmp (name, "localhost6")
-	    && strcmp (name, "localhost.localdomain")
-	    && strcmp (name, "localhost6.localdomain6"))
-		return TRUE;
-	return FALSE;
-}
-
-/******************************************************************/
-
-/* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
-static gboolean
-get_gre_eui64_u_bit (guint32 addr)
-{
-	static const struct {
-		guint32 mask;
-		guint32 result;
-	} items[] = {
-		{ 0xff000000 }, { 0x7f000000 },  /* IPv4 loopback */
-		{ 0xf0000000 }, { 0xe0000000 },  /* IPv4 multicast */
-		{ 0xffffff00 }, { 0xe0000000 },  /* IPv4 local multicast */
-		{ 0xffffffff }, { INADDR_BROADCAST },  /* limited broadcast */
-		{ 0xff000000 }, { 0x00000000 },  /* zero net */
-		{ 0xff000000 }, { 0x0a000000 },  /* private 10 (RFC3330) */
-		{ 0xfff00000 }, { 0xac100000 },  /* private 172 */
-		{ 0xffff0000 }, { 0xc0a80000 },  /* private 192 */
-		{ 0xffff0000 }, { 0xa9fe0000 },  /* IPv4 link-local */
-		{ 0xffffff00 }, { 0xc0586300 },  /* anycast 6-to-4 */
-		{ 0xffffff00 }, { 0xc0000200 },  /* test 192 */
-		{ 0xfffe0000 }, { 0xc6120000 },  /* test 198 */
-	};
-	guint i;
-
-	for (i = 0; i < G_N_ELEMENTS (items); i++) {
-		if ((addr & htonl (items[i].mask)) == htonl (items[i].result))
-			return 0x00; /* "local" scope */
-	}
-	return 0x02; /* "universal" scope */
-}
-
-/**
- * nm_utils_get_ipv6_interface_identifier:
- * @link_type: the hardware link type
- * @hwaddr: the hardware address of the interface
- * @hwaddr_len: the length (in bytes) of @hwaddr
- * @dev_id: the device identifier, if any
- * @out_iid: on success, filled with the interface identifier; on failure
- * zeroed out
- *
- * Constructs an interface identifier in "Modified EUI-64" format which is
- * suitable for constructing IPv6 addresses.  Note that the identifier is
- * not obscured in any way (eg, RFC3041).
- *
- * Returns: %TRUE if the interface identifier could be constructed, %FALSE if
- * if could not be constructed.
- */
-gboolean
-nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
-                                        const guint8 *hwaddr,
-                                        guint hwaddr_len,
-                                        guint dev_id,
-                                        NMUtilsIPv6IfaceId *out_iid)
-{
-	guint32 addr;
-
-	g_return_val_if_fail (hwaddr != NULL, FALSE);
-	g_return_val_if_fail (hwaddr_len > 0, FALSE);
-	g_return_val_if_fail (out_iid != NULL, FALSE);
-
-	out_iid->id = 0;
-
-	switch (link_type) {
-	case NM_LINK_TYPE_INFINIBAND:
-		/* Use the port GUID per http://tools.ietf.org/html/rfc4391#section-8,
-		 * making sure to set the 'u' bit to 1.  The GUID is the lower 64 bits
-		 * of the IPoIB interface's hardware address.
-		 */
-		g_return_val_if_fail (hwaddr_len == INFINIBAND_ALEN, FALSE);
-		memcpy (out_iid->id_u8, hwaddr + INFINIBAND_ALEN - 8, 8);
-		out_iid->id_u8[0] |= 0x02;
-		return TRUE;
-	case NM_LINK_TYPE_GRE:
-	case NM_LINK_TYPE_GRETAP:
-		/* Hardware address is the network-endian IPv4 address */
-		g_return_val_if_fail (hwaddr_len == 4, FALSE);
-		addr = * (guint32 *) hwaddr;
-		out_iid->id_u8[0] = get_gre_eui64_u_bit (addr);
-		out_iid->id_u8[1] = 0x00;
-		out_iid->id_u8[2] = 0x5E;
-		out_iid->id_u8[3] = 0xFE;
-		memcpy (out_iid->id_u8 + 4, &addr, 4);
-		return TRUE;
-	default:
-		if (hwaddr_len == ETH_ALEN) {
-			/* Translate 48-bit MAC address to a 64-bit Modified EUI-64.  See
-			 * http://tools.ietf.org/html/rfc4291#appendix-A and the Linux
-			 * kernel's net/ipv6/addrconf.c::ipv6_generate_eui64() function.
-			 */
-			out_iid->id_u8[0] = hwaddr[0];
-			out_iid->id_u8[1] = hwaddr[1];
-			out_iid->id_u8[2] = hwaddr[2];
-			if (dev_id) {
-				out_iid->id_u8[3] = (dev_id >> 8) & 0xff;
-				out_iid->id_u8[4] = dev_id & 0xff;
-			} else {
-				out_iid->id_u8[0] ^= 0x02;
-				out_iid->id_u8[3] = 0xff;
-				out_iid->id_u8[4] = 0xfe;
-			}
-			out_iid->id_u8[5] = hwaddr[3];
-			out_iid->id_u8[6] = hwaddr[4];
-			out_iid->id_u8[7] = hwaddr[5];
-			return TRUE;
-		}
-		break;
-	}
-	return FALSE;
-}
-void
-nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
-                                            const NMUtilsIPv6IfaceId iid)
-{
-	memcpy (addr->s6_addr + 8, &iid.id_u8, 8);
-}
-
-void
-nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
-                                                 const struct in6_addr *addr)
-{
-	memcpy (iid, addr->s6_addr + 8, 8);
-}
-
-static gboolean
-_set_stable_privacy (struct in6_addr *addr,
-                     const char *ifname,
-                     const char *uuid,
-                     guint dad_counter,
-                     gchar *secret_key,
-                     gsize key_len,
-                     GError **error)
-{
-	GChecksum *sum;
-	guint8 digest[32];
-	guint32 tmp[2];
-	gsize len = sizeof (digest);
-
-	g_return_val_if_fail (key_len, FALSE);
-
-	/* Documentation suggests that this can fail.
-	 * Maybe in case of a missing algorithm in crypto library? */
-	sum = g_checksum_new (G_CHECKSUM_SHA256);
-	if (!sum) {
-		g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		                     "Can't create a SHA256 hash");
-		return FALSE;
-	}
-
-	key_len = MIN (key_len, G_MAXUINT32);
-
-	g_checksum_update (sum, addr->s6_addr, 8);
-	g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
-	if (!uuid)
-		uuid = "";
-	g_checksum_update (sum, (const guchar *) uuid, strlen (uuid) + 1);
-	tmp[0] = htonl (dad_counter);
-	tmp[1] = htonl (key_len);
-	g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
-	g_checksum_update (sum, (const guchar *) secret_key, key_len);
-
-	g_checksum_get_digest (sum, digest, &len);
-	g_checksum_free (sum);
-
-	g_return_val_if_fail (len == 32, FALSE);
-
-	memcpy (addr->s6_addr + 8, &digest[0], 8);
-
-	return TRUE;
-}
-
-#define RFC7217_IDGEN_RETRIES 3
-/**
- * nm_utils_ipv6_addr_set_stable_privacy:
- *
- * Extend the address prefix with an interface identifier using the
- * RFC 7217 Stable Privacy mechanism.
- *
- * Returns: %TRUE on success, %FALSE if the address could not be generated.
- */
-gboolean
-nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
-                                       const char *ifname,
-                                       const char *uuid,
-                                       guint dad_counter,
-                                       GError **error)
-{
-	gchar *secret_key = NULL;
-	gsize key_len = 0;
-	gboolean success = FALSE;
-
-	if (dad_counter >= RFC7217_IDGEN_RETRIES) {
-		g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		                     "Too many DAD collisions");
-		return FALSE;
-	}
-
-	/* Let's try to load a saved secret key first. */
-	if (g_file_get_contents (NMSTATEDIR "/secret_key", &secret_key, &key_len, NULL)) {
-		if (key_len < 16) {
-			g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-			                     "Key is too short to be usable");
-			key_len = 0;
-		}
-	} else {
-		int urandom = open ("/dev/urandom", O_RDONLY);
-		mode_t key_mask;
-
-		if (!urandom) {
-			g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-			             "Can't open /dev/urandom: %s", strerror (errno));
-			return FALSE;
-		}
-
-		/* RFC7217 mandates the key SHOULD be at least 128 bits.
-		 * Let's use twice as much. */
-		key_len = 32;
-		secret_key = g_malloc (key_len);
-
-		key_mask = umask (0077);
-		if (read (urandom, secret_key, key_len) == key_len) {
-			if (!g_file_set_contents (NMSTATEDIR "/secret_key", secret_key, key_len, error)) {
-				g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key");
-				key_len = 0;
-			}
-		} else {
-			g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-			                     "Could not obtain a secret");
-			key_len = 0;
-		}
-		umask (key_mask);
-		close (urandom);
-	}
-
-	if (key_len) {
-		success = _set_stable_privacy (addr, ifname, uuid, dad_counter,
-		                               secret_key, key_len, error);
-	}
-
-	g_free (secret_key);
-	return success;
-}
-
-/**
- * nm_utils_setpgid:
- * @unused: unused
- *
- * This can be passed as a child setup function to the g_spawn*() family
- * of functions, to ensure that the child is in its own process group
- * (and thus, in some situations, will not be killed when NetworkManager
- * is killed).
- */
-void
-nm_utils_setpgid (gpointer unused G_GNUC_UNUSED)
-{
-	pid_t pid;
-
-	pid = getpid ();
-	setpgid (pid, pid);
-}
+/******************************************************************************/
 
 /**
  * nm_utils_g_value_set_object_path:
@@ -3523,23 +785,4 @@ nm_utils_g_value_set_object_path_array (GValue *value,
 	g_value_take_boxed (value, paths);
 }
 
-/**
- * nm_utils_g_value_set_strv:
- * @value: a #GValue, initialized to store a #G_TYPE_STRV
- * @strings: a #GPtrArray of strings
- *
- * Converts @strings to a #GStrv and stores it in @value.
- */
-void
-nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings)
-{
-	char **strv;
-	int i;
-
-	strv = g_new (char *, strings->len + 1);
-	for (i = 0; i < strings->len; i++)
-		strv[i] = g_strdup (strings->pdata[i]);
-	strv[i] = NULL;
-
-	g_value_take_boxed (value, strv);
-}
+/******************************************************************************/
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index acd3d55a..b3c384da 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -15,296 +15,19 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2004 - 2014 Red Hat, Inc.
+ * Copyright 2004 - 2016 Red Hat, Inc.
  * Copyright 2005 - 2008 Novell, Inc.
  */
 
 #ifndef __NETWORKMANAGER_UTILS_H__
 #define __NETWORKMANAGER_UTILS_H__
 
-#include <stdio.h>
-#include <arpa/inet.h>
-
-#include "nm-default.h"
-#include "nm-connection.h"
-
-/*****************************************************************************/
-
-#define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \
-static TYPE *singleton_instance
-
-#define NM_DEFINE_SINGLETON_REGISTER(TYPE) \
-NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
-static void \
-_singleton_instance_weak_ref_cb (gpointer data, \
-                                 GObject *where_the_object_was) \
-{ \
-	nm_log_dbg (LOGD_CORE, "disposing %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
-	singleton_instance = NULL; \
-} \
-static inline void \
-nm_singleton_instance_register (void) \
-{ \
-	g_object_weak_ref (G_OBJECT (singleton_instance), _singleton_instance_weak_ref_cb, NULL); \
-	_nm_singleton_instance_register_destruction (G_OBJECT (singleton_instance)); \
-}
-
-void _nm_singleton_instance_register_destruction (GObject *instance);
-
-/* By default, the getter will assert that the singleton will be created only once. You can
- * change this by redefining NM_DEFINE_SINGLETON_ALLOW_MULTIPLE. */
-#ifndef NM_DEFINE_SINGLETON_ALLOW_MULTIPLE
-#define NM_DEFINE_SINGLETON_ALLOW_MULTIPLE     FALSE
-#endif
-
-#define NM_DEFINE_SINGLETON_GETTER(TYPE, GETTER, GTYPE, ...) \
-NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
-NM_DEFINE_SINGLETON_REGISTER (TYPE); \
-TYPE * \
-GETTER (void) \
-{ \
-	if (G_UNLIKELY (!singleton_instance)) { \
-		static char _already_created = FALSE; \
-\
-		g_assert (!_already_created || (NM_DEFINE_SINGLETON_ALLOW_MULTIPLE)); \
-		_already_created = TRUE;\
-		singleton_instance = (g_object_new (GTYPE, ##__VA_ARGS__, NULL)); \
-		g_assert (singleton_instance); \
-		nm_singleton_instance_register (); \
-		nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
-	} \
-	return singleton_instance; \
-}
-
-/* attach @instance to the data or @owner. @owner owns a reference
- * to @instance thus the lifetime of @instance is at least as long
- * as that of @owner. Use this when @owner depends on @instance. */
-#define NM_UTILS_KEEP_ALIVE(owner, instance, unique_token) \
-    G_STMT_START { \
-         g_object_set_data_full (G_OBJECT (owner), \
-                                 ".nm-utils-keep-alive-" unique_token "", \
-                                 g_object_ref (instance), \
-                                 g_object_unref); \
-    } G_STMT_END
-
-/*****************************************************************************/
-
-/**
- * NMUtilsError:
- * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
- * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
- *   pending aynchronous operations, the operation is cancelled with this
- *   error reason. Depending on the usage, this might indicate a bug because
- *   usually the target object should stay alive as long as there are pending
- *   operations.
- */
-typedef enum {
-	NM_UTILS_ERROR_UNKNOWN = 0,                 /*< nick=Unknown >*/
-	NM_UTILS_ERROR_CANCELLED_DISPOSING,         /*< nick=CancelledDisposing >*/
-} NMUtilsError;
-
-#define NM_UTILS_ERROR (nm_utils_error_quark ())
-GQuark nm_utils_error_quark (void);
-
-void nm_utils_error_set_cancelled (GError **error,
-                                   gboolean is_disposing,
-                                   const char *instance_name);
-gboolean nm_utils_error_is_cancelled (GError *error,
-                                      gboolean consider_is_disposing);
-
-/*****************************************************************************/
-
-gint nm_utils_ascii_str_to_bool (const char *str,
-                                 gint default_value);
-
-/*****************************************************************************/
-
-gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
-
-in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
-const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
-
-/**
- * nm_utils_ip6_route_metric_normalize:
- * @metric: the route metric
- *
- * For IPv6 route, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
- * Thus, when comparing metric (values), we want to treat zero as NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6.
- *
- * Returns: @metric, if @metric is not zero, otherwise 1024.
- */
-static inline guint32
-nm_utils_ip6_route_metric_normalize (guint32 metric)
-{
-	return metric ? metric : 1024 /*NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6*/;
-}
-
-int nm_spawn_process (const char *args, GError **error);
-
-int nm_utils_modprobe (GError **error, gboolean suppress_error_loggin, const char *arg1, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * str_if_set:
- * @str: input string that will be returned if @str is not %NULL
- * @fallback: if @str is %NULL, return @fallback instead
- *
- * This utility function is useful when printing a string to avoid passing
- * %NULL. E.g. printf ("%s", str_if_set (get_string(), "(none)"));
- *
- * Returns: either @str or @fallback, depending on whether @str is %NULL.
- */
-static inline const char *
-str_if_set (const char *str, const char *fallback)
-{
-	return str ? str : fallback;
-}
-
-guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
-
-void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain,
-                                 const char *log_name, guint32 wait_before_kill_msec,
-                                 guint32 sleep_duration_msec, guint32 max_wait_msec);
-
-typedef void (*NMUtilsKillChildAsyncCb) (pid_t pid, gboolean success, int child_status, void *user_data);
-void nm_utils_kill_child_async (pid_t pid, int sig, guint64 log_domain, const char *log_name,
-                                guint32 wait_before_kill_msec,
-                                NMUtilsKillChildAsyncCb callback, void *user_data);
-gboolean nm_utils_kill_child_sync (pid_t pid, int sig, guint64 log_domain, const char *log_name,
-                                   int *child_status, guint32 wait_before_kill_msec,
-                                   guint32 sleep_duration_msec);
-
-const char *nm_utils_find_helper (const char *progname,
-                                  const char *try_first,
-                                  GError **error);
-
-typedef enum {
-	NM_MATCH_SPEC_NO_MATCH  = 0,
-	NM_MATCH_SPEC_MATCH     = 1,
-	NM_MATCH_SPEC_NEG_MATCH = 2,
-} NMMatchSpecMatchType;
-
-NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char *device_type);
-NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
-NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
-NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
-NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
-GSList *nm_match_spec_split (const char *value);
-char *nm_match_spec_join (GSList *specs);
-
-extern char _nm_utils_to_string_buffer[2096];
-
-void     nm_utils_to_string_buffer_init (char **buf, gsize *len);
-gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
+#include "nm-core-utils.h"
 
 /*****************************************************************************/
 
-typedef struct {
-	unsigned flag;
-	const char *name;
-} NMUtilsFlags2StrDesc;
-
-#define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
-
-#define _NM_UTILS_FLAGS2STR_DEFINE(scope, fcn_name, flags_type, ...) \
-scope const char * \
-fcn_name (flags_type flags, char *buf, gsize len) \
-{ \
-	static const NMUtilsFlags2StrDesc descs[] = { \
-		__VA_ARGS__ \
-	}; \
-	G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
-	return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
-};
-
-#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
-	_NM_UTILS_FLAGS2STR_DEFINE (, fcn_name, flags_type, __VA_ARGS__)
-#define NM_UTILS_FLAGS2STR_DEFINE_STATIC(fcn_name, flags_type, ...) \
-	_NM_UTILS_FLAGS2STR_DEFINE (static, fcn_name, flags_type, __VA_ARGS__)
-
-const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
-                                gsize n_descs,
-                                unsigned flags,
-                                char *buf,
-                                gsize len);
-
-/*****************************************************************************/
-
-typedef struct {
-	int value;
-	const char *name;
-} NMUtilsEnum2StrDesc;
-
-#define NM_UTILS_ENUM2STR(v, n) { .value = v, .name = ""n, }
-
-#define _NM_UTILS_ENUM2STR_DEFINE(scope, fcn_name, enum_type, ...) \
-scope const char * \
-fcn_name (enum_type val, char *buf, gsize len) \
-{ \
-	static const NMUtilsEnum2StrDesc descs[] = { \
-		__VA_ARGS__ \
-	}; \
-	G_STATIC_ASSERT (sizeof (enum_type) <= sizeof (int)); \
-	return nm_utils_enum2str (descs, G_N_ELEMENTS (descs), val, buf, len); \
-}
-
-#define NM_UTILS_ENUM2STR_DEFINE(fcn_name, enum_type, ...) \
-	_NM_UTILS_ENUM2STR_DEFINE (, fcn_name, enum_type, __VA_ARGS__)
-#define NM_UTILS_ENUM2STR_DEFINE_STATIC(fcn_name, enum_type, ...) \
-	_NM_UTILS_ENUM2STR_DEFINE (static, fcn_name, enum_type, __VA_ARGS__)
-
-const char *nm_utils_enum2str (const NMUtilsEnum2StrDesc *descs,
-                               gsize n_descs,
-                               int val,
-                               char *buf,
-                               gsize len);
-
-/*****************************************************************************/
-
-#define _NM_UTILS_STRING_LOOKUP_TABLE_DEFINE(scope, fcn_name, lookup_type, unknown_val, ...) \
-scope const char * \
-fcn_name (lookup_type idx) \
-{ \
-	static const char *const descs[] = { \
-		__VA_ARGS__ \
-	}; \
-	if ((gssize) idx >= 0 && idx < G_N_ELEMENTS (descs)) \
-		return descs[idx]; \
-	return unknown_val; \
-}
-
-#define NM_UTILS_STRING_LOOKUP_TABLE_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
-	_NM_UTILS_STRING_LOOKUP_TABLE_DEFINE (, fcn_name, lookup_type, unknown_val, __VA_ARGS__)
-#define NM_UTILS_STRING_LOOKUP_TABLE_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
-	_NM_UTILS_STRING_LOOKUP_TABLE_DEFINE (static, fcn_name, lookup_type, unknown_val, __VA_ARGS__)
-
-/* Call the string-lookup-table function @fcn_name. If the function returns
- * %NULL, the numeric index is converted to string using a alloca() buffer.
- * Beware: this macro uses alloca(). */
-#define NM_UTILS_STRING_LOOKUP_TABLE(fcn_name, idx) \
-	({ \
-		typeof (idx) _idx = (idx); \
-		const char *_s; \
-		\
-		_s = fcn_name (_idx); \
-		if (!_s) { \
-			_s = g_alloca (30); \
-			\
-			g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
-		} \
-		_s; \
-	})
-
-/*****************************************************************************/
-
-void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) __attribute__((__format__ (__printf__, 3, 4)));
-void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
-void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
-
 const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);
 
-const char *nm_utils_get_ip_config_method (NMConnection *connection,
-                                           GType         ip_setting_type);
-
 void nm_utils_complete_generic (NMConnection *connection,
                                 const char *ctype,
                                 const GSList *existing,
@@ -313,101 +36,17 @@ void nm_utils_complete_generic (NMConnection *connection,
                                 const char *ifname_prefix,
                                 gboolean default_enable_ipv6);
 
-char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id);
-
-GPtrArray *nm_utils_read_resolv_conf_nameservers (const char *rc_contents);
-GPtrArray *nm_utils_read_resolv_conf_dns_options (const char *rc_contents);
-
 typedef gboolean (NMUtilsMatchFilterFunc) (NMConnection *connection, gpointer user_data);
 
 NMConnection *nm_utils_match_connection (GSList *connections,
                                          NMConnection *original,
                                          gboolean device_has_carrier,
+                                         gint64 default_v4_metric,
+                                         gint64 default_v6_metric,
                                          NMUtilsMatchFilterFunc match_filter_func,
                                          gpointer match_filter_data);
 
-int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b);
-
-void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
-
-#define NM_UTILS_NS_PER_SECOND  ((gint64) 1000000000)
-gint64 nm_utils_get_monotonic_timestamp_ns (void);
-gint64 nm_utils_get_monotonic_timestamp_us (void);
-gint64 nm_utils_get_monotonic_timestamp_ms (void);
-gint32 nm_utils_get_monotonic_timestamp_s (void);
-gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns);
-
-gboolean    nm_utils_is_valid_path_component (const char *name);
-const char *ASSERT_VALID_PATH_COMPONENT (const char *name);
-const char *nm_utils_ip6_property_path (const char *ifname, const char *property);
-const char *nm_utils_ip4_property_path (const char *ifname, const char *property);
-
-gboolean nm_utils_is_specific_hostname (const char *name);
-
-/* IPv6 Interface Identifer helpers */
-
-/**
- * NMUtilsIPv6IfaceId:
- * @id: convenience member for validity checking; never use directly
- * @id_u8: the 64-bit Interface Identifier
- *
- * Holds a 64-bit IPv6 Interface Identifier.  The IID is a sequence of bytes
- * and should not normally be treated as a %guint64, but this is done for
- * convenience of validity checking and initialization.
- */
-struct _NMUtilsIPv6IfaceId {
-	union {
-		guint64 id;
-		guint8  id_u8[8];
-	};
-};
-
-#define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } }
-
-gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
-                                                 const guint8 *hwaddr,
-                                                 guint len,
-                                                 guint dev_id,
-                                                 NMUtilsIPv6IfaceId *out_iid);
-
-void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
-                                                 const NMUtilsIPv6IfaceId iid);
-
-gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
-                                                const char *ifname,
-                                                const char *uuid,
-                                                guint dad_counter,
-                                                GError **error);
-
-void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
-                                                      const struct in6_addr *addr);
-
-void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
-
-void nm_utils_setpgid (gpointer unused);
-
-typedef enum {
-	NM_UTILS_TEST_NONE                              = 0,
-
-	/* Internal flag, marking that either nm_utils_get_testing() or _nm_utils_set_testing() was called. */
-	_NM_UTILS_TEST_INITIALIZED                      = (1LL << 0),
-
-	/* Indicate that test mode is enabled in general. Explicitly calling _nm_utils_set_testing() will always set this flag. */
-	_NM_UTILS_TEST_GENERAL                          = (1LL << 1),
-
-	/* Don't check the owner of keyfiles during testing. */
-	NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK            = (1LL << 2),
-
-	_NM_UTILS_TEST_LAST,
-	NM_UTILS_TEST_ALL                               = (((_NM_UTILS_TEST_LAST - 1) << 1) - 1) & ~(_NM_UTILS_TEST_INITIALIZED),
-} NMUtilsTestFlags;
-
-gboolean nm_utils_get_testing_initialized (void);
-NMUtilsTestFlags nm_utils_get_testing (void);
-void _nm_utils_set_testing (NMUtilsTestFlags flags);
-
 void nm_utils_g_value_set_object_path (GValue *value, gpointer object);
-void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings);
 
 /**
  * NMUtilsObjectFunc:
@@ -423,4 +62,6 @@ void nm_utils_g_value_set_object_path_array (GValue *value,
                                              NMUtilsObjectFunc filter_func,
                                              gpointer user_data);
 
+/*****************************************************************************/
+
 #endif /* __NETWORKMANAGER_UTILS_H__ */
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c
index d3f1423f..a3fa4901 100644
--- a/src/devices/adsl/nm-atm-manager.c
+++ b/src/devices/adsl/nm-atm-manager.c
@@ -18,13 +18,12 @@
  * Copyright (C) 2009 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <gudev/gudev.h>
 #include <gmodule.h>
 
-#include "nm-default.h"
 #include "nm-atm-manager.h"
 #include "nm-setting-adsl.h"
 #include "nm-device-adsl.h"
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c
index dd9a1203..e7a91e0a 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -18,7 +18,7 @@
  * Pantelis Koukousoulas <pktoss@gmail.com>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/socket.h>
 #include <linux/atmdev.h>
@@ -32,7 +32,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-device-adsl.h"
 #include "nm-device-private.h"
 #include "nm-enum-types.h"
@@ -449,7 +448,6 @@ act_stage3_ip4_config_start (NMDevice *device,
 {
 	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
 	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
-	NMConnection *connection;
 	NMSettingAdsl *s_adsl;
 	NMActRequest *req;
 	GError *err = NULL;
@@ -458,11 +456,7 @@ act_stage3_ip4_config_start (NMDevice *device,
 
 	req = nm_device_get_act_request (device);
 	g_assert (req);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_assert (req);
-
-	s_adsl = nm_connection_get_setting_adsl (connection);
+	s_adsl = (NMSettingAdsl *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_ADSL);
 	g_assert (s_adsl);
 
 	/* PPPoE uses the NAS interface, not the ATM interface */
diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h
index 4262fa76..67810b94 100644
--- a/src/devices/bluetooth/nm-bluez-common.h
+++ b/src/devices/bluetooth/nm-bluez-common.h
@@ -21,8 +21,6 @@
 #ifndef __NETWORKMANAGER_BLUEZ_COMMON_H__
 #define __NETWORKMANAGER_BLUEZ_COMMON_H__
 
-#include "config.h"
-
 #define BLUETOOTH_CONNECT_DUN "dun"
 #define BLUETOOTH_CONNECT_NAP "nap"
 
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index b7032143..71226813 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -19,11 +19,10 @@
  * Copyright (C) 2013 Intel Corporation.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-core-internal.h"
 
 #include "nm-bt-error.h"
@@ -1014,7 +1013,7 @@ nm_bluez_device_new (const char *path,
 	const char *interface_name = NULL;
 
 	g_return_val_if_fail (path != NULL, NULL);
-	g_return_val_if_fail (provider != NULL, NULL);
+	g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (provider), NULL);
 	g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL);
 
 	self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE,
@@ -1028,7 +1027,7 @@ nm_bluez_device_new (const char *path,
 	priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
 
 	priv->bluez_version = bluez_version;
-	priv->provider = provider;
+	priv->provider = g_object_ref (provider);
 	g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL);
 	if (adapter_address)
 		set_adapter_address (self, adapter_address);
@@ -1102,9 +1101,11 @@ dispose (GObject *object)
 	}
 #endif
 
-	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self);
-	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self);
-	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self);
+	if (priv->provider) {
+		g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self);
+		g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self);
+		g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self);
+	}
 
 	g_slist_free_full (priv->connections, g_object_unref);
 	priv->connections = NULL;
@@ -1120,6 +1121,8 @@ dispose (GObject *object)
 		nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL, NULL);
 		g_object_unref (to_delete);
 	}
+
+	g_clear_object (&priv->provider);
 }
 
 static void
diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h
index 0e54fcb0..c9560540 100644
--- a/src/devices/bluetooth/nm-bluez-device.h
+++ b/src/devices/bluetooth/nm-bluez-device.h
@@ -21,9 +21,6 @@
 #ifndef __NETWORKMANAGER_BLUEZ_DEVICE_H__
 #define __NETWORKMANAGER_BLUEZ_DEVICE_H__
 
-
-#include "config.h"
-#include "nm-default.h"
 #include "nm-connection.h"
 #include "nm-connection-provider.h"
 
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index 6903356c..f66b5abe 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -18,14 +18,13 @@
  * Copyright (C) 2013 - 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <signal.h>
 #include <string.h>
 #include <stdlib.h>
 #include <gmodule.h>
 
-#include "nm-default.h"
 #include "nm-bluez-manager.h"
 #include "nm-device-factory.h"
 #include "nm-setting-bluetooth.h"
@@ -397,6 +396,10 @@ dispose (GObject *object)
 	cleanup_checking (self, TRUE);
 
 	priv->bluez_version = 0;
+
+	g_clear_object (&priv->provider);
+
+	G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object);
 }
 
 static void
@@ -404,8 +407,7 @@ nm_bluez_manager_init (NMBluezManager *self)
 {
 	NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self);
 
-	priv->provider = nm_connection_provider_get ();
-	g_assert (priv->provider);
+	priv->provider = g_object_ref (nm_connection_provider_get ());
 }
 
 static NMDevice *
diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c
index 04ae833a..deeebcb6 100644
--- a/src/devices/bluetooth/nm-bluez4-adapter.c
+++ b/src/devices/bluetooth/nm-bluez4-adapter.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2009 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-bluez4-adapter.h"
 #include "nm-bluez-device.h"
diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c
index c5ba120c..146612a8 100644
--- a/src/devices/bluetooth/nm-bluez4-manager.c
+++ b/src/devices/bluetooth/nm-bluez4-manager.c
@@ -19,13 +19,12 @@
  * Copyright (C) 2007 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <signal.h>
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-bluez-manager.h"
 #include "nm-bluez4-manager.h"
 #include "nm-bluez4-adapter.h"
diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c
index 875a662f..4c93feba 100644
--- a/src/devices/bluetooth/nm-bluez5-dun.c
+++ b/src/devices/bluetooth/nm-bluez5-dun.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/socket.h>
 #include <bluetooth/sdp.h>
@@ -32,7 +32,6 @@
 
 #include "nm-bluez5-dun.h"
 #include "nm-bt-error.h"
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 
 struct _NMBluez5DunContext {
diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c
index c9f5828d..e44e87d8 100644
--- a/src/devices/bluetooth/nm-bluez5-manager.c
+++ b/src/devices/bluetooth/nm-bluez5-manager.c
@@ -20,13 +20,12 @@
  * Copyright (C) 2013 Intel Corporation.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <signal.h>
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-bluez-manager.h"
 #include "nm-bluez5-manager.h"
 #include "nm-bluez-device.h"
diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c
index 9c35d8b6..18391187 100644
--- a/src/devices/bluetooth/nm-bt-error.c
+++ b/src/devices/bluetooth/nm-bt-error.c
@@ -18,9 +18,8 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
-
 #include "nm-default.h"
+
 #include "nm-bt-error.h"
 
 GQuark
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c
index 1e3f9cdc..e151b795 100644
--- a/src/devices/bluetooth/nm-device-bt.c
+++ b/src/devices/bluetooth/nm-device-bt.c
@@ -18,12 +18,11 @@
  * Copyright (C) 2009 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-bluez-common.h"
 #include "nm-bluez-device.h"
 #include "nm-device-bt.h"
diff --git a/src/devices/nm-arping-manager.c b/src/devices/nm-arping-manager.c
new file mode 100644
index 00000000..dfb20b4b
--- /dev/null
+++ b/src/devices/nm-arping-manager.c
@@ -0,0 +1,449 @@
+/* -*- 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.
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "nm-arping-manager.h"
+#include "nm-platform.h"
+#include "nm-utils.h"
+#include "NetworkManagerUtils.h"
+
+typedef enum {
+	STATE_INIT,
+	STATE_PROBING,
+	STATE_PROBE_DONE,
+	STATE_ANNOUNCING,
+} State;
+
+typedef struct {
+	int            ifindex;
+	State          state;
+	GHashTable    *addresses;
+	guint          completed;
+	guint          timer;
+	guint          round2_id;
+} NMArpingManagerPrivate;
+
+typedef struct {
+	in_addr_t address;
+	GPid pid;
+	guint watch;
+	gboolean duplicate;
+	NMArpingManager *manager;
+} AddressInfo;
+
+enum {
+	PROBE_TERMINATED,
+	LAST_SIGNAL,
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (NMArpingManager, nm_arping_manager, G_TYPE_OBJECT)
+
+#define NM_ARPING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ARPING_MANAGER, NMArpingManagerPrivate))
+
+#define _NMLOG_DOMAIN         LOGD_IP4
+#define _NMLOG_PREFIX_NAME    "arping"
+#define _NMLOG(level, ...) \
+    G_STMT_START { \
+        char _sbuf[64]; \
+        \
+        nm_log ((level), _NMLOG_DOMAIN, \
+                "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
+                _NMLOG_PREFIX_NAME, \
+                self ? nm_sprintf_buf (_sbuf, "[%p,%d]", \
+                                       self, \
+                                       NM_ARPING_MANAGER_GET_PRIVATE (self)->ifindex) : "" \
+                _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+    } G_STMT_END
+
+/**
+ * nm_arping_manager_add_address:
+ * @self: a #NMArpingManager
+ * @address: an IP address
+ *
+ * Add @address to the list of IP addresses to probe.
+
+ * Returns: %TRUE on success, %FALSE if the address was already in the list
+ */
+gboolean
+nm_arping_manager_add_address (NMArpingManager *self, in_addr_t address)
+{
+	NMArpingManagerPrivate *priv;
+	AddressInfo *info;
+
+	g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE);
+	priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	g_return_val_if_fail (priv->state == STATE_INIT, FALSE);
+
+	if (g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address))) {
+		_LOGD ("address already exists");
+		return FALSE;
+	}
+
+	info = g_slice_new0 (AddressInfo);
+	info->address = address;
+	info->manager = self;
+
+	g_hash_table_insert (priv->addresses, GUINT_TO_POINTER (address), info);
+
+	return TRUE;
+}
+
+static void
+arping_watch_cb (GPid pid, gint status, gpointer user_data)
+{
+	AddressInfo *info = user_data;
+	NMArpingManager *self = info->manager;
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	const char *addr;
+
+	info->pid = 0;
+	info->watch = 0;
+	addr = nm_utils_inet4_ntop (info->address, NULL);
+
+	if (WIFEXITED (status)) {
+		if (WEXITSTATUS (status) != 0) {
+			_LOGD ("%s already used in the %s network",
+			       addr, nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex));
+			info->duplicate = TRUE;
+		} else
+			_LOGD ("DAD succeeded for %s", addr);
+	} else {
+		_LOGD ("stopped unexpectedly with status %d for %s", status, addr);
+	}
+
+	if (++priv->completed == g_hash_table_size (priv->addresses)) {
+		priv->state = STATE_PROBE_DONE;
+		nm_clear_g_source (&priv->timer);
+		g_signal_emit (self, signals[PROBE_TERMINATED], 0);
+	}
+}
+
+static gboolean
+arping_timeout_cb (gpointer user_data)
+{
+	NMArpingManager *self = user_data;
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	GHashTableIter iter;
+	AddressInfo *info;
+
+	priv->timer = 0;
+
+	g_hash_table_iter_init (&iter, priv->addresses);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) {
+		nm_clear_g_source (&info->watch);
+		if (info->pid) {
+			_LOGD ("DAD timed out for %s",
+			       nm_utils_inet4_ntop (info->address, NULL));
+			nm_utils_kill_child_async (info->pid, SIGTERM, LOGD_IP4,
+			                           "arping", 1000, NULL, NULL);
+			info->pid = 0;
+		}
+	}
+
+	priv->state = STATE_PROBE_DONE;
+	g_signal_emit (self, signals[PROBE_TERMINATED], 0);
+
+	return G_SOURCE_REMOVE;
+}
+
+/**
+ * nm_arping_manager_start_probe:
+ * @self: a #NMArpingManager
+ * @timeout: maximum probe duration in milliseconds
+ * @error: location to store error, or %NULL
+ *
+ * Start probing IP addresses for duplicates; when the probe terminates a
+ * PROBE_TERMINATED signal is emitted.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ */
+gboolean
+nm_arping_manager_start_probe (NMArpingManager *self, guint timeout, GError **error)
+{
+	const char *argv[] = { NULL, "-D", "-q", "-I", NULL, "-c", NULL, "-w", NULL, NULL, NULL };
+	NMArpingManagerPrivate *priv;
+	GHashTableIter iter;
+	AddressInfo *info;
+	gs_free char *timeout_str = NULL;
+
+	g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE);
+	g_return_val_if_fail (!error || !*error, FALSE);
+	g_return_val_if_fail (timeout, FALSE);
+
+	priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	g_return_val_if_fail (priv->state == STATE_INIT, FALSE);
+
+	argv[4] = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex);
+	if (!argv[4]) {
+		/* The device was probably just removed. */
+		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+		             "can't find a name for ifindex %d", priv->ifindex);
+		return FALSE;
+	}
+
+	priv->completed = 0;
+
+	argv[0] = nm_utils_find_helper ("arping", NULL, NULL);
+	if (!argv[0]) {
+		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+		                     "arping could not be found");
+		return FALSE;
+	}
+
+	timeout_str = g_strdup_printf ("%u", timeout / 1000 + 2);
+	argv[6] = timeout_str;
+	argv[8] = timeout_str;
+
+	g_hash_table_iter_init (&iter, priv->addresses);
+
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) {
+		gs_free char *tmp_str = NULL;
+		gboolean success;
+
+		argv[9] = nm_utils_inet4_ntop (info->address, NULL);
+		_LOGD ("run %s", (tmp_str = g_strjoinv (" ", (char **) argv)));
+
+		success = g_spawn_async (NULL, (char **) argv, NULL,
+		                         G_SPAWN_STDOUT_TO_DEV_NULL |
+		                         G_SPAWN_STDERR_TO_DEV_NULL |
+		                         G_SPAWN_DO_NOT_REAP_CHILD,
+		                         NULL, NULL, &info->pid, NULL);
+
+		info->watch = g_child_watch_add (info->pid, arping_watch_cb, info);
+	}
+
+	priv->timer = g_timeout_add (timeout, arping_timeout_cb, self);
+	priv->state = STATE_PROBING;
+
+	return TRUE;
+}
+
+/**
+ * nm_arping_manager_reset:
+ * @self: a #NMArpingManager
+ *
+ * Stop any operation in progress and reset @self to the initial state.
+ */
+void
+nm_arping_manager_reset (NMArpingManager *self)
+{
+	NMArpingManagerPrivate *priv;
+
+	g_return_if_fail (NM_IS_ARPING_MANAGER (self));
+	priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+
+	nm_clear_g_source (&priv->timer);
+	nm_clear_g_source (&priv->round2_id);
+	g_hash_table_remove_all (priv->addresses);
+
+	priv->state = STATE_INIT;
+}
+
+/**
+ * nm_arping_manager_destroy:
+ * @self: the #NMArpingManager
+ *
+ * Calls nm_arping_manager_reset() and unrefs @self.
+ */
+void
+nm_arping_manager_destroy (NMArpingManager *self)
+{
+	g_return_if_fail (NM_IS_ARPING_MANAGER (self));
+
+	nm_arping_manager_reset (self);
+	g_object_unref (self);
+}
+
+/**
+ * nm_arping_manager_check_address:
+ * @self: a #NMArpingManager
+ * @address: an IP address
+ *
+ * Check if an IP address is duplicate. @address must have been added with
+ * nm_arping_manager_add_address().
+ *
+ * Returns: %TRUE if the address is not duplicate, %FALSE otherwise
+ */
+gboolean
+nm_arping_manager_check_address (NMArpingManager *self, in_addr_t address)
+{
+	NMArpingManagerPrivate *priv;
+	AddressInfo *info;
+
+	g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE);
+	priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	g_return_val_if_fail (   priv->state == STATE_INIT
+	                      || priv->state == STATE_PROBE_DONE, FALSE);
+
+	info = g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address));
+	g_return_val_if_fail (info, FALSE);
+
+	return !info->duplicate;
+}
+
+static void
+send_announcements (NMArpingManager *self, const char *mode_arg)
+{
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	const char *argv[] = { NULL, mode_arg, "-q", "-I", NULL, "-c", "1", NULL, NULL };
+	int ip_arg = G_N_ELEMENTS (argv) - 2;
+	GError *error = NULL;
+	GHashTableIter iter;
+	AddressInfo *info;
+
+	argv[4] = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex);
+	if (!argv[4]) {
+		/* The device was probably just removed. */
+		_LOGW ("can't find a name for ifindex %d", priv->ifindex);
+		return;
+	}
+
+	argv[0] = nm_utils_find_helper ("arping", NULL, NULL);
+	if (!argv[0]) {
+		_LOGW ("arping could not be found; no ARPs will be sent");
+		return;
+	}
+
+	g_hash_table_iter_init (&iter, priv->addresses);
+
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) {
+		gs_free char *tmp_str = NULL;
+		gboolean success;
+
+		if (info->duplicate)
+			continue;
+
+		argv[ip_arg] = nm_utils_inet4_ntop (info->address, NULL);
+		_LOGD ("run %s", (tmp_str = g_strjoinv (" ", (char **) argv)));
+
+		success = g_spawn_async (NULL, (char **) argv, NULL,
+		                         G_SPAWN_STDOUT_TO_DEV_NULL |
+		                         G_SPAWN_STDERR_TO_DEV_NULL,
+		                         NULL, NULL, NULL, &error);
+		if (!success) {
+			_LOGW ("could not send ARP for address %s: %s", argv[ip_arg],
+			       error->message);
+			g_clear_error (&error);
+		}
+	}
+}
+
+static gboolean
+arp_announce_round2 (gpointer self)
+{
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+
+	priv->round2_id = 0;
+	send_announcements (self, "-U");
+	priv->state = STATE_INIT;
+	g_hash_table_remove_all (priv->addresses);
+
+	return G_SOURCE_REMOVE;
+}
+
+/**
+ * nm_arping_manager_announce_addresses:
+ * @self: a #NMArpingManager
+ *
+ * Start announcing addresses.
+ */
+void
+nm_arping_manager_announce_addresses (NMArpingManager *self)
+{
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+
+	g_return_if_fail (   priv->state == STATE_INIT
+	                  || priv->state == STATE_PROBE_DONE);
+
+	send_announcements (self, "-A");
+	nm_clear_g_source (&priv->round2_id);
+	priv->round2_id = g_timeout_add_seconds (2, arp_announce_round2, self);
+	priv->state = STATE_ANNOUNCING;
+}
+
+static void
+destroy_address_info (gpointer data)
+{
+	AddressInfo *info = (AddressInfo *) data;
+
+	nm_clear_g_source (&info->watch);
+
+	if (info->pid) {
+		nm_utils_kill_child_async (info->pid, SIGTERM, LOGD_IP4, "arping",
+		                           1000, NULL, NULL);
+	}
+
+	g_slice_free (AddressInfo, info);
+}
+
+static void
+dispose (GObject *object)
+{
+	NMArpingManager *self = NM_ARPING_MANAGER (object);
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+
+	nm_clear_g_source (&priv->timer);
+	nm_clear_g_source (&priv->round2_id);
+	g_clear_pointer (&priv->addresses, g_hash_table_destroy);
+
+	G_OBJECT_CLASS (nm_arping_manager_parent_class)->dispose (object);
+}
+
+static void
+nm_arping_manager_init (NMArpingManager *self)
+{
+	NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+
+	priv->addresses = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                         NULL, destroy_address_info);
+	priv->state = STATE_INIT;
+}
+
+NMArpingManager *
+nm_arping_manager_new (int ifindex)
+{
+	NMArpingManager *self;
+	NMArpingManagerPrivate *priv;
+
+	self = g_object_new (NM_TYPE_ARPING_MANAGER, NULL);
+	priv = NM_ARPING_MANAGER_GET_PRIVATE (self);
+	priv->ifindex = ifindex;
+
+	return self;
+}
+
+static void
+nm_arping_manager_class_init (NMArpingManagerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMArpingManagerPrivate));
+
+	object_class->dispose = dispose;
+
+	signals[PROBE_TERMINATED] =
+		g_signal_new (NM_ARPING_MANAGER_PROBE_TERMINATED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              0, NULL, NULL, NULL,
+		              G_TYPE_NONE, 0);
+}
diff --git a/src/devices/nm-arping-manager.h b/src/devices/nm-arping-manager.h
new file mode 100644
index 00000000..4a4f8d4b
--- /dev/null
+++ b/src/devices/nm-arping-manager.h
@@ -0,0 +1,53 @@
+/* -*- 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.
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_ARPING_MANAGER__
+#define __NM_ARPING_MANAGER__
+
+#include <netinet/in.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_ARPING_MANAGER            (nm_arping_manager_get_type ())
+#define NM_ARPING_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ARPING_MANAGER, NMArpingManager))
+#define NM_ARPING_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_ARPING_MANAGER, NMArpingManagerClass))
+#define NM_IS_ARPING_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ARPING_MANAGER))
+#define NM_IS_ARPING_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_ARPING_MANAGER))
+#define NM_ARPING_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_ARPING_MANAGER, NMArpingManagerClass))
+
+#define NM_ARPING_MANAGER_PROBE_TERMINATED  "probe-terminated"
+
+struct _NMArpingManager {
+	GObject parent;
+};
+
+typedef struct {
+	GObjectClass parent;
+} NMArpingManagerClass;
+
+GType nm_arping_manager_get_type (void);
+
+NMArpingManager *nm_arping_manager_new (int ifindex);
+void nm_arping_manager_destroy (NMArpingManager *self);
+gboolean nm_arping_manager_add_address (NMArpingManager *self, in_addr_t address);
+gboolean nm_arping_manager_start_probe (NMArpingManager *self, guint timeout, GError **error);
+gboolean nm_arping_manager_check_address (NMArpingManager *self, in_addr_t address);
+void nm_arping_manager_announce_addresses (NMArpingManager *self);
+void nm_arping_manager_reset (NMArpingManager *self);
+
+G_END_DECLS
+
+#endif /* __NM_ARPING_MANAGER__ */
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index dfd1de6d..cef104e6 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -18,12 +18,11 @@
  * Copyright 2011 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-device-bond.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
@@ -75,7 +74,6 @@ check_connection_available (NMDevice *device,
 static gboolean
 check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
-	const char *iface;
 	NMSettingBond *s_bond;
 
 	if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection))
@@ -85,11 +83,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
 		return FALSE;
 
-	/* Bond connections must specify the virtual interface name */
-	iface = nm_connection_get_interface_name (connection);
-	if (!iface || strcmp (nm_device_get_iface (device), iface))
-		return FALSE;
-
 	/* FIXME: match bond properties like mode, etc? */
 
 	return TRUE;
@@ -457,7 +450,7 @@ create_and_realize (NMDevice *device,
 	g_assert (iface);
 
 	plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create bond interface '%s' for '%s': %s",
 		             iface,
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index 843c5be4..cc72b003 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -18,11 +18,10 @@
  * Copyright 2011 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-device-bridge.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
@@ -73,7 +72,6 @@ check_connection_available (NMDevice *device,
 static gboolean
 check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
-	const char *iface;
 	NMSettingBridge *s_bridge;
 	const char *mac_address;
 
@@ -84,11 +82,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	if (!s_bridge || !nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
 		return FALSE;
 
-	/* Bridge connections must specify the virtual interface name */
-	iface = nm_connection_get_interface_name (connection);
-	if (!iface || strcmp (nm_device_get_iface (device), iface))
-		return FALSE;
-
 	mac_address = nm_setting_bridge_get_mac_address (s_bridge);
 	if (mac_address && nm_device_is_real (device)) {
 		const char *hw_addr;
@@ -405,7 +398,7 @@ create_and_realize (NMDevice *device,
 	                                     hwaddr ? mac_address : NULL,
 	                                     hwaddr ? ETH_ALEN : 0,
 	                                     out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create bridge interface '%s' for '%s': %s",
 		             iface,
diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c
index 9165de31..d034ddfc 100644
--- a/src/devices/nm-device-ethernet-utils.c
+++ b/src/devices/nm-device-ethernet-utils.c
@@ -16,12 +16,12 @@
  * (C) Copyright 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include <nm-connection.h>
-#include "nm-default.h"
+#include "nm-connection.h"
+
 #include "nm-device-ethernet-utils.h"
 
 char *
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index a2396ec8..2fb84276 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <netinet/in.h>
 #include <string.h>
@@ -29,7 +29,6 @@
 
 #include <gudev/gudev.h>
 
-#include "nm-default.h"
 #include "nm-device-ethernet.h"
 #include "nm-device-private.h"
 #include "nm-activation-request.h"
@@ -64,8 +63,6 @@ G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
 #define PPPOE_RECONNECT_DELAY 7
 #define PPPOE_ENCAP_OVERHEAD  8 /* 2 bytes for PPP, 6 for PPPoE */
 
-static NMSetting *device_get_setting (NMDevice *device, GType setting_type);
-
 typedef struct Supplicant {
 	NMSupplicantManager *mgr;
 	NMSupplicantInterface *iface;
@@ -429,52 +426,18 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	return TRUE;
 }
 
-/* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around.
-   It's here now to keep the patch short. */
-static NMSetting *
-device_get_setting (NMDevice *device, GType setting_type)
-{
-	NMActRequest *req;
-	NMSetting *setting = NULL;
-
-	req = nm_device_get_act_request (device);
-	if (req) {
-		NMConnection *connection;
-
-		connection = nm_act_request_get_applied_connection (req);
-		if (connection)
-			setting = nm_connection_get_setting (connection, setting_type);
-	}
-
-	return setting;
-}
-
 /*****************************************************************************/
 /* 802.1X */
 
 static void
-remove_supplicant_timeouts (NMDeviceEthernet *self)
+supplicant_interface_clear_handlers (NMDeviceEthernet *self)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
-	nm_clear_g_source (&priv->supplicant.con_timeout_id);
 	nm_clear_g_source (&priv->supplicant_timeout_id);
-}
-
-static void
-remove_supplicant_interface_error_handler (NMDeviceEthernet *self)
-{
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-
-	if (priv->supplicant.iface_error_id != 0) {
-		g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
-		priv->supplicant.iface_error_id = 0;
-	}
-
-	if (priv->supplicant.iface_con_error_cb_id > 0) {
-		g_source_remove (priv->supplicant.iface_con_error_cb_id);
-		priv->supplicant.iface_con_error_cb_id = 0;
-	}
+	nm_clear_g_source (&priv->supplicant.con_timeout_id);
+	nm_clear_g_source (&priv->supplicant.iface_con_error_cb_id);
+	nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id);
 }
 
 static void
@@ -482,18 +445,13 @@ supplicant_interface_release (NMDeviceEthernet *self)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
-	remove_supplicant_timeouts (self);
-	remove_supplicant_interface_error_handler (self);
+	supplicant_interface_clear_handlers (self);
 
-	if (priv->supplicant.iface_state_id > 0) {
-		g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
-		priv->supplicant.iface_state_id = 0;
-	}
+	nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id);
 
 	if (priv->supplicant.iface) {
 		nm_supplicant_interface_disconnect (priv->supplicant.iface);
-		nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface);
-		priv->supplicant.iface = NULL;
+		g_clear_object (&priv->supplicant.iface);
 	}
 }
 
@@ -656,8 +614,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 		}
 		break;
 	case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
-		remove_supplicant_interface_error_handler (self);
-		remove_supplicant_timeouts (self);
+		supplicant_interface_clear_handlers (self);
 
 		/* If this is the initial association during device activation,
 		 * schedule the next activation stage.
@@ -677,7 +634,6 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 		break;
 	case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
 		supplicant_interface_release (self);
-		remove_supplicant_timeouts (self);
 
 		if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
 			nm_device_state_changed (device,
@@ -804,14 +760,15 @@ supplicant_interface_init (NMDeviceEthernet *self)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
-	/* Create supplicant interface */
-	priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr,
-	                                                          nm_device_get_iface (NM_DEVICE (self)),
-	                                                          FALSE);
+	supplicant_interface_release (self);
+
+	priv->supplicant.iface = nm_supplicant_manager_create_interface (priv->supplicant.mgr,
+	                                                                 nm_device_get_iface (NM_DEVICE (self)),
+	                                                                 FALSE);
+
 	if (!priv->supplicant.iface) {
 		_LOGE (LOGD_DEVICE | LOGD_ETHER,
 		       "Couldn't initialize supplicant interface");
-		supplicant_interface_release (self);
 		return FALSE;
 	}
 
@@ -850,7 +807,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 {
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-	NMActRequest *req;
 	NMSettingWired *s_wired;
 	const char *cloned_mac;
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
@@ -859,15 +815,11 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 
 	ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason);
 	if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
-		req = nm_device_get_act_request (NM_DEVICE (self));
-		g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-		s_wired = (NMSettingWired *) device_get_setting (dev, NM_TYPE_SETTING_WIRED);
+		s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
 		if (s_wired) {
 			/* Set device MAC address if the connection wants to change it */
 			cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-			if (cloned_mac)
-				nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER);
+			nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER);
 		}
 
 		/* If we're re-activating a PPPoE connection a short while after
@@ -878,7 +830,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 		if (priv->last_pppoe_time) {
 			gint32 delay = nm_utils_get_monotonic_timestamp_s () - priv->last_pppoe_time;
 
-			if (delay < PPPOE_RECONNECT_DELAY && device_get_setting (dev, NM_TYPE_SETTING_PPPOE)) {
+			if (   delay < PPPOE_RECONNECT_DELAY
+			    && nm_device_get_applied_setting (dev, NM_TYPE_SETTING_PPPOE)) {
 				_LOGI (LOGD_DEVICE, "delaying PPPoE reconnect for %d seconds to ensure peer is ready...",
 				       delay);
 				g_assert (!priv->pppoe_wait_id);
@@ -980,7 +933,6 @@ static NMActStageReturn
 pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-	NMConnection *connection;
 	NMSettingPppoe *s_pppoe;
 	NMActRequest *req;
 	GError *err = NULL;
@@ -989,10 +941,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas
 	req = nm_device_get_act_request (NM_DEVICE (self));
 	g_assert (req);
 
-	connection = nm_act_request_get_applied_connection (req);
-	g_assert (req);
-
-	s_pppoe = nm_connection_get_setting_pppoe (connection);
+	s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_PPPOE);
 	g_assert (s_pppoe);
 
 	priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self)));
@@ -1064,7 +1013,7 @@ dcb_configure (NMDevice *device)
 
 	dcb_timeout_cleanup (device);
 
-	s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB);
+	s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB);
 	g_assert (s_dcb);
 	if (!nm_dcb_setup (nm_device_get_iface (device), s_dcb, &error)) {
 		_LOGW (LOGD_DCB, "Activation: (ethernet) failed to enable DCB/FCoE: %s",
@@ -1210,7 +1159,7 @@ wake_on_lan_enable (NMDevice *device)
 	const char *password = NULL;
 	gs_free char *value = NULL;
 
-	s_wired = (NMSettingWired *) device_get_setting (device, NM_TYPE_SETTING_WIRED);
+	s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
 	if (s_wired) {
 		wol = nm_setting_wired_get_wake_on_lan (s_wired);
 		password = nm_setting_wired_get_wake_on_lan_password (s_wired);
@@ -1255,7 +1204,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION));
+	s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device,
+	                                                              NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
 
 	dcb_timeout_cleanup (device);
@@ -1268,7 +1218,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
 		NMSetting8021x *security;
 
-		security = (NMSetting8021x *) device_get_setting (device, NM_TYPE_SETTING_802_1X);
+		security = (NMSetting8021x *) nm_device_get_applied_setting (device,
+		                                                             NM_TYPE_SETTING_802_1X);
 		if (security) {
 			/* FIXME: for now 802.1x is mutually exclusive with DCB */
 			return nm_8021x_stage2_config (self, reason);
@@ -1278,7 +1229,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	wake_on_lan_enable (device);
 
 	/* DCB and FCoE setup */
-	s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB);
+	s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB);
 	if (s_dcb) {
 		/* lldpad really really wants the carrier to be up */
 		if (nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device))) {
@@ -1307,7 +1258,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	                           NM_SETTING_PPPOE_SETTING_NAME)) {
 		NMSettingPpp *s_ppp;
 
-		s_ppp = (NMSettingPpp *) device_get_setting (device, NM_TYPE_SETTING_PPP);
+		s_ppp = (NMSettingPpp *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPP);
 		if (s_ppp) {
 			guint32 mtu = 0, mru = 0, mxu;
 
@@ -1337,7 +1288,7 @@ act_stage3_ip4_config_start (NMDevice *device,
 
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION));
+	s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device, NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
 
 	connection_type = nm_setting_connection_get_connection_type (s_con);
@@ -1396,7 +1347,7 @@ deactivate (NMDevice *device)
 	dcb_carrier_cleanup (device);
 
 	/* Tear down DCB/FCoE if it was enabled */
-	s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB);
+	s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB);
 	if (s_dcb) {
 		if (!nm_dcb_cleanup (nm_device_get_iface (device), &error)) {
 			_LOGW (LOGD_DEVICE | LOGD_HW, "failed to disable DCB/FCoE: %s",
@@ -1406,7 +1357,7 @@ deactivate (NMDevice *device)
 	}
 
 	/* Set last PPPoE connection time */
-	if (device_get_setting (device, NM_TYPE_SETTING_PPPOE))
+	if (nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE))
 		NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s ();
 
 	/* Reset MAC address back to initial address */
@@ -1653,6 +1604,8 @@ dispose (GObject *object)
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
+	supplicant_interface_release (self);
+
 	nm_clear_g_source (&priv->pppoe_wait_id);
 
 	dcb_timeout_cleanup (NM_DEVICE (self));
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c
index 75731b14..bd0ec002 100644
--- a/src/devices/nm-device-factory.c
+++ b/src/devices/nm-device-factory.c
@@ -18,17 +18,16 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <string.h>
-
 #include <gmodule.h>
 
 #include "nm-device-factory.h"
-#include "nm-default.h"
 #include "nm-platform.h"
+#include "nm-utils.h"
 
 const NMLinkType _nm_device_factory_no_default_links[] = { NM_LINK_TYPE_NONE };
 const char *_nm_device_factory_no_default_settings[] = { NULL };
@@ -156,35 +155,46 @@ nm_device_factory_get_connection_parent (NMDeviceFactory *factory,
 	return NULL;
 }
 
-static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
-{
-	const char *iface;
-
-	/* For any other virtual connection, NMSettingConnection:interface-name is
-	 * the virtual device name.
-	 */
-	iface = nm_connection_get_interface_name (connection);
-	g_return_val_if_fail (iface != NULL, NULL);
-	return g_strdup (iface);
-}
-
 char *
-nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory,
-                                          NMConnection *connection,
-                                          const char *parent_iface)
+nm_device_factory_get_connection_iface (NMDeviceFactory *factory,
+                                        NMConnection *connection,
+                                        const char *parent_iface,
+                                        GError **error)
 {
+	NMDeviceFactoryInterface *klass;
+	char *ifname;
+
 	g_return_val_if_fail (factory != NULL, NULL);
 	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (!error || !*error, NULL);
 
-	if (!nm_connection_is_virtual (connection))
+	klass = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
+
+	if (klass->get_connection_iface)
+		ifname = klass->get_connection_iface (factory, connection, parent_iface);
+	else
+		ifname = g_strdup (nm_connection_get_interface_name (connection));
+
+	if (!ifname) {
+		g_set_error (error,
+		             NM_MANAGER_ERROR,
+		             NM_MANAGER_ERROR_FAILED,
+		             "failed to determine interface name: error determine name for %s",
+		             nm_connection_get_connection_type (connection));
 		return NULL;
+	}
 
-	if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name)
-		return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name (factory, connection, parent_iface);
-	return NULL;
+	if (!nm_utils_iface_valid_name (ifname)) {
+		g_set_error (error,
+		             NM_MANAGER_ERROR,
+		             NM_MANAGER_ERROR_FAILED,
+		             "failed to determine interface name: name \"%s\" is invalid",
+		             ifname);
+		g_free (ifname);
+		return NULL;
+	}
+
+	return ifname;
 }
 
 /*******************************************************************/
@@ -192,8 +202,6 @@ nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory,
 static void
 nm_device_factory_default_init (NMDeviceFactoryInterface *factory_iface)
 {
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
-
 	/* Signals */
 	signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED,
 	                                      NM_TYPE_DEVICE_FACTORY,
diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h
index 9b7cb35a..ae78968a 100644
--- a/src/devices/nm-device-factory.h
+++ b/src/devices/nm-device-factory.h
@@ -101,19 +101,19 @@ typedef struct {
 	                                       NMConnection *connection);
 
 	/**
-	 * get_virtual_iface_name:
+	 * get_connection_iface:
 	 * @factory: the #NMDeviceFactory
-	 * @connection: the #NMConnection to return the virtual interface name for
-	 * @parent_iface: parent interface name
+	 * @connection: the #NMConnection to return the interface name for
+	 * @parent_iface: optional parent interface name for virtual devices
 	 *
 	 * Given a connection, returns the interface name that a device activating
 	 * that connection would have.
 	 *
 	 * Returns: the interface name, or %NULL
 	 */
-	char * (*get_virtual_iface_name) (NMDeviceFactory *factory,
-	                                  NMConnection *connection,
-	                                  const char *parent_iface);
+	char * (*get_connection_iface) (NMDeviceFactory *factory,
+	                                NMConnection *connection,
+	                                const char *parent_iface);
 
 	/**
 	 * create_device:
@@ -175,9 +175,10 @@ void       nm_device_factory_get_supported_types (NMDeviceFactory *factory,
 const char *nm_device_factory_get_connection_parent (NMDeviceFactory *factory,
                                                      NMConnection *connection);
 
-char *     nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory,
-                                                     NMConnection *connection,
-                                                     const char *parent_iface);
+char *     nm_device_factory_get_connection_iface (NMDeviceFactory *factory,
+                                                   NMConnection *connection,
+                                                   const char *parent_iface,
+                                                   GError **error);
 
 void       nm_device_factory_start       (NMDeviceFactory *factory);
 
diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c
index 2e9c134a..d90840d2 100644
--- a/src/devices/nm-device-generic.c
+++ b/src/devices/nm-device-generic.c
@@ -18,7 +18,7 @@
  * Copyright 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-device-generic.h"
 #include "nm-device-private.h"
@@ -138,7 +138,7 @@ constructor (GType type,
 	                                                                       n_construct_params,
 	                                                                       construct_params);
 
-	nm_device_set_unmanaged_flags_initial (NM_DEVICE (object), NM_UNMANAGED_DEFAULT, TRUE);
+	nm_device_set_unmanaged_flags ((NMDevice *) object, NM_UNMANAGED_BY_DEFAULT, TRUE);
 
 	return object;
 }
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index 45df49fe..79bcb57c 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -18,11 +18,10 @@
  * Copyright 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <linux/if_infiniband.h>
 
-#include "nm-default.h"
 #include "nm-device-infiniband.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
@@ -69,8 +68,6 @@ static NMActStageReturn
 act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 {
 	NMActStageReturn ret;
-	NMActRequest *req;
-	NMConnection *connection;
 	NMSettingInfiniband *s_infiniband;
 	const char *transport_mode;
 	char *mode_path;
@@ -82,12 +79,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
 		return ret;
 
-	req = nm_device_get_act_request (dev);
-	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_assert (connection);
-	s_infiniband = nm_connection_get_setting_infiniband (connection);
+	s_infiniband = (NMSettingInfiniband *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_INFINIBAND);
 	g_assert (s_infiniband);
 
 	transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);
@@ -272,7 +264,7 @@ create_and_realize (NMDevice *device,
 	}
 
 	plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
 		             nm_device_get_iface (device),
@@ -406,9 +398,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
 }
 
 static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
+get_connection_iface (NMDeviceFactory *factory,
+                      NMConnection *connection,
+                      const char *parent_iface)
 {
 	NMSettingInfiniband *s_infiniband;
 
@@ -430,6 +422,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband,
 	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME),
 	factory_iface->create_device = create_device;
 	factory_iface->get_connection_parent = get_connection_parent;
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
+	factory_iface->get_connection_iface = get_connection_iface;
 	)
 
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
index 6d0df059..0ba813eb 100644
--- a/src/devices/nm-device-ip-tunnel.c
+++ b/src/devices/nm-device-ip-tunnel.c
@@ -18,7 +18,7 @@
  * Copyright 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <netinet/in.h>
@@ -28,7 +28,6 @@
 
 #include "nm-device-ip-tunnel.h"
 #include "nm-device-private.h"
-#include "nm-default.h"
 #include "nm-manager.h"
 #include "nm-platform.h"
 #include "nm-device-factory.h"
@@ -554,13 +553,13 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link)
 		else if (lnk->proto == IPPROTO_IPV6)
 			return NM_IP_TUNNEL_MODE_IP6IP6;
 		else
-			return NM_IP_TUNNEL_MODE_UKNOWN;
+			return NM_IP_TUNNEL_MODE_UNKNOWN;
 	case NM_LINK_TYPE_IPIP:
 		return NM_IP_TUNNEL_MODE_IPIP;
 	case NM_LINK_TYPE_SIT:
 		return NM_IP_TUNNEL_MODE_SIT;
 	default:
-		g_return_val_if_reached (NM_IP_TUNNEL_MODE_UKNOWN);
+		g_return_val_if_reached (NM_IP_TUNNEL_MODE_UNKNOWN);
 	}
 }
 
@@ -661,7 +660,7 @@ create_and_realize (NMDevice *device,
 		}
 
 		plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink);
-		if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+		if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 			             "Failed to create GRE interface '%s' for '%s': %s",
 			             iface,
@@ -687,7 +686,7 @@ create_and_realize (NMDevice *device,
 		lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel);
 
 		plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink);
-		if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+		if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 					"Failed to create SIT interface '%s' for '%s': %s",
 					iface,
@@ -713,7 +712,7 @@ create_and_realize (NMDevice *device,
 		lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel);
 
 		plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink);
-		if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+		if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 					"Failed to create IPIP interface '%s' for '%s': %s",
 					iface,
@@ -742,7 +741,7 @@ create_and_realize (NMDevice *device,
 		lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6;
 
 		plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink);
-		if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+		if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 			             "Failed to create IPIP interface '%s' for '%s': %s",
 			             iface,
@@ -997,7 +996,7 @@ create_device (NMDeviceFactory *factory,
 		mode = platform_link_to_tunnel_mode (plink);
 	}
 
-	if (mode == NM_IP_TUNNEL_MODE_UKNOWN)
+	if (mode == NM_IP_TUNNEL_MODE_UNKNOWN)
 		return NULL;
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL,
@@ -1023,9 +1022,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
 }
 
 static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
+get_connection_iface (NMDeviceFactory *factory,
+                      NMConnection *connection,
+                      const char *parent_iface)
 {
 	const char *ifname;
 	NMSettingIPTunnel *s_ip_tunnel;
@@ -1048,5 +1047,5 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel,
 	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME),
 	factory_iface->create_device = create_device;
 	factory_iface->get_connection_parent = get_connection_parent;
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
+	factory_iface->get_connection_iface = get_connection_iface;
 )
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index 8123a793..2dc9d4f6 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -18,11 +18,10 @@
  * Copyright 2013 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-device-macvlan.h"
 #include "nm-device-private.h"
 #include "nm-connection-provider.h"
@@ -127,7 +126,7 @@ parent_state_changed (NMDevice *parent,
 	if (reason == NM_DEVICE_STATE_REASON_CARRIER)
 		return;
 
-	nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason);
+	nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
 }
 
 static void
@@ -139,8 +138,7 @@ nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent)
 	if (parent == priv->parent)
 		return;
 
-	if (priv->parent_state_id)
-		nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id);
+	nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id);
 
 	g_clear_object (&priv->parent);
 
@@ -152,10 +150,10 @@ nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent)
 		                                          device);
 
 		/* Set parent-dependent unmanaged flag */
-		nm_device_set_unmanaged_flags (device,
-		                               NM_UNMANAGED_PARENT,
-		                               !nm_device_get_managed (parent),
-		                               NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
+		nm_device_set_unmanaged_by_flags (device,
+		                                  NM_UNMANAGED_PARENT,
+		                                  !nm_device_get_managed (parent, FALSE),
+		                                  NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
 	}
 
 	/* Recheck availability now that the parent has changed */
@@ -239,7 +237,7 @@ create_and_realize (NMDevice *device,
 	lnk.tap = nm_setting_macvlan_get_tap (s_macvlan);
 
 	plerr = nm_platform_link_macvlan_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create %s interface '%s' for '%s': %s",
 		             lnk.tap ? "macvtap" : "macvlan",
@@ -377,7 +375,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
 	NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device);
 	NMSettingMacvlan *s_macvlan;
-	const char *parent, *iface = NULL;
+	const char *parent = NULL;
 
 	if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection))
 		return FALSE;
@@ -410,13 +408,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 		}
 	}
 
-	/* Ensure the interface name matches */
-	iface = nm_connection_get_interface_name (connection);
-	if (iface) {
-		if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0)
-			return FALSE;
-	}
-
 	return TRUE;
 }
 
@@ -503,8 +494,6 @@ update_connection (NMDevice *device, NMConnection *connection)
 static NMActStageReturn
 act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 {
-	NMActRequest *req;
-	NMConnection *connection;
 	NMSettingWired *s_wired;
 	const char *cloned_mac;
 	NMActStageReturn ret;
@@ -515,18 +504,11 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
 		return ret;
 
-	req = nm_device_get_act_request (dev);
-	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	s_wired = nm_connection_get_setting_wired (connection);
+	s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
 	if (s_wired) {
 		/* Set device MAC address if the connection wants to change it */
 		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-		if (cloned_mac)
-			nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW);
+		nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW);
 	}
 
 	return TRUE;
@@ -621,6 +603,14 @@ set_property (GObject *object, guint prop_id,
 }
 
 static void
+dispose (GObject *object)
+{
+	nm_device_macvlan_set_parent (NM_DEVICE_MACVLAN (object), NULL);
+
+	G_OBJECT_CLASS (nm_device_macvlan_parent_class)->dispose (object);
+}
+
+static void
 nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -630,6 +620,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
 
 	NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP)
 
+	object_class->dispose = dispose;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
@@ -744,9 +735,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
 }
 
 static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
+get_connection_iface (NMDeviceFactory *factory,
+                      NMConnection *connection,
+                      const char *parent_iface)
 {
 	NMSettingMacvlan *s_macvlan;
 	const char *ifname;
@@ -768,6 +759,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACVLAN, Macvlan, macvlan,
 	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_MACVLAN_SETTING_NAME),
 	factory_iface->create_device = create_device;
 	factory_iface->get_connection_parent = get_connection_parent;
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
+	factory_iface->get_connection_iface = get_connection_iface;
 	)
 
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index 5010e906..602c2c85 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -95,7 +95,6 @@ void nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave
 
 void nm_device_set_carrier (NMDevice *self, gboolean carrier);
 
-void nm_device_emit_recheck_auto_activate (NMDevice *device);
 void nm_device_queue_recheck_assume (NMDevice *device);
 void nm_device_queue_recheck_available (NMDevice *device,
                                         NMDeviceStateReason available_reason,
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index 91ef8fe7..a8ae3edc 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -18,13 +18,12 @@
  * Copyright 2013 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 
-#include "nm-default.h"
 #include "nm-activation-request.h"
 #include "nm-device-tun.h"
 #include "nm-device-private.h"
@@ -222,7 +221,7 @@ create_and_realize (NMDevice *device,
 	                                  nm_setting_tun_get_vnet_hdr (s_tun),
 	                                  nm_setting_tun_get_multi_queue (s_tun),
 	                                  out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create TUN/TAP interface '%s' for '%s': %s",
 		             iface,
@@ -285,8 +284,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 {
 	NMDeviceTun *self = NM_DEVICE_TUN (device);
 	NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
-	NMActRequest *req;
-	NMConnection *connection;
 	NMSettingWired *s_wired;
 	const char *cloned_mac;
 	NMActStageReturn ret;
@@ -301,18 +298,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	if (g_strcmp0 (priv->mode, "tap"))
 		return NM_ACT_STAGE_RETURN_SUCCESS;
 
-	req = nm_device_get_act_request (device);
-	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	s_wired = nm_connection_get_setting_wired (connection);
+	s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
 	if (s_wired) {
 		/* Set device MAC address if the connection wants to change it */
 		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-		if (cloned_mac)
-			nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
+		nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
 	}
 
 	return NM_ACT_STAGE_RETURN_SUCCESS;
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index a1bf0d21..ff198a7d 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -18,7 +18,7 @@
  * Copyright 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -29,7 +29,6 @@
 
 #include "nm-device-veth.h"
 #include "nm-device-private.h"
-#include "nm-default.h"
 #include "nm-manager.h"
 #include "nm-platform.h"
 #include "nm-device-factory.h"
@@ -188,7 +187,7 @@ create_device (NMDeviceFactory *factory,
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH,
 	                                  NM_DEVICE_IFACE, iface,
 	                                  NM_DEVICE_TYPE_DESC, "Veth",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
+	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VETH,
 	                                  NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VETH,
 	                                  NULL);
 }
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index f8710412..e6e3708b 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -18,11 +18,10 @@
  * Copyright 2011 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/socket.h>
 
-#include "nm-default.h"
 #include "nm-device-vlan.h"
 #include "nm-manager.h"
 #include "nm-utils.h"
@@ -77,7 +76,7 @@ parent_state_changed (NMDevice *parent,
 	if (reason == NM_DEVICE_STATE_REASON_CARRIER)
 		return;
 
-	nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason);
+	nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
 }
 
 static void
@@ -115,7 +114,8 @@ parent_hwaddr_changed (NMDevice *parent,
 			 * removing the IPv6 configuration; reapply it.
 			 */
 			s_ip6 = nm_connection_get_setting_ip6_config (connection);
-			nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6);
+			if (s_ip6)
+				nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6);
 		}
 	}
 }
@@ -144,10 +144,10 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent)
 		                                           G_CALLBACK (parent_hwaddr_changed), device);
 
 		/* Set parent-dependent unmanaged flag */
-		nm_device_set_unmanaged_flags (device,
-		                               NM_UNMANAGED_PARENT,
-		                               !nm_device_get_managed (parent),
-		                               NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
+		nm_device_set_unmanaged_by_flags (device,
+		                                  NM_UNMANAGED_PARENT,
+		                                  !nm_device_get_managed (parent, FALSE),
+		                                  NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
 	}
 
 	/* Recheck availability now that the parent has changed */
@@ -237,7 +237,7 @@ create_and_realize (NMDevice *device,
 	                                   vlan_id,
 	                                   nm_setting_vlan_get_flags (s_vlan),
 	                                   out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create VLAN interface '%s' for '%s': %s",
 		             iface,
@@ -389,7 +389,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
 	NMSettingVlan *s_vlan;
-	const char *parent, *iface = NULL;
+	const char *parent = NULL;
 
 	if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
 		return FALSE;
@@ -415,16 +415,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 		}
 	}
 
-	/* Ensure the interface name matches.  If not specified we assume a match
-	 * since both the parent interface and the VLAN ID matched by the time we
-	 * get here.
-	 */
-	iface = nm_connection_get_interface_name (connection);
-	if (iface) {
-		if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0)
-			return FALSE;
-	}
-
 	return TRUE;
 }
 
@@ -546,8 +536,6 @@ update_connection (NMDevice *device, NMConnection *connection)
 static NMActStageReturn
 act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 {
-	NMActRequest *req;
-	NMConnection *connection;
 	NMSettingVlan *s_vlan;
 	NMSettingWired *s_wired;
 	const char *cloned_mac;
@@ -559,21 +547,14 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
 	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
 		return ret;
 
-	req = nm_device_get_act_request (dev);
-	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	s_wired = nm_connection_get_setting_wired (connection);
+	s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
 	if (s_wired) {
 		/* Set device MAC address if the connection wants to change it */
 		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-		if (cloned_mac)
-			nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN);
+		nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN);
 	}
 
-	s_vlan = nm_connection_get_setting_vlan (connection);
+	s_vlan = (NMSettingVlan *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_VLAN);
 	if (s_vlan) {
 		gs_free NMVlanQosMapping *ingress_map = NULL;
 		gs_free NMVlanQosMapping *egress_map = NULL;
@@ -765,9 +746,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
 }
 
 static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
+get_connection_iface (NMDeviceFactory *factory,
+                      NMConnection *connection,
+                      const char *parent_iface)
 {
 	const char *ifname;
 	NMSettingVlan *s_vlan;
@@ -796,6 +777,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (VLAN, Vlan, vlan,
 	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VLAN_SETTING_NAME),
 	factory_iface->create_device = create_device;
 	factory_iface->get_connection_parent = get_connection_parent;
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
+	factory_iface->get_connection_iface = get_connection_iface;
 	)
 
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index aab90539..79942458 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -18,11 +18,10 @@
  * Copyright 2013 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-device-vxlan.h"
 #include "nm-device-private.h"
 #include "nm-manager.h"
@@ -224,7 +223,7 @@ create_and_realize (NMDevice *device,
 	props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan);
 
 	plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create VXLAN interface '%s' for '%s': %s",
 		             iface,
@@ -296,7 +295,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
 	NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device);
 	NMSettingVxlan *s_vxlan;
-	const char *iface, *parent;
+	const char *parent;
 
 	if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection))
 		return FALSE;
@@ -305,12 +304,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	if (!s_vxlan)
 		return FALSE;
 
-	iface = nm_connection_get_interface_name (connection);
-	if (iface) {
-		if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0)
-			return FALSE;
-	}
-
 	if (nm_device_is_real (device)) {
 		parent = nm_setting_vxlan_get_parent (s_vxlan);
 		if (   parent
@@ -510,8 +503,6 @@ update_connection (NMDevice *device, NMConnection *connection)
 static NMActStageReturn
 act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 {
-	NMActRequest *req;
-	NMConnection *connection;
 	NMSettingWired *s_wired;
 	const char *cloned_mac;
 	NMActStageReturn ret;
@@ -522,18 +513,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
 		return ret;
 
-	req = nm_device_get_act_request (device);
-	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
-	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
-
-	s_wired = nm_connection_get_setting_wired (connection);
+	s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
 	if (s_wired) {
 		/* Set device MAC address if the connection wants to change it */
 		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-		if (cloned_mac)
-			nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
+		nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
 	}
 
 	return NM_ACT_STAGE_RETURN_SUCCESS;
@@ -818,9 +802,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
 }
 
 static char *
-get_virtual_iface_name (NMDeviceFactory *factory,
-                        NMConnection *connection,
-                        const char *parent_iface)
+get_connection_iface (NMDeviceFactory *factory,
+                      NMConnection *connection,
+                      const char *parent_iface)
 {
 	const char *ifname;
 	NMSettingVxlan *s_vxlan;
@@ -842,6 +826,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan,
 	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VXLAN_SETTING_NAME),
 	factory_iface->create_device = create_device;
 	factory_iface->get_connection_parent = get_connection_parent;
-	factory_iface->get_virtual_iface_name = get_virtual_iface_name;
+	factory_iface->get_connection_iface = get_connection_iface;
 	)
 
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 93782a45..cdd3f7cb 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <netinet/in.h>
 #include <string.h>
@@ -34,7 +34,6 @@
 #include <netlink/route/addr.h>
 #include <linux/if_addr.h>
 
-#include "nm-default.h"
 #include "nm-device.h"
 #include "nm-device-private.h"
 #include "NetworkManagerUtils.h"
@@ -64,6 +63,7 @@
 #include "nm-lldp-listener.h"
 #include "sd-ipv4ll.h"
 #include "nm-audit-manager.h"
+#include "nm-arping-manager.h"
 
 #include "nm-device-logging.h"
 _LOG_DECLARE_SELF (NMDevice);
@@ -94,8 +94,7 @@ enum {
 };
 static guint signals[LAST_SIGNAL] = { 0 };
 
-enum {
-	PROP_0,
+NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
 	PROP_UDI,
 	PROP_IFACE,
 	PROP_IP_IFACE,
@@ -132,8 +131,7 @@ enum {
 	PROP_LLDP_NEIGHBORS,
 	PROP_REAL,
 	PROP_SLAVES,
-	LAST_PROP
-};
+);
 
 #define DEFAULT_AUTOCONNECT TRUE
 
@@ -193,10 +191,16 @@ typedef struct {
 	int ifindex;
 } DeleteOnDeactivateData;
 
+typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean);
+
+typedef struct {
+	ArpingCallback callback;
+	NMDevice *device;
+	NMIP4Config **configs;
+} ArpingData;
+
 typedef struct _NMDevicePrivate {
 	gboolean in_state_changed;
-	gboolean initialized;
-	gboolean platform_link_initialized;
 
 	guint device_link_changed_id;
 	guint device_ip_link_changed_id;
@@ -234,7 +238,7 @@ typedef struct _NMDevicePrivate {
 	char *        physical_port_id;
 	guint         dev_id;
 
-	gboolean                managed_touched_by_user;
+	NMUnmanagedFlags        unmanaged_mask;
 	NMUnmanagedFlags        unmanaged_flags;
 	gboolean                is_nm_owned; /* whether the device is a device owned and created by NM */
 	DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */
@@ -300,7 +304,6 @@ typedef struct _NMDevicePrivate {
 	NMDhcp4Config * dhcp4_config;
 	guint           dhcp4_restart_id;
 
-	guint           arp_round2_id;
 	PingInfo        gw_ping;
 
 	/* dnsmasq stuff for shared connections */
@@ -315,12 +318,19 @@ typedef struct _NMDevicePrivate {
 	sd_ipv4ll *    ipv4ll;
 	guint          ipv4ll_timeout;
 
+	/* IPv4 DAD stuff */
+	struct {
+		GSList *          dad_list;
+		NMArpingManager * announcing;
+	} arping;
+
 	/* IP6 configuration info */
 	NMIP6Config *  ip6_config;
 	IpState        ip6_state;
 	NMIP6Config *  con_ip6_config; /* config from the setting */
 	NMIP6Config *  wwan_ip6_config;
 	NMIP6Config *  ext_ip6_config; /* Stuff added outside NM */
+	NMIP6Config *  ext_ip6_config_captured; /* Configuration captured from platform. */
 	GSList *       vpn6_configs;   /* VPNs which use this device */
 	gboolean       nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */
 	guint32        ip6_mtu;
@@ -390,13 +400,10 @@ static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success);
 static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason);
 
 static gboolean addrconf6_start_with_link_ready (NMDevice *self);
-static gboolean dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection);
 static NMActStageReturn linklocal6_start (NMDevice *self);
 
 static void _carrier_wait_check_queued_act_request (NMDevice *self);
 
-static gboolean nm_device_get_default_unmanaged (NMDevice *self);
-
 static const char *_activation_func_to_string (ActivationHandleFunc func);
 static void activation_source_handle_cb (NMDevice *self, int family);
 
@@ -408,10 +415,6 @@ static void _set_state_full (NMDevice *self,
 static gboolean queued_ip4_config_change (gpointer user_data);
 static gboolean queued_ip6_config_change (gpointer user_data);
 
-static void _set_unmanaged_flags (NMDevice *self,
-                                  NMUnmanagedFlags flags,
-                                  gboolean unmanaged);
-
 /***********************************************************/
 
 #define QUEUED_PREFIX "queued state change to "
@@ -446,74 +449,75 @@ state_to_string (NMDeviceState state)
 	return queued_state_to_string (state) + strlen (QUEUED_PREFIX);
 }
 
-NM_UTILS_STRING_LOOKUP_TABLE_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, NULL,
-	[NM_DEVICE_STATE_REASON_UNKNOWN]                  = "unknown",
-	[NM_DEVICE_STATE_REASON_NONE]                     = "none",
-	[NM_DEVICE_STATE_REASON_NOW_MANAGED]              = "managed",
-	[NM_DEVICE_STATE_REASON_NOW_UNMANAGED]            = "unmanaged",
-	[NM_DEVICE_STATE_REASON_CONFIG_FAILED]            = "config-failed",
-	[NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE]    = "ip-config-unavailable",
-	[NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED]        = "ip-config-expired",
-	[NM_DEVICE_STATE_REASON_NO_SECRETS]               = "no-secrets",
-	[NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT]    = "supplicant-disconnect",
-	[NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED] = "supplicant-config-failed",
-	[NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED]        = "supplicant-failed",
-	[NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT]       = "supplicant-timeout",
-	[NM_DEVICE_STATE_REASON_PPP_START_FAILED]         = "ppp-start-failed",
-	[NM_DEVICE_STATE_REASON_PPP_DISCONNECT]           = "ppp-disconnect",
-	[NM_DEVICE_STATE_REASON_PPP_FAILED]               = "ppp-failed",
-	[NM_DEVICE_STATE_REASON_DHCP_START_FAILED]        = "dhcp-start-failed",
-	[NM_DEVICE_STATE_REASON_DHCP_ERROR]               = "dhcp-error",
-	[NM_DEVICE_STATE_REASON_DHCP_FAILED]              = "dhcp-failed",
-	[NM_DEVICE_STATE_REASON_SHARED_START_FAILED]      = "sharing-start-failed",
-	[NM_DEVICE_STATE_REASON_SHARED_FAILED]            = "sharing-failed",
-	[NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED]      = "autoip-start-failed",
-	[NM_DEVICE_STATE_REASON_AUTOIP_ERROR]             = "autoip-error",
-	[NM_DEVICE_STATE_REASON_AUTOIP_FAILED]            = "autoip-failed",
-	[NM_DEVICE_STATE_REASON_MODEM_BUSY]               = "modem-busy",
-	[NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE]       = "modem-no-dialtone",
-	[NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER]         = "modem-no-carrier",
-	[NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT]       = "modem-dial-timeout",
-	[NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED]        = "modem-dial-failed",
-	[NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED]        = "modem-init-failed",
-	[NM_DEVICE_STATE_REASON_GSM_APN_FAILED]           = "gsm-apn-failed",
-	[NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING] = "gsm-registration-idle",
-	[NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED]  = "gsm-registration-denied",
-	[NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT] = "gsm-registration-timeout",
-	[NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED]  = "gsm-registration-failed",
-	[NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED]     = "gsm-pin-check-failed",
-	[NM_DEVICE_STATE_REASON_FIRMWARE_MISSING]         = "firmware-missing",
-	[NM_DEVICE_STATE_REASON_REMOVED]                  = "removed",
-	[NM_DEVICE_STATE_REASON_SLEEPING]                 = "sleeping",
-	[NM_DEVICE_STATE_REASON_CONNECTION_REMOVED]       = "connection-removed",
-	[NM_DEVICE_STATE_REASON_USER_REQUESTED]           = "user-requested",
-	[NM_DEVICE_STATE_REASON_CARRIER]                  = "carrier-changed",
-	[NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED]       = "connection-assumed",
-	[NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE]     = "supplicant-available",
-	[NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND]          = "modem-not-found",
-	[NM_DEVICE_STATE_REASON_BT_FAILED]                = "bluetooth-failed",
-	[NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED]     = "gsm-sim-not-inserted",
-	[NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED]     = "gsm-sim-pin-required",
-	[NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED]     = "gsm-sim-puk-required",
-	[NM_DEVICE_STATE_REASON_GSM_SIM_WRONG]            = "gsm-sim-wrong",
-	[NM_DEVICE_STATE_REASON_INFINIBAND_MODE]          = "infiniband-mode",
-	[NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED]        = "dependency-failed",
-	[NM_DEVICE_STATE_REASON_BR2684_FAILED]            = "br2684-bridge-failed",
-	[NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE] = "modem-manager-unavailable",
-	[NM_DEVICE_STATE_REASON_SSID_NOT_FOUND]           = "ssid-not-found",
-	[NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED] = "secondary-connection-failed",
-	[NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED]          = "dcb-fcoe-failed",
-	[NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED]     = "teamd-control-failed",
-	[NM_DEVICE_STATE_REASON_MODEM_FAILED]             = "modem-failed",
-	[NM_DEVICE_STATE_REASON_MODEM_AVAILABLE]          = "modem-available",
-	[NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT]        = "sim-pin-incorrect",
-	[NM_DEVICE_STATE_REASON_NEW_ACTIVATION]           = "new-activation",
-	[NM_DEVICE_STATE_REASON_PARENT_CHANGED]           = "parent-changed",
-	[NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED]   = "parent-managed-changed",
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_UNKNOWN,                        "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NONE,                           "none"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_MANAGED,                    "managed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_UNMANAGED,                  "unmanaged"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONFIG_FAILED,                  "config-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,          "ip-config-unavailable"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED,              "ip-config-expired"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NO_SECRETS,                     "no-secrets"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT,          "supplicant-disconnect"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED,       "supplicant-config-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED,              "supplicant-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT,             "supplicant-timeout"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_START_FAILED,               "ppp-start-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_DISCONNECT,                 "ppp-disconnect"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_FAILED,                     "ppp-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_START_FAILED,              "dhcp-start-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_ERROR,                     "dhcp-error"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_FAILED,                    "dhcp-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_START_FAILED,            "sharing-start-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_FAILED,                  "sharing-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED,            "autoip-start-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_ERROR,                   "autoip-error"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_FAILED,                  "autoip-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_BUSY,                     "modem-busy"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE,             "modem-no-dialtone"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER,               "modem-no-carrier"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT,             "modem-dial-timeout"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED,              "modem-dial-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED,              "modem-init-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_APN_FAILED,                 "gsm-apn-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, "gsm-registration-idle"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED,        "gsm-registration-denied"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT,       "gsm-registration-timeout"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED,        "gsm-registration-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED,           "gsm-pin-check-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_FIRMWARE_MISSING,               "firmware-missing"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_REMOVED,                        "removed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SLEEPING,                       "sleeping"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,             "connection-removed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_USER_REQUESTED,                 "user-requested"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CARRIER,                        "carrier-changed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,             "connection-assumed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,           "supplicant-available"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,                "modem-not-found"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BT_FAILED,                      "bluetooth-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED,           "gsm-sim-not-inserted"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED,           "gsm-sim-pin-required"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED,           "gsm-sim-puk-required"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_WRONG,                  "gsm-sim-wrong"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_INFINIBAND_MODE,                "infiniband-mode"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED,              "dependency-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BR2684_FAILED,                  "br2684-bridge-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE,      "modem-manager-unavailable"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SSID_NOT_FOUND,                 "ssid-not-found"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED,    "secondary-connection-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED,                "dcb-fcoe-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED,           "teamd-control-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_FAILED,                   "modem-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_AVAILABLE,                "modem-available"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT,              "sim-pin-incorrect"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION,                 "new-activation"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED,                 "parent-changed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED,         "parent-managed-changed"),
 );
 
 #define reason_to_string(reason) \
-	NM_UTILS_STRING_LOOKUP_TABLE (_reason_to_string, reason)
+	NM_UTILS_LOOKUP_STR (_reason_to_string, reason)
 
 /***********************************************************/
 
@@ -649,7 +653,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface)
 
 	/* Emit change notification */
 	if (g_strcmp0 (old_ip_iface, priv->ip_iface))
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
+		_notify (self, PROP_IP_IFACE);
 	g_free (old_ip_iface);
 }
 
@@ -772,6 +776,7 @@ nm_device_get_priority (NMDevice *self)
 	switch (nm_device_get_device_type (self)) {
 	/* 50 is reserved for VPN (NM_VPN_ROUTE_METRIC_DEFAULT) */
 	case NM_DEVICE_TYPE_ETHERNET:
+	case NM_DEVICE_TYPE_VETH:
 		return 100;
 	case NM_DEVICE_TYPE_INFINIBAND:
 		return 150;
@@ -981,6 +986,26 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla
 	return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags);
 }
 
+NMSetting *
+nm_device_get_applied_setting (NMDevice *device, GType setting_type)
+{
+	NMActRequest *req;
+	NMSetting *setting = NULL;
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	req = nm_device_get_act_request (device);
+	if (req) {
+		NMConnection *connection;
+
+		connection = nm_act_request_get_applied_connection (req);
+		if (connection)
+			setting = nm_connection_get_setting (connection, setting_type);
+	}
+
+	return setting;
+}
+
 RfKillType
 nm_device_get_rfkill_type (NMDevice *self)
 {
@@ -1158,6 +1183,7 @@ nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean co
 	 * when slaves change.
 	 */
 	nm_device_update_hw_address (self);
+	nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, NM_UNMAN_FLAG_OP_FORGET, NM_DEVICE_STATE_REASON_REMOVED);
 }
 
 /**
@@ -1173,54 +1199,6 @@ can_unmanaged_external_down (NMDevice *self)
 	return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
 }
 
-/**
- * nm_device_finish_init:
- * @self: the master device
- *
- * Whatever needs to be done post-initialization, when the device has a DBus
- * object name.
- */
-void
-nm_device_finish_init (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	g_assert (priv->initialized == FALSE);
-
-	/* Do not manage externally created software devices until they are IFF_UP */
-	if (   NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)
-	    && priv->ifindex > 0
-	    && (   !priv->up
-	        || !priv->platform_link_initialized))
-		nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE);
-
-	if (priv->master)
-		nm_device_master_enslave_slave (priv->master, self, NULL);
-
-	if (priv->ifindex > 0) {
-		if (priv->ifindex == 1) {
-			/* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag.
-			 * Later we might want to manage 'lo' too. Currently that doesn't work because
-			 * NetworkManager might down the interface or remove the 127.0.0.1 address. */
-			nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_LOOPBACK, TRUE);
-		} else if (priv->platform_link_initialized || (priv->is_nm_owned && nm_device_is_software (self))) {
-			gboolean platform_unmanaged = FALSE;
-
-			if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged))
-				nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_DEFAULT, platform_unmanaged);
-		} else {
-			/* Hardware and externally-created software links stay unmanaged
-			 * until they are fully initialized by the platform. NM created
-			 * links must be available for activation immediately and thus
-			 * do not get the PLATFORM_INIT unmanaged flag set.
-			 */
-			nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_PLATFORM_INIT, TRUE);
-		}
-	}
-
-	priv->initialized = TRUE;
-}
-
 static void
 update_dynamic_ip_setup (NMDevice *self)
 {
@@ -1272,7 +1250,7 @@ carrier_changed (NMDevice *self, gboolean carrier)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
-	if (!nm_device_get_managed (self))
+	if (priv->state <= NM_DEVICE_STATE_UNMANAGED)
 		return;
 
 	nm_device_recheck_available_connections (self);
@@ -1304,8 +1282,6 @@ carrier_changed (NMDevice *self, gboolean carrier)
 	}
 
 	if (carrier) {
-		g_warn_if_fail (priv->state >= NM_DEVICE_STATE_UNAVAILABLE);
-
 		if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
 			nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED,
 			                       NM_DEVICE_STATE_REASON_CARRIER);
@@ -1324,8 +1300,6 @@ carrier_changed (NMDevice *self, gboolean carrier)
 			update_dynamic_ip_setup (self);
 		}
 	} else {
-		g_return_if_fail (priv->state >= NM_DEVICE_STATE_UNAVAILABLE);
-
 		if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
 			if (nm_device_queued_state_peek (self) >= NM_DEVICE_STATE_DISCONNECTED)
 				nm_device_queued_state_clear (self);
@@ -1378,7 +1352,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
 		return;
 
 	priv->carrier = carrier;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_CARRIER);
+	_notify (self, PROP_CARRIER);
 
 	if (priv->carrier) {
 		_LOGI (LOGD_DEVICE, "link connected");
@@ -1450,7 +1424,6 @@ device_link_changed (NMDevice *self)
 	NMPlatformLink info;
 	const NMPlatformLink *pllink;
 	int ifindex;
-	gboolean just_initialized = FALSE;
 	gboolean was_up;
 
 	priv->device_link_changed_id = 0;
@@ -1467,26 +1440,26 @@ device_link_changed (NMDevice *self)
 		/* Update UDI to what udev gives us */
 		g_free (priv->udi);
 		priv->udi = g_strdup (udi);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+		_notify (self, PROP_UDI);
 	}
 
 	if (g_strcmp0 (info.driver, priv->driver)) {
 		/* Update driver to what udev gives us */
 		g_free (priv->driver);
 		priv->driver = g_strdup (info.driver);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
+		_notify (self, PROP_DRIVER);
 	}
 
 	/* Update MTU if it has changed. */
 	if (priv->mtu != info.mtu) {
 		priv->mtu = info.mtu;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_MTU);
+		_notify (self, PROP_MTU);
 	}
 
 	if (info.driver && g_strcmp0 (priv->driver, info.driver) != 0) {
 		g_free (priv->driver);
 		priv->driver = g_strdup (info.driver);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
+		_notify (self, PROP_DRIVER);
 	}
 
 	if (info.name[0] && strcmp (priv->iface, info.name) != 0) {
@@ -1498,9 +1471,9 @@ device_link_changed (NMDevice *self)
 		/* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */
 		ip_ifname_changed = !priv->ip_iface;
 
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE);
+		_notify (self, PROP_IFACE);
 		if (ip_ifname_changed)
-			g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
+			_notify (self, PROP_IP_IFACE);
 
 		/* Re-match available connections against the new interface name */
 		nm_device_recheck_available_connections (self);
@@ -1524,71 +1497,62 @@ device_link_changed (NMDevice *self)
 	if (ip_ifname_changed)
 		update_dynamic_ip_setup (self);
 
-	if (priv->ifindex > 0 && !priv->platform_link_initialized && info.initialized) {
-		gboolean platform_unmanaged = FALSE;
-
-		priv->platform_link_initialized = TRUE;
-
-		if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) {
-			nm_device_set_unmanaged_flags (self,
-			                               NM_UNMANAGED_DEFAULT,
-			                               platform_unmanaged,
-			                               NM_DEVICE_STATE_REASON_USER_REQUESTED);
-		}
-
-		nm_device_set_unmanaged_flags (self,
-		                               NM_UNMANAGED_PLATFORM_INIT,
-		                               FALSE,
-		                               NM_DEVICE_STATE_REASON_NOW_MANAGED);
-
-		just_initialized = TRUE;
-	}
-
 	was_up = priv->up;
-	priv->up = NM_FLAGS_HAS (info.flags, IFF_UP);
+	priv->up = NM_FLAGS_HAS (info.n_ifi_flags, IFF_UP);
+
+	if (   priv->ifindex > 0
+	    && info.initialized
+	    && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
+		NMDeviceStateReason reason;
+
+		nm_device_set_unmanaged_by_user_udev (self);
+
+		/* If the devices that need an external IFF_UP go managed below,
+		 * it means they're already up. In that case we should use an "assumed"
+		 * reason to prevent the cleanup sequence from being run on transition
+		 * from "unmanaged" to "unavailable". */
+		if (   priv->up
+		    && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)
+		    && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) {
+			/* Ensure the assume check is queued before any queued state changes
+			 * from the transition to UNAVAILABLE.
+			 */
+			nm_device_queue_recheck_assume (self);
+			reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED;
+		} else
+			reason = NM_DEVICE_STATE_REASON_NOW_MANAGED;
 
-	if (   priv->platform_link_initialized
-	    && (   just_initialized
-	        || priv->up != was_up)) {
+		nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason);
+	}
 
+	if (   priv->ifindex > 0
+	    && priv->up != was_up
+	    && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) {
 		/* Manage externally-created software interfaces only when they are IFF_UP */
-		g_assert (priv->ifindex > 0);
-		if (NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) {
-			gboolean external_down = !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN);
-
-			if (external_down && NM_FLAGS_HAS (info.flags, IFF_UP)) {
-				if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) {
-					/* Ensure the assume check is queued before any queued state changes
-					 * from the transition to UNAVAILABLE.
-					 */
-					nm_device_queue_recheck_assume (self);
-
-					/* Resetting the EXTERNAL_DOWN flag may change the device's state
-					 * to UNAVAILABLE.  To ensure that the state change doesn't touch
-					 * the device before assumption occurs, pass
-					 * NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED as the reason.
-					 */
-					nm_device_set_unmanaged_flags (self,
-					                               NM_UNMANAGED_EXTERNAL_DOWN,
-					                               FALSE,
-					                               NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
-				} else {
-					/* Don't trigger a state change; if the device is in a
-					 * state higher than UNAVAILABLE, it is already IFF_UP
-					 * or an explicit activation request was received.
-					 */
-					_set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, FALSE);
-				}
-			} else if (!external_down && !NM_FLAGS_HAS (info.flags, IFF_UP) && nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) {
-				/* If the device is already disconnected and is set !IFF_UP,
-				 * unmanage it.
-				 */
-				nm_device_set_unmanaged_flags (self,
-				                               NM_UNMANAGED_EXTERNAL_DOWN,
-				                               TRUE,
-				                               NM_DEVICE_STATE_REASON_USER_REQUESTED);
-			}
+		if (   priv->up
+		    && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) {
+			/* Ensure the assume check is queued before any queued state changes
+			 * from the transition to UNAVAILABLE.
+			 */
+			nm_device_queue_recheck_assume (self);
 		}
+
+		/* In case of @priv->up, resetting the EXTERNAL_DOWN flag may change the device's
+		 * state to UNAVAILABLE. To ensure that the state change doesn't touch
+		 * the device before assumption occurs, pass NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED
+		 * as the reason.
+		 *
+		 * In case of !@priv->up, and the device is already unmanaged for other reasons, the
+		 * state-change-reason has no effect.
+		 * If the device is managed for an explict user-request, the state-change-reason
+		 * also has no effect, because the device stays managed.
+		 *
+		 * The state-change-reason only has effect if the device was assumed
+		 * and is now to be unmanaged. */
+		nm_device_set_unmanaged_by_flags (self,
+		                                  NM_UNMANAGED_EXTERNAL_DOWN,
+		                                  !priv->up,
+		                                  NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
 	}
 
 	device_recheck_slave_status (self, &info);
@@ -1617,7 +1581,7 @@ device_ip_link_changed (NMDevice *self)
 		g_free (priv->ip_iface);
 		priv->ip_iface = g_strdup (pllink->name);
 
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
+		_notify (self, PROP_IP_IFACE);
 		update_dynamic_ip_setup (self);
 	}
 	return G_SOURCE_REMOVE;
@@ -1782,7 +1746,11 @@ nm_device_create_and_realize (NMDevice *self,
 	realize_start_setup (self, plink);
 	nm_device_realize_finish (self, plink);
 
-	g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE);
+	if (nm_device_get_managed (self, FALSE)) {
+		nm_device_state_changed (self,
+		                         NM_DEVICE_STATE_UNAVAILABLE,
+		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
+	}
 	return TRUE;
 }
 
@@ -1798,25 +1766,24 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
 	if (udi && !g_strcmp0 (udi, priv->udi)) {
 		g_free (priv->udi);
 		priv->udi = g_strdup (udi);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+		_notify (self, PROP_UDI);
 	}
 
 	if (!g_strcmp0 (plink->name, priv->iface)) {
 		g_free (priv->iface);
 		priv->iface = g_strdup (plink->name);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE);
+		_notify (self, PROP_IFACE);
 	}
 
 	priv->ifindex = plink->ifindex;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX);
+	_notify (self, PROP_IFINDEX);
 
-	priv->up = NM_FLAGS_HAS (plink->flags, IFF_UP);
+	priv->up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP);
 	if (plink->driver && g_strcmp0 (plink->driver, priv->driver) != 0) {
 		g_free (priv->driver);
 		priv->driver = g_strdup (plink->driver);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
+		_notify (self, PROP_DRIVER);
 	}
-	priv->platform_link_initialized = plink->initialized;
 }
 
 static void
@@ -1874,6 +1841,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 
 	/* The device should not be realized */
 	g_return_if_fail (!priv->real);
+	g_return_if_fail (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT));
 	g_return_if_fail (priv->ip_ifindex <= 0);
 	g_return_if_fail (priv->ip_iface == NULL);
 
@@ -1891,7 +1859,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 
 	if (priv->ifindex > 0) {
 		priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
+		_notify (self, PROP_PHYSICAL_PORT_ID);
 
 		priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex);
 
@@ -1899,7 +1867,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 			priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE;
 
 		priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_MTU);
+		_notify (self, PROP_MTU);
 
 		nm_platform_link_get_driver_info (NM_PLATFORM_GET,
 		                                  priv->ifindex,
@@ -1907,9 +1875,9 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 		                                  &priv->driver_version,
 		                                  &priv->firmware_version);
 		if (priv->driver_version)
-			g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION);
+			_notify (self, PROP_DRIVER_VERSION);
 		if (priv->firmware_version)
-			g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION);
+			_notify (self, PROP_FIRMWARE_VERSION);
 
 		if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET))
 			priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ifindex);
@@ -1921,7 +1889,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 	if (!priv->udi) {
 		/* Use a placeholder UDI until we get a real one */
 		priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+		_notify (self, PROP_UDI);
 	}
 
 	/* trigger initial ip config change to initialize ip-config */
@@ -1951,9 +1919,26 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 		priv->carrier = TRUE;
 	}
 
-	g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
+	_notify (self, PROP_CAPABILITIES);
 
 	klass->realize_start_notify (self, plink);
+
+	/* Do not manage externally created software devices until they are IFF_UP */
+	if (   priv->ifindex > 0
+	    && plink
+	    && !priv->up
+	    && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self))
+		nm_device_set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE);
+
+	/* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag.
+	 * Later we might want to manage 'lo' too. Currently that doesn't work because
+	 * NetworkManager might down the interface or remove the 127.0.0.1 address. */
+	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_LOOPBACK, priv->ifindex == 1);
+
+	nm_device_set_unmanaged_by_user_udev (self);
+
+	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
+	                               plink && !plink->initialized);
 }
 
 /**
@@ -1977,17 +1962,15 @@ nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink)
 
 	g_return_if_fail (!priv->real);
 
-	if (plink) {
-		update_device_from_platform_link (self, plink);
+	if (plink)
 		device_recheck_slave_status (self, plink);
-	}
 
 	priv->real = TRUE;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
+	_notify (self, PROP_REAL);
 
 	nm_device_recheck_available_connections (self);
 
-	/* Balanced by a freeze in realize_start_setup() */
+	/* Balanced by a freeze in realize_start_setup(). */
 	g_object_thaw_notify (G_OBJECT (self));
 }
 
@@ -2000,7 +1983,7 @@ unrealize_notify (NMDevice *self)
 }
 
 static gboolean
-available_connection_check_delete_unrealized_on_idle (gpointer user_data)
+available_connections_check_delete_unrealized_on_idle (gpointer user_data)
 {
 	NMDevice *self = user_data;
 	NMDevicePrivate *priv;
@@ -2019,7 +2002,7 @@ available_connection_check_delete_unrealized_on_idle (gpointer user_data)
 }
 
 static void
-available_connection_check_delete_unrealized (NMDevice *self)
+available_connections_check_delete_unrealized (NMDevice *self)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
@@ -2028,7 +2011,7 @@ available_connection_check_delete_unrealized (NMDevice *self)
 
 	if (   g_hash_table_size (priv->available_connections) == 0
 	    && !nm_device_is_real (self))
-		priv->check_delete_unrealized_id = g_idle_add (available_connection_check_delete_unrealized_on_idle, self);
+		priv->check_delete_unrealized_id = g_idle_add (available_connections_check_delete_unrealized_on_idle, self);
 }
 
 /**
@@ -2078,32 +2061,32 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
 
 	if (priv->ifindex > 0) {
 		priv->ifindex = 0;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX);
+		_notify (self, PROP_IFINDEX);
 	}
 	priv->ip_ifindex = 0;
 	if (priv->ip_iface) {
 		g_clear_pointer (&priv->ip_iface, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
+		_notify (self, PROP_IP_IFACE);
 	}
 	if (priv->driver_version) {
 		g_clear_pointer (&priv->driver_version, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION);
+		_notify (self, PROP_DRIVER_VERSION);
 	}
 	if (priv->firmware_version) {
 		g_clear_pointer (&priv->firmware_version, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION);
+		_notify (self, PROP_FIRMWARE_VERSION);
 	}
 	if (priv->udi) {
 		g_clear_pointer (&priv->udi, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+		_notify (self, PROP_UDI);
 	}
 	if (priv->hw_addr) {
 		g_clear_pointer (&priv->hw_addr, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS);
+		_notify (self, PROP_HW_ADDRESS);
 	}
 	if (priv->physical_port_id) {
 		g_clear_pointer (&priv->physical_port_id, g_free);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
+		_notify (self, PROP_PHYSICAL_PORT_ID);
 	}
 
 	g_clear_pointer (&priv->perm_hw_addr, g_free);
@@ -2112,15 +2095,27 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
 	priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
 	if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
 		priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
+	_notify (self, PROP_CAPABILITIES);
 
 	priv->real = FALSE;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
+	_notify (self, PROP_REAL);
 
 	nm_device_set_autoconnect (self, DEFAULT_AUTOCONNECT);
 
 	g_object_thaw_notify (G_OBJECT (self));
 
+	nm_device_set_unmanaged_flags (self,
+	                               NM_UNMANAGED_PLATFORM_INIT,
+	                               TRUE);
+
+	nm_device_set_unmanaged_flags (self,
+	                               NM_UNMANAGED_PARENT |
+	                               NM_UNMANAGED_LOOPBACK |
+	                               NM_UNMANAGED_USER_UDEV |
+	                               NM_UNMANAGED_EXTERNAL_DOWN |
+	                               NM_UNMANAGED_IS_SLAVE,
+	                               NM_UNMAN_FLAG_OP_FORGET);
+
 	nm_device_state_changed (self,
 	                         NM_DEVICE_STATE_UNMANAGED,
 	                         remove_resources ?
@@ -2295,10 +2290,13 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure)
 
 		/* no need to emit
 		 *
-		 *   g_object_notify (G_OBJECT (slave), NM_DEVICE_MASTER);
+		 *   _notify (slave, PROP_MASTER);
 		 *
 		 * because slave_priv->is_enslaved is not true, thus the value
 		 * didn't change yet. */
+
+		g_warn_if_fail (!NM_FLAGS_HAS (slave_priv->unmanaged_mask, NM_UNMANAGED_IS_SLAVE));
+		nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
 	} else
 		g_return_if_fail (slave_priv->master == self);
 
@@ -2476,8 +2474,8 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success)
 				_LOGI (LOGD_DEVICE, "enslaved to %s", nm_device_get_iface (priv->master));
 
 			priv->is_enslaved = TRUE;
-			g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER);
-			g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES);
+			_notify (self, PROP_MASTER);
+			_notify (priv->master, PROP_SLAVES);
 		} else if (activating) {
 			_LOGW (LOGD_DEVICE, "Activation: connection '%s' could not be enslaved",
 			       nm_connection_get_id (connection));
@@ -2535,8 +2533,8 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason)
 
 	if (priv->is_enslaved) {
 		priv->is_enslaved = FALSE;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER);
-		g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES);
+		_notify (self, PROP_MASTER);
+		_notify (priv->master, PROP_SLAVES);
 	}
 }
 
@@ -2662,19 +2660,12 @@ nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect)
 
 	g_return_if_fail (NM_IS_DEVICE (self));
 
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	if (priv->autoconnect == autoconnect)
-		return;
+	autoconnect = !!autoconnect;
 
-	if (autoconnect) {
-		/* Default-unmanaged devices never autoconnect */
-		if (!nm_device_get_default_unmanaged (self)) {
-			priv->autoconnect = TRUE;
-			g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT);
-		}
-	} else {
-		priv->autoconnect = FALSE;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT);
+	priv = NM_DEVICE_GET_PRIVATE (self);
+	if (priv->autoconnect != autoconnect) {
+		priv->autoconnect = autoconnect;
+		_notify (self, PROP_AUTOCONNECT);
 	}
 }
 
@@ -2980,15 +2971,18 @@ nm_device_complete_connection (NMDevice *self,
 static gboolean
 check_connection_compatible (NMDevice *self, NMConnection *connection)
 {
-	NMSettingConnection *s_con;
-	const char *config_iface, *device_iface;
+	const char *device_iface = nm_device_get_iface (self);
+	gs_free char *conn_iface = nm_manager_get_connection_iface (nm_manager_get (),
+	                                                            connection,
+	                                                            NULL, NULL);
 
-	s_con = nm_connection_get_setting_connection (connection);
-	g_assert (s_con);
+	/* We always need a interface name for virtual devices, but for
+	 * physical ones a connection without interface name is fine for
+	 * any device. */
+	if (!conn_iface)
+		return !nm_connection_is_virtual (connection);
 
-	config_iface = nm_setting_connection_get_interface_name (s_con);
-	device_iface = nm_device_get_iface (self);
-	if (config_iface && strcmp (config_iface, device_iface) != 0)
+	if (strcmp (conn_iface, device_iface) != 0)
 		return FALSE;
 
 	return TRUE;
@@ -3401,7 +3395,7 @@ lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec,
 {
 	NMDevice *self = NM_DEVICE (user_data);
 
-	g_object_notify (G_OBJECT (self), NM_DEVICE_LLDP_NEIGHBORS);
+	_notify (self, PROP_LLDP_NEIGHBORS);
 }
 
 static gboolean
@@ -3457,7 +3451,7 @@ activate_stage1_device_prepare (NMDevice *self)
 	priv->ip4_state = priv->ip6_state = IP_NONE;
 
 	/* Notify the new ActiveConnection along with the state change */
-	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
+	_notify (self, PROP_ACTIVE_CONNECTION);
 
 	nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
 
@@ -3629,12 +3623,12 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
 }
 
 /*
- * nm_device_check_ip_failed
+ * check_ip_failed
  *
  * Progress the device to appropriate state if both IPv4 and IPv6 failed
  */
 static void
-nm_device_check_ip_failed (NMDevice *self, gboolean may_fail)
+check_ip_failed (NMDevice *self, gboolean may_fail)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMDeviceState state;
@@ -3664,6 +3658,212 @@ nm_device_check_ip_failed (NMDevice *self, gboolean may_fail)
 	                         NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
 }
 
+/*
+ * check_ip_done
+ *
+ * Progress the device to ip connectivity check state if IPv4 or IPv6 succeeded
+ */
+static void
+check_ip_done (NMDevice *self)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+	if (nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG)
+		return;
+
+	if (priv->ip4_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET))
+		return;
+
+	if (priv->ip6_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET6))
+		return;
+
+	nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
+}
+
+/*********************************************/
+/* IPv4 DAD stuff */
+
+static guint
+get_ipv4_dad_timeout (NMDevice *self)
+{
+	NMConnection *connection;
+	NMSettingIPConfig *s_ip4 = NULL;
+	gs_free char *value = NULL;
+	gint ret = 0;
+
+	connection = nm_device_get_applied_connection (self);
+	if (connection)
+		s_ip4 = nm_connection_get_setting_ip4_config (connection);
+
+	if (s_ip4) {
+		ret = nm_setting_ip_config_get_dad_timeout (s_ip4);
+
+		if (ret < 0) {
+			value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+			                                               "ipv4.dad-timeout", self);
+			ret = _nm_utils_ascii_str_to_int64 (value, 10, -1,
+			                                    NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX,
+			                                    -1);
+			ret = ret < 0 ? 0 : ret;
+		}
+	}
+
+	return ret;
+}
+
+static void
+arping_data_destroy (gpointer ptr, GClosure *closure)
+{
+	ArpingData *data = ptr;
+	int i;
+
+	if (data) {
+		for (i = 0; data->configs && data->configs[i]; i++)
+			g_object_unref (data->configs[i]);
+		g_free (data->configs);
+		g_slice_free (ArpingData, data);
+	}
+}
+
+static void
+ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean success)
+{
+	NMIP4Config *empty;
+
+	if (success) {
+		empty = nm_ip4_config_new (nm_device_get_ip_ifindex (self));
+		nm_device_activate_schedule_ip4_config_result (self, empty);
+		g_object_unref (empty);
+	} else {
+		nm_device_queue_state (self, NM_DEVICE_STATE_FAILED,
+		                       NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+	}
+}
+
+static void
+arping_manager_probe_terminated (NMArpingManager *arping_manager, ArpingData *data)
+{
+	NMDevice *self;
+	NMDevicePrivate *priv;
+	const NMPlatformIP4Address *address;
+	gboolean result, success = TRUE;
+	int i, j;
+
+	g_assert (data);
+	self = data->device;
+	priv = NM_DEVICE_GET_PRIVATE (self);
+
+	for (i = 0; data->configs && data->configs[i]; i++) {
+		for (j = 0; j < nm_ip4_config_get_num_addresses (data->configs[i]); j++) {
+			address = nm_ip4_config_get_address (data->configs[i], j);
+			result = nm_arping_manager_check_address (arping_manager, address->address);
+			success &= result;
+
+			_NMLOG (result ? LOGL_DEBUG : LOGL_WARN,
+			        LOGD_DEVICE,
+			        "IPv4 DAD result: address %s is %s",
+			        nm_utils_inet4_ntop (address->address, NULL),
+			        result ? "unique" : "duplicate");
+		}
+	}
+
+	data->callback (self, data->configs, success);
+
+	priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager);
+	nm_arping_manager_destroy (arping_manager);
+}
+
+/**
+ * ipv4_dad_start:
+ * @self: device instance
+ * @configs: NULL-terminated array of IPv4 configurations
+ * @cb: callback function
+ *
+ * Start IPv4 DAD on device @self, check addresses in @configs and call @cb
+ * when the procedure ends. @cb will be called in any case, even if DAD can't
+ * be started. @configs will be unreferenced after @cb has been called.
+ */
+static void
+ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	NMArpingManager *arping_manager;
+	const NMPlatformIP4Address *address;
+	ArpingData *data;
+	guint timeout;
+	gboolean ret, addr_found;
+	const guint8 *hw_addr;
+	size_t hw_addr_len = 0;
+	GError *error = NULL;
+	guint i, j;
+
+	g_return_if_fail (NM_IS_DEVICE (self));
+	g_return_if_fail (configs);
+	g_return_if_fail (cb);
+
+	for (i = 0, addr_found = FALSE; configs[i]; i++) {
+		if (nm_ip4_config_get_num_addresses (configs[i]) > 0) {
+			addr_found = TRUE;
+			break;
+		}
+	}
+
+	timeout = get_ipv4_dad_timeout (self);
+	hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET,
+	                                        nm_device_get_ip_ifindex (self),
+	                                        &hw_addr_len);
+
+	if (   !timeout
+	    || !hw_addr
+	    || !hw_addr_len
+	    || !addr_found
+	    || nm_device_uses_assumed_connection (self)) {
+
+		/* DAD not needed, signal success */
+		cb (self, configs, TRUE);
+
+		for (i = 0; configs[i]; i++)
+			g_object_unref (configs[i]);
+		g_free (configs);
+
+		return;
+	}
+
+	/* don't take additional references of @arping_manager that outlive @self.
+	 * Otherwise, the callback can be invoked on a dangling pointer as we don't
+	 * disconnect the handler. */
+	arping_manager = nm_arping_manager_new (nm_device_get_ip_ifindex (self));
+	priv->arping.dad_list = g_slist_append (priv->arping.dad_list, arping_manager);
+
+	data = g_slice_new0 (ArpingData);
+	data->configs = configs;
+	data->callback = cb;
+	data->device = self;
+
+	for (i = 0; configs[i]; i++) {
+		for (j = 0; j < nm_ip4_config_get_num_addresses (configs[i]); j++) {
+			address = nm_ip4_config_get_address (configs[i], j);
+			nm_arping_manager_add_address (arping_manager, address->address);
+		}
+	}
+
+	g_signal_connect_data (arping_manager, NM_ARPING_MANAGER_PROBE_TERMINATED,
+	                       G_CALLBACK (arping_manager_probe_terminated), data,
+	                       arping_data_destroy, 0);
+
+	ret = nm_arping_manager_start_probe (arping_manager, timeout, &error);
+
+	if (!ret) {
+		_LOGW (LOGD_DEVICE, "arping probe failed: %s", error->message);
+
+		/* DAD could not be started, signal success */
+		cb (self, configs, TRUE);
+
+		priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager);
+		nm_arping_manager_destroy (arping_manager);
+	}
+}
+
 /*********************************************/
 /* IPv4LL stuff */
 
@@ -3738,14 +3938,14 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
 		if (r < 0) {
 			_LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r);
 			priv->ip4_state = IP_FAIL;
-			nm_device_check_ip_failed (self, FALSE);
+			check_ip_failed (self, FALSE);
 			return;
 		}
 
 		if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) {
 			_LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr);
 			priv->ip4_state = IP_FAIL;
-			nm_device_check_ip_failed (self, FALSE);
+			check_ip_failed (self, FALSE);
 			return;
 		}
 
@@ -3753,7 +3953,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
 		if (config == NULL) {
 			_LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config");
 			priv->ip4_state = IP_FAIL;
-			nm_device_check_ip_failed (self, FALSE);
+			check_ip_failed (self, FALSE);
 			return;
 		}
 
@@ -3764,7 +3964,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
 			if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) {
 				_LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change.");
 				priv->ip4_state = IP_FAIL;
-				nm_device_check_ip_failed (self, FALSE);
+				check_ip_failed (self, FALSE);
 			}
 		} else
 			g_assert_not_reached ();
@@ -3774,7 +3974,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
 	default:
 		_LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event);
 		priv->ip4_state = IP_FAIL;
-		nm_device_check_ip_failed (self, FALSE);
+		check_ip_failed (self, FALSE);
 	}
 }
 
@@ -3985,7 +4185,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
 
 	if (priv->dhcp4_config) {
 		nm_exported_object_clear_and_unexport (&priv->dhcp4_config);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
+		_notify (self, PROP_DHCP4_CONFIG);
 	}
 }
 
@@ -4156,6 +4356,8 @@ END_ADD_DEFAULT_ROUTE:
 		priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4);
 	}
 
+	nm_ip4_config_addresses_sort (composite);
+
 	/* Allow setting MTU etc */
 	if (commit) {
 		if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
@@ -4253,6 +4455,17 @@ dhcp4_fail (NMDevice *self, gboolean timeout)
 }
 
 static void
+dhcp4_dad_cb (NMDevice *self, NMIP4Config **configs, gboolean success)
+{
+	if (success)
+		nm_device_activate_schedule_ip4_config_result (self, configs[1]);
+	else {
+		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED,
+		                         NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+	}
+}
+
+static void
 dhcp4_state_changed (NMDhcpClient *client,
                      NMDhcpState state,
                      NMIP4Config *ip4_config,
@@ -4262,6 +4475,8 @@ dhcp4_state_changed (NMDhcpClient *client,
 {
 	NMDevice *self = NM_DEVICE (user_data);
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	NMIP4Config *manual, **configs;
+	NMConnection *connection;
 
 	g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE);
 	g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config));
@@ -4279,11 +4494,23 @@ dhcp4_state_changed (NMDhcpClient *client,
 		}
 
 		nm_dhcp4_config_set_options (priv->dhcp4_config, options);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
+		_notify (self, PROP_DHCP4_CONFIG);
 
-		if (priv->ip4_state == IP_CONF)
-			nm_device_activate_schedule_ip4_config_result (self, ip4_config);
-		else if (priv->ip4_state == IP_DONE) {
+		if (priv->ip4_state == IP_CONF) {
+			connection = nm_device_get_applied_connection (self);
+			g_assert (connection);
+
+			manual = nm_ip4_config_new (nm_device_get_ip_ifindex (self));
+			nm_ip4_config_merge_setting (manual,
+			                             nm_connection_get_setting_ip4_config (connection),
+			                             nm_device_get_ip4_route_metric (self));
+
+			configs = g_new0 (NMIP4Config *, 3);
+			configs[0] = manual;
+			configs[1] = g_object_ref (ip4_config);
+
+			ipv4_dad_start (self, configs, dhcp4_dad_cb);
+		} else if (priv->ip4_state == IP_DONE) {
 			dhcp4_lease_change (self, ip4_config);
 			nm_device_update_metered (self);
 		}
@@ -4312,7 +4539,7 @@ dhcp4_get_timeout (NMDevice *self, NMSettingIP4Config *s_ip4)
 	gs_free char *value = NULL;
 	int timeout;
 
-	timeout = nm_setting_ip4_config_get_dhcp_timeout (s_ip4);
+	timeout = nm_setting_ip_config_get_dhcp_timeout (NM_SETTING_IP_CONFIG (s_ip4));
 	if (timeout)
 		return timeout;
 
@@ -4629,10 +4856,17 @@ act_stage3_ip4_config_start (NMDevice *self,
 	else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0)
 		ret = ipv4ll_start (self, reason);
 	else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
-		/* Use only IPv4 config from the connection data */
-		*out_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self));
-		g_assert (*out_config);
-		ret = NM_ACT_STAGE_RETURN_SUCCESS;
+		NMIP4Config **configs, *config;
+
+		config = nm_ip4_config_new (nm_device_get_ip_ifindex (self));
+		nm_ip4_config_merge_setting (config,
+		                             nm_connection_get_setting_ip4_config (connection),
+		                             nm_device_get_ip4_route_metric (self));
+
+		configs = g_new0 (NMIP4Config *, 2);
+		configs[0] = config;
+		ipv4_dad_start (self, configs, ipv4_manual_method_apply);
+		ret = NM_ACT_STAGE_RETURN_POSTPONE;
 	} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
 		*out_config = shared4_new_config (self, connection, reason);
 		if (*out_config) {
@@ -4676,7 +4910,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
 
 	if (priv->dhcp6_config) {
 		nm_exported_object_clear_and_unexport (&priv->dhcp6_config);
-		g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+		_notify (self, PROP_DHCP6_CONFIG);
 	}
 }
 
@@ -5011,7 +5245,7 @@ dhcp6_state_changed (NMDhcpClient *client,
 				priv->dhcp6_ip6_config = g_object_ref (ip6_config);
 				priv->dhcp6_event_id = g_strdup (event_id);
 				nm_dhcp6_config_set_options (priv->dhcp6_config, options);
-				g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+				_notify (self, PROP_DHCP6_CONFIG);
 			}
 		}
 
@@ -5057,9 +5291,7 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
 	GByteArray *tmp = NULL;
 	const guint8 *hw_addr;
 	size_t hw_addr_len = 0;
-	const struct in6_addr *ll_addr = NULL;
-	NMIP6Config *ip6_config;
-	int i;
+	const NMPlatformIP6Address *ll_addr = NULL;
 
 	g_assert (connection);
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
@@ -5071,22 +5303,16 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
 		g_byte_array_append (tmp, hw_addr, hw_addr_len);
 	}
 
-	ip6_config = priv->ext_ip6_config;
-	for (i = 0; ip6_config && i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
-		const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i);
+	if (priv->ext_ip6_config_captured)
+		ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE);
 
-		if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
-			ll_addr = &addr->address;
-			break;
-		}
-	}
 	g_return_val_if_fail (ll_addr, FALSE);
 
 	priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (),
 	                                                nm_device_get_ip_iface (self),
 	                                                nm_device_get_ip_ifindex (self),
 	                                                tmp,
-	                                                ll_addr,
+	                                                &ll_addr->address,
 	                                                nm_connection_get_uuid (connection),
 	                                                nm_device_get_ip6_route_metric (self),
 	                                                nm_setting_ip_config_get_dhcp_send_hostname (s_ip6),
@@ -5169,27 +5395,6 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release)
 
 /******************************************/
 
-static gboolean
-have_ip6_address (const NMIP6Config *ip6_config, gboolean linklocal)
-{
-	guint i;
-
-	if (!ip6_config)
-		return FALSE;
-
-	linklocal = !!linklocal;
-
-	for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
-		const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i);
-
-		if ((IN6_IS_ADDR_LINKLOCAL (&addr->address) == linklocal) &&
-		    !(addr->flags & IFA_F_TENTATIVE))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
 static void
 linklocal6_cleanup (NMDevice *self)
 {
@@ -5223,7 +5428,7 @@ linklocal6_complete (NMDevice *self)
 	const char *method;
 
 	g_assert (priv->linklocal6_timeout_id);
-	g_assert (have_ip6_address (priv->ip6_config, TRUE));
+	g_assert (nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE));
 
 	linklocal6_cleanup (self);
 
@@ -5271,7 +5476,7 @@ check_and_add_ipv6ll_addr (NMDevice *self)
 
 			addr = nm_ip6_config_get_address (priv->ip6_config, i);
 			if (   IN6_IS_ADDR_LINKLOCAL (&addr->address)
-			    && !(addr->flags & IFA_F_DADFAILED)) {
+			    && !(addr->n_ifa_flags & IFA_F_DADFAILED)) {
 				/* Already have an LL address, nothing to do */
 				return;
 			}
@@ -5288,9 +5493,9 @@ check_and_add_ipv6ll_addr (NMDevice *self)
 	if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
 		if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr,
 		                                            nm_device_get_iface (self),
-			                                    nm_connection_get_uuid (connection),
+		                                            nm_connection_get_uuid (connection),
 		                                            priv->linklocal6_dad_counter++,
-			                                    &error)) {
+		                                            &error)) {
 			_LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
 			g_clear_error (&error);
 			linklocal6_failed (self);
@@ -5340,7 +5545,8 @@ linklocal6_start (NMDevice *self)
 
 	linklocal6_cleanup (self);
 
-	if (have_ip6_address (priv->ip6_config, TRUE))
+	if (   priv->ip6_config
+	    && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE))
 		return NM_ACT_STAGE_RETURN_FINISH;
 
 	connection = nm_device_get_applied_connection (self);
@@ -5421,7 +5627,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self)
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	int i;
 	int system_support;
-	guint ifa_flags = 0x00;
+	guint32 ifa_flags = 0x00;
 
 	/*
 	 * Check, whether kernel is recent enough to help user space handling RA.
@@ -5477,7 +5683,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self)
 			if (address.preferred > address.lifetime)
 				address.preferred = address.lifetime;
 			address.source = NM_IP_CONFIG_SOURCE_RDISC;
-			address.flags = ifa_flags;
+			address.n_ifa_flags = ifa_flags;
 
 			nm_ip6_config_add_address (priv->ac_ip6_config, &address);
 		}
@@ -5575,7 +5781,8 @@ rdisc_ra_timeout (NMRDisc *rdisc, NMDevice *self)
 		 * IPv6 configuration, like manual IPv6 addresses or external IPv6
 		 * config, consider that sufficient for IPv6 success.
 		 */
-		if (have_ip6_address (priv->ip6_config, FALSE))
+		if (   priv->ip6_config
+		    && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, FALSE))
 			nm_device_activate_schedule_ip6_config_result (self);
 		else
 			nm_device_activate_schedule_ip6_config_timeout (self);
@@ -5769,7 +5976,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
 
 		if (enable) {
 			/* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */
-			value = nm_platform_sysctl_get (NM_PLATFORM_GET, 
+			value = nm_platform_sysctl_get (NM_PLATFORM_GET,
 			                                nm_utils_ip6_property_path (nm_device_get_ip_iface (self), "disable_ipv6"));
 			if (g_strcmp0 (value, "0") == 0)
 				nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1");
@@ -6054,8 +6261,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self)
 	} else if (ret == NM_ACT_STAGE_RETURN_FINISH) {
 		/* Early finish, nothing more to do */
 		priv->ip6_state = IP_DONE;
-		if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
-			nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
+		check_ip_done (self);
 	} else if (ret == NM_ACT_STAGE_RETURN_WAIT) {
 		/* Wait for something to try IP config again */
 		priv->ip6_state = IP_WAIT;
@@ -6116,7 +6322,7 @@ activate_stage3_ip_config_start (NMDevice *self)
 	    && !nm_device_activate_stage3_ip6_start (self))
 		return;
 
-	nm_device_check_ip_failed (self, TRUE);
+	check_ip_failed (self, TRUE);
 }
 
 static gboolean
@@ -6251,7 +6457,7 @@ activate_stage4_ip4_config_timeout (NMDevice *self)
 
 	priv->ip4_state = IP_FAIL;
 
-	nm_device_check_ip_failed (self, FALSE);
+	check_ip_failed (self, FALSE);
 }
 
 
@@ -6311,7 +6517,7 @@ activate_stage4_ip6_config_timeout (NMDevice *self)
 
 	priv->ip6_state = IP_FAIL;
 
-	nm_device_check_ip_failed (self, FALSE);
+	check_ip_failed (self, FALSE);
 }
 
 
@@ -6410,16 +6616,16 @@ start_sharing (NMDevice *self, NMIP4Config *config)
 	req = nm_device_get_act_request (self);
 	g_assert (req);
 
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface);
-	add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface);
-	add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface);
-	add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface);
 	add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask);
+	add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface);
+	add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface);
+	add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface);
+	add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface);
+	add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface);
+	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface);
+	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface);
+	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface);
+	add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface);
 
 	nm_act_request_set_shared (req, TRUE);
 
@@ -6438,77 +6644,14 @@ start_sharing (NMDevice *self, NMIP4Config *config)
 }
 
 static void
-send_arps (NMDevice *self, const char *mode_arg)
-{
-	const char *argv[] = { NULL, mode_arg, "-q", "-I", nm_device_get_ip_iface (self), "-c", "1", NULL, NULL };
-	int ip_arg = G_N_ELEMENTS (argv) - 2;
-	NMConnection *connection;
-	NMSettingIPConfig *s_ip4;
-	int i, num;
-	NMIPAddress *addr;
-	GError *error = NULL;
-
-	connection = nm_device_get_applied_connection (self);
-	if (!connection)
-		return;
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (!s_ip4)
-		return;
-	num = nm_setting_ip_config_get_num_addresses (s_ip4);
-	if (num == 0)
-		return;
-
-	argv[0] = nm_utils_find_helper ("arping", NULL, NULL);
-	if (!argv[0]) {
-		_LOGW (LOGD_DEVICE | LOGD_IP4, "arping could not be found; no ARPs will be sent");
-		return;
-	}
-
-	for (i = 0; i < num; i++) {
-		gs_free char *tmp_str = NULL;
-		gboolean success;
-
-		addr = nm_setting_ip_config_get_address (s_ip4, i);
-		argv[ip_arg] = nm_ip_address_get_address (addr);
-
-		_LOGD (LOGD_DEVICE | LOGD_IP4,
-		       "arping: run %s", (tmp_str = g_strjoinv (" ", (char **) argv)));
-		success = g_spawn_async (NULL, (char **) argv, NULL,
-		                         G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
-		                         NULL, NULL, NULL, &error);
-		if (!success) {
-			_LOGW (LOGD_DEVICE | LOGD_IP4,
-			       "arping: could not send ARP for local address %s: %s",
-			       argv[ip_arg], error->message);
-			g_clear_error (&error);
-		}
-	}
-}
-
-static gboolean
-arp_announce_round2 (gpointer user_data)
-{
-	NMDevice *self = user_data;
-	NMDevicePrivate *priv;
-
-	g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
-
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	priv->arp_round2_id = 0;
-
-	if (   priv->state >= NM_DEVICE_STATE_IP_CONFIG
-	    && priv->state <= NM_DEVICE_STATE_ACTIVATED)
-		send_arps (self, "-U");
-
-	return G_SOURCE_REMOVE;
-}
-
-static void
 arp_cleanup (NMDevice *self)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
-	nm_clear_g_source (&priv->arp_round2_id);
+	if (priv->arping.announcing) {
+		nm_arping_manager_destroy (priv->arping.announcing);
+		priv->arping.announcing = NULL;
+	}
 }
 
 static void
@@ -6517,10 +6660,19 @@ arp_announce (NMDevice *self)
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
-	int num;
+	guint num, i;
+	const guint8 *hw_addr;
+	size_t hw_addr_len = 0;
 
 	arp_cleanup (self);
 
+	hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET,
+	                                        nm_device_get_ip_ifindex (self),
+	                                        &hw_addr_len);
+
+	if (!hw_addr_len || !hw_addr)
+		return;
+
 	/* We only care about manually-configured addresses; DHCP- and autoip-configured
 	 * ones should already have been seen on the network at this point.
 	 */
@@ -6534,8 +6686,19 @@ arp_announce (NMDevice *self)
 	if (num == 0)
 		return;
 
-	send_arps (self, "-A");
-	priv->arp_round2_id = g_timeout_add_seconds (2, arp_announce_round2, self);
+	priv->arping.announcing = nm_arping_manager_new (nm_device_get_ip_ifindex (self));
+
+	for (i = 0; i < num; i++) {
+		NMIPAddress *ip = nm_setting_ip_config_get_address (s_ip4, i);
+		in_addr_t addr;
+
+		if (inet_pton (AF_INET, nm_ip_address_get_address (ip), &addr) == 1)
+			nm_arping_manager_add_address (priv->arping.announcing, addr);
+		else
+			g_warn_if_reached ();
+	}
+
+	nm_arping_manager_announce_addresses (priv->arping.announcing);
 }
 
 static void
@@ -6597,13 +6760,11 @@ activate_stage5_ip4_config_commit (NMDevice *self)
 
 	arp_announce (self);
 
-	/* Enter the IP_CHECK state if this is the first method to complete */
-	priv->ip4_state = IP_DONE;
-
 	nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
 
-	if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
-		nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
+	/* Enter the IP_CHECK state if this is the first method to complete */
+	priv->ip4_state = IP_DONE;
+	check_ip_done (self);
 }
 
 static void
@@ -6690,26 +6851,24 @@ activate_stage5_ip6_config_commit (NMDevice *self)
 				 * then ensure dispatcher scripts get the DHCP lease information.
 				 */
 				nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE,
-						    nm_device_get_settings_connection (self),
-						    nm_device_get_applied_connection (self),
-						    self,
-						    NULL,
-						    NULL,
-						    NULL);
+				                    nm_device_get_settings_connection (self),
+				                    nm_device_get_applied_connection (self),
+				                    self,
+				                    NULL,
+				                    NULL,
+				                    NULL);
 			} else {
 				/* still waiting for first dhcp6 lease. */
 				return;
 			}
 		}
 
-		/* Enter the IP_CHECK state if this is the first method to complete */
-		priv->ip6_state = IP_DONE;
-
 		nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
 		nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
 
-		if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
-			nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
+		/* Enter the IP_CHECK state if this is the first method to complete */
+		priv->ip6_state = IP_DONE;
+		check_ip_done (self);
 	} else {
 		_LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed");
 		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
@@ -6760,7 +6919,7 @@ clear_act_request (NMDevice *self)
 	nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
 
 	g_clear_object (&priv->act_request);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
+	_notify (self, PROP_ACTIVE_CONNECTION);
 }
 
 static void
@@ -6792,7 +6951,7 @@ _update_ip4_address (NMDevice *self)
 		addr = nm_ip4_config_get_address (priv->ip4_config, 0)->address;
 		if (addr != priv->ip4_address) {
 			priv->ip4_address = addr;
-			g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS);
+			_notify (self, PROP_IP4_ADDRESS);
 		}
 	}
 }
@@ -6911,25 +7070,23 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
 	addrconf6_cleanup (self);
 }
 
-G_GNUC_NULL_TERMINATED
 static gboolean
-_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **error, ...)
+_hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GError **error, const char **argv)
 {
-	va_list ap;
-	const char *key;
 	guint found_keys = 0;
+	guint i;
+
+	nm_assert (argv && argv[0]);
 
 #if NM_MORE_ASSERTS > 10
 	/* Assert that the keys are unique. */
 	{
 		gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
 
-		va_start (ap, error);
-		while ((key = va_arg (ap, const char *))) {
-			if (!g_hash_table_add (check_dups, (char *) key))
+		for (i = 0; argv[i]; i++) {
+			if (!g_hash_table_add (check_dups, (char *) argv[i]))
 				nm_assert (FALSE);
 		}
-		va_end (ap);
 		nm_assert (g_hash_table_size (check_dups) > 0);
 	}
 #endif
@@ -6937,12 +7094,10 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e
 	if (!hash || g_hash_table_size (hash) == 0)
 		return TRUE;
 
-	va_start (ap, error);
-	while ((key = va_arg (ap, const char *))) {
-		if (g_hash_table_contains (hash, key))
+	for (i = 0; argv[i]; i++) {
+		if (g_hash_table_contains (hash, argv[i]))
 			found_keys++;
 	}
-	va_end (ap);
 
 	if (found_keys != g_hash_table_size (hash)) {
 		GHashTableIter iter;
@@ -6954,14 +7109,12 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e
 
 		g_hash_table_iter_init (&iter, hash);
 		while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) {
-			va_start (ap, error);
-			while ((key = va_arg (ap, const char *))) {
-				if (!strcmp (key, k)) {
+			for (i = 0; argv[i]; i++) {
+				if (!strcmp (argv[i], k)) {
 					first_invalid_key = k;
 					break;
 				}
 			}
-			va_end (ap);
 			if (first_invalid_key)
 				break;
 		}
@@ -6978,6 +7131,7 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e
 
 	return TRUE;
 }
+#define _hash_check_invalid_keys(hash, setting_name, error, ...) _hash_check_invalid_keys_impl (hash, setting_name, error, ((const char *[]) { __VA_ARGS__, NULL }))
 
 void
 nm_device_reactivate_ip4_config (NMDevice *self,
@@ -7002,8 +7156,10 @@ nm_device_reactivate_ip4_config (NMDevice *self,
 			priv->ip4_state = IP_WAIT;
 			if (!nm_device_activate_stage3_ip4_start (self))
 				_LOGW (LOGD_IP4, "Failed to apply IPv4 configuration");
-		} else
-			ip4_config_merge_and_apply (self, NULL, TRUE, NULL);
+		} else {
+			if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL))
+				_LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration");
+		}
 	}
 }
 
@@ -7030,8 +7186,10 @@ nm_device_reactivate_ip6_config (NMDevice *self,
 			priv->ip6_state = IP_WAIT;
 			if (!nm_device_activate_stage3_ip6_start (self))
 				_LOGW (LOGD_IP6, "Failed to apply IPv6 configuration");
-		} else
-			ip6_config_merge_and_apply (self, TRUE, NULL);
+		} else {
+			if (!ip6_config_merge_and_apply (self, TRUE, NULL))
+				_LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration");
+		}
 	}
 }
 
@@ -7039,6 +7197,8 @@ nm_device_reactivate_ip6_config (NMDevice *self,
 /* reapply_connection:
  * @connection: the new connection settings to be applied or %NULL to reapply
  *   the current settings connection
+ * @version_id: either zero, or the current version id for the applied
+ *   connection.
  * @error: the error if %FALSE is returned
  *
  * Change configuration of an already configured device if possible.
@@ -7049,6 +7209,7 @@ nm_device_reactivate_ip6_config (NMDevice *self,
 static gboolean
 reapply_connection (NMDevice *self,
                     NMConnection *connection,
+                    guint64 version_id,
                     GError **error)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@@ -7079,24 +7240,36 @@ reapply_connection (NMDevice *self,
 	if (!_hash_check_invalid_keys (diffs, NULL, error,
 	                               NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	                               NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	                               NM_SETTING_CONNECTION_SETTING_NAME,
-	                               NULL))
+	                               NM_SETTING_CONNECTION_SETTING_NAME))
 		return FALSE;
 
 	if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL,
 	                               NM_SETTING_CONNECTION_SETTING_NAME,
 	                               error,
 	                               NM_SETTING_CONNECTION_ZONE,
-	                               NM_SETTING_CONNECTION_METERED,
-	                               NULL))
+	                               NM_SETTING_CONNECTION_METERED))
 		return FALSE;
 
-	_LOGD (LOGD_DEVICE, "reapply");
+	if (   version_id != 0
+	    && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) {
+		g_set_error_literal (error,
+		                     NM_DEVICE_ERROR,
+		                     NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
+		                     "Reapply failed because device changed in the meantime and the version-id mismatches");
+		return FALSE;
+	}
 
 	/**************************************************************************
 	 * Update applied connection
 	 *************************************************************************/
 
+	if (diffs)
+		nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request);
+
+	_LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)",
+	       (long long unsigned) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)),
+	       diffs ? "" : " (unmodified)");
+
 	if (diffs) {
 		con_old = applied_clone  = nm_simple_connection_new_clone (applied);
 		con_new = applied;
@@ -7122,6 +7295,11 @@ reapply_connection (NMDevice *self,
 	return TRUE;
 }
 
+typedef struct {
+	NMConnection *connection;
+	guint64 version_id;
+} ReapplyData;
+
 static void
 reapply_cb (NMDevice *self,
             GDBusMethodInvocation *context,
@@ -7129,9 +7307,17 @@ reapply_cb (NMDevice *self,
             GError *error,
             gpointer user_data)
 {
-	gs_unref_object NMConnection *connection = NM_CONNECTION (user_data);
+	ReapplyData *reapply_data = user_data;
+	guint64 version_id = 0;
+	gs_unref_object NMConnection *connection = NULL;
 	GError *local = NULL;
 
+	if (reapply_data) {
+		connection = reapply_data->connection;
+		version_id = reapply_data->version_id;
+		g_slice_free (ReapplyData, reapply_data);
+	}
+
 	if (error) {
 		nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message);
 		g_dbus_method_invocation_return_gerror (context, error);
@@ -7140,6 +7326,7 @@ reapply_cb (NMDevice *self,
 
 	if (!reapply_connection (self,
 	                         connection ? : (NMConnection *) nm_device_get_settings_connection (self),
+	                         version_id,
 	                         &local)) {
 		nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message);
 		g_dbus_method_invocation_take_error (context, local);
@@ -7154,17 +7341,19 @@ static void
 impl_device_reapply (NMDevice *self,
                      GDBusMethodInvocation *context,
                      GVariant *settings,
-                     guint flags)
+                     guint64 version_id,
+                     guint32 flags)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMSettingsConnection *settings_connection;
 	NMConnection *connection = NULL;
 	GError *error = NULL;
+	ReapplyData *reapply_data;
 
 	/* No flags supported as of now. */
 	if (flags != 0) {
 		error = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ACTIVE,
+		                             NM_DEVICE_ERROR_FAILED,
 		                             "Invalid flags specified");
 		nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message);
 		g_dbus_method_invocation_take_error (context, error);
@@ -7195,6 +7384,13 @@ impl_device_reapply (NMDevice *self,
 		nm_connection_clear_secrets (connection);
 	}
 
+	if (connection || version_id) {
+		reapply_data = g_slice_new (ReapplyData);
+		reapply_data->connection = connection;
+		reapply_data->version_id = version_id;
+	} else
+		reapply_data = NULL;
+
 	/* Ask the manager to authenticate this request for us */
 	g_signal_emit (self, signals[AUTH_REQUEST], 0,
 	               context,
@@ -7202,10 +7398,104 @@ impl_device_reapply (NMDevice *self,
 	               NM_AUTH_PERMISSION_NETWORK_CONTROL,
 	               TRUE,
 	               reapply_cb,
-	               connection);
+	               reapply_data);
+}
+
+/*****************************************************************************/
+
+static void
+get_applied_connection_cb (NMDevice *self,
+                           GDBusMethodInvocation *context,
+                           NMAuthSubject *subject,
+                           GError *error,
+                           gpointer user_data /* possibly dangling pointer */)
+{
+	NMDevicePrivate *priv;
+	NMConnection *applied_connection;
+	GVariant *settings;
+
+	g_return_if_fail (NM_IS_DEVICE (self));
+
+	if (error) {
+		g_dbus_method_invocation_return_gerror (context, error);
+		return;
+	}
+
+	priv = NM_DEVICE_GET_PRIVATE (self);
+
+	applied_connection = nm_device_get_applied_connection (self);
+
+	if (!applied_connection) {
+		error = g_error_new_literal (NM_DEVICE_ERROR,
+		                             NM_DEVICE_ERROR_NOT_ACTIVE,
+		                             "Device is not activated");
+		g_dbus_method_invocation_take_error (context, error);
+		return;
+	}
+
+	if (applied_connection != user_data) {
+		/* The applied connection changed due to a race. Reauthenticate. */
+		g_signal_emit (self, signals[AUTH_REQUEST], 0,
+		               context,
+		               applied_connection,
+		               NM_AUTH_PERMISSION_NETWORK_CONTROL,
+		               TRUE,
+		               get_applied_connection_cb,
+		               applied_connection /* no need take a ref. We will not dereference this pointer. */);
+		return;
+	}
+
+	settings = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
+	if (!settings)
+		settings = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
+
+	g_dbus_method_invocation_return_value (context,
+	                                       g_variant_new ("(@a{sa{sv}}t)",
+	                                                      settings,
+	                                                      nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)));
 }
 
 static void
+impl_device_get_applied_connection (NMDevice *self,
+                                    GDBusMethodInvocation *context,
+                                    guint32 flags)
+{
+	NMConnection *applied_connection;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_DEVICE (self));
+
+	/* No flags supported as of now. */
+	if (flags != 0) {
+		error = g_error_new_literal (NM_DEVICE_ERROR,
+		                             NM_DEVICE_ERROR_FAILED,
+		                             "Invalid flags specified");
+		g_dbus_method_invocation_take_error (context, error);
+		return;
+	}
+
+	applied_connection = nm_device_get_applied_connection (self);
+	if (!applied_connection) {
+		error = g_error_new_literal (NM_DEVICE_ERROR,
+		                             NM_DEVICE_ERROR_NOT_ACTIVE,
+		                             "Device is not activated");
+		g_dbus_method_invocation_take_error (context, error);
+		return;
+	}
+
+	/* Ask the manager to authenticate this request for us */
+	g_signal_emit (self, signals[AUTH_REQUEST], 0,
+	               context,
+	               applied_connection,
+	               NM_AUTH_PERMISSION_NETWORK_CONTROL,
+	               TRUE,
+	               get_applied_connection_cb,
+	               applied_connection /* no need take a ref. We will not dereference this pointer. */);
+}
+
+/*****************************************************************************/
+
+static void
 disconnect_cb (NMDevice *self,
                GDBusMethodInvocation *context,
                NMAuthSubject *subject,
@@ -7329,6 +7619,7 @@ _device_activate (NMDevice *self, NMActRequest *req)
 
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
+	g_return_val_if_fail (nm_device_get_managed (self, FALSE), FALSE);
 
 	/* Ensure the activation request is still valid; the master may have
 	 * already failed in which case activation of this device should not proceed.
@@ -7347,13 +7638,6 @@ _device_activate (NMDevice *self, NMActRequest *req)
 
 	delete_on_deactivate_unschedule (self);
 
-	/* Move default unmanaged devices to DISCONNECTED state here */
-	if (nm_device_get_default_unmanaged (self) && priv->state == NM_DEVICE_STATE_UNMANAGED) {
-		nm_device_state_changed (self,
-		                         NM_DEVICE_STATE_DISCONNECTED,
-		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
-	}
-
 	/* note: don't notify D-Bus of the new AC here, but do it later when
 	 * changing state to PREPARE so that the two properties change together.
 	 */
@@ -7602,7 +7886,7 @@ nm_device_set_ip4_config (NMDevice *self,
 		_update_ip4_address (self);
 
 		if (old_config != priv->ip4_config)
-			g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
+			_notify (self, PROP_IP4_CONFIG);
 		g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
 
 		if (old_config != priv->ip4_config)
@@ -7769,7 +8053,7 @@ nm_device_set_ip6_config (NMDevice *self,
 
 	if (has_changes) {
 		if (old_config != priv->ip6_config)
-			g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
+			_notify (self, PROP_IP6_CONFIG);
 		g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
 
 		if (old_config != priv->ip6_config)
@@ -8275,7 +8559,7 @@ nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing)
 	priv = NM_DEVICE_GET_PRIVATE (self);
 	if (priv->firmware_missing != new_missing) {
 		priv->firmware_missing = new_missing;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_MISSING);
+		_notify (self, PROP_FIRMWARE_MISSING);
 	}
 }
 
@@ -8295,7 +8579,7 @@ nm_device_set_nm_plugin_missing (NMDevice *self, gboolean new_missing)
 	priv = NM_DEVICE_GET_PRIVATE (self);
 	if (priv->nm_plugin_missing != new_missing) {
 		priv->nm_plugin_missing = new_missing;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_NM_PLUGIN_MISSING);
+		_notify (self, PROP_NM_PLUGIN_MISSING);
 	}
 }
 
@@ -8507,7 +8791,6 @@ update_ip6_config (NMDevice *self, gboolean initial)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	int ifindex;
-	gboolean linklocal6_just_completed = FALSE;
 	gboolean capture_resolv_conf;
 	NMDnsManagerResolvConfMode resolv_conf_mode;
 
@@ -8520,12 +8803,11 @@ update_ip6_config (NMDevice *self, gboolean initial)
 
 	/* IPv6 */
 	g_clear_object (&priv->ext_ip6_config);
-	priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
-	if (priv->ext_ip6_config) {
+	g_clear_object (&priv->ext_ip6_config_captured);
+	priv->ext_ip6_config_captured = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+	if (priv->ext_ip6_config_captured) {
 
-		/* Check this before modifying ext_ip6_config */
-		linklocal6_just_completed = priv->linklocal6_timeout_id &&
-		                            have_ip6_address (priv->ext_ip6_config, TRUE);
+		priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured);
 
 		/* This function was called upon external changes. Remove the configuration
 		 * (addresses,routes) that is no longer present externally from the internal
@@ -8557,7 +8839,9 @@ update_ip6_config (NMDevice *self, gboolean initial)
 		ip6_config_merge_and_apply (self, FALSE, NULL);
 	}
 
-	if (linklocal6_just_completed) {
+	if (   priv->linklocal6_timeout_id
+	    && priv->ext_ip6_config_captured
+	    && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) {
 		/* linklocal6 is ready now, do the state transition... we are also
 		 * invoked as g_idle_add, so no problems with reentrance doing it now.
 		 */
@@ -8673,8 +8957,8 @@ device_ipx_changed (NMPlatform *platform,
 
 		if (   priv->state > NM_DEVICE_STATE_DISCONNECTED
 		    && priv->state < NM_DEVICE_STATE_DEACTIVATING
-                    && (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED)
-		        || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE))) {
+		    && (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
+		        || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE))) {
 			priv->dad6_failed_addrs = g_slist_append (priv->dad6_failed_addrs,
 			                                          g_memdup (addr, sizeof (NMPlatformIP6Address)));
 		}
@@ -8690,119 +8974,319 @@ device_ipx_changed (NMPlatform *platform,
 	}
 }
 
+/*****************************************************************************/
+
+NM_UTILS_FLAGS2STR_DEFINE (nm_unmanaged_flags2str, NMUnmanagedFlags,
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_SLEEPING, "sleeping"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_QUITTING, "quitting"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_PARENT, "parent"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_LOOPBACK, "loopback"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_PLATFORM_INIT, "platform-init"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_EXPLICIT, "user-explicit"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_BY_DEFAULT, "by-default"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_SETTINGS, "user-settings"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_UDEV, "user-udev"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_EXTERNAL_DOWN, "external-down"),
+	NM_UTILS_FLAGS2STR (NM_UNMANAGED_IS_SLAVE, "is-slave"),
+);
+
+static const char *
+_unmanaged_flags2str (NMUnmanagedFlags flags, NMUnmanagedFlags mask, char *buf, gsize len)
+{
+	char buf2[512];
+	char *b;
+	char *tmp, *tmp2;
+	gsize l;
+
+	nm_utils_to_string_buffer_init (&buf, &len);
+	if (!len)
+		return buf;
+
+	b = buf;
+
+	mask |= flags;
+
+	nm_unmanaged_flags2str (flags, b, len);
+	l = strlen (b);
+	b += l;
+	len -= l;
+
+	nm_unmanaged_flags2str (mask & ~flags, buf2, sizeof (buf2));
+	if (buf2[0]) {
+		gboolean add_separator = l > 0;
+
+		tmp = buf2;
+		while (TRUE) {
+			if (add_separator)
+				nm_utils_strbuf_append_c (&b, &len, ',');
+			add_separator = TRUE;
+
+			tmp2 = strchr (tmp, ',');
+			if (tmp2)
+				tmp2[0] = '\0';
+
+			nm_utils_strbuf_append_c (&b, &len, '!');
+			nm_utils_strbuf_append_str (&b, &len, tmp);
+			if (!tmp2)
+				break;
+
+			tmp = &tmp2[1];
+		}
+	}
+
+	return buf;
+}
+
+static gboolean
+_get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean for_user_request)
+{
+	/* Evaluate the managed state based on the unmanaged flags.
+	 *
+	 * Some flags are authoritative, meaning they always cause
+	 * the device to be unmanaged (e.g. @NM_UNMANAGED_PLATFORM_INIT).
+	 *
+	 * OTOH, some flags can be overwritten. For example NM_UNMANAGED_USER_SETTINGS
+	 * is ignored once NM_UNMANAGED_USER_EXPLICIT is set. The idea is that
+	 * the flag from the configuration has no effect once the user explicitly
+	 * touches the unmanaged flags. */
+
+	if (for_user_request) {
+
+		/* @for_user_request can make the result only ~more~ managed.
+		 * If the flags already indicate a managed state for a non-user-request,
+		 * then it is also managed for an explict user-request.
+		 *
+		 * Effectively, this check is redundant, as the code below already
+		 * already ensures that. Still, express this invariant explictly here. */
+		if (_get_managed_by_flags (flags, mask, FALSE))
+			return TRUE;
+
+		/* A for-user-request, is effectively the same as pretending
+		 * that user-dbus flag is cleared. */
+		mask |= NM_UNMANAGED_USER_EXPLICIT;
+		flags &= ~NM_UNMANAGED_USER_EXPLICIT;
+	}
+
+	if (   NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_SETTINGS)
+	    && !NM_FLAGS_ANY (flags, NM_UNMANAGED_USER_SETTINGS)) {
+		/* NM_UNMANAGED_USER_SETTINGS can only explicitly unmanage a device. It cannot
+		 * *manage* it. Having NM_UNMANAGED_USER_SETTINGS explicitly not set, is the
+		 * same as having it not set at all. */
+		mask &= ~NM_UNMANAGED_USER_SETTINGS;
+	}
+
+	if (NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_UDEV)) {
+		/* configuration from udev or nm-config overwrites the by-default flag
+		 * which is based on the device type. */
+		flags &= ~NM_UNMANAGED_BY_DEFAULT;
+	}
+
+	if (   NM_FLAGS_HAS (mask, NM_UNMANAGED_IS_SLAVE)
+	    && !NM_FLAGS_HAS (flags, NM_UNMANAGED_IS_SLAVE)) {
+		/* for an enslaved device, by-default doesn't matter */
+		flags &= ~NM_UNMANAGED_BY_DEFAULT;
+	}
+
+	if (NM_FLAGS_HAS (mask, NM_UNMANAGED_USER_EXPLICIT)) {
+		/* if the device is managed by user-decision, certain other flags
+		 * are ignored. */
+
+		flags &= ~(  NM_UNMANAGED_BY_DEFAULT
+		           | NM_UNMANAGED_USER_UDEV
+		           | NM_UNMANAGED_EXTERNAL_DOWN);
+	}
+
+	return flags == NM_UNMANAGED_NONE;
+}
+
 /**
- * nm_device_get_managed():
+ * nm_device_get_managed:
  * @self: the #NMDevice
+ * @for_user_request: whether to check the flags for an explict user-request
+ *
+ * Whether the device is unmanaged according to the unmanaged flags.
  *
- * Returns: %TRUE if the device is managed
+ * Returns: %TRUE if the device is unmanaged because of the flags.
  */
 gboolean
-nm_device_get_managed (NMDevice *self)
+nm_device_get_managed (NMDevice *self, gboolean for_user_request)
 {
 	NMDevicePrivate *priv;
-	gboolean managed;
 
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 
-	priv = NM_DEVICE_GET_PRIVATE (self);
+	if (!nm_device_is_real (self)) {
+		/* a unrealized device is always considered unmanaged. */
+		return FALSE;
+	}
 
-	/* Return the composite of all managed flags.  However, if the device
-	 * is a default-unmanaged device, and would be managed except for the
-	 * default-unmanaged flag (eg, only NM_UNMANAGED_DEFAULT is set) then
-	 * the device is managed whenever it's not in the UNMANAGED state.
-	 */
-	managed = !NM_FLAGS_ANY (priv->unmanaged_flags, ~NM_UNMANAGED_DEFAULT);
-	if (managed && NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_DEFAULT))
-		managed = (priv->state > NM_DEVICE_STATE_UNMANAGED);
+	priv = NM_DEVICE_GET_PRIVATE (self);
 
-	return managed;
+	return _get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, for_user_request);
 }
 
 /**
- * nm_device_get_unmanaged_flags():
+ * nm_device_get_unmanaged_flags:
  * @self: the #NMDevice
- * @flag: return only the selected flags
+ * @flag: the unmanaged flags to check.
+ *
+ * Return the unmanaged flags of the device.
  *
- * Returns: the unmanage flags of the device (filtered with @flag)
+ * Returns: the flags of the device ( & @flag)
  */
 NMUnmanagedFlags
 nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag)
 {
+	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
+	g_return_val_if_fail (flag != NM_UNMANAGED_NONE, FALSE);
+
 	return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag;
 }
 
 /**
- * nm_device_get_default_unmanaged():
- * @self: the #NMDevice
+ * _set_unmanaged_flags:
+ * @self: the #NMDevice instance
+ * @flags: which #NMUnmanagedFlags to set.
+ * @set_op: whether to set/clear/forget the flags. You can also pass
+ *   boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
+ *   and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
+ * @allow_state_transition: if %FALSE, setting flags never triggers a device
+ *   state change. If %TRUE, the device can change state, if it is real and
+ *   switches from managed to unmanaged (or vice versa).
+ * @reason: the device state reason passed to nm_device_state_changed() if
+ *   the device becomes managed/unmanaged. This is only relevant if the
+ *   device switches state and if @allow_state_transition is %TRUE.
  *
- * Returns: %TRUE if the device is by default unmanaged
- */
-static gboolean
-nm_device_get_default_unmanaged (NMDevice *self)
-{
-	return !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_DEFAULT);
-}
-
+ * Set the unmanaged flags of the device.
+ **/
 static void
 _set_unmanaged_flags (NMDevice *self,
                       NMUnmanagedFlags flags,
-                      gboolean unmanaged)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (unmanaged) {
-		if (!NM_FLAGS_ALL (priv->unmanaged_flags, flags)) {
-			_LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)",
-			       (long long unsigned) (priv->unmanaged_flags | flags),
-			       (long long unsigned) priv->unmanaged_flags,
-			       "set",
-			       (long long unsigned) flags);
-			priv->unmanaged_flags |= flags;
-		}
-	} else {
-		if (NM_FLAGS_ANY (priv->unmanaged_flags, flags)) {
-			_LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)",
-			       (long long unsigned) (priv->unmanaged_flags & (~flags)),
-			       (long long unsigned) priv->unmanaged_flags,
-			       "clear",
-			       (long long unsigned) flags);
-			priv->unmanaged_flags &= ~flags;
-		}
-	}
-}
-
-void
-nm_device_set_unmanaged_flags (NMDevice *self,
-                               NMUnmanagedFlags flag,
-                               gboolean unmanaged,
-                               NMDeviceStateReason reason)
+                      NMUnmanFlagOp set_op,
+                      gboolean allow_state_transition,
+                      NMDeviceStateReason reason)
 {
 	NMDevicePrivate *priv;
-	gboolean was_managed, now_managed;
+	gboolean was_managed, transition_state;
+	NMUnmanagedFlags old_flags, old_mask;
+	const char *operation = NULL;
+	char str1[512];
+	char str2[512];
 
 	g_return_if_fail (NM_IS_DEVICE (self));
-	g_return_if_fail (flag <= NM_UNMANAGED_LAST);
+	g_return_if_fail (flags);
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
 
-	was_managed = nm_device_get_managed (self);
-	_set_unmanaged_flags (self, flag, unmanaged);
-	now_managed = nm_device_get_managed (self);
+	if (!priv->real)
+		allow_state_transition = FALSE;
+	was_managed = allow_state_transition && nm_device_get_managed (self, FALSE);
+
+	old_flags = priv->unmanaged_flags;
+	old_mask = priv->unmanaged_mask;
 
-	if (was_managed != now_managed) {
-		_LOGD (LOGD_DEVICE, "now %s", unmanaged ? "unmanaged" : "managed");
+	switch (set_op) {
+	case NM_UNMAN_FLAG_OP_FORGET:
+		priv->unmanaged_mask &= ~flags;
+		priv->unmanaged_flags &= ~flags;
+		operation = "forget";
+		break;
+	case NM_UNMAN_FLAG_OP_SET_UNMANAGED:
+		priv->unmanaged_mask |= flags;
+		priv->unmanaged_flags |= flags;
+		operation = "set-unmanaged";
+		break;
+	case NM_UNMAN_FLAG_OP_SET_MANAGED:
+		priv->unmanaged_mask |= flags;
+		priv->unmanaged_flags &= ~flags;
+		operation = "set-managed";
+		break;
+	default:
+		g_return_if_reached ();
+	}
 
-		g_object_notify (G_OBJECT (self), NM_DEVICE_MANAGED);
+	if (   old_flags == priv->unmanaged_flags
+	    && old_mask == priv->unmanaged_mask)
+		return;
 
-		if (unmanaged)
+	transition_state =    allow_state_transition
+	                   && was_managed != nm_device_get_managed (self, FALSE)
+	                   && (   was_managed
+	                       || (   !was_managed
+	                           && nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED));
+
+#define _FMTX "[%s%s0x%0x/0x%x/%s"
+#define _FMT(flags, mask, str) \
+	_unmanaged_flags2str ((flags), (mask), str, sizeof (str)), \
+	((flags) | (mask)) ? "=" : "", \
+	(flags), \
+	(mask), \
+	(_get_managed_by_flags (flags, mask, FALSE) \
+	     ? "managed" \
+	     : (_get_managed_by_flags (flags, mask, TRUE) \
+	            ? "manageable" \
+	            : "unmanaged"))
+	_LOGD (LOGD_DEVICE, "unmanaged: flags set to "_FMTX"%s, %s [%s=0x%0x]%s%s%s)",
+	       _FMT (priv->unmanaged_flags, priv->unmanaged_mask, str1),
+	       priv->real ? "" : "/unrealized",
+	       operation,
+	       nm_unmanaged_flags2str (flags, str2, sizeof (str2)),
+	       flags,
+	       NM_PRINT_FMT_QUOTED (allow_state_transition,
+	                            ", reason ",
+	                            reason_to_string (reason),
+	                            transition_state ? ", transition-state" : "",
+	                            ""));
+#undef _FMT
+
+	if (transition_state) {
+		if (was_managed)
 			nm_device_state_changed (self, NM_DEVICE_STATE_UNMANAGED, reason);
-		else if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)
+		else
 			nm_device_state_changed (self, NM_DEVICE_STATE_UNAVAILABLE, reason);
 	}
 }
 
+/**
+ * @self: the #NMDevice instance
+ * @flags: which #NMUnmanagedFlags to set.
+ * @set_op: whether to set/clear/forget the flags. You can also pass
+ *   boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
+ *   and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
+ *
+ * Set the unmanaged flags of the device (does not trigger a state change).
+ **/
+void
+nm_device_set_unmanaged_flags (NMDevice *self,
+                               NMUnmanagedFlags flags,
+                               NMUnmanFlagOp set_op)
+{
+	_set_unmanaged_flags (self, flags, set_op, FALSE, NM_DEVICE_STATE_REASON_NONE);
+}
+
+/**
+ * nm_device_set_unmanaged_by_flags:
+ * @self: the #NMDevice instance
+ * @flags: which #NMUnmanagedFlags to set.
+ * @set_op: whether to set/clear/forget the flags. You can also pass
+ *   boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
+ *   and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
+ * @reason: the device state reason passed to nm_device_state_changed() if
+ *   the device becomes managed/unmanaged.
+ *
+ * Set the unmanaged flags of the device and possibly trigger a state change.
+ **/
+void
+nm_device_set_unmanaged_by_flags (NMDevice *self,
+                                  NMUnmanagedFlags flags,
+                                  NMUnmanFlagOp set_op,
+                                  NMDeviceStateReason reason)
+{
+	_set_unmanaged_flags (self, flags, set_op, TRUE, reason);
+}
+
 void
-nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs)
+nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs)
 {
 	NMDevicePrivate *priv;
 	gboolean unmanaged;
@@ -8811,46 +9295,36 @@ nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unma
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
 
-	if (priv->managed_touched_by_user)
-		return;
-
 	unmanaged = nm_device_spec_match_list (self, unmanaged_specs);
-	nm_device_set_unmanaged_flags (self,
-	                               NM_UNMANAGED_USER,
-	                               unmanaged,
-	                               unmanaged
-	                                   ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED
-	                                   : NM_DEVICE_STATE_REASON_NOW_MANAGED);
+
+	nm_device_set_unmanaged_by_flags (self,
+	                                  NM_UNMANAGED_USER_SETTINGS,
+	                                  unmanaged,
+	                                  unmanaged
+	                                      ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED
+	                                      : NM_DEVICE_STATE_REASON_NOW_MANAGED);
 }
 
-/**
- * nm_device_set_unmanaged_flags_initial():
- * @self: the #NMDevice
- * @flag: an #NMUnmanagedFlag
- * @unmanaged: %TRUE or %FALSE to set or clear @flag
- *
- * Like nm_device_set_unmanaged_flags(), but must be set before the device is
- * initialized by nm_device_finish_init(), and does not trigger state changes.
- * Should only be used when initializing a device.
- */
 void
-nm_device_set_unmanaged_flags_initial (NMDevice *self,
-                                       NMUnmanagedFlags flag,
-                                       gboolean unmanaged)
+nm_device_set_unmanaged_by_user_udev (NMDevice *self)
 {
-	NMDevicePrivate *priv;
+	int ifindex;
+	gboolean platform_unmanaged = FALSE;
 
-	g_return_if_fail (NM_IS_DEVICE (self));
-	g_return_if_fail (flag <= NM_UNMANAGED_LAST);
+	ifindex = self->priv->ifindex;
 
-	priv = NM_DEVICE_GET_PRIVATE (self);
-	g_return_if_fail (priv->initialized == FALSE);
+	if (   ifindex <= 0
+	    || !nm_platform_link_get_unmanaged (NM_PLATFORM_GET, ifindex, &platform_unmanaged))
+		return;
 
-	_set_unmanaged_flags (self, flag, unmanaged);
+	nm_device_set_unmanaged_by_flags (self,
+	                                  NM_UNMANAGED_USER_UDEV,
+	                                  platform_unmanaged,
+	                                  NM_DEVICE_STATE_REASON_USER_REQUESTED);
 }
 
 void
-nm_device_set_unmanaged_quitting (NMDevice *self)
+nm_device_set_unmanaged_by_quitting (NMDevice *self)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	gboolean need_deactivate = nm_device_is_activating (self) ||
@@ -8860,11 +9334,11 @@ nm_device_set_unmanaged_quitting (NMDevice *self)
 	if (need_deactivate)
 		_set_state_full (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NOW_UNMANAGED, TRUE);
 
-	nm_device_set_unmanaged_flags (self,
-	                               NM_UNMANAGED_INTERNAL,
-	                               TRUE,
-	                               need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED
-	                                               : NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
+	nm_device_set_unmanaged_by_flags (self,
+	                                  NM_UNMANAGED_QUITTING,
+	                                  TRUE,
+	                                  need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED
+	                                                  : NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
 }
 
 /*****************************************************************************/
@@ -8901,6 +9375,7 @@ nm_device_reapply_settings_immediately (NMDevice *self)
 	NMSettingConnection *s_con_applied;
 	const char *zone;
 	NMMetered metered;
+	guint64 version_id;
 
 	g_return_if_fail (NM_IS_DEVICE (self));
 
@@ -8923,7 +9398,8 @@ nm_device_reapply_settings_immediately (NMDevice *self)
 	if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)),
 	               nm_setting_connection_get_zone (s_con_applied)) != 0) {
 
-		_LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s", NM_PRINT_FMT_QUOTE_STRING (zone));
+		version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request);
+		_LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (long long unsigned) version_id);
 
 		g_object_set (G_OBJECT (s_con_applied),
 		              NM_SETTING_CONNECTION_ZONE, zone,
@@ -8934,7 +9410,8 @@ nm_device_reapply_settings_immediately (NMDevice *self)
 
 	if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) {
 
-		_LOGD (LOGD_DEVICE, "reapply setting: metered = %d", (int) metered);
+		version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request);
+		_LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (long long unsigned) version_id);
 
 		g_object_set (G_OBJECT (s_con_applied),
 		              NM_SETTING_CONNECTION_METERED, metered,
@@ -9017,7 +9494,7 @@ nm_device_update_metered (NMDevice *self)
 	if (value != priv->metered) {
 		_LOGD (LOGD_DEVICE, "set metered value %d", value);
 		priv->metered = value;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_METERED);
+		_notify (self, PROP_METERED);
 	}
 }
 
@@ -9029,11 +9506,21 @@ _nm_device_check_connection_available (NMDevice *self,
 {
 	NMDeviceState state;
 
+	/* an unrealized software device is always available, hardware devices never. */
+	if (!nm_device_is_real (self)) {
+		if (nm_device_is_software (self))
+			return nm_device_check_connection_compatible (self, connection);
+		return FALSE;
+	}
+
 	state = nm_device_get_state (self);
 	if (state < NM_DEVICE_STATE_UNMANAGED)
 		return FALSE;
 	if (   state < NM_DEVICE_STATE_UNAVAILABLE
-	    && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
+	    && (   (   !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
+	            && !nm_device_get_managed (self, FALSE))
+	        || (    NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
+	            && !nm_device_get_managed (self, TRUE))))
 		return FALSE;
 	if (   state < NM_DEVICE_STATE_DISCONNECTED
 	    && !nm_device_is_software (self)
@@ -9100,34 +9587,30 @@ nm_device_check_connection_available (NMDevice *self,
 }
 
 static void
-_signal_available_connections_changed (NMDevice *self)
+available_connections_notify (NMDevice *self)
 {
-	g_object_notify (G_OBJECT (self), NM_DEVICE_AVAILABLE_CONNECTIONS);
+	_notify (self, PROP_AVAILABLE_CONNECTIONS);
 }
 
-static void
-_clear_available_connections (NMDevice *self, gboolean do_signal)
+static gboolean
+available_connections_del_all (NMDevice *self)
 {
-	g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (self)->available_connections);
-	if (do_signal == TRUE)
-		_signal_available_connections_changed (self);
+	if (g_hash_table_size (self->priv->available_connections) == 0)
+		return FALSE;
+	g_hash_table_remove_all (self->priv->available_connections);
+	return TRUE;
 }
 
 static gboolean
-_try_add_available_connection (NMDevice *self, NMConnection *connection)
+available_connections_add (NMDevice *self, NMConnection *connection)
 {
-	if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL)) {
-		g_hash_table_add (NM_DEVICE_GET_PRIVATE (self)->available_connections,
-		                  g_object_ref (connection));
-		return TRUE;
-	}
-	return FALSE;
+	return nm_g_hash_table_add (self->priv->available_connections, g_object_ref (connection));
 }
 
 static gboolean
-_del_available_connection (NMDevice *self, NMConnection *connection)
+available_connections_del (NMDevice *self, NMConnection *connection)
 {
-	return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (self)->available_connections, connection);
+	return g_hash_table_remove (self->priv->available_connections, connection);
 }
 
 static gboolean
@@ -9162,22 +9645,55 @@ nm_device_recheck_available_connections (NMDevice *self)
 {
 	NMDevicePrivate *priv;
 	const GSList *connections, *iter;
+	gboolean changed = FALSE;
+	GHashTableIter h_iter;
+	NMConnection *connection;
 
 	g_return_if_fail (NM_IS_DEVICE (self));
 
 	priv = NM_DEVICE_GET_PRIVATE(self);
 
 	if (priv->con_provider) {
-		_clear_available_connections (self, FALSE);
+		gs_unref_hashtable GHashTable *prune_list = NULL;
+
+		if (g_hash_table_size (priv->available_connections) > 0) {
+			prune_list = g_hash_table_new (g_direct_hash, g_direct_equal);
+			g_hash_table_iter_init (&h_iter, priv->available_connections);
+			while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL))
+				g_hash_table_add (prune_list, connection);
+		}
 
 		connections = nm_connection_provider_get_connections (priv->con_provider);
-		for (iter = connections; iter; iter = g_slist_next (iter))
-			_try_add_available_connection (self, NM_CONNECTION (iter->data));
+		for (iter = connections; iter; iter = g_slist_next (iter)) {
+			connection = NM_CONNECTION (iter->data);
+
+			if (nm_device_check_connection_available (self,
+				                                  connection,
+				                                  NM_DEVICE_CHECK_CON_AVAILABLE_NONE,
+				                                  NULL)) {
+				if (available_connections_add (self, connection))
+					changed = TRUE;
+			} else {
+				if (prune_list && g_hash_table_remove (prune_list, connection))
+					changed = TRUE;
+			}
+		}
 
-		_signal_available_connections_changed (self);
+		if (prune_list) {
+			g_hash_table_iter_init (&h_iter, prune_list);
+			while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) {
+				if (available_connections_del (self, connection))
+					changed = TRUE;
+			}
+		}
+	} else {
+		if (available_connections_del_all (self))
+			changed = TRUE;
 	}
 
-	available_connection_check_delete_unrealized (self);
+	if (changed)
+		available_connections_notify (self);
+	available_connections_check_delete_unrealized (self);
 }
 
 /**
@@ -9209,7 +9725,7 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object
 			 * compatible with it.
 			 */
 			if (   !specific_object /* << Optimization: we know that the connection is available without @specific_object.  */
-			    || nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object))
+			    || nm_device_check_connection_available (self, connection, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, specific_object))
 				g_ptr_array_add (array, connection);
 		}
 	}
@@ -9217,45 +9733,38 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object
 }
 
 static void
-cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
+cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
 {
+	gboolean changed;
 	NMDevice *self = user_data;
 
 	g_return_if_fail (NM_IS_DEVICE (self));
+	g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
 
-	if (_try_add_available_connection (self, connection))
-		_signal_available_connections_changed (self);
-}
-
-static void
-cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
-{
-	NMDevice *self = user_data;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
+	if (nm_device_check_connection_available (self,
+	                                          connection,
+	                                          _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
+	                                          NULL))
+		changed = available_connections_add (self, connection);
+	else
+		changed = available_connections_del (self, connection);
 
-	if (_del_available_connection (self, connection)) {
-		_signal_available_connections_changed (self);
-		available_connection_check_delete_unrealized (self);
+	if (changed) {
+		available_connections_notify (self);
+		available_connections_check_delete_unrealized (self);
 	}
 }
 
 static void
-cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
+cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
 {
 	NMDevice *self = user_data;
-	gboolean added, deleted;
 
 	g_return_if_fail (NM_IS_DEVICE (self));
 
-	/* FIXME: don't remove it from the hash if it's just going to get re-added */
-	deleted = _del_available_connection (self, connection);
-	added = _try_add_available_connection (self, connection);
-
-	/* Only signal if the connection was removed OR added, but not both */
-	if (added != deleted) {
-		_signal_available_connections_changed (self);
-		available_connection_check_delete_unrealized (self);
+	if (available_connections_del (self, connection)) {
+		available_connections_notify (self);
+		available_connections_check_delete_unrealized (self);
 	}
 }
 
@@ -9309,7 +9818,7 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser
 	_LOGD (LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action);
 
 	if (count == 1)
-		g_object_notify (G_OBJECT (self), NM_DEVICE_HAS_PENDING_ACTION);
+		_notify (self, PROP_HAS_PENDING_ACTION);
 
 	return TRUE;
 }
@@ -9344,7 +9853,7 @@ nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean as
 			g_free (iter->data);
 			priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
 			if (priv->pending_actions == NULL)
-				g_object_notify (G_OBJECT (self), NM_DEVICE_HAS_PENDING_ACTION);
+				_notify (self, PROP_HAS_PENDING_ACTION);
 			return TRUE;
 		}
 		count++;
@@ -9453,6 +9962,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
 	g_clear_object (&priv->con_ip6_config);
 	g_clear_object (&priv->ac_ip6_config);
 	g_clear_object (&priv->ext_ip6_config);
+	g_clear_object (&priv->ext_ip6_config_captured);
 	g_clear_object (&priv->wwan_ip6_config);
 	g_clear_object (&priv->ip6_config);
 
@@ -9466,7 +9976,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
 	/* Clear legacy IPv4 address property */
 	if (priv->ip4_address) {
 		priv->ip4_address = 0;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS);
+		_notify (self, PROP_IP4_ADDRESS);
 	}
 
 	if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
@@ -9733,11 +10243,11 @@ ip_config_valid (NMDeviceState state)
 static void
 notify_ip_properties (NMDevice *self)
 {
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+	_notify (self, PROP_IP_IFACE);
+	_notify (self, PROP_IP4_CONFIG);
+	_notify (self, PROP_DHCP4_CONFIG);
+	_notify (self, PROP_IP6_CONFIG);
+	_notify (self, PROP_DHCP6_CONFIG);
 }
 
 static void
@@ -9840,14 +10350,16 @@ _set_state_full (NMDevice *self,
 	 * can retry device initialization.
 	 */
 	if (   (priv->state == state)
-	    && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) {
-		_LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d] (skip due to missing firmware)",
+	    && (   state != NM_DEVICE_STATE_UNAVAILABLE
+	        || !priv->firmware_missing)) {
+		_LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]%s",
 		       state_to_string (old_state),
 		       state_to_string (state),
 		       reason_to_string (reason),
 		       old_state,
 		       state,
-		       reason);
+		       reason,
+		       priv->firmware_missing ? " (missing firmware)" : "");
 		return;
 	}
 
@@ -9875,13 +10387,13 @@ _set_state_full (NMDevice *self,
 	req = priv->act_request ? g_object_ref (priv->act_request) : NULL;
 
 	if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
-		_clear_available_connections (self, TRUE);
+		if (available_connections_del_all (self))
+			available_connections_notify (self);
 		_clear_queued_act_request (priv);
 	}
 
 	/* Update the available connections list when a device first becomes available */
-	if (   (state >= NM_DEVICE_STATE_DISCONNECTED && old_state < NM_DEVICE_STATE_DISCONNECTED)
-	    || nm_device_get_default_unmanaged (self))
+	if (state >= NM_DEVICE_STATE_DISCONNECTED && old_state < NM_DEVICE_STATE_DISCONNECTED)
 		nm_device_recheck_available_connections (self);
 
 	/* Handle the new state here; but anything that could trigger
@@ -9963,8 +10475,8 @@ _set_state_full (NMDevice *self,
 	    && state <= NM_DEVICE_STATE_ACTIVATED)
 		nm_device_set_autoconnect (self, TRUE);
 
-	g_object_notify (G_OBJECT (self), NM_DEVICE_STATE);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_STATE_REASON);
+	_notify (self, PROP_STATE);
+	_notify (self, PROP_STATE_REASON);
 	g_signal_emit_by_name (self, NM_DEVICE_STATE_CHANGED, state, old_state, reason);
 
 	/* Post-process the event after internal notification */
@@ -9982,11 +10494,7 @@ _set_state_full (NMDevice *self,
 			                                   NM_DEVICE_STATE_REASON_NONE,
 			                                   NM_DEVICE_STATE_REASON_NONE);
 		} else {
-			if (old_state == NM_DEVICE_STATE_UNMANAGED)
-				_LOGD (LOGD_DEVICE, "device not yet available for transition to DISCONNECTED");
-			else if (   old_state > NM_DEVICE_STATE_UNAVAILABLE
-			         && nm_device_get_default_unmanaged (self))
-				nm_device_queue_state (self, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE);
+			_LOGD (LOGD_DEVICE, "device not yet available for transition to DISCONNECTED");
 		}
 		break;
 	case NM_DEVICE_STATE_DEACTIVATING:
@@ -10032,9 +10540,6 @@ _set_state_full (NMDevice *self,
 				break;
 			/* fall through */
 		}
-		if (   old_state > NM_DEVICE_STATE_DISCONNECTED
-		    && nm_device_get_default_unmanaged (self))
-			nm_device_queue_state (self, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE);
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		_LOGI (LOGD_DEVICE, "Activation: successful, device activated.");
@@ -10149,6 +10654,9 @@ _set_state_full (NMDevice *self,
 		g_object_unref (req);
 
 	priv->in_state_changed = FALSE;
+
+	if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED))
+		_notify (self, PROP_MANAGED);
 }
 
 void
@@ -10297,7 +10805,7 @@ nm_device_update_hw_address (NMDevice *self)
 			priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen);
 
 			_LOGD (LOGD_HW | LOGD_DEVICE, "hardware address now %s", priv->hw_addr);
-			g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS);
+			_notify (self, PROP_HW_ADDRESS);
 		}
 	} else {
 		/* Invalid or no hardware address */
@@ -10306,7 +10814,7 @@ nm_device_update_hw_address (NMDevice *self)
 			priv->hw_addr_len = 0;
 			_LOGD (LOGD_HW | LOGD_DEVICE,
 			       "previous hardware address is no longer valid");
-			g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS);
+			_notify (self, PROP_HW_ADDRESS);
 		}
 	}
 }
@@ -10347,7 +10855,11 @@ nm_device_set_hw_addr (NMDevice *self, const char *addr,
 	const char *cur_addr = nm_device_get_hw_address (self);
 	guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
 
-	g_return_val_if_fail (addr != NULL, FALSE);
+	/* Fall back to the permanent address */
+	if (!addr)
+		addr = priv->perm_hw_addr;
+	if (!addr)
+		return FALSE;
 
 	/* Do nothing if current MAC is same */
 	if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
@@ -10498,7 +11010,8 @@ nm_device_init (NMDevice *self)
 	priv->dhcp_timeout = 0;
 	priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
 	priv->autoconnect = DEFAULT_AUTOCONNECT;
-	priv->unmanaged_flags = NM_UNMANAGED_INTERNAL;
+	priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT;
+	priv->unmanaged_mask = priv->unmanaged_flags;
 	priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
 	priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
 
@@ -10533,7 +11046,7 @@ constructor (GType type,
 
 		if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) {
 			priv->ifindex = pllink->ifindex;
-			priv->up = NM_FLAGS_HAS (pllink->flags, IFF_UP);
+			priv->up = NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP);
 		}
 	}
 
@@ -10563,7 +11076,7 @@ constructed (GObject *object)
 	g_assert (priv->con_provider);
 	g_signal_connect (priv->con_provider,
 	                  NM_CP_SIGNAL_CONNECTION_ADDED,
-	                  G_CALLBACK (cp_connection_added),
+	                  G_CALLBACK (cp_connection_added_or_updated),
 	                  self);
 
 	g_signal_connect (priv->con_provider,
@@ -10573,18 +11086,9 @@ constructed (GObject *object)
 
 	g_signal_connect (priv->con_provider,
 	                  NM_CP_SIGNAL_CONNECTION_UPDATED,
-	                  G_CALLBACK (cp_connection_updated),
+	                  G_CALLBACK (cp_connection_added_or_updated),
 	                  self);
 
-	/* Update default-unmanaged device available connections immediately,
-	 * since they don't transition from UNMANAGED (and thus the state handler
-	 * doesn't run and update them) until something external happens.
-	 */
-	if (nm_device_get_default_unmanaged (self)) {
-		nm_device_set_autoconnect (self, FALSE);
-		nm_device_recheck_available_connections (self);
-	}
-
 	G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
 
 	_LOGD (LOGD_DEVICE, "constructed (%s)", G_OBJECT_TYPE_NAME (self));
@@ -10599,6 +11103,11 @@ dispose (GObject *object)
 
 	_LOGD (LOGD_DEVICE, "disposing");
 
+	g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
+	priv->arping.dad_list = NULL;
+
+	arp_cleanup (self);
+
 	g_signal_handlers_disconnect_by_func (nm_config_get (), config_changed_update_ignore_carrier, self);
 
 	dispatcher_cleanup (self);
@@ -10623,13 +11132,12 @@ dispose (GObject *object)
 	link_disconnect_action_cancel (self);
 
 	if (priv->con_provider) {
-		g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added, self);
+		g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added_or_updated, self);
 		g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self);
-		g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_updated, self);
 		priv->con_provider = NULL;
 	}
 
-	g_hash_table_remove_all (priv->available_connections);
+	available_connections_del_all (self);
 
 	nm_clear_g_source (&priv->carrier_wait_id);
 
@@ -10698,7 +11206,6 @@ set_property (GObject *object, guint prop_id,
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	const char *hw_addr, *p;
 	guint count;
-	gboolean val_bool;
 
 	switch (prop_id) {
 	case PROP_UDI:
@@ -10732,18 +11239,26 @@ set_property (GObject *object, guint prop_id,
 	case PROP_IP4_ADDRESS:
 		priv->ip4_address = g_value_get_uint (value);
 		break;
-	case PROP_MANAGED:
-		val_bool = g_value_get_boolean (value);
-		priv->managed_touched_by_user = TRUE;
-		nm_device_set_unmanaged_flags (self,
-		                               NM_UNMANAGED_USER | (val_bool ? NM_UNMANAGED_DEFAULT : NM_UNMANAGED_NONE),
-		                               !val_bool,
-		                               NM_DEVICE_STATE_REASON_USER_REQUESTED);
+	case PROP_MANAGED: {
+		gboolean managed;
+		NMDeviceStateReason reason;
+
+		managed = g_value_get_boolean (value);
+		if (managed)
+			reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED;
+		else
+			reason = NM_DEVICE_STATE_REASON_REMOVED;
+		nm_device_set_unmanaged_by_flags (self,
+		                                  NM_UNMANAGED_USER_EXPLICIT,
+		                                  !managed,
+		                                  reason);
 		break;
+	}
 	case PROP_AUTOCONNECT:
 		nm_device_set_autoconnect (self, g_value_get_boolean (value));
 		break;
 	case PROP_FIRMWARE_MISSING:
+		/* construct only */
 		priv->firmware_missing = g_value_get_boolean (value);
 		break;
 	case PROP_NM_PLUGIN_MISSING:
@@ -10878,7 +11393,8 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_uint (value, priv->link_type);
 		break;
 	case PROP_MANAGED:
-		g_value_set_boolean (value, nm_device_get_managed (self));
+		/* The managed state exposed on D-Bus only depends on the current device state alone. */
+		g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED);
 		break;
 	case PROP_AUTOCONNECT:
 		g_value_set_boolean (value, priv->autoconnect);
@@ -11002,232 +11518,169 @@ nm_device_class_init (NMDeviceClass *klass)
 	klass->get_ip_iface_identifier = get_ip_iface_identifier;
 
 	/* Properties */
-	g_object_class_install_property
-		(object_class, PROP_UDI,
-		 g_param_spec_string (NM_DEVICE_UDI, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IFACE,
-		 g_param_spec_string (NM_DEVICE_IFACE, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IP_IFACE,
-		 g_param_spec_string (NM_DEVICE_IP_IFACE, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_DRIVER,
-		 g_param_spec_string (NM_DEVICE_DRIVER, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_DRIVER_VERSION,
-		 g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_FIRMWARE_VERSION,
-		 g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_CAPABILITIES,
-		 g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "",
-		                    0, G_MAXUINT32, NM_DEVICE_CAP_NONE,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_CARRIER,
-		 g_param_spec_boolean (NM_DEVICE_CARRIER, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_MTU,
-		 g_param_spec_uint (NM_DEVICE_MTU, "", "",
-		                    0, G_MAXUINT32, 1500,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IP4_ADDRESS,
-		 g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, "", "",
-		                    0, G_MAXUINT32, 0, /* FIXME */
-		                    G_PARAM_READWRITE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IP4_CONFIG,
-		 g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_DHCP4_CONFIG,
-		 g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IP6_CONFIG,
-		 g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_DHCP6_CONFIG,
-		 g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_STATE,
-		 g_param_spec_uint (NM_DEVICE_STATE, "", "",
-		                    0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_STATE_REASON,
-		 g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "",
-		                       G_VARIANT_TYPE ("(uu)"),
-		                       NULL,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_ACTIVE_CONNECTION,
-		 g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_DEVICE_TYPE,
-		 g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "",
-		                    0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_LINK_TYPE,
-		 g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "",
-		                    0, G_MAXUINT32, NM_LINK_TYPE_NONE,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_MANAGED,
-		 g_param_spec_boolean (NM_DEVICE_MANAGED, "", "",
-		                       FALSE,
-		                       G_PARAM_READWRITE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_AUTOCONNECT,
-		 g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "",
-		                       DEFAULT_AUTOCONNECT,
-		                       G_PARAM_READWRITE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_FIRMWARE_MISSING,
-		 g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_NM_PLUGIN_MISSING,
-		 g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_TYPE_DESC,
-		 g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_RFKILL_TYPE,
-		 g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, "", "",
-		                    RFKILL_TYPE_WLAN,
-		                    RFKILL_TYPE_MAX,
-		                    RFKILL_TYPE_UNKNOWN,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IFINDEX,
-		 g_param_spec_int (NM_DEVICE_IFINDEX, "", "",
-		                   0, G_MAXINT, 0,
-		                   G_PARAM_READABLE |
-		                   G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_AVAILABLE_CONNECTIONS,
-		 g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "",
-		                     G_TYPE_STRV,
-		                     G_PARAM_READABLE |
-		                     G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_PHYSICAL_PORT_ID,
-		 g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_IS_MASTER,
-		 g_param_spec_boolean (NM_DEVICE_IS_MASTER, "", "",
-		                       FALSE,
-		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_MASTER,
-		 g_param_spec_object (NM_DEVICE_MASTER, "", "",
-		                      NM_TYPE_DEVICE,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_HW_ADDRESS,
-		 g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_HAS_PENDING_ACTION,
-		 g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_UDI] =
+	    g_param_spec_string (NM_DEVICE_UDI, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IFACE] =
+	    g_param_spec_string (NM_DEVICE_IFACE, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IP_IFACE] =
+	    g_param_spec_string (NM_DEVICE_IP_IFACE, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_DRIVER] =
+	    g_param_spec_string (NM_DEVICE_DRIVER, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_DRIVER_VERSION] =
+	    g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_FIRMWARE_VERSION] =
+	    g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_CAPABILITIES] =
+	    g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "",
+	                       0, G_MAXUINT32, NM_DEVICE_CAP_NONE,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_CARRIER] =
+	    g_param_spec_boolean (NM_DEVICE_CARRIER, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_MTU] =
+	    g_param_spec_uint (NM_DEVICE_MTU, "", "",
+	                       0, G_MAXUINT32, 1500,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IP4_ADDRESS] =
+	    g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, "", "",
+	                       0, G_MAXUINT32, 0, /* FIXME */
+	                       G_PARAM_READWRITE |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IP4_CONFIG] =
+	    g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_DHCP4_CONFIG] =
+	    g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IP6_CONFIG] =
+	    g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_DHCP6_CONFIG] =
+	    g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_STATE] =
+	    g_param_spec_uint (NM_DEVICE_STATE, "", "",
+	                       0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_STATE_REASON] =
+	    g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "",
+	                          G_VARIANT_TYPE ("(uu)"),
+	                          NULL,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_ACTIVE_CONNECTION] =
+	    g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_DEVICE_TYPE] =
+	    g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "",
+	                       0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
+	                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_LINK_TYPE] =
+	    g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "",
+	                       0, G_MAXUINT32, NM_LINK_TYPE_NONE,
+	                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_MANAGED] =
+	    g_param_spec_boolean (NM_DEVICE_MANAGED, "", "",
+	                          FALSE,
+	                          G_PARAM_READWRITE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_AUTOCONNECT] =
+	    g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "",
+	                          DEFAULT_AUTOCONNECT,
+	                          G_PARAM_READWRITE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_FIRMWARE_MISSING] =
+	    g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "",
+	                          FALSE,
+	                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_NM_PLUGIN_MISSING] =
+	    g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "",
+	                          FALSE,
+	                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_TYPE_DESC] =
+	    g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_RFKILL_TYPE] =
+	    g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, "", "",
+	                       RFKILL_TYPE_WLAN,
+	                       RFKILL_TYPE_MAX,
+	                       RFKILL_TYPE_UNKNOWN,
+	                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IFINDEX] =
+	    g_param_spec_int (NM_DEVICE_IFINDEX, "", "",
+	                      0, G_MAXINT, 0,
+	                      G_PARAM_READABLE |
+	                      G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_AVAILABLE_CONNECTIONS] =
+	    g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "",
+	                        G_TYPE_STRV,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_PHYSICAL_PORT_ID] =
+	    g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IS_MASTER] =
+	    g_param_spec_boolean (NM_DEVICE_IS_MASTER, "", "",
+	                          FALSE,
+	                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_MASTER] =
+	    g_param_spec_object (NM_DEVICE_MASTER, "", "",
+	                         NM_TYPE_DEVICE,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_HW_ADDRESS] =
+	    g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_HAS_PENDING_ACTION] =
+	    g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * NMDevice:metered:
@@ -11236,99 +11689,95 @@ nm_device_class_init (NMDeviceClass *klass)
 	 *
 	 * Since: 1.2
 	 **/
-	g_object_class_install_property
-		(object_class, PROP_METERED,
-		 g_param_spec_uint (NM_DEVICE_METERED, "", "",
-		                    0, G_MAXUINT32, NM_METERED_UNKNOWN,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_LLDP_NEIGHBORS,
-		 g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "",
-		                       G_VARIANT_TYPE ("aa{sv}"),
-		                       NULL,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_REAL,
-		 g_param_spec_boolean (NM_DEVICE_REAL, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_SLAVES,
-	     g_param_spec_boxed (NM_DEVICE_SLAVES, "", "",
-	                         G_TYPE_STRV,
-	                         G_PARAM_READABLE |
-	                         G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_METERED] =
+	    g_param_spec_uint (NM_DEVICE_METERED, "", "",
+	                       0, G_MAXUINT32, NM_METERED_UNKNOWN,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_LLDP_NEIGHBORS] =
+	    g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "",
+	                          G_VARIANT_TYPE ("aa{sv}"),
+	                          NULL,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_REAL] =
+	    g_param_spec_boolean (NM_DEVICE_REAL, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_SLAVES] =
+	    g_param_spec_boxed (NM_DEVICE_SLAVES, "", "",
+	                        G_TYPE_STRV,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	/* Signals */
 	signals[STATE_CHANGED] =
-		g_signal_new (NM_DEVICE_STATE_CHANGED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMDeviceClass, state_changed),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 3,
-		              G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
+	    g_signal_new (NM_DEVICE_STATE_CHANGED,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_LAST,
+	                  G_STRUCT_OFFSET (NMDeviceClass, state_changed),
+	                  NULL, NULL, NULL,
+	                  G_TYPE_NONE, 3,
+	                  G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
 
 	signals[AUTOCONNECT_ALLOWED] =
-		g_signal_new ("autoconnect-allowed",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              0,
-		              autoconnect_allowed_accumulator, NULL, NULL,
-		              G_TYPE_BOOLEAN, 0);
+	    g_signal_new ("autoconnect-allowed",
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_LAST,
+	                  0,
+	                  autoconnect_allowed_accumulator, NULL, NULL,
+	                  G_TYPE_BOOLEAN, 0);
 
 	signals[AUTH_REQUEST] =
-		g_signal_new (NM_DEVICE_AUTH_REQUEST,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              /* context, connection, permission, allow_interaction, callback, user_data */
-		              G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
+	    g_signal_new (NM_DEVICE_AUTH_REQUEST,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  /* context, connection, permission, allow_interaction, callback, user_data */
+	                  G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
 
 	signals[IP4_CONFIG_CHANGED] =
-		g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
+	    g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
 
 	signals[IP6_CONFIG_CHANGED] =
-		g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
+	    g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
 
 	signals[REMOVED] =
-		g_signal_new (NM_DEVICE_REMOVED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              G_TYPE_NONE, 0);
+	    g_signal_new (NM_DEVICE_REMOVED,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  G_TYPE_NONE, 0);
 
 	signals[RECHECK_AUTO_ACTIVATE] =
-		g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              G_TYPE_NONE, 0);
+	    g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  G_TYPE_NONE, 0);
 
 	signals[RECHECK_ASSUME] =
-		g_signal_new (NM_DEVICE_RECHECK_ASSUME,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL, NULL,
-		              G_TYPE_NONE, 0);
+	    g_signal_new (NM_DEVICE_RECHECK_ASSUME,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0, NULL, NULL, NULL,
+	                  G_TYPE_NONE, 0);
 
 	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
 	                                        NMDBUS_TYPE_DEVICE_SKELETON,
 	                                        "Reapply", impl_device_reapply,
+	                                        "GetAppliedConnection", impl_device_get_applied_connection,
 	                                        "Disconnect", impl_device_disconnect,
 	                                        "Delete", impl_device_delete,
 	                                        NULL);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index e173b2db..9b9edda4 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -103,12 +103,14 @@ typedef enum NMActStageReturn NMActStageReturn;
 typedef enum { /*< skip >*/
 	NM_DEVICE_CHECK_CON_AVAILABLE_NONE                                  = 0,
 
-	_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER     = (1L << 0),
-	_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP           = (1L << 1),
-	NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST                      = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER
+	_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST                     = (1L << 0),
+	_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER     = (1L << 1),
+	_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP           = (1L << 2),
+	NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST                      = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST
+	                                                                    | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER
 	                                                                    | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP,
 
-	NM_DEVICE_CHECK_CON_AVAILABLE_ALL                                   = (1L << 2) - 1,
+	NM_DEVICE_CHECK_CON_AVAILABLE_ALL                                   = (1L << 3) - 1,
 } NMDeviceCheckConAvailableFlags;
 
 struct _NMDevicePrivate;
@@ -324,8 +326,6 @@ typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
 
 GType nm_device_get_type (void);
 
-void            nm_device_finish_init   (NMDevice *device);
-
 const char *	nm_device_get_udi		(NMDevice *dev);
 const char *	nm_device_get_iface		(NMDevice *dev);
 int             nm_device_get_ifindex	(NMDevice *dev);
@@ -375,6 +375,7 @@ NMSettingsConnection *  nm_device_get_settings_connection       (NMDevice *dev);
 NMConnection *          nm_device_get_applied_connection        (NMDevice *dev);
 gboolean                nm_device_has_unmodified_applied_connection (NMDevice *self,
                                                                      NMSettingCompareFlags compare_flags);
+NMSetting *             nm_device_get_applied_setting           (NMDevice *dev, GType setting_type);
 
 void            nm_device_removed        (NMDevice *dev);
 
@@ -421,45 +422,67 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device);
 /**
  * NMUnmanagedFlags:
  * @NM_UNMANAGED_NONE: placeholder value
- * @NM_UNMANAGED_INTERNAL: %TRUE when unmanaged by internal decision (ie,
- *   because NM is sleeping or not managed for some other reason)
+ * @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping.
+ * @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down.
  * @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged
  * @NM_UNMANAGED_LOOPBACK: %TRUE for unmanaging loopback device
  * @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not
- *   yet initialized
- * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs)
- * @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices)
+ *   yet initialized. Unrealized device are also unmanaged for this reason.
+ * @NM_UNMANAGED_USER_EXPLICIT: %TRUE when unmanaged by explicit user decision
+ *   (e.g. via a D-Bus command)
+ * @NM_UNMANAGED_USER_SETTINGS: %TRUE when unmanaged by user decision via
+ *   the settings plugin (for example keyfile.unmanaged-devices or ifcfg-rh's
+ *   NM_CONTROLLED=no)
+ * @NM_UNMANAGED_BY_DEFAULT: %TRUE for certain device types where we unmanage
+ *   them by default
+ * @NM_UNMANAGED_USER_UDEV: %TRUE when unmanaged by user decision (via UDev rule)
  * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM
+ * @NM_UNMANAGED_IS_SLAVE: indicates that the device is enslaved. Note that
+ *   setting the NM_UNMANAGED_IS_SLAVE to %TRUE makes no sense, this flag has only
+ *   meaning to set a slave device as managed if the parent is managed too.
  */
 typedef enum { /*< skip >*/
 	NM_UNMANAGED_NONE          = 0,
 
-	NM_UNMANAGED_INTERNAL      = (1LL <<  0),
-	NM_UNMANAGED_PARENT        = (1LL <<  1),
-	NM_UNMANAGED_LOOPBACK      = (1LL <<  2),
-	NM_UNMANAGED_PLATFORM_INIT = (1LL <<  3),
-	NM_UNMANAGED_USER          = (1LL <<  4),
-
-	NM_UNMANAGED_DEFAULT       = (1LL <<  8),
+	/* these flags are authorative. If one of them is set,
+	 * the device cannot be managed. */
+	NM_UNMANAGED_SLEEPING      = (1LL <<  0),
+	NM_UNMANAGED_QUITTING      = (1LL <<  1),
+	NM_UNMANAGED_PARENT        = (1LL <<  2),
+	NM_UNMANAGED_LOOPBACK      = (1LL <<  3),
+	NM_UNMANAGED_PLATFORM_INIT = (1LL <<  4),
+	NM_UNMANAGED_USER_EXPLICIT = (1LL <<  5),
+	NM_UNMANAGED_USER_SETTINGS = (1LL <<  6),
+
+	/* These flags can be non-effective and be overwritten
+	 * by other flags. */
+	NM_UNMANAGED_BY_DEFAULT    = (1LL <<  8),
+	NM_UNMANAGED_USER_UDEV     = (1LL << 10),
 	NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 11),
+	NM_UNMANAGED_IS_SLAVE      = (1LL << 12),
 
-	/* Boundary value */
-	__NM_UNMANAGED_LAST,
-	NM_UNMANAGED_LAST          = __NM_UNMANAGED_LAST - 1,
-	NM_UNMANAGED_ALL           = ((NM_UNMANAGED_LAST << 1) - 1),
 } NMUnmanagedFlags;
 
-gboolean nm_device_get_managed (NMDevice *device);
+typedef enum {
+	NM_UNMAN_FLAG_OP_SET_MANAGED        = FALSE,
+	NM_UNMAN_FLAG_OP_SET_UNMANAGED      = TRUE,
+	NM_UNMAN_FLAG_OP_FORGET             = 2,
+} NMUnmanFlagOp;
+
+const char *nm_unmanaged_flags2str (NMUnmanagedFlags flags, char *buf, gsize len);
+
+gboolean nm_device_get_managed (NMDevice *device, gboolean for_user_request);
 NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *device, NMUnmanagedFlags flag);
 void nm_device_set_unmanaged_flags (NMDevice *device,
-                                    NMUnmanagedFlags flag,
-                                    gboolean unmanaged,
-                                    NMDeviceStateReason reason);
-void nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs);
-void nm_device_set_unmanaged_flags_initial (NMDevice *device,
-                                            NMUnmanagedFlags flag,
-                                            gboolean unmanaged);
-void nm_device_set_unmanaged_quitting (NMDevice *device);
+                                    NMUnmanagedFlags flags,
+                                    NMUnmanFlagOp set_op);
+void nm_device_set_unmanaged_by_flags (NMDevice *device,
+                                       NMUnmanagedFlags flags,
+                                       NMUnmanFlagOp set_op,
+                                       NMDeviceStateReason reason);
+void nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs);
+void nm_device_set_unmanaged_by_user_udev (NMDevice *self);
+void nm_device_set_unmanaged_by_quitting (NMDevice *device);
 
 gboolean nm_device_get_is_nm_owned (NMDevice *device);
 
@@ -481,6 +504,7 @@ gboolean nm_device_unrealize          (NMDevice *device,
 
 gboolean nm_device_get_autoconnect (NMDevice *device);
 void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect);
+void nm_device_emit_recheck_auto_activate (NMDevice *device);
 
 void nm_device_state_changed (NMDevice *device,
                               NMDeviceState state,
diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c
index 91181292..81827817 100644
--- a/src/devices/nm-lldp-listener.c
+++ b/src/devices/nm-lldp-listener.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <net/ethernet.h>
 
@@ -65,6 +65,32 @@ typedef struct {
 
 static void process_lldp_neighbors (NMLldpListener *self);
 
+/*****************************************************************************/
+
+#define _NMLOG_PREFIX_NAME                "lldp"
+#define _NMLOG_DOMAIN                     LOGD_DEVICE
+#define _NMLOG(level, ...) \
+    G_STMT_START { \
+        const NMLogLevel _level = (level); \
+        \
+        if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \
+            char _sbuf[64]; \
+            int _ifindex = (self) ? NM_LLDP_LISTENER_GET_PRIVATE (self)->ifindex : 0; \
+            \
+            _nm_log (_level, _NMLOG_DOMAIN, 0, \
+                     "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
+                     _NMLOG_PREFIX_NAME, \
+                     ((_ifindex > 0) \
+                        ? nm_sprintf_buf (_sbuf, "[%p,%d]", (self), _ifindex) \
+                        : ((self) \
+                            ? nm_sprintf_buf (_sbuf, "[%p]", (self)) \
+                            : "")) \
+                     _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+        } \
+    } G_STMT_END \
+
+/*****************************************************************************/
+
 static void
 gvalue_destroy (gpointer data)
 {
@@ -100,11 +126,13 @@ static guint
 lldp_neighbor_id_hash (gconstpointer ptr)
 {
 	const LLDPNeighbor *neigh = ptr;
+	guint hash;
 
-	return g_str_hash (neigh->chassis_id) ^
-	       g_str_hash (neigh->port_id) ^
-	       neigh->chassis_id_type ^
-	       (neigh->port_id_type * 33);
+	hash =   23423423u  + ((guint) (neigh->chassis_id ? g_str_hash (neigh->chassis_id) : 12321u));
+	hash = (hash * 33u) + ((guint) (neigh->port_id ? g_str_hash (neigh->port_id) : 34342343u));
+	hash = (hash * 33u) + ((guint) neigh->chassis_id_type);
+	hash = (hash * 33u) + ((guint) neigh->port_id_type);
+	return hash;
 }
 
 static gboolean
@@ -119,18 +147,22 @@ lldp_neighbor_id_equal (gconstpointer a, gconstpointer b)
 }
 
 static void
-lldp_neighbor_free (gpointer data)
+lldp_neighbor_free (LLDPNeighbor *neighbor)
 {
-	LLDPNeighbor *neighbor = data;
-
 	if (neighbor) {
 		g_free (neighbor->chassis_id);
 		g_free (neighbor->port_id);
 		g_hash_table_unref (neighbor->tlvs);
-		g_free (neighbor);
+		g_slice_free (LLDPNeighbor, neighbor);
 	}
 }
 
+static void
+lldp_neighbor_freep (LLDPNeighbor **ptr)
+{
+	lldp_neighbor_free (*ptr);
+}
+
 static gboolean
 lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b)
 {
@@ -207,8 +239,12 @@ lldp_hash_table_equal (GHashTable *a, GHashTable *b)
 static gboolean
 lldp_timeout (gpointer user_data)
 {
-	NMLldpListener *self = NM_LLDP_LISTENER (user_data);
-	NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
+	NMLldpListener *self = user_data;
+	NMLldpListenerPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE);
+
+	priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 
 	priv->timer = 0;
 
@@ -222,24 +258,26 @@ static void
 process_lldp_neighbors (NMLldpListener *self)
 {
 	NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
-	sd_lldp_packet **packets = NULL;
+	nm_auto_free sd_lldp_packet **packets = NULL;
 	GHashTable *hash;
 	int num, i;
 
+	g_return_if_fail (priv->lldp_handle);
+
 	num = sd_lldp_get_packets (priv->lldp_handle, &packets);
 	if (num < 0) {
-		nm_log_dbg (LOGD_DEVICE, "LLDP: error %d retrieving neighbor packets for %s",
-		            num, priv->iface);
+		_LOGD ("process: error %d retrieving neighbor packets for %s",
+		        num, priv->iface);
 		return;
 	}
 
 	hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal,
-	                              lldp_neighbor_free, NULL);
+	                              (GDestroyNotify) lldp_neighbor_free, NULL);
 
 	for (i = 0; packets && i < num; i++) {
+		nm_auto (lldp_neighbor_freep) LLDPNeighbor *neigh = NULL;
 		uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8;
 		uint16_t chassis_id_len, port_id_len, len, data16;
-		LLDPNeighbor *neigh;
 		GValue *value;
 		char *str;
 		int r;
@@ -257,37 +295,32 @@ process_lldp_neighbors (NMLldpListener *self)
 		if (r < 0)
 			goto next_packet;
 
-		neigh = g_malloc0 (sizeof (LLDPNeighbor));
+		neigh = g_slice_new0 (LLDPNeighbor);
 		neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy);
 		neigh->chassis_id_type = chassis_id_type;
 		neigh->port_id_type = port_id_type;
 		sd_lldp_packet_get_destination_type (packets[i], &neigh->dest);
 
-		if (chassis_id_len < 1) {
-			lldp_neighbor_free (neigh);
+		if (chassis_id_len < 1)
 			goto next_packet;
-		}
 
 		switch (chassis_id_type) {
 		case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
 		case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
 		case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
 		case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
-			neigh->chassis_id = strndup ((char *) chassis_id, chassis_id_len);
+			neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len);
 			break;
 		case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
 			neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len);
 			break;
 		default:
-			nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported chassis ID type %d", chassis_id_type);
-			lldp_neighbor_free (neigh);
+			_LOGD ("process: unsupported chassis ID type %d", chassis_id_type);
 			goto next_packet;
 		}
 
-		if (port_id_len < 1) {
-			lldp_neighbor_free (neigh);
+		if (port_id_len < 1)
 			goto next_packet;
-		}
 
 		switch (port_id_type) {
 		case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
@@ -300,8 +333,7 @@ process_lldp_neighbors (NMLldpListener *self)
 			neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len);
 			break;
 		default:
-			nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported port ID type %d", port_id_type);
-			lldp_neighbor_free (neigh);
+			_LOGD ("process: unsupported port ID type %d", port_id_type);
 			goto next_packet;
 		}
 
@@ -346,16 +378,15 @@ process_lldp_neighbors (NMLldpListener *self)
 			g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value);
 		}
 
-		nm_log_dbg (LOGD_DEVICE, "LLDP: new neigh: CHASSIS='%s' PORT='%s'",
-		            neigh->chassis_id, neigh->port_id);
+		_LOGD ("process: new neigh: CHASSIS='%s' PORT='%s'",
+		        neigh->chassis_id, neigh->port_id);
 
 		g_hash_table_add (hash, neigh);
+		neigh = NULL;
 next_packet:
 		sd_lldp_packet_unref (packets[i]);
 	}
 
-	g_free (packets);
-
 	if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) {
 		g_hash_table_destroy (hash);
 	} else {
@@ -380,6 +411,7 @@ lldp_event_handler (sd_lldp *lldp, int event, void *userdata)
 	NMLldpListenerPrivate *priv;
 
 	g_return_if_fail (NM_IS_LLDP_LISTENER (self));
+
 	priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 
 	if (priv->timer > 0) {
@@ -446,6 +478,7 @@ nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface,
 
 	priv->ifindex = ifindex;
 	priv->iface = strdup (iface);
+	_LOGD ("start");
 	return TRUE;
 
 err:
@@ -466,6 +499,7 @@ nm_lldp_listener_stop (NMLldpListener *self)
 	priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 
 	if (priv->lldp_handle) {
+		_LOGD ("stop");
 		sd_lldp_stop (priv->lldp_handle);
 		sd_lldp_detach_event (priv->lldp_handle);
 		sd_lldp_unref (priv->lldp_handle);
@@ -481,6 +515,7 @@ nm_lldp_listener_stop (NMLldpListener *self)
 	}
 
 	nm_clear_g_source (&priv->timer);
+	priv->ifindex = 0;
 }
 
 gboolean
@@ -595,7 +630,9 @@ nm_lldp_listener_init (NMLldpListener *self)
 
 	priv->lldp_neighbors = g_hash_table_new_full (lldp_neighbor_id_hash,
 	                                              lldp_neighbor_id_equal,
-	                                              lldp_neighbor_free, NULL);
+	                                              (GDestroyNotify) lldp_neighbor_free, NULL);
+
+	_LOGT ("lldp listener created");
 }
 
 NMLldpListener *
@@ -623,6 +660,8 @@ finalize (GObject *object)
 
 	nm_clear_g_variant (&priv->variant);
 
+	_LOGT ("lldp listener destroyed");
+
 	G_OBJECT_CLASS (nm_lldp_listener_parent_class)->finalize (object);
 }
 
diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h
index 492752c1..10c43e7c 100644
--- a/src/devices/nm-lldp-listener.h
+++ b/src/devices/nm-lldp-listener.h
@@ -21,9 +21,6 @@
 #ifndef __NM_LLDP_LISTENER__
 #define __NM_LLDP_LISTENER__
 
-#include "nm-glib.h"
-#include "nm-types.h"
-
 G_BEGIN_DECLS
 
 #define NM_TYPE_LLDP_LISTENER            (nm_lldp_listener_get_type ())
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index c0b83b84..c3d48b41 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -18,7 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -27,7 +27,6 @@
 #include <teamdctl.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-device-team.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
@@ -85,7 +84,6 @@ check_connection_available (NMDevice *device,
 static gboolean
 check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
-	const char *iface;
 	NMSettingTeam *s_team;
 
 	if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection))
@@ -95,11 +93,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
 		return FALSE;
 
-	/* Team connections must specify the virtual interface name */
-	iface = nm_connection_get_interface_name (connection);
-	if (!iface || strcmp (nm_device_get_iface (device), iface))
-		return FALSE;
-
 	/* FIXME: match team properties like mode, etc? */
 
 	return TRUE;
@@ -218,6 +211,7 @@ master_update_slave_connection (NMDevice *self,
 
 	err = teamdctl_port_config_get_raw_direct (tdc, iface_slave, (char **)&team_port_config);
 	port_config = g_strdup (team_port_config);
+	teamdctl_disconnect (tdc);
 	teamdctl_free (tdc);
 	if (err) {
 		g_set_error (error,
@@ -501,7 +495,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self);
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
 	gs_free_error GError *error = NULL;
-	NMConnection *connection;
 	NMSettingTeam *s_team;
 	const char *cfg;
 
@@ -511,9 +504,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
 		return ret;
 
-	connection = nm_device_get_applied_connection (device);
-	g_assert (connection);
-	s_team = nm_connection_get_setting_team (connection);
+	s_team = (NMSettingTeam *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_TEAM);
 	g_assert (s_team);
 
 	if (priv->tdc) {
@@ -673,7 +664,7 @@ create_and_realize (NMDevice *device,
 	NMPlatformError plerr;
 
 	plerr = nm_platform_link_team_add (NM_PLATFORM_GET, iface, out_plink);
-	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+	if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
 		             "Failed to create team master interface '%s' for '%s': %s",
 		             iface,
diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c
index 5f9e142a..971efe87 100644
--- a/src/devices/team/nm-team-factory.c
+++ b/src/devices/team/nm-team-factory.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <gmodule.h>
@@ -26,7 +26,6 @@
 #include "nm-device-factory.h"
 #include "nm-team-factory.h"
 #include "nm-device-team.h"
-#include "nm-default.h"
 #include "nm-platform.h"
 #include "nm-core-internal.h"
 
diff --git a/src/devices/tests/Makefile.am b/src/devices/tests/Makefile.am
index 330377b0..e4f4d3fe 100644
--- a/src/devices/tests/Makefile.am
+++ b/src/devices/tests/Makefile.am
@@ -23,7 +23,8 @@ DEVICES_LDADD = \
 @GNOME_CODE_COVERAGE_RULES@
 
 noinst_PROGRAMS = \
-	test-lldp
+	test-lldp \
+	test-arping
 
 test_lldp_SOURCES = \
 	test-lldp.c \
@@ -37,6 +38,19 @@ test_lldp_CPPFLAGS = \
 
 test_lldp_LDADD = $(DEVICES_LDADD)
 
+test_arping_SOURCES = \
+	test-arping.c \
+	../nm-arping-manager.c \
+	$(top_srcdir)/src/platform/tests/test-common.c
+
+test_arping_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir)/src/platform/tests \
+	-DSETUP=nm_linux_platform_setup
+
+test_arping_LDADD = $(DEVICES_LDADD)
+
 @VALGRIND_RULES@
 TESTS = \
-	test-lldp
+	test-lldp \
+	test-arping
diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in
index 1cfe46b6..1cb73d28 100644
--- a/src/devices/tests/Makefile.in
+++ b/src/devices/tests/Makefile.in
@@ -88,8 +88,8 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-noinst_PROGRAMS = test-lldp$(EXEEXT)
-TESTS = test-lldp$(EXEEXT)
+noinst_PROGRAMS = test-lldp$(EXEEXT) test-arping$(EXEEXT)
+TESTS = test-lldp$(EXEEXT) test-arping$(EXEEXT)
 subdir = src/devices/tests
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
@@ -113,15 +113,20 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 PROGRAMS = $(noinst_PROGRAMS)
+am_test_arping_OBJECTS = test_arping-test-arping.$(OBJEXT) \
+	test_arping-nm-arping-manager.$(OBJEXT) \
+	test_arping-test-common.$(OBJEXT)
+test_arping_OBJECTS = $(am_test_arping_OBJECTS)
+test_arping_DEPENDENCIES = $(DEVICES_LDADD)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
 am_test_lldp_OBJECTS = test_lldp-test-lldp.$(OBJEXT) \
 	test_lldp-nm-lldp-listener.$(OBJEXT) \
 	test_lldp-test-common.$(OBJEXT)
 test_lldp_OBJECTS = $(am_test_lldp_OBJECTS)
 test_lldp_DEPENDENCIES = $(DEVICES_LDADD)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -156,8 +161,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(test_lldp_SOURCES)
-DIST_SOURCES = $(test_lldp_SOURCES)
+SOURCES = $(test_arping_SOURCES) $(test_lldp_SOURCES)
+DIST_SOURCES = $(test_arping_SOURCES) $(test_lldp_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -685,6 +690,17 @@ test_lldp_CPPFLAGS = \
 	-DSETUP=nm_linux_platform_setup
 
 test_lldp_LDADD = $(DEVICES_LDADD)
+test_arping_SOURCES = \
+	test-arping.c \
+	../nm-arping-manager.c \
+	$(top_srcdir)/src/platform/tests/test-common.c
+
+test_arping_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir)/src/platform/tests \
+	-DSETUP=nm_linux_platform_setup
+
+test_arping_LDADD = $(DEVICES_LDADD)
 all: all-am
 
 .SUFFIXES:
@@ -728,6 +744,10 @@ clean-noinstPROGRAMS:
 	echo " rm -f" $$list; \
 	rm -f $$list
 
+test-arping$(EXEEXT): $(test_arping_OBJECTS) $(test_arping_DEPENDENCIES) $(EXTRA_test_arping_DEPENDENCIES) 
+	@rm -f test-arping$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(test_arping_OBJECTS) $(test_arping_LDADD) $(LIBS)
+
 test-lldp$(EXEEXT): $(test_lldp_OBJECTS) $(test_lldp_DEPENDENCIES) $(EXTRA_test_lldp_DEPENDENCIES) 
 	@rm -f test-lldp$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(test_lldp_OBJECTS) $(test_lldp_LDADD) $(LIBS)
@@ -738,6 +758,9 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-nm-arping-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-test-arping.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-test-common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-nm-lldp-listener.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-lldp.Po@am__quote@
@@ -763,6 +786,48 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+test_arping-test-arping.o: test-arping.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-arping.o -MD -MP -MF $(DEPDIR)/test_arping-test-arping.Tpo -c -o test_arping-test-arping.o `test -f 'test-arping.c' || echo '$(srcdir)/'`test-arping.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-arping.Tpo $(DEPDIR)/test_arping-test-arping.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-arping.c' object='test_arping-test-arping.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-arping.o `test -f 'test-arping.c' || echo '$(srcdir)/'`test-arping.c
+
+test_arping-test-arping.obj: test-arping.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-arping.obj -MD -MP -MF $(DEPDIR)/test_arping-test-arping.Tpo -c -o test_arping-test-arping.obj `if test -f 'test-arping.c'; then $(CYGPATH_W) 'test-arping.c'; else $(CYGPATH_W) '$(srcdir)/test-arping.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-arping.Tpo $(DEPDIR)/test_arping-test-arping.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-arping.c' object='test_arping-test-arping.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-arping.obj `if test -f 'test-arping.c'; then $(CYGPATH_W) 'test-arping.c'; else $(CYGPATH_W) '$(srcdir)/test-arping.c'; fi`
+
+test_arping-nm-arping-manager.o: ../nm-arping-manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-nm-arping-manager.o -MD -MP -MF $(DEPDIR)/test_arping-nm-arping-manager.Tpo -c -o test_arping-nm-arping-manager.o `test -f '../nm-arping-manager.c' || echo '$(srcdir)/'`../nm-arping-manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-nm-arping-manager.Tpo $(DEPDIR)/test_arping-nm-arping-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../nm-arping-manager.c' object='test_arping-nm-arping-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-nm-arping-manager.o `test -f '../nm-arping-manager.c' || echo '$(srcdir)/'`../nm-arping-manager.c
+
+test_arping-nm-arping-manager.obj: ../nm-arping-manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-nm-arping-manager.obj -MD -MP -MF $(DEPDIR)/test_arping-nm-arping-manager.Tpo -c -o test_arping-nm-arping-manager.obj `if test -f '../nm-arping-manager.c'; then $(CYGPATH_W) '../nm-arping-manager.c'; else $(CYGPATH_W) '$(srcdir)/../nm-arping-manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-nm-arping-manager.Tpo $(DEPDIR)/test_arping-nm-arping-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../nm-arping-manager.c' object='test_arping-nm-arping-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-nm-arping-manager.obj `if test -f '../nm-arping-manager.c'; then $(CYGPATH_W) '../nm-arping-manager.c'; else $(CYGPATH_W) '$(srcdir)/../nm-arping-manager.c'; fi`
+
+test_arping-test-common.o: $(top_srcdir)/src/platform/tests/test-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-common.o -MD -MP -MF $(DEPDIR)/test_arping-test-common.Tpo -c -o test_arping-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-common.Tpo $(DEPDIR)/test_arping-test-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_arping-test-common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c
+
+test_arping-test-common.obj: $(top_srcdir)/src/platform/tests/test-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-common.obj -MD -MP -MF $(DEPDIR)/test_arping-test-common.Tpo -c -o test_arping-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-common.Tpo $(DEPDIR)/test_arping-test-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_arping-test-common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi`
+
 test_lldp-test-lldp.o: test-lldp.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-lldp.o -MD -MP -MF $(DEPDIR)/test_lldp-test-lldp.Tpo -c -o test_lldp-test-lldp.o `test -f 'test-lldp.c' || echo '$(srcdir)/'`test-lldp.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-lldp.Tpo $(DEPDIR)/test_lldp-test-lldp.Po
@@ -1011,6 +1076,13 @@ test-lldp.log: test-lldp$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+test-arping.log: test-arping$(EXEEXT)
+	@p='test-arping$(EXEEXT)'; \
+	b='test-arping'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 .test.log:
 	@p='$<'; \
 	$(am__set_b); \
diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c
new file mode 100644
index 00000000..36e17631
--- /dev/null
+++ b/src/devices/tests/test-arping.c
@@ -0,0 +1,139 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-platform.c - Handle runtime kernel networking configuration
+ *
+ * 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) 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-arping-manager.h"
+#include "test-common.h"
+
+#define IFACE_VETH0 "nm-test-veth0"
+#define IFACE_VETH1 "nm-test-veth1"
+
+#define ADDR1 0x01010101
+#define ADDR2 0x02020202
+#define ADDR3 0x03030303
+#define ADDR4 0x04040404
+
+typedef struct {
+	int ifindex0;
+	int ifindex1;
+} test_fixture;
+
+static void
+fixture_setup (test_fixture *fixture, gconstpointer user_data)
+{
+	/* create veth pair. */
+	nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1);
+	fixture->ifindex0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex;
+	fixture->ifindex1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex;
+
+	g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL));
+	g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL));
+}
+
+typedef struct {
+	in_addr_t addresses[8];
+	in_addr_t peer_addresses[8];
+	gboolean expected_result[8];
+} TestInfo;
+
+static void
+arping_manager_probe_terminated (NMArpingManager *arping_manager, GMainLoop *loop)
+{
+	g_main_loop_quit (loop);
+}
+
+static void
+test_arping_common (test_fixture *fixture, TestInfo *info)
+{
+	gs_unref_object NMArpingManager *manager = NULL;
+	GMainLoop *loop;
+	int i;
+
+	if (!nm_utils_find_helper ("arping", NULL, NULL)) {
+		g_test_skip ("arping binary is missing");
+		return;
+	}
+
+	manager = nm_arping_manager_new (fixture->ifindex0);
+	g_assert (manager != NULL);
+
+	for (i = 0; info->addresses[i]; i++)
+		g_assert (nm_arping_manager_add_address (manager, info->addresses[i]));
+
+	for (i = 0; info->peer_addresses[i]; i++) {
+		nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i],
+		                        24, 0, 3600, 1800, NULL);
+	}
+
+	loop = g_main_loop_new (NULL, FALSE);
+	g_signal_connect (manager, NM_ARPING_MANAGER_PROBE_TERMINATED,
+	                  G_CALLBACK (arping_manager_probe_terminated), loop);
+	g_assert (nm_arping_manager_start_probe (manager, 100, NULL));
+	g_assert (nmtst_main_loop_run (loop, 1000));
+
+	for (i = 0; info->addresses[i]; i++) {
+		g_assert_cmpint (nm_arping_manager_check_address (manager, info->addresses[i]),
+		                 ==,
+		                 info->expected_result[i]);
+	}
+
+	g_main_loop_unref (loop);
+}
+
+static void
+test_arping_1 (test_fixture *fixture, gconstpointer user_data)
+{
+	TestInfo info = { .addresses       = { ADDR1, ADDR2, ADDR3 },
+	                  .peer_addresses  = { ADDR4 },
+	                  .expected_result = { TRUE, TRUE, TRUE } };
+
+	test_arping_common (fixture, &info);
+}
+
+static void
+test_arping_2 (test_fixture *fixture, gconstpointer user_data)
+{
+	TestInfo info = { .addresses       = { ADDR1, ADDR2, ADDR3, ADDR4 },
+	                  .peer_addresses  = { ADDR3, ADDR2 },
+	                  .expected_result = { TRUE, FALSE, FALSE, TRUE } };
+
+	test_arping_common (fixture, &info);
+}
+
+static void
+fixture_teardown (test_fixture *fixture, gconstpointer user_data)
+{
+	nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex0);
+	nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex1);
+}
+
+void
+init_tests (int *argc, char ***argv)
+{
+	nmtst_init_with_logging (argc, argv, NULL, "ALL");
+}
+
+void
+setup_tests (void)
+{
+	g_test_add ("/arping/1", test_fixture, NULL, fixture_setup, test_arping_1, fixture_teardown);
+	g_test_add ("/arping/2", test_fixture, NULL, fixture_setup, test_arping_2, fixture_teardown);
+}
diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c
index c339d9ca..dfae58b1 100644
--- a/src/devices/tests/test-lldp.c
+++ b/src/devices/tests/test-lldp.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <fcntl.h>
 #include <linux/if_tun.h>
@@ -26,7 +26,6 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "nm-default.h"
 #include "nm-lldp-listener.h"
 #include "test-common.h"
 
@@ -95,7 +94,6 @@ get_lldp_neighbor_attribute (GVariant *neighbors,
 	GVariantIter iter, attrs_iter;
 	GVariant *variant, *attr_variant;
 	const char *attr_name;
-	GVariant *chassis_v, *port_v, *attr_v;
 
 	g_return_val_if_fail (g_variant_is_of_type (neighbors,
 	                                            G_VARIANT_TYPE ("aa{sv}")),
@@ -103,31 +101,34 @@ get_lldp_neighbor_attribute (GVariant *neighbors,
 	g_variant_iter_init (&iter, neighbors);
 
 	while (g_variant_iter_next (&iter, "@a{sv}", &variant)) {
-		g_variant_iter_init (&attrs_iter, variant);
-		chassis_v = NULL;
-		port_v = NULL;
-		attr_v = NULL;
+		gs_unref_variant GVariant *chassis_v = NULL;
+		gs_unref_variant GVariant *port_v = NULL;
+		gs_unref_variant GVariant *attr_v = NULL;
 
+		g_variant_iter_init (&attrs_iter, variant);
 		while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) {
-			if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID))
+			if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) {
+				g_assert (!chassis_v);
 				chassis_v = attr_variant;
-			else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID))
+			} else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) {
+				g_assert (!port_v);
 				port_v = attr_variant;
-			else if (!g_strcmp0 (attr_name, name))
+			} else if (!g_strcmp0 (attr_name, name)) {
+				g_assert (!attr_v);
 				attr_v = attr_variant;
+			} else
+				g_variant_unref (attr_variant);
 		}
 
-		if (   g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING)
+		g_variant_unref (variant);
+
+		if (   chassis_v
+		    && port_v
+		    && g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING)
 		    && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING)
 		    && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL))
-		    && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) {
-
-			g_variant_ref (attr_v);
-			g_variant_unref (variant);
-
-			return attr_v;
-		}
-		g_variant_unref (variant);
+		    && !g_strcmp0 (port, g_variant_get_string (port_v, NULL)))
+			return g_variant_ref (attr_v);
 	}
 
 	/* neighbor not found */
@@ -137,7 +138,7 @@ get_lldp_neighbor_attribute (GVariant *neighbors,
 static void
 test_receive_frame (test_fixture *fixture, gconstpointer user_data)
 {
-	NMLldpListener *listener;
+	gs_unref_object NMLldpListener *listener = NULL;
 	GMainLoop *loop;
 	TestInfo info = { };
 	GVariant *neighbors, *attr;
@@ -182,6 +183,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data)
 	g_assert (attr != NULL);
 	g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING));
 	g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port");
+	nm_clear_g_variant (&attr);
 
 	/* Check system name */
 	attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3",
@@ -189,6 +191,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data)
 	g_assert (attr != NULL);
 	g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING));
 	g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS");
+	nm_clear_g_variant (&attr);
 
 	/* Check destination */
 	attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3",
@@ -197,6 +200,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data)
 	g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING));
 	g_assert_cmpstr (g_variant_get_string (attr, NULL), ==,
 	                 NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE);
+	nm_clear_g_variant (&attr);
 
 	g_clear_pointer (&loop, g_main_loop_unref);
 }
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index 23ebd9c8..11da011e 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -24,7 +24,7 @@
  * (C) Copyright 2009 One Laptop per Child
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <netinet/in.h>
 #include <string.h>
@@ -35,7 +35,6 @@
 #include <sys/ioctl.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "nm-device.h"
 #include "nm-device-wifi.h"
 #include "nm-device-olpc-mesh.h"
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 64da03e1..da2a0f4a 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -19,14 +19,13 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <netinet/in.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "nm-device.h"
 #include "nm-device-wifi.h"
 #include "nm-device-private.h"
@@ -125,8 +124,6 @@ static gboolean check_scanning_allowed (NMDeviceWifi *self);
 
 static void schedule_scan (NMDeviceWifi *self, gboolean backoff);
 
-static void cancel_pending_scan (NMDeviceWifi *self);
-
 static void cleanup_association_attempt (NMDeviceWifi * self,
                                          gboolean disconnect);
 
@@ -194,13 +191,12 @@ supplicant_interface_acquire (NMDeviceWifi *self)
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
 	g_return_val_if_fail (self != NULL, FALSE);
-	/* interface already acquired? */
-	g_return_val_if_fail (priv->sup_iface == NULL, TRUE);
+	g_return_val_if_fail (!priv->sup_iface, TRUE);
 
-	priv->sup_iface = nm_supplicant_manager_iface_get (priv->sup_mgr,
-	                                                   nm_device_get_iface (NM_DEVICE (self)),
-	                                                   TRUE);
-	if (priv->sup_iface == NULL) {
+	priv->sup_iface = nm_supplicant_manager_create_interface (priv->sup_mgr,
+	                                                          nm_device_get_iface (NM_DEVICE (self)),
+	                                                          TRUE);
+	if (!priv->sup_iface) {
 		_LOGE (LOGD_WIFI, "Couldn't initialize supplicant interface");
 		return FALSE;
 	}
@@ -249,7 +245,7 @@ supplicant_interface_release (NMDeviceWifi *self)
 
 	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
-	cancel_pending_scan (self);
+	nm_clear_g_source (&priv->pending_scan_id);
 
 	/* Reset the scan interval to be pretty frequent when disconnected */
 	priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
@@ -259,16 +255,13 @@ supplicant_interface_release (NMDeviceWifi *self)
 	nm_clear_g_source (&priv->ap_dump_id);
 
 	if (priv->sup_iface) {
-		remove_supplicant_interface_error_handler (self);
-
 		/* Clear supplicant interface signal handlers */
 		g_signal_handlers_disconnect_by_data (priv->sup_iface, self);
 
 		/* Tell the supplicant to disconnect from the current AP */
 		nm_supplicant_interface_disconnect (priv->sup_iface);
 
-		nm_supplicant_manager_iface_release (priv->sup_mgr, priv->sup_iface);
-		priv->sup_iface = NULL;
+		g_clear_object (&priv->sup_iface);
 	}
 }
 
@@ -495,8 +488,6 @@ deactivate (NMDevice *device)
 	if (nm_device_get_initial_hw_address (device))
 		nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI);
 
-	nm_platform_wifi_set_powersave (NM_PLATFORM_GET, ifindex, 0);
-
 	/* Ensure we're in infrastructure mode after deactivation; some devices
 	 * (usually older ones) don't scan well in adhoc mode.
 	 */
@@ -513,7 +504,7 @@ deactivate (NMDevice *device)
 
 	/* Ensure we trigger a scan after deactivating a Hotspot */
 	if (old_mode == NM_802_11_MODE_AP) {
-		cancel_pending_scan (self);
+		nm_clear_g_source (&priv->pending_scan_id);
 		request_wireless_scan (self, NULL);
 	}
 }
@@ -926,13 +917,26 @@ can_auto_connect (NMDevice *device,
                   char **specific_object)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMSettingWireless *s_wifi;
 	NMAccessPoint *ap;
-	const char *method = NULL;
+	const char *method, *mode;
 	guint64 timestamp = 0;
 
 	if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->can_auto_connect (device, connection, specific_object))
 		return FALSE;
 
+	s_wifi = nm_connection_get_setting_wireless (connection);
+	g_return_val_if_fail (s_wifi, FALSE);
+
+	/* Always allow autoconnect for AP and non-autoconf Ad-Hoc */
+	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
+	mode = nm_setting_wireless_get_mode (s_wifi);
+	if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0)
+		return TRUE;
+	else if (   g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0
+	         && g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) != 0)
+		return TRUE;
+
 	/* Don't autoconnect to networks that have been tried at least once
 	 * but haven't been successful, since these are often accidental choices
 	 * from the menu and the user may not know the password.
@@ -942,11 +946,6 @@ can_auto_connect (NMDevice *device,
 			return FALSE;
 	}
 
-	/* Use the connection if it's a shared connection */
-	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
-	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
-		return TRUE;
-
 	ap = find_first_compatible_ap (self, connection, FALSE);
 	if (ap) {
 		/* All good; connection is usable */
@@ -1027,6 +1026,7 @@ request_scan_cb (NMDevice *device,
                  gpointer user_data)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMDeviceWifiPrivate *priv;
 	gs_unref_variant GVariant *new_scan_options = user_data;
 
 	if (error) {
@@ -1042,7 +1042,9 @@ request_scan_cb (NMDevice *device,
 		return;
 	}
 
-	cancel_pending_scan (self);
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	nm_clear_g_source (&priv->pending_scan_id);
 	request_wireless_scan (self, new_scan_options);
 	g_dbus_method_invocation_return_value (context, NULL);
 }
@@ -1366,7 +1368,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
 	/* Cancel the pending scan if it would happen later than (now + the scan_interval) */
 	if (priv->pending_scan_id) {
 		if (now + priv->scan_interval < priv->scheduled_scan_time)
-			cancel_pending_scan (self);
+			nm_clear_g_source (&priv->pending_scan_id);
 	}
 
 	if (!priv->pending_scan_id) {
@@ -1399,15 +1401,6 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
 	}
 }
 
-
-static void
-cancel_pending_scan (NMDeviceWifi *self)
-{
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-
-	nm_clear_g_source (&priv->pending_scan_id);
-}
-
 static void
 supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
                                gboolean success,
@@ -2205,7 +2198,7 @@ build_supplicant_config (NMDeviceWifi *self,
 	NMSettingMacRandomization mac_randomization_fallback;
 	gs_free char *svalue = NULL;
 
-	g_return_val_if_fail (self != NULL, NULL);
+	g_return_val_if_fail (priv->sup_iface, NULL);
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
 	g_return_val_if_fail (s_wireless != NULL, NULL);
@@ -2323,8 +2316,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 
 	/* Set spoof MAC to the interface */
 	cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
-	if (cloned_mac)
-		nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI);
+	nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI);
 
 	/* AP mode never uses a specific object or existing scanned AP */
 	if (priv->mode != NM_802_11_MODE_AP) {
@@ -2393,6 +2385,38 @@ ensure_hotspot_frequency (NMDeviceWifi *self,
 	nm_ap_set_freq (ap, freq);
 }
 
+static void
+set_powersave (NMDevice *device)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessPowersave powersave;
+	gs_free char *value = NULL;
+
+	s_wireless = (NMSettingWireless *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRELESS);
+	g_return_if_fail (s_wireless);
+
+	powersave = nm_setting_wireless_get_powersave (s_wireless);
+	if (powersave == NM_SETTING_WIRELESS_POWERSAVE_DEFAULT) {
+		value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+		                                               "wifi.powersave",
+		                                               device);
+		powersave = _nm_utils_ascii_str_to_int64 (value, 10,
+		                                          NM_SETTING_WIRELESS_POWERSAVE_IGNORE,
+		                                          NM_SETTING_WIRELESS_POWERSAVE_ENABLE,
+		                                          NM_SETTING_WIRELESS_POWERSAVE_IGNORE);
+	}
+
+	_LOGT (LOGD_WIFI, "powersave is set to %u", (unsigned int) powersave);
+
+	if (powersave == NM_SETTING_WIRELESS_POWERSAVE_IGNORE)
+		return;
+
+	nm_platform_wifi_set_powersave (NM_PLATFORM_GET,
+	                                nm_device_get_ifindex (device),
+	                                powersave == NM_SETTING_WIRELESS_POWERSAVE_ENABLE);
+}
+
 static NMActStageReturn
 act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 {
@@ -2459,11 +2483,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap))
 		ensure_hotspot_frequency (self, s_wireless, ap);
 
-	if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) {
-		nm_platform_wifi_set_powersave (NM_PLATFORM_GET,
-		                                nm_device_get_ifindex (device),
-		                                nm_setting_wireless_get_powersave (s_wireless));
-	}
+	if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA)
+		set_powersave (device);
 
 	/* Build up the supplicant configuration */
 	config = build_supplicant_config (self, connection, nm_ap_get_freq (ap), &error);
@@ -2817,7 +2838,7 @@ device_state_changed (NMDevice *device,
 	case NM_DEVICE_STATE_DISCONNECTED:
 		/* Kick off a scan to get latest results */
 		priv->scan_interval = SCAN_INTERVAL_MIN;
-		cancel_pending_scan (self);
+		nm_clear_g_source (&priv->pending_scan_id);
 		request_wireless_scan (self, NULL);
 		break;
 	default:
diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c
index d7916aa0..bcf439da 100644
--- a/src/devices/wifi/nm-wifi-ap-utils.c
+++ b/src/devices/wifi/nm-wifi-ap-utils.c
@@ -18,12 +18,11 @@
  * (C) Copyright 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-wifi-ap-utils.h"
 #include "nm-utils.h"
 
@@ -162,7 +161,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec,
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("a connection using '%s' authentication cannot specific WPA protocols"),
+		             _("a connection using '%s' authentication cannot specify WPA protocols"),
 		             tag);
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 		                NM_SETTING_WIRELESS_SECURITY_PROTO);
@@ -178,7 +177,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec,
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
 			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("a connection using '%s' authentication cannot specific WPA ciphers"),
+			             _("a connection using '%s' authentication cannot specify WPA ciphers"),
 			             tag);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 			                NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
@@ -195,7 +194,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec,
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
 			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("a connection using '%s' authentication cannot specific WPA ciphers"),
+			             _("a connection using '%s' authentication cannot specify WPA ciphers"),
 			             tag);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 			                NM_SETTING_WIRELESS_SECURITY_GROUP);
@@ -207,7 +206,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec,
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("a connection using '%s' authentication cannot specific a WPA password"),
+		             _("a connection using '%s' authentication cannot specify a WPA password"),
 		             tag);
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 		                NM_SETTING_WIRELESS_SECURITY_PSK);
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index 771d6704..307825c6 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -19,12 +19,11 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-wifi-ap.h"
 #include "nm-wifi-ap-utils.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index 7f56dc74..2d5f8faf 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2011 - 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <gmodule.h>
 
@@ -66,6 +66,7 @@ create_device (NMDeviceFactory *factory,
                gboolean *out_ignore)
 {
 	NMDeviceWifiCapabilities capabilities;
+	NM80211Mode mode;
 
 	g_return_val_if_fail (iface != NULL, NULL);
 	g_return_val_if_fail (plink != NULL, NULL);
@@ -79,6 +80,16 @@ create_device (NMDeviceFactory *factory,
 		return NULL;
 	}
 
+	/* Ignore monitor-mode and other unhandled interface types.
+	 * FIXME: keep TYPE_MONITOR devices in UNAVAILABLE state and manage
+	 * them if/when they change to a handled type.
+	 */
+	mode = nm_platform_wifi_get_mode (NM_PLATFORM_GET, plink->ifindex);
+	if (mode == NM_802_11_MODE_UNKNOWN) {
+		*out_ignore = TRUE;
+		return NULL;
+	}
+
 	if (plink->type == NM_LINK_TYPE_WIFI)
 		return nm_device_wifi_new (iface, capabilities);
 	else
diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c
index b5642fe2..01990bee 100644
--- a/src/devices/wifi/tests/test-wifi-ap-utils.c
+++ b/src/devices/wifi/tests/test-wifi-ap-utils.c
@@ -18,11 +18,10 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-wifi-ap-utils.h"
 
 #include "nm-core-internal.h"
@@ -594,7 +593,7 @@ wpa_flags_for_idx (guint32 idx)
 		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
 	else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP)
 		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
-	else if (IDX_WPA_RSN_PSK_PCCMP_GCCMP)
+	else if (NM_IN_SET (idx, IDX_WPA_PSK_PTKIP_PCCMP_GTKIP, IDX_WPA_RSN_PSK_PCCMP_GCCMP))
 		return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
 	else if (idx == IDX_WPA_8021X)
 		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index edecd24d..e9c4f02e 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2009 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-device-modem.h"
 #include "nm-modem.h"
 #include "nm-device-private.h"
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 427f3ed6..6343416c 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
@@ -26,7 +26,6 @@
 
 #include "nm-modem-broadband.h"
 #include "nm-core-internal.h"
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
 #include "nm-platform.h"
@@ -52,6 +51,7 @@ typedef struct {
 	MMSimpleConnectProperties *connect_properties;
 	GArray *ip_types;
 	guint ip_types_i;
+	guint ip_type_tries;
 	GError *first_error;
 } ConnectContext;
 
@@ -331,11 +331,17 @@ connect_ready (MMModemSimple *simple_iface,
 		} else
 			g_error_free (error);
 
-		/* If the modem/provider lies and the IP type we tried isn't supported,
-		 * retry with the next one, if any.
-		 */
-		ctx->ip_types_i++;
-		connect_context_clear (self);
+		if (ctx->ip_type_tries == 0 && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) {
+			/* Try one more time */
+			ctx->ip_type_tries++;
+		} else {
+			/* If the modem/provider lies and the IP type we tried isn't supported,
+			 * retry with the next one, if any.
+			 */
+			ctx->ip_types_i++;
+			ctx->ip_type_tries = 0;
+		}
+		connect_context_step (self);
 		return;
 	}
 
@@ -485,9 +491,10 @@ connect_context_step (NMModemBroadband *self)
 			else
 				g_assert_not_reached ();
 
-			nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'",
+			nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s' (try %d)",
 			            nm_modem_get_uid (NM_MODEM (self)),
-			            nm_modem_ip_type_to_string (current));
+			            nm_modem_ip_type_to_string (current),
+			            ctx->ip_type_tries + 1);
 
 			mm_modem_simple_connect (self->priv->simple_iface,
 			                         ctx->connect_properties,
diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c
index c28d86ad..79082c41 100644
--- a/src/devices/wwan/nm-modem-manager.c
+++ b/src/devices/wwan/nm-modem-manager.c
@@ -20,14 +20,13 @@
  * Copyright (C) 2009 Canonical Ltd.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
 #include <libmm-glib.h>
 
 #include "nm-modem-manager.h"
-#include "nm-default.h"
 #include "nm-dbus-compat.h"
 #include "nm-modem.h"
 #include "nm-modem-broadband.h"
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index 15104307..c1736ecf 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -19,20 +19,19 @@
  * Copyright (C) 2009 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-modem.h"
 
 #include <string.h>
 
-#include "nm-modem.h"
 #include "nm-core-internal.h"
 #include "nm-platform.h"
 #include "nm-setting-connection.h"
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
 #include "nm-modem-enum-types.h"
 #include "nm-route-manager.h"
-#include "gsystem-local-alloc.h"
 
 G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT)
 
diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c
index 2fd9e0bd..805aea69 100644
--- a/src/devices/wwan/nm-wwan-factory.c
+++ b/src/devices/wwan/nm-wwan-factory.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <gmodule.h>
@@ -29,7 +29,6 @@
 #include "nm-setting-cdma.h"
 #include "nm-modem-manager.h"
 #include "nm-device-modem.h"
-#include "nm-default.h"
 #include "nm-platform.h"
 
 static GType nm_wwan_factory_get_type (void);
diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c
index 59c69c2a..0aeb6118 100644
--- a/src/dhcp-manager/nm-dhcp-client.c
+++ b/src/dhcp-manager/nm-dhcp-client.c
@@ -17,7 +17,9 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-dhcp-client.h"
 
 #include <string.h>
 #include <sys/types.h>
@@ -28,13 +30,10 @@
 #include <stdlib.h>
 #include <uuid/uuid.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-utils.h"
-#include "nm-dhcp-client.h"
 #include "nm-dhcp-utils.h"
 #include "nm-platform.h"
-#include "gsystem-local-alloc.h"
 
 typedef struct {
 	char *       iface;
@@ -338,7 +337,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
 }
 
 static gboolean
-daemon_timeout (gpointer user_data)
+transaction_timeout (gpointer user_data)
 {
 	NMDhcpClient *self = NM_DHCP_CLIENT (user_data);
 	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
@@ -361,6 +360,9 @@ daemon_watch_cb (GPid pid, gint status, gpointer user_data)
 	guint64 log_domain;
 	guint ip_ver;
 
+	g_return_if_fail (priv->watch_id);
+	priv->watch_id = 0;
+
 	log_domain = priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4;
 	ip_ver = priv->ipv6 ? 6 : 4;
 
@@ -390,19 +392,28 @@ daemon_watch_cb (GPid pid, gint status, gpointer user_data)
 }
 
 void
-nm_dhcp_client_watch_child (NMDhcpClient *self, pid_t pid)
+nm_dhcp_client_start_timeout (NMDhcpClient *self)
 {
 	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
 
-	g_return_if_fail (priv->pid == -1);
-	priv->pid = pid;
-
 	/* Set up a timeout on the transaction to kill it after the timeout */
 	g_assert (priv->timeout_id == 0);
 	priv->timeout_id = g_timeout_add_seconds (priv->timeout,
-	                                          daemon_timeout,
+	                                          transaction_timeout,
 	                                          self);
-	g_assert (priv->watch_id == 0);
+}
+
+void
+nm_dhcp_client_watch_child (NMDhcpClient *self, pid_t pid)
+{
+	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
+
+	g_return_if_fail (priv->pid == -1);
+	priv->pid = pid;
+
+	nm_dhcp_client_start_timeout (self);
+
+	g_return_if_fail (priv->watch_id == 0);
 	priv->watch_id = g_child_watch_add (pid, daemon_watch_cb, self);
 }
 
@@ -734,7 +745,7 @@ maybe_add_option (GHashTable *hash,
 	}
 
 	if (g_str_has_prefix (key, NEW_TAG))
-		key += STRLEN (NEW_TAG);
+		key += NM_STRLEN (NEW_TAG);
 	if (!key[0])
 		return;
 
diff --git a/src/dhcp-manager/nm-dhcp-client.h b/src/dhcp-manager/nm-dhcp-client.h
index 7e28391d..1c78c5b1 100644
--- a/src/dhcp-manager/nm-dhcp-client.h
+++ b/src/dhcp-manager/nm-dhcp-client.h
@@ -154,6 +154,8 @@ void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name
 
 void nm_dhcp_client_stop_pid (pid_t pid, const char *iface);
 
+void nm_dhcp_client_start_timeout (NMDhcpClient *self);
+
 void nm_dhcp_client_watch_child (NMDhcpClient *self, pid_t pid);
 
 void nm_dhcp_client_set_state (NMDhcpClient *self,
diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
index 5340d21a..bf2df1e0 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
@@ -17,20 +17,19 @@
  * Copyright (C) 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-dhcp-dhclient-utils.h"
 
 #include <string.h>
 #include <ctype.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
-#include "nm-dhcp-dhclient-utils.h"
 #include "nm-dhcp-utils.h"
 #include "nm-ip4-config.h"
 #include "nm-utils.h"
 #include "nm-platform.h"
 #include "NetworkManagerUtils.h"
-#include "nm-macros-internal.h"
 
 #define CLIENTID_TAG            "send dhcp-client-identifier"
 
@@ -148,9 +147,9 @@ read_client_id (const char *str)
 	gs_free char *s = NULL;
 	char *p;
 
-	g_assert (!strncmp (str, CLIENTID_TAG, STRLEN (CLIENTID_TAG)));
+	g_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
 
-	str += STRLEN (CLIENTID_TAG);
+	str += NM_STRLEN (CLIENTID_TAG);
 	while (g_ascii_isspace (*str))
 		str++;
 
@@ -188,7 +187,7 @@ nm_dhcp_dhclient_get_client_id_from_config_file (const char *path)
 
 	lines = g_strsplit_set (contents, "\n\r", 0);
 	for (line = lines; lines && *line; line++) {
-		if (!strncmp (*line, CLIENTID_TAG, STRLEN (CLIENTID_TAG)))
+		if (!strncmp (*line, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)))
 			return read_client_id (*line);
 	}
 	return NULL;
diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c
index 972fb506..bc4345fe 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient.c
@@ -24,6 +24,8 @@
 #include <time.h>
 #undef _XOPEN_SOURCE
 
+#include "nm-default.h"
+
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -33,7 +35,6 @@
 #include <arpa/inet.h>
 #include <ctype.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-dhclient.h"
 #include "nm-utils.h"
 #include "nm-dhcp-dhclient-utils.h"
diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c
index ebbbb081..8060cc6a 100644
--- a/src/dhcp-manager/nm-dhcp-dhcpcd.c
+++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c
@@ -21,7 +21,7 @@
  */
 
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -31,7 +31,6 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-dhcpcd.h"
 #include "nm-dhcp-manager.h"
 #include "nm-utils.h"
diff --git a/src/dhcp-manager/nm-dhcp-helper.c b/src/dhcp-manager/nm-dhcp-helper.c
index 15b63d94..7667084d 100644
--- a/src/dhcp-manager/nm-dhcp-helper.c
+++ b/src/dhcp-manager/nm-dhcp-helper.c
@@ -18,15 +18,13 @@
  * Copyright (C) 2007 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
 
-#include "nm-default.h"
-
 #define NM_DHCP_CLIENT_DBUS_IFACE   "org.freedesktop.nm_dhcp_client"
 
 static const char * ignore[] = {"PATH", "SHLVL", "_", "PWD", "dhc_dbus", NULL};
diff --git a/src/dhcp-manager/nm-dhcp-listener.c b/src/dhcp-manager/nm-dhcp-listener.c
index f6fafb80..595b2097 100644
--- a/src/dhcp-manager/nm-dhcp-listener.c
+++ b/src/dhcp-manager/nm-dhcp-listener.c
@@ -17,7 +17,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -27,7 +27,6 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-listener.h"
 #include "nm-core-internal.h"
 #include "nm-bus-manager.h"
diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c
index cb74a5bc..44c3365d 100644
--- a/src/dhcp-manager/nm-dhcp-manager.c
+++ b/src/dhcp-manager/nm-dhcp-manager.c
@@ -20,7 +20,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -32,7 +32,6 @@
 #include <fcntl.h>
 #include <stdio.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-manager.h"
 #include "nm-dhcp-dhclient.h"
 #include "nm-dhcp-dhcpcd.h"
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c
index 4f68a0b6..b5a3d67c 100644
--- a/src/dhcp-manager/nm-dhcp-systemd.c
+++ b/src/dhcp-manager/nm-dhcp-systemd.c
@@ -16,7 +16,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -28,7 +28,6 @@
 #include <ctype.h>
 #include <net/if_arp.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-systemd.h"
 #include "nm-utils.h"
 #include "nm-dhcp-utils.h"
@@ -37,21 +36,20 @@
 
 #include "sd-dhcp-client.h"
 #include "sd-dhcp6-client.h"
-#include "dhcp-protocol.h"
+
+/* we use a private systemd header, thus need to include nm-sd-adapt.h. */
+#include "nm-sd-adapt.h"
 #include "dhcp-lease-internal.h"
-#include "dhcp6-protocol.h"
-#include "dhcp6-lease-internal.h"
 
 G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
 
 #define NM_DHCP_SYSTEMD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdPrivate))
 
 typedef struct {
-	struct sd_dhcp_client *client4;
-	struct sd_dhcp6_client *client6;
+	sd_dhcp_client *client4;
+	sd_dhcp6_client *client6;
 	char *lease_file;
 
-	guint timeout_id;
 	guint request_count;
 
 	gboolean privacy;
@@ -62,7 +60,6 @@ typedef struct {
 #define DHCP_OPTION_NIS_DOMAIN         40
 #define DHCP_OPTION_NIS_SERVERS        41
 #define DHCP_OPTION_DOMAIN_SEARCH     119
-#define DHCP_OPTION_RFC3442_ROUTES    121
 #define DHCP_OPTION_MS_ROUTES         249
 #define DHCP_OPTION_WPAD              252
 
@@ -88,53 +85,53 @@ typedef struct {
 #define REQPREFIX "requested_"
 
 static const ReqOption dhcp4_requests[] = {
-	{ DHCP_OPTION_SUBNET_MASK,            REQPREFIX "subnet_mask",                     TRUE },
-	{ DHCP_OPTION_TIME_OFFSET,            REQPREFIX "time_offset",                     TRUE },
-	{ DHCP_OPTION_ROUTER,                 REQPREFIX "routers",                         TRUE },
-	{ DHCP_OPTION_DOMAIN_NAME_SERVER,     REQPREFIX "domain_name_servers",             TRUE },
-	{ DHCP_OPTION_HOST_NAME,              REQPREFIX "host_name",                       TRUE },
-	{ DHCP_OPTION_DOMAIN_NAME,            REQPREFIX "domain_name",                     TRUE },
-	{ DHCP_OPTION_INTERFACE_MTU,          REQPREFIX "interface_mtu",                   TRUE },
-	{ DHCP_OPTION_BROADCAST,              REQPREFIX "broadcast_address",               TRUE },
-	{ DHCP_OPTION_STATIC_ROUTE,           REQPREFIX "static_routes",                   TRUE },
-	{ DHCP_OPTION_NIS_DOMAIN,             REQPREFIX "nis_domain",                      TRUE },
-	{ DHCP_OPTION_NIS_SERVERS,            REQPREFIX "nis_servers",                     TRUE },
-	{ DHCP_OPTION_NTP_SERVER,             REQPREFIX "ntp_servers",                     TRUE },
-	{ DHCP_OPTION_SERVER_IDENTIFIER,      REQPREFIX "dhcp_server_identifier",          TRUE },
-	{ DHCP_OPTION_DOMAIN_SEARCH,          REQPREFIX "domain_search",                   TRUE },
-	{ DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE },
-	{ DHCP_OPTION_MS_ROUTES,              REQPREFIX "ms_classless_static_routes",      TRUE },
-	{ DHCP_OPTION_WPAD,                   REQPREFIX "wpad",                            TRUE },
+	{ SD_DHCP_OPTION_SUBNET_MASK,            REQPREFIX "subnet_mask",                     TRUE },
+	{ SD_DHCP_OPTION_TIME_OFFSET,            REQPREFIX "time_offset",                     TRUE },
+	{ SD_DHCP_OPTION_ROUTER,                 REQPREFIX "routers",                         TRUE },
+	{ SD_DHCP_OPTION_DOMAIN_NAME_SERVER,     REQPREFIX "domain_name_servers",             TRUE },
+	{ SD_DHCP_OPTION_HOST_NAME,              REQPREFIX "host_name",                       TRUE },
+	{ SD_DHCP_OPTION_DOMAIN_NAME,            REQPREFIX "domain_name",                     TRUE },
+	{ SD_DHCP_OPTION_INTERFACE_MTU,          REQPREFIX "interface_mtu",                   TRUE },
+	{ SD_DHCP_OPTION_BROADCAST,              REQPREFIX "broadcast_address",               TRUE },
+	{ SD_DHCP_OPTION_STATIC_ROUTE,           REQPREFIX "static_routes",                   TRUE },
+	{ DHCP_OPTION_NIS_DOMAIN,                REQPREFIX "nis_domain",                      TRUE },
+	{ DHCP_OPTION_NIS_SERVERS,               REQPREFIX "nis_servers",                     TRUE },
+	{ SD_DHCP_OPTION_NTP_SERVER,             REQPREFIX "ntp_servers",                     TRUE },
+	{ SD_DHCP_OPTION_SERVER_IDENTIFIER,      REQPREFIX "dhcp_server_identifier",          TRUE },
+	{ DHCP_OPTION_DOMAIN_SEARCH,             REQPREFIX "domain_search",                   TRUE },
+	{ SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE },
+	{ DHCP_OPTION_MS_ROUTES,                 REQPREFIX "ms_classless_static_routes",      TRUE },
+	{ DHCP_OPTION_WPAD,                      REQPREFIX "wpad",                            TRUE },
 
 	/* Internal values */
-	{ DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry",                          FALSE },
-	{ DHCP_OPTION_CLIENT_IDENTIFIER,     REQPREFIX "dhcp_client_identifier",          FALSE },
-	{ DHCP_OPTION_IP_ADDRESS,            REQPREFIX "ip_address",                      FALSE },
+	{ SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,  REQPREFIX "expiry",                          FALSE },
+	{ SD_DHCP_OPTION_CLIENT_IDENTIFIER,      REQPREFIX "dhcp_client_identifier",          FALSE },
+	{ DHCP_OPTION_IP_ADDRESS,                REQPREFIX "ip_address",                      FALSE },
 	{ 0, NULL, FALSE }
 };
 
 static const ReqOption dhcp6_requests[] = {
-	{ DHCP6_OPTION_CLIENTID,       REQPREFIX "dhcp6_client_id",     TRUE },
+	{ SD_DHCP6_OPTION_CLIENTID,              REQPREFIX "dhcp6_client_id",     TRUE },
 
 	/* Don't request server ID by default; some servers don't reply to
 	 * Information Requests that request the Server ID.
 	 */
-	{ DHCP6_OPTION_SERVERID,       REQPREFIX "dhcp6_server_id",     FALSE },
+	{ SD_DHCP6_OPTION_SERVERID,              REQPREFIX "dhcp6_server_id",     FALSE },
 
-	{ DHCP6_OPTION_DNS_SERVERS,    REQPREFIX "dhcp6_name_servers",  TRUE },
-	{ DHCP6_OPTION_DOMAIN_LIST,    REQPREFIX "dhcp6_domain_search", TRUE },
-	{ DHCP6_OPTION_SNTP_SERVERS,   REQPREFIX "dhcp6_sntp_servers",  TRUE },
+	{ SD_DHCP6_OPTION_DNS_SERVERS,           REQPREFIX "dhcp6_name_servers",  TRUE },
+	{ SD_DHCP6_OPTION_DOMAIN_LIST,           REQPREFIX "dhcp6_domain_search", TRUE },
+	{ SD_DHCP6_OPTION_SNTP_SERVERS,          REQPREFIX "dhcp6_sntp_servers",  TRUE },
 
 	/* Internal values */
-	{ DHCP6_OPTION_IP_ADDRESS,     REQPREFIX "ip6_address",         FALSE },
-	{ DHCP6_OPTION_PREFIXLEN,      REQPREFIX "ip6_prefixlen",       FALSE },
-	{ DHCP6_OPTION_PREFERRED_LIFE, REQPREFIX "preferred_life",      FALSE },
-	{ DHCP6_OPTION_MAX_LIFE,       REQPREFIX "max_life",            FALSE },
-	{ DHCP6_OPTION_STARTS,         REQPREFIX "starts",              FALSE },
-	{ DHCP6_OPTION_LIFE_STARTS,    REQPREFIX "life_starts",         FALSE },
-	{ DHCP6_OPTION_RENEW,          REQPREFIX "renew",               FALSE },
-	{ DHCP6_OPTION_REBIND,         REQPREFIX "rebind",              FALSE },
-	{ DHCP6_OPTION_IAID,           REQPREFIX "iaid",                FALSE },
+	{ DHCP6_OPTION_IP_ADDRESS,               REQPREFIX "ip6_address",         FALSE },
+	{ DHCP6_OPTION_PREFIXLEN,                REQPREFIX "ip6_prefixlen",       FALSE },
+	{ DHCP6_OPTION_PREFERRED_LIFE,           REQPREFIX "preferred_life",      FALSE },
+	{ DHCP6_OPTION_MAX_LIFE,                 REQPREFIX "max_life",            FALSE },
+	{ DHCP6_OPTION_STARTS,                   REQPREFIX "starts",              FALSE },
+	{ DHCP6_OPTION_LIFE_STARTS,              REQPREFIX "life_starts",         FALSE },
+	{ DHCP6_OPTION_RENEW,                    REQPREFIX "renew",               FALSE },
+	{ DHCP6_OPTION_REBIND,                   REQPREFIX "rebind",              FALSE },
+	{ DHCP6_OPTION_IAID,                     REQPREFIX "iaid",                FALSE },
 	{ 0, NULL, FALSE }
 };
 
@@ -151,7 +148,7 @@ take_option (GHashTable *options,
 	for (i = 0; requests[i].name; i++) {
 		if (requests[i].num == option) {
 			g_hash_table_insert (options,
-			                     (gpointer) (requests[i].name + STRLEN (REQPREFIX)),
+			                     (gpointer) (requests[i].name + NM_STRLEN (REQPREFIX)),
 			                     value);
 			break;
 		}
@@ -216,13 +213,14 @@ lease_to_ip4_config (const char *iface,
 	guint32 lifetime = 0, i;
 	NMPlatformIP4Address address;
 	GString *l;
-	struct sd_dhcp_route *routes;
+	gs_free sd_dhcp_route **routes = NULL;
 	guint16 mtu;
 	int r, num;
 	guint64 end_time;
 	const void *data;
 	gsize data_len;
 	gboolean metered = FALSE;
+	gboolean static_default_gateway = FALSE;
 
 	g_return_val_if_fail (lease != NULL, NULL);
 
@@ -243,7 +241,7 @@ lease_to_ip4_config (const char *iface,
 	LOG_LEASE (LOGD_DHCP4, "  plen %d", address.plen);
 	add_option (options,
 	            dhcp4_requests,
-	            DHCP_OPTION_SUBNET_MASK,
+	            SD_DHCP_OPTION_SUBNET_MASK,
 	            nm_utils_inet4_ntop (tmp_addr.s_addr, NULL));
 
 	/* Lease time */
@@ -254,21 +252,12 @@ lease_to_ip4_config (const char *iface,
 	LOG_LEASE (LOGD_DHCP4, "  expires in %" G_GUINT32_FORMAT " seconds", lifetime);
 	add_option_u64 (options,
 	                dhcp4_requests,
-	                DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
+	                SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
 	                end_time);
 
 	address.source = NM_IP_CONFIG_SOURCE_DHCP;
 	nm_ip4_config_add_address (ip4_config, &address);
 
-	/* Gateway */
-	r = sd_dhcp_lease_get_router (lease, &tmp_addr);
-	if (r == 0) {
-		nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr);
-		str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL);
-		LOG_LEASE (LOGD_DHCP4, "  gateway %s", str);
-		add_option (options, dhcp4_requests, DHCP_OPTION_ROUTER, str);
-	}
-
 	/* DNS Servers */
 	num = sd_dhcp_lease_get_dns (lease, &addr_list);
 	if (num > 0) {
@@ -282,7 +271,7 @@ lease_to_ip4_config (const char *iface,
 			}
 		}
 		if (l->len)
-			add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME_SERVER, l->str);
+			add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, l->str);
 		g_string_free (l, TRUE);
 	}
 
@@ -298,14 +287,14 @@ lease_to_ip4_config (const char *iface,
 			nm_ip4_config_add_domain (ip4_config, *s);
 		}
 		g_strfreev (domains);
-		add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME, str);
+		add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, str);
 	}
 
 	/* Hostname */
 	r = sd_dhcp_lease_get_hostname (lease, &str);
 	if (r == 0) {
 		LOG_LEASE (LOGD_DHCP4, "  hostname '%s'", str);
-		add_option (options, dhcp4_requests, DHCP_OPTION_HOST_NAME, str);
+		add_option (options, dhcp4_requests, SD_DHCP_OPTION_HOST_NAME, str);
 	}
 
 	/* Routes */
@@ -313,32 +302,70 @@ lease_to_ip4_config (const char *iface,
 	if (num > 0) {
 		l = g_string_sized_new (30);
 		for (i = 0; i < num; i++) {
-			NMPlatformIP4Route route;
+			NMPlatformIP4Route route = { 0 };
 			const char *gw_str;
-
-			memset (&route, 0, sizeof (route));
-			route.network = routes[i].dst_addr.s_addr;
-			route.plen = routes[i].dst_prefixlen;
-			route.gateway = routes[i].gw_addr.s_addr;
-			route.source = NM_IP_CONFIG_SOURCE_DHCP;
-			route.metric = default_priority;
-			nm_ip4_config_add_route (ip4_config, &route);
-
-			str = nm_utils_inet4_ntop (route.network, buf);
-			gw_str = nm_utils_inet4_ntop (route.gateway, NULL);
-			LOG_LEASE (LOGD_DHCP4, "  static route %s/%d gw %s", str, route.plen, gw_str);
-
-			g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str);
+			guint8 plen;
+			struct in_addr a;
+
+			if (sd_dhcp_route_get_destination (routes[i], &a) < 0)
+				continue;
+			route.network = a.s_addr;
+
+			if (sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0)
+				continue;
+			route.plen = plen;
+
+			if (sd_dhcp_route_get_gateway (routes[i], &a) < 0)
+				continue;
+			route.gateway = a.s_addr;
+
+			if (route.plen) {
+				route.source = NM_IP_CONFIG_SOURCE_DHCP;
+				route.metric = default_priority;
+				nm_ip4_config_add_route (ip4_config, &route);
+
+				str = nm_utils_inet4_ntop (route.network, buf);
+				gw_str = nm_utils_inet4_ntop (route.gateway, NULL);
+				LOG_LEASE (LOGD_DHCP4, "  static route %s/%d gw %s", str, route.plen, gw_str);
+
+				g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str);
+			} else {
+				if (!static_default_gateway) {
+					static_default_gateway = TRUE;
+					nm_ip4_config_set_gateway (ip4_config, route.gateway);
+
+					str = nm_utils_inet4_ntop (route.gateway, NULL);
+					LOG_LEASE (LOGD_DHCP4, "  gateway %s", str);
+					add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str);
+				}
+			}
 		}
-		add_option (options, dhcp4_requests, DHCP_OPTION_RFC3442_ROUTES, l->str);
+		if (l->len)
+			add_option (options, dhcp4_requests, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, l->str);
 		g_string_free (l, TRUE);
 	}
 
+	/* If the DHCP server returns both a Classless Static Routes option and a
+	 * Router option, the DHCP client MUST ignore the Router option [RFC 3442].
+	 * Be more lenient and ignore the Router option only if Classless Static
+	 * Routes contain a default gateway (as other DHCP backends do).
+	 */
+	/* Gateway */
+	if (!static_default_gateway) {
+		r = sd_dhcp_lease_get_router (lease, &tmp_addr);
+		if (r == 0) {
+			nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr);
+			str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL);
+			LOG_LEASE (LOGD_DHCP4, "  gateway %s", str);
+			add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str);
+		}
+	}
+
 	/* MTU */
 	r = sd_dhcp_lease_get_mtu (lease, &mtu);
 	if (r == 0 && mtu) {
 		nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
-		add_option_u32 (options, dhcp4_requests, DHCP_OPTION_INTERFACE_MTU, mtu);
+		add_option_u32 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu);
 		LOG_LEASE (LOGD_DHCP4, "  mtu %u", mtu);
 	}
 
@@ -351,13 +378,13 @@ lease_to_ip4_config (const char *iface,
 			LOG_LEASE (LOGD_DHCP4, "  ntp server '%s'", str);
 			g_string_append_printf (l, "%s%s", l->len ? " " : "", str);
 		}
-		add_option (options, dhcp4_requests, DHCP_OPTION_NTP_SERVER, l->str);
+		add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, l->str);
 		g_string_free (l, TRUE);
 	}
 
 	r = sd_dhcp_lease_get_vendor_specific (lease, &data, &data_len);
 	if (r >= 0)
-		metered = !!memmem (data, data_len, "ANDROID_METERED", STRLEN ("ANDROID_METERED"));
+		metered = !!memmem (data, data_len, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED"));
 	nm_ip4_config_set_metered (ip4_config, metered);
 
 	return ip4_config;
@@ -517,7 +544,7 @@ get_arp_type (const GByteArray *hwaddr)
 	else if (hwaddr->len == INFINIBAND_ALEN)
 		return ARPHRD_INFINIBAND;
 	else
-		g_assert_not_reached ();
+		return ARPHRD_NONE;
 }
 
 static gboolean
@@ -534,6 +561,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 	const char *hostname, *fqdn;
 	int r, i;
 	gboolean success = FALSE;
+	guint16 arp_type;
 
 	g_assert (priv->client4 == NULL);
 	g_assert (priv->client6 == NULL);
@@ -555,10 +583,16 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 
 	hwaddr = nm_dhcp_client_get_hw_addr (client);
 	if (hwaddr) {
+		arp_type= get_arp_type (hwaddr);
+		if (arp_type == ARPHRD_NONE) {
+			nm_log_warn (LOGD_DHCP4, "(%s): failed to determine ARP type", iface);
+			goto error;
+		}
+
 		r = sd_dhcp_client_set_mac (priv->client4,
 		                            hwaddr->data,
 		                            hwaddr->len,
-		                            get_arp_type (hwaddr));
+		                            arp_type);
 		if (r < 0) {
 			nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP MAC address (%d)", iface, r);
 			goto error;
@@ -661,6 +695,8 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 		goto error;
 	}
 
+	nm_dhcp_client_start_timeout (client);
+
 	success = TRUE;
 
 error:
@@ -807,10 +843,13 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid)
 	NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (client);
 	int r = 0;
 
-	if (priv->client4)
+	if (priv->client4) {
+		sd_dhcp_client_set_callback (priv->client4, NULL, NULL);
 		r = sd_dhcp_client_stop (priv->client4);
-	else if (priv->client6)
+	} else if (priv->client6) {
+		sd_dhcp6_client_set_callback (priv->client6, NULL, NULL);
 		r = sd_dhcp6_client_stop (priv->client6);
+	}
 
 	if (r) {
 		nm_log_warn (priv->client6 ? LOGD_DHCP6 : LOGD_DHCP4,
diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c
index 591a0d1f..be563a69 100644
--- a/src/dhcp-manager/nm-dhcp-utils.c
+++ b/src/dhcp-manager/nm-dhcp-utils.c
@@ -17,14 +17,13 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-dhcp-utils.h"
 #include "nm-utils.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c
index f9e1e1eb..0561d43c 100644
--- a/src/dhcp-manager/tests/test-dhcp-dhclient.c
+++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c
@@ -18,20 +18,18 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <unistd.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-dhcp-dhclient-utils.h"
 #include "nm-dhcp-utils.h"
 #include "nm-utils.h"
 #include "nm-ip4-config.h"
 #include "nm-platform.h"
-#include "nm-macros-internal.h"
 
 #include "nm-test-utils.h"
 
@@ -295,9 +293,9 @@ static void
 test_existing_ascii_client_id (void)
 {
 	gs_unref_bytes GBytes *new_client_id = NULL;
-	char buf[STRLEN (EACID) + 1] = { 0 };
+	char buf[NM_STRLEN (EACID) + 1] = { 0 };
 
-	memcpy (buf + 1, EACID, STRLEN (EACID));
+	memcpy (buf + 1, EACID, NM_STRLEN (EACID));
 	new_client_id = g_bytes_new (buf, sizeof (buf));
 	test_config (existing_ascii_client_id_orig, existing_ascii_client_id_expected,
 	             FALSE, NULL, NULL,
diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c
index 49987c40..38051326 100644
--- a/src/dhcp-manager/tests/test-dhcp-utils.c
+++ b/src/dhcp-manager/tests/test-dhcp-utils.c
@@ -17,15 +17,14 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
 
-#include <nm-utils.h>
+#include "nm-utils.h"
 
-#include "nm-default.h"
 #include "nm-dhcp-utils.h"
 #include "nm-platform.h"
 
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c
index 63e37bf3..8663dfd8 100644
--- a/src/dns-manager/nm-dns-dnsmasq.c
+++ b/src/dns-manager/nm-dns-dnsmasq.c
@@ -18,7 +18,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -27,7 +27,6 @@
 #include <arpa/inet.h>
 #include <sys/stat.h>
 
-#include "nm-default.h"
 #include "nm-dns-dnsmasq.h"
 #include "nm-utils.h"
 #include "nm-ip4-config.h"
@@ -145,15 +144,15 @@ add_global_config (GString *str, const NMGlobalDnsConfig *config)
 	for (i = 0; i < nm_global_dns_config_get_num_domains (config); i++) {
 		NMGlobalDnsDomain *domain = nm_global_dns_config_get_domain (config, i);
 		const char *const *servers = nm_global_dns_domain_get_servers (domain);
+		const char *name = nm_global_dns_domain_get_name (domain);
+
+		g_return_if_fail (name);
 
 		for (j = 0; servers && servers[j]; j++) {
-			if (!strcmp (servers[j], "*"))
+			if (!strcmp (name, "*"))
 				g_string_append_printf (str, "server=%s\n", servers[j]);
-			else {
-				g_string_append_printf (str, "server=/%s/%s\n",
-				                        nm_global_dns_domain_get_name (domain),
-				                        servers[j]);
-			}
+			else
+				g_string_append_printf (str, "server=/%s/%s\n", name, servers[j]);
 		}
 
 	}
diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c
index 01e8bf1d..79d345be 100644
--- a/src/dns-manager/nm-dns-manager.c
+++ b/src/dns-manager/nm-dns-manager.c
@@ -21,7 +21,7 @@
  *   and others
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -35,7 +35,6 @@
 
 #include <linux/fs.h>
 
-#include "nm-default.h"
 #include "nm-utils.h"
 #include "nm-core-internal.h"
 #include "nm-dns-manager.h"
@@ -82,6 +81,10 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT)
 #define NETCONFIG_PATH "/sbin/netconfig"
 #endif
 
+#define PLUGIN_RATELIMIT_INTERVAL    30
+#define PLUGIN_RATELIMIT_BURST       5
+#define PLUGIN_RATELIMIT_DELAY       300
+
 NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager);
 
 /*********************************************************************************************/
@@ -130,6 +133,12 @@ typedef struct {
 	NMConfig *config;
 
 	gboolean dns_touched;
+
+	struct {
+		guint64 ts;
+		guint num_restarts;
+		guint timer;
+	} plugin_ratelimit;
 } NMDnsManagerPrivate;
 
 enum {
@@ -357,7 +366,6 @@ dispatch_netconfig (NMDnsManager *self,
 
 	if (searches) {
 		str = g_strjoinv (" ", searches);
-
 		write_to_netconfig (self, fd, "DNSSEARCH", str);
 		g_free (str);
 	}
@@ -405,10 +413,9 @@ write_resolv_conf (FILE *f,
                    char **options,
                    GError **error)
 {
-	char *searches_str = NULL;
-	char *nameservers_str = NULL;
-	char *options_str = NULL;
-	gboolean retval = FALSE;
+	gs_free char *searches_str = NULL;
+	gs_free char *nameservers_str = NULL;
+	gs_free char *options_str = NULL;
 	char *tmp_str;
 	GString *str;
 	int i;
@@ -425,11 +432,10 @@ write_resolv_conf (FILE *f,
 		g_free (tmp_str);
 	}
 
-	str = g_string_new ("");
-
 	if (nameservers) {
 		int num = g_strv_length (nameservers);
 
+		str = g_string_new ("");
 		for (i = 0; i < num; i++) {
 			if (i == 3) {
 				g_string_append (str, "# ");
@@ -443,28 +449,22 @@ write_resolv_conf (FILE *f,
 			g_string_append (str, nameservers[i]);
 			g_string_append_c (str, '\n');
 		}
+		nameservers_str = g_string_free (str, FALSE);
 	}
 
-	nameservers_str = g_string_free (str, FALSE);
-
 	if (fprintf (f, "# Generated by NetworkManager\n%s%s%s",
 	             searches_str ? searches_str : "",
-	             nameservers_str,
-	             options_str ? options_str : "") > 0)
-		retval = TRUE;
-	else {
+	             nameservers_str ? nameservers_str : "",
+	             options_str ? options_str : "") < 0) {
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not write " _PATH_RESCONF ": %s\n",
+		             "Could not write " _PATH_RESCONF ": %s",
 		             g_strerror (errno));
+		return FALSE;
 	}
 
-	g_free (searches_str);
-	g_free (nameservers_str);
-	g_free (options_str);
-
-	return retval;
+	return TRUE;
 }
 
 static SpawnResult
@@ -474,9 +474,9 @@ dispatch_resolvconf (NMDnsManager *self,
                      char **options,
                      GError **error)
 {
-	char *cmd;
+	gs_free char *cmd = NULL;
 	FILE *f;
-	gboolean retval = FALSE;
+	gboolean success = FALSE;
 	int errnosv, err;
 
 	if (!g_file_test (RESOLVCONF_PATH, G_FILE_TEST_IS_EXECUTABLE)) {
@@ -487,39 +487,46 @@ dispatch_resolvconf (NMDnsManager *self,
 		return SR_NOTFOUND;
 	}
 
-	if (searches || nameservers) {
-		cmd = g_strconcat (RESOLVCONF_PATH, " -a ", "NetworkManager", NULL);
-		_LOGI ("Writing DNS information to %s", RESOLVCONF_PATH);
-		if ((f = popen (cmd, "w")) == NULL)
-			g_set_error (error,
-			             NM_MANAGER_ERROR,
-			             NM_MANAGER_ERROR_FAILED,
-			             "Could not write to %s: %s\n",
-			             RESOLVCONF_PATH,
-			             g_strerror (errno));
-		else {
-			retval = write_resolv_conf (f, searches, nameservers, options, error);
-			err = pclose (f);
-			if (err < 0) {
-				errnosv = errno;
-				g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errnosv),
-				             "Failed to close pipe to resolvconf: %d", errnosv);
-				retval = FALSE;
-			} else if (err > 0) {
-				_LOGW ("resolvconf failed with status %d", err);
-				retval = FALSE;
-			}
-		}
-	} else {
-		cmd = g_strconcat (RESOLVCONF_PATH, " -d ", "NetworkManager", NULL);
+	if (!searches && !nameservers) {
 		_LOGI ("Removing DNS information from %s", RESOLVCONF_PATH);
-		if (nm_spawn_process (cmd, error) == 0)
-			retval = TRUE;
+
+		cmd = g_strconcat (RESOLVCONF_PATH, " -d ", "NetworkManager", NULL);
+		if (nm_spawn_process (cmd, error) != 0)
+			return SR_ERROR;
+
+		return SR_SUCCESS;
+	}
+
+	_LOGI ("Writing DNS information to %s", RESOLVCONF_PATH);
+
+	cmd = g_strconcat (RESOLVCONF_PATH, " -a ", "NetworkManager", NULL);
+	if ((f = popen (cmd, "w")) == NULL) {
+		g_set_error (error,
+		             NM_MANAGER_ERROR,
+		             NM_MANAGER_ERROR_FAILED,
+		             "Could not write to %s: %s",
+		             RESOLVCONF_PATH,
+		             g_strerror (errno));
+		return SR_ERROR;
 	}
 
-	g_free (cmd);
+	success = write_resolv_conf (f, searches, nameservers, options, error);
+	err = pclose (f);
+	if (err < 0) {
+		errnosv = errno;
+		g_clear_error (error);
+		g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errnosv),
+		             "Failed to close pipe to resolvconf: %d", errnosv);
+		return SR_ERROR;
+	} else if (err > 0) {
+		_LOGW ("resolvconf failed with status %d", err);
+		g_clear_error (error);
+		g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+		             "resolvconf failed with status %d", err);
+		return SR_ERROR;
+	}
 
-	return retval ? SR_SUCCESS : SR_ERROR;
+	return success ? SR_SUCCESS : SR_ERROR;
 }
 
 #define MY_RESOLV_CONF NMRUNDIR "/resolv.conf"
@@ -536,7 +543,7 @@ update_resolv_conf (NMDnsManager *self,
 {
 	FILE *f;
 	struct stat st;
-	gboolean ret;
+	gboolean success;
 
 	/* If we are not managing /etc/resolv.conf and it points to
 	 * MY_RESOLV_CONF, don't write the private DNS configuration to
@@ -544,15 +551,12 @@ update_resolv_conf (NMDnsManager *self,
 	 * some external application.
 	 */
 	if (!install_etc) {
-		char *path = g_file_read_link (_PATH_RESCONF, NULL);
-		gboolean ours = !g_strcmp0 (path, MY_RESOLV_CONF);
+		gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL);
 
-		g_free (path);
-
-		if (ours) {
+		if (g_strcmp0 (path, MY_RESOLV_CONF) == 0) {
 			_LOGD ("not updating " MY_RESOLV_CONF
 			       " since it points to " _PATH_RESCONF);
-			return SR_ERROR;
+			return SR_SUCCESS;
 		}
 	}
 
@@ -560,36 +564,35 @@ update_resolv_conf (NMDnsManager *self,
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not open %s: %s\n",
+		             "Could not open %s: %s",
 		             MY_RESOLV_CONF_TMP,
 		             g_strerror (errno));
 		return SR_ERROR;
 	}
 
-	ret = write_resolv_conf (f, searches, nameservers, options, error);
+	success = write_resolv_conf (f, searches, nameservers, options, error);
 
 	if (fclose (f) < 0) {
-		if (ret) {
+		if (success) {
 			/* only set an error here if write_resolv_conf() was successful,
 			 * since its error is more important.
 			 */
 			g_set_error (error,
 			             NM_MANAGER_ERROR,
 			             NM_MANAGER_ERROR_FAILED,
-			             "Could not close %s: %s\n",
+			             "Could not close %s: %s",
 			             MY_RESOLV_CONF_TMP,
 			             g_strerror (errno));
 		}
-	}
-
-	if (!ret)
+		return SR_ERROR;
+	} else if (!success)
 		return SR_ERROR;
 
 	if (rename (MY_RESOLV_CONF_TMP, MY_RESOLV_CONF) < 0) {
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not replace %s: %s\n",
+		             "Could not replace %s: %s",
 		             MY_RESOLV_CONF,
 		             g_strerror (errno));
 		return SR_ERROR;
@@ -598,44 +601,50 @@ update_resolv_conf (NMDnsManager *self,
 	if (!install_etc)
 		return SR_SUCCESS;
 
-	/* Don't overwrite a symbolic link unless it points to MY_RESOLV_CONF. */
+	/* A symlink pointing to NM's own resolv.conf (MY_RESOLV_CONF) is always
+	 * overwritten to ensure that changes are indicated with inotify.  Symlinks
+	 * pointing to any other file are never overwritten.
+	 */
 	if (lstat (_PATH_RESCONF, &st) != -1) {
-		/* Don't overwrite a symbolic link. */
 		if (S_ISLNK (st.st_mode)) {
 			if (stat (_PATH_RESCONF, &st) != -1) {
-				char *path = g_file_read_link (_PATH_RESCONF, NULL);
-				gboolean not_ours = g_strcmp0 (path, MY_RESOLV_CONF) != 0;
+				gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL);
 
-				g_free (path);
-				if (not_ours)
+				if (g_strcmp0 (path, MY_RESOLV_CONF) != 0) {
+					/* It's not NM's symlink; do nothing */
 					return SR_SUCCESS;
+				}
+
+				/* resolv.conf is a symlink owned by NM and the target is accessible
+				 */
 			} else {
-				if (errno != ENOENT)
-					return SR_SUCCESS;
-				g_set_error (error,
-				             NM_MANAGER_ERROR,
-				             NM_MANAGER_ERROR_FAILED,
-				             "Could not stat %s: %s\n",
-				             _PATH_RESCONF,
-				             g_strerror (errno));
-				return SR_ERROR;
+				/* resolv.conf is a symlink but the target is not accessible;
+				 * some other program is probably managing resolv.conf and
+				 * NM should not touch it.
+				 */
+				return SR_SUCCESS;
 			}
 		}
 	} else if (errno != ENOENT) {
+		/* NM cannot read /etc/resolv.conf */
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not lstat %s: %s\n",
+		             "Could not lstat %s: %s",
 		             _PATH_RESCONF,
 		             g_strerror (errno));
 		return SR_ERROR;
 	}
 
+	/* By this point, either /etc/resolv.conf does not exist, is a regular
+	 * file, or is a symlink already owned by NM.  In all cases /etc/resolv.conf
+	 * is replaced with a symlink pointing to NM's resolv.conf in /var/run/.
+	 */
 	if (unlink (RESOLV_CONF_TMP) == -1 && errno != ENOENT) {
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not unlink %s: %s\n",
+		             "Could not unlink %s: %s",
 		             RESOLV_CONF_TMP,
 		             g_strerror (errno));
 		return SR_ERROR;
@@ -645,7 +654,7 @@ update_resolv_conf (NMDnsManager *self,
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not create symlink %s pointing to %s: %s\n",
+		             "Could not create symlink %s pointing to %s: %s",
 		             RESOLV_CONF_TMP,
 		             MY_RESOLV_CONF,
 		             g_strerror (errno));
@@ -656,7 +665,7 @@ update_resolv_conf (NMDnsManager *self,
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_FAILED,
-		             "Could not rename %s to %s: %s\n",
+		             "Could not rename %s to %s: %s",
 		             RESOLV_CONF_TMP,
 		             _PATH_RESCONF,
 		             g_strerror (errno));
@@ -799,6 +808,7 @@ update_dns (NMDnsManager *self,
 	g_return_val_if_fail (!error || !*error, FALSE);
 
 	priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+	nm_clear_g_source (&priv->plugin_ratelimit.timer);
 
 	if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) {
 		update = FALSE;
@@ -863,7 +873,8 @@ update_dns (NMDnsManager *self,
 	if (priv->hostname) {
 		const char *hostdomain = strchr (priv->hostname, '.');
 
-		if (hostdomain) {
+		if (   hostdomain
+		    && !nm_utils_ipaddr_valid (AF_UNSPEC, priv->hostname)) {
 			hostdomain++;
 			if (DOMAIN_IS_VALID (hostdomain))
 				add_string_item (rc.searches, hostdomain);
@@ -1022,20 +1033,47 @@ plugin_failed (NMDnsPlugin *plugin, gpointer user_data)
 	}
 }
 
-static void
-plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data)
+static gboolean
+plugin_child_quit_update_dns (gpointer user_data)
 {
-	NMDnsManager *self = NM_DNS_MANAGER (user_data);
 	GError *error = NULL;
-
-	_LOGW ("plugin %s child quit unexpectedly; refreshing DNS",
-	             nm_dns_plugin_get_name (plugin));
+	NMDnsManager *self = NM_DNS_MANAGER (user_data);
 
 	/* Let the plugin try to spawn the child again */
 	if (!update_dns (self, FALSE, &error)) {
 		_LOGW ("could not commit DNS changes: %s", error->message);
 		g_clear_error (&error);
 	}
+
+	return G_SOURCE_REMOVE;
+}
+
+static void
+plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data)
+{
+	NMDnsManager *self = NM_DNS_MANAGER (user_data);
+	NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+	gint64 ts = nm_utils_get_monotonic_timestamp_ms ();
+
+	_LOGW ("plugin %s child quit unexpectedly", nm_dns_plugin_get_name (plugin));
+
+	if (   !priv->plugin_ratelimit.ts
+	    || (ts - priv->plugin_ratelimit.ts) / 1000 > PLUGIN_RATELIMIT_INTERVAL) {
+		priv->plugin_ratelimit.ts = ts;
+		priv->plugin_ratelimit.num_restarts = 0;
+	} else {
+		priv->plugin_ratelimit.num_restarts++;
+		if (priv->plugin_ratelimit.num_restarts > PLUGIN_RATELIMIT_BURST) {
+			_LOGW ("plugin %s child respawning too fast, delaying update for %u seconds",
+			        nm_dns_plugin_get_name (plugin), PLUGIN_RATELIMIT_DELAY);
+			priv->plugin_ratelimit.timer = g_timeout_add_seconds (PLUGIN_RATELIMIT_DELAY,
+			                                                      plugin_child_quit_update_dns,
+			                                                      self);
+			return;
+		}
+	}
+
+	plugin_child_quit_update_dns (self);
 }
 
 gboolean
diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c
index a8236696..8313ed13 100644
--- a/src/dns-manager/nm-dns-plugin.c
+++ b/src/dns-manager/nm-dns-plugin.c
@@ -17,7 +17,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#include "nm-default.h"
 #include "nm-dns-plugin.h"
 #include "NetworkManagerUtils.h"
 
@@ -33,7 +32,7 @@ typedef struct {
 	gboolean disposed;
 
 	GPid pid;
-	guint32 watch_id;
+	guint watch_id;
 	char *progname;
 	char *pidfile;
 } NMDnsPluginPrivate;
@@ -130,6 +129,7 @@ watch_cb (GPid pid, gint status, gpointer user_data)
 	NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
 
 	priv->pid = 0;
+	priv->watch_id = 0;
 	g_free (priv->progname);
 	priv->progname = NULL;
 
diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c
index d36e3f85..4c1af103 100644
--- a/src/dns-manager/nm-dns-unbound.c
+++ b/src/dns-manager/nm-dns-unbound.c
@@ -17,7 +17,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  * Author: Pavel Å imerda <psimerda@redhat.com>
  */
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-dns-unbound.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c
index 4a5255a4..e920611a 100644
--- a/src/dns-manager/nm-dns-utils.c
+++ b/src/dns-manager/nm-dns-utils.c
@@ -17,7 +17,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <arpa/inet.h>
 #include <string.h>
diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c
index a17caad3..9e388acf 100644
--- a/src/dnsmasq-manager/nm-dnsmasq-manager.c
+++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -28,21 +28,23 @@
 #include <arpa/inet.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-dnsmasq-manager.h"
 #include "nm-dnsmasq-utils.h"
 #include "nm-utils.h"
 #include "NetworkManagerUtils.h"
+#include "nm-core-internal.h"
 
 typedef struct {
 	char *iface;
 	char *pidfile;
 	GPid pid;
-	guint32 dm_watch_id;
+	guint dm_watch_id;
 } NMDnsMasqManagerPrivate;
 
 #define NM_DNSMASQ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManagerPrivate))
 
+#define CONFDIR NMCONFDIR "/dnsmasq-shared.d"
+
 G_DEFINE_TYPE (NMDnsMasqManager, nm_dnsmasq_manager, G_TYPE_OBJECT)
 
 enum {
@@ -170,7 +172,7 @@ dm_exit_code (guint dm_exit_status)
 	case 4:
 		msg = "Memory allocation failure";
 		break;
-	case 5: 
+	case 5:
 		msg = "Other problem";
 		break;
 	default:
@@ -200,7 +202,7 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data)
 	} else {
 		nm_log_warn (LOGD_SHARING, "dnsmasq died from an unknown cause");
 	}
-  
+
 	priv->pid = 0;
 	priv->dm_watch_id = 0;
 
@@ -209,19 +211,20 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data)
 
 static NMCmdLine *
 create_dm_cmd_line (const char *iface,
-                    NMIP4Config *ip4_config,
+                    const NMPlatformIP4Address *listen_address,
                     const char *pidfile,
                     GError **error)
 {
 	NMCmdLine *cmd;
 	GString *s;
-	const NMPlatformIP4Address *tmp;
 	char first[INET_ADDRSTRLEN];
 	char last[INET_ADDRSTRLEN];
 	char localaddr[INET_ADDRSTRLEN];
 	char *error_desc = NULL;
 	const char *dm_binary;
 
+	g_return_val_if_fail (listen_address, NULL);
+
 	dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, error);
 	if (!dm_binary)
 		return NULL;
@@ -255,16 +258,13 @@ create_dm_cmd_line (const char *iface,
 	 */
 	nm_cmd_line_add_string (cmd, "--strict-order");
 
-	/* Find the IP4 address to use */
-	tmp = nm_ip4_config_get_address (ip4_config, 0);
-
 	s = g_string_new ("--listen-address=");
-	nm_utils_inet4_ntop (tmp->address, localaddr);
+	nm_utils_inet4_ntop (listen_address->address, localaddr);
 	g_string_append (s, localaddr);
 	nm_cmd_line_add_string (cmd, s->str);
 	g_string_free (s, TRUE);
 
-	if (!nm_dnsmasq_utils_get_range (tmp, first, last, &error_desc)) {
+	if (!nm_dnsmasq_utils_get_range (listen_address, first, last, &error_desc)) {
 		g_set_error_literal (error,
 		                     NM_MANAGER_ERROR,
 		                     NM_MANAGER_ERROR_FAILED,
@@ -292,39 +292,49 @@ create_dm_cmd_line (const char *iface,
 	nm_cmd_line_add_string (cmd, s->str);
 	g_string_free (s, TRUE);
 
+	/* dnsmasq exits if the conf dir is not present */
+	if (g_file_test (CONFDIR, G_FILE_TEST_IS_DIR))
+		nm_cmd_line_add_string (cmd, "--conf-dir=" CONFDIR);
+
 	return cmd;
 }
 
 static void
-kill_existing_for_iface (const char *iface, const char *pidfile)
+kill_existing_by_pidfile (const char *pidfile)
 {
 	char *contents = NULL;
-	glong pid;
-	char *proc_path = NULL;
+	pid_t pid;
+	char proc_path[250];
 	char *cmdline_contents = NULL;
+	guint64 start_time;
+	const char *exe;
+
+	if (   !pidfile
+	    || !g_file_get_contents (pidfile, &contents, NULL, NULL))
+		return;
 
-	if (!g_file_get_contents (pidfile, &contents, NULL, NULL))
+	pid = _nm_utils_ascii_str_to_int64 (contents, 10, 1, G_MAXUINT64, 0);
+	if (pid == 0)
 		goto out;
 
-	pid = strtol (contents, NULL, 10);
-	if (pid < 1 || pid > INT_MAX)
+	start_time = nm_utils_get_start_time_for_pid (pid, NULL, NULL);
+	if (start_time == 0)
 		goto out;
 
-	proc_path = g_strdup_printf ("/proc/%ld/cmdline", pid);
+	nm_sprintf_buf (proc_path, "/proc/%lld/cmdline", (long long) pid);
 	if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL))
 		goto out;
 
-	if (strstr (cmdline_contents, "bin/dnsmasq")) {
-		if (kill (pid, 0) == 0) {
-			nm_log_dbg (LOGD_SHARING, "Killing stale dnsmasq process %ld", pid);
-			kill (pid, SIGKILL);
-		}
-		unlink (pidfile);
+	exe = strrchr (cmdline_contents, '/');
+	if (   (exe && strcmp (&exe[1], "dnsmasq") == 0)
+	    || (strcmp (cmdline_contents, DNSMASQ_PATH) == 0)) {
+		nm_utils_kill_process_sync (pid, start_time, SIGKILL, LOGD_SHARING,
+		                            "dnsmasq", 0, 0, 500);
 	}
 
 out:
+	unlink (pidfile);
 	g_free (cmdline_contents);
-	g_free (proc_path);
 	g_free (contents);
 }
 
@@ -335,17 +345,17 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
 {
 	NMDnsMasqManagerPrivate *priv;
 	NMCmdLine *dm_cmd;
-	char *cmd_str;
+	gs_free char *cmd_str = NULL;
 
 	g_return_val_if_fail (NM_IS_DNSMASQ_MANAGER (manager), FALSE);
-	if (error)
-		g_return_val_if_fail (*error == NULL, FALSE);
+	g_return_val_if_fail (!error || !*error, FALSE);
+	g_return_val_if_fail (nm_ip4_config_get_num_addresses (ip4_config) > 0, FALSE);
 
 	priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager);
 
-	kill_existing_for_iface (priv->iface, priv->pidfile);
+	kill_existing_by_pidfile (priv->pidfile);
 
-	dm_cmd = create_dm_cmd_line (priv->iface, ip4_config, priv->pidfile, error);
+	dm_cmd = create_dm_cmd_line (priv->iface, nm_ip4_config_get_address (ip4_config, 0), priv->pidfile, error);
 	if (!dm_cmd)
 		return FALSE;
 
@@ -353,9 +363,8 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
 
 	nm_log_info (LOGD_SHARING, "Starting dnsmasq...");
 
-	cmd_str = nm_cmd_line_to_str (dm_cmd);
-	nm_log_dbg (LOGD_SHARING, "Command line: %s", cmd_str);
-	g_free (cmd_str);
+	nm_log_dbg (LOGD_SHARING, "Command line: %s",
+	            (cmd_str = nm_cmd_line_to_str (dm_cmd)));
 
 	priv->pid = 0;
 	if (!g_spawn_async (NULL, (char **) dm_cmd->array->pdata, NULL,
diff --git a/src/dnsmasq-manager/nm-dnsmasq-utils.c b/src/dnsmasq-manager/nm-dnsmasq-utils.c
index 4394ae7b..bf8faecd 100644
--- a/src/dnsmasq-manager/nm-dnsmasq-utils.c
+++ b/src/dnsmasq-manager/nm-dnsmasq-utils.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
index 04bf1b4d..850ae4f6 100644
--- a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
+++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
@@ -18,11 +18,10 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-dnsmasq-utils.h"
 
 #include "nm-test-utils.h"
diff --git a/src/main-utils.c b/src/main-utils.c
index 7425d0bc..e0f254b7 100644
--- a/src/main-utils.c
+++ b/src/main-utils.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2005 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <errno.h>
@@ -32,7 +32,6 @@
 #include <glib-unix.h>
 #include <gmodule.h>
 
-#include "nm-default.h"
 #include "main-utils.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/main.c b/src/main.c
index ee8e0f2d..9495a9ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2005 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <getopt.h>
 #include <locale.h>
@@ -35,7 +35,6 @@
 #include <string.h>
 #include <sys/resource.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "NetworkManagerUtils.h"
 #include "main-utils.h"
@@ -165,17 +164,11 @@ _init_nm_debug (const char *debug)
 		{ "RLIMIT_CORE", D_RLIMIT_CORE },
 		{ "fatal-warnings", D_FATAL_WARNINGS },
 	};
-	guint flags = 0;
+	guint flags;
 	const char *env = getenv ("NM_DEBUG");
 
-	if (env && strcasecmp (env, "help") != 0) {
-		/* g_parse_debug_string() prints options to stderr if the variable
-		 * is set to "help". Don't allow that. */
-		flags = g_parse_debug_string (env,  keys, G_N_ELEMENTS (keys));
-	}
-
-	if (debug && strcasecmp (debug, "help") != 0)
-		flags |= g_parse_debug_string (debug,  keys, G_N_ELEMENTS (keys));
+	flags  = nm_utils_parse_debug_string (env, keys, G_N_ELEMENTS (keys));
+	flags |= nm_utils_parse_debug_string (debug, keys, G_N_ELEMENTS (keys));
 
 	if (NM_FLAGS_HAS (flags, D_RLIMIT_CORE)) {
 		/* only enable this, if explicitly requested, because it might
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c
index 30e98fca..17b1d75d 100644
--- a/src/nm-activation-request.c
+++ b/src/nm-activation-request.c
@@ -19,16 +19,14 @@
  * Copyright (C) 2007 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
-
 #include "nm-activation-request.h"
-#include "nm-default.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-8021x.h"
 #include "nm-device.h"
@@ -346,7 +344,7 @@ nm_act_request_add_share_rule (NMActRequest *req,
 	rule = g_malloc0 (sizeof (ShareRule));
 	rule->table = g_strdup (table);
 	rule->rule = g_strdup (table_rule);
-	priv->share_rules = g_slist_append (priv->share_rules, rule);
+	priv->share_rules = g_slist_prepend (priv->share_rules, rule);
 }
 
 /********************************************************************/
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index ad6b08b3..f275b3ef 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -18,9 +18,8 @@
  * Copyright (C) 2008 - 2014 Red Hat, Inc.
  */
 
-#include "config.h"
-
 #include "nm-default.h"
+
 #include "nm-active-connection.h"
 #include "nm-dbus-interface.h"
 #include "nm-device.h"
@@ -46,6 +45,8 @@ typedef struct {
 	char *specific_object;
 	NMDevice *device;
 
+	guint64 version_id;
+
 	char *pending_activation_id;
 
 	gboolean is_default;
@@ -121,14 +122,15 @@ static void _device_cleanup (NMActiveConnection *self);
 
 /****************************************************************/
 
-NM_UTILS_STRING_LOOKUP_TABLE_DEFINE_STATIC (_state_to_string, NMActiveConnectionState, NULL,
-	[NM_ACTIVE_CONNECTION_STATE_UNKNOWN]            = "unknown",
-	[NM_ACTIVE_CONNECTION_STATE_ACTIVATING]         = "activating",
-	[NM_ACTIVE_CONNECTION_STATE_ACTIVATED]          = "activated",
-	[NM_ACTIVE_CONNECTION_STATE_DEACTIVATING]       = "deactivating",
-	[NM_ACTIVE_CONNECTION_STATE_DEACTIVATED]        = "deactivated",
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_state_to_string, NMActiveConnectionState,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_UNKNOWN,      "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATING,   "activating"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATED,    "activated"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, "deactivating"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,  "deactivated"),
 );
-#define state_to_string(state) NM_UTILS_STRING_LOOKUP_TABLE (_state_to_string, state)
+#define state_to_string(state) NM_UTILS_LOOKUP_STR (_state_to_string, state)
 
 /****************************************************************/
 
@@ -795,10 +797,45 @@ nm_active_connection_authorize (NMActiveConnection *self,
 
 /****************************************************************/
 
+static guint64
+_version_id_new (void)
+{
+	static guint64 id = 0;
+
+	return ++id;
+}
+
+guint64
+nm_active_connection_version_id_get (NMActiveConnection *self)
+{
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
+
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->version_id;
+}
+
+guint64
+nm_active_connection_version_id_bump (NMActiveConnection *self)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE  (self);
+	priv->version_id = _version_id_new ();
+	_LOGT ("new version-id %llu", (long long unsigned) priv->version_id);
+	return priv->version_id;
+}
+
+/****************************************************************/
+
 static void
 nm_active_connection_init (NMActiveConnection *self)
 {
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
+
 	_LOGT ("creating");
+
+	priv->version_id = _version_id_new ();
 }
 
 static void
@@ -809,7 +846,7 @@ constructed (GObject *object)
 
 	G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
 
-	_LOGD ("constructed (%s)", G_OBJECT_TYPE_NAME (self));
+	_LOGD ("constructed (%s, version-id %llu)", G_OBJECT_TYPE_NAME (self), (long long unsigned) priv->version_id);
 
 	g_return_if_fail (priv->subject);
 }
diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h
index f57f2081..a7b3d0cd 100644
--- a/src/nm-active-connection.h
+++ b/src/nm-active-connection.h
@@ -83,6 +83,9 @@ typedef struct {
 	                                NMMetered new_value);
 } NMActiveConnectionClass;
 
+guint64 nm_active_connection_version_id_get (NMActiveConnection *self);
+guint64 nm_active_connection_version_id_bump (NMActiveConnection *self);
+
 GType         nm_active_connection_get_type (void);
 
 typedef void (*NMActiveConnectionAuthResultFunc) (NMActiveConnection *self,
diff --git a/src/nm-audit-manager.c b/src/nm-audit-manager.c
index 007e4321..b4cfb20b 100644
--- a/src/nm-audit-manager.c
+++ b/src/nm-audit-manager.c
@@ -18,7 +18,9 @@
  * Copyright 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-audit-manager.h"
 
 #include <errno.h>
 #include <string.h>
@@ -26,13 +28,8 @@
 #include <libaudit.h>
 #endif
 
-#include "gsystem-local-alloc.h"
-#include "nm-audit-manager.h"
-#include "nm-glib.h"
 #include "nm-auth-subject.h"
 #include "nm-config.h"
-#include "nm-logging.h"
-#include "nm-macros-internal.h"
 #include "nm-settings-connection.h"
 
 #define AUDIT_LOG_LEVEL LOGL_INFO
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
index bc519eb1..e2e22aca 100644
--- a/src/nm-auth-manager.c
+++ b/src/nm-auth-manager.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-auth-manager.h"
 
-#include "nm-default.h"
 #include "nm-errors.h"
 #include "nm-core-internal.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c
index c4b6e579..494d52d3 100644
--- a/src/nm-auth-subject.c
+++ b/src/nm-auth-subject.c
@@ -26,14 +26,13 @@
  * makes requests, like process identifier and user UID.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-auth-subject.h"
 
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-bus-manager.h"
 #include "nm-enum-types.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/nm-auth-subject.h b/src/nm-auth-subject.h
index 1682ba7f..5f507058 100644
--- a/src/nm-auth-subject.h
+++ b/src/nm-auth-subject.h
@@ -21,10 +21,6 @@
 #ifndef __NETWORKMANAGER_AUTH_SUBJECT_H__
 #define __NETWORKMANAGER_AUTH_SUBJECT_H__
 
-#include "config.h"
-
-#include "nm-default.h"
-
 #define NM_TYPE_AUTH_SUBJECT            (nm_auth_subject_get_type ())
 #define NM_AUTH_SUBJECT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubject))
 #define NM_AUTH_SUBJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c
index 8c1c4dac..e741546b 100644
--- a/src/nm-auth-utils.c
+++ b/src/nm-auth-utils.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2010 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-setting-connection.h"
 #include "nm-auth-utils.h"
 #include "nm-auth-subject.h"
diff --git a/src/nm-bus-manager.c b/src/nm-bus-manager.c
index a82b3883..b6245b24 100644
--- a/src/nm-bus-manager.c
+++ b/src/nm-bus-manager.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
@@ -27,7 +27,6 @@
 #include <errno.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-bus-manager.h"
 #include "nm-core-internal.h"
diff --git a/src/nm-bus-manager.h b/src/nm-bus-manager.h
index 8e72a3ce..49579d46 100644
--- a/src/nm-bus-manager.h
+++ b/src/nm-bus-manager.h
@@ -22,10 +22,6 @@
 #ifndef __NM_BUS_MANAGER_H__
 #define __NM_BUS_MANAGER_H__
 
-#include "config.h"
-
-#include "nm-default.h"
-
 G_BEGIN_DECLS
 
 #define NM_TYPE_BUS_MANAGER (nm_bus_manager_get_type ())
@@ -33,7 +29,7 @@ G_BEGIN_DECLS
 #define NM_BUS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NM_TYPE_BUS_MANAGER, NMBusManagerClass))
 #define NM_IS_BUS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NM_TYPE_BUS_MANAGER))
 #define NM_IS_BUS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NM_TYPE_BUS_MANAGER))
-#define NM_BUS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NM_TYPE_BUS_MANAGER, NMBusManagerClass)) 
+#define NM_BUS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NM_TYPE_BUS_MANAGER, NMBusManagerClass))
 
 #define NM_BUS_MANAGER_DBUS_CONNECTION_CHANGED          "dbus-connection-changed"
 #define NM_BUS_MANAGER_PRIVATE_CONNECTION_NEW           "private-connection-new"
diff --git a/src/nm-config-data.c b/src/nm-config-data.c
index e2b6c3a6..1702b551 100644
--- a/src/nm-config-data.c
+++ b/src/nm-config-data.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-config-data.h"
 
@@ -29,8 +29,6 @@
 #include "nm-device.h"
 #include "nm-core-internal.h"
 #include "nm-keyfile-internal.h"
-#include "nm-macros-internal.h"
-#include "nm-default.h"
 
 typedef struct {
 	char *group_name;
@@ -118,7 +116,7 @@ G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT)
 #define _HAS_PREFIX(str, prefix) \
 	({ \
 		const char *_str = (str); \
-		g_str_has_prefix ( _str, ""prefix"") && _str[STRLEN(prefix)] != '\0'; \
+		g_str_has_prefix ( _str, ""prefix"") && _str[NM_STRLEN(prefix)] != '\0'; \
 	})
 
 /************************************************************************/
@@ -325,7 +323,7 @@ _nm_config_data_get_keyfile_user (const NMConfigData *self)
  * nm_config_data_get_groups:
  * @self: the #NMConfigData instance
  *
- * Returns: (transfer-full): the list of groups in the configuration. The order
+ * Returns: (transfer full): the list of groups in the configuration. The order
  * of the section is undefined, as the configuration gets merged from multiple
  * sources.
  */
@@ -431,7 +429,7 @@ _merge_keyfiles (GKeyFile *keyfile_user, GKeyFile *keyfile_intern)
 
 			if (   !is_intern && !is_atomic
 			    && _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
-				const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
+				const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
 
 				if (!g_key_file_has_key (keyfile_intern, group, key_base, NULL))
 					g_key_file_remove_key (keyfile, group, key_base, NULL);
@@ -474,8 +472,8 @@ _nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy)
 
 	if (a_is_connection && b_is_connection) {
 		/* if both are connection groups, we want the explicit [connection] group first. */
-		a_is_connection = a[STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
-		b_is_connection = b[STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
+		a_is_connection = a[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
+		b_is_connection = b[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
 
 		if (a_is_connection != b_is_connection) {
 			if (a_is_connection)
@@ -1127,7 +1125,7 @@ _get_connection_infos (GKeyFile *keyfile)
 	else if (ngroups > 0) {
 		for (i = 0, j = 0; i < ngroups; i++) {
 			if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)) {
-				if (groups[i][STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0')
+				if (groups[i][NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0')
 					connection_tag = groups[i];
 				else
 					groups[j++] = groups[i];
diff --git a/src/nm-config.c b/src/nm-config.c
index 15ef886b..58fd96cb 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -19,12 +19,11 @@
  * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdio.h>
 
-#include "nm-default.h"
 #include "nm-config.h"
 #include "nm-utils.h"
 #include "nm-device.h"
@@ -117,7 +116,7 @@ static void _set_config_data (NMConfig *self, NMConfigData *new_data, int signal
 #define _HAS_PREFIX(str, prefix) \
 	({ \
 		const char *_str = (str); \
-		g_str_has_prefix ( _str, ""prefix"") && _str[STRLEN(prefix)] != '\0'; \
+		g_str_has_prefix ( _str, ""prefix"") && _str[NM_STRLEN(prefix)] != '\0'; \
 	})
 
 /************************************************************************/
@@ -1188,7 +1187,7 @@ intern_config_read (const char *filename,
 					continue;
 				g_key_file_set_value (keyfile_intern, group, key, value_set);
 			} else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) {
-				const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_SET)];
+				const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_SET)];
 				gs_free char *value_was = NULL;
 				gs_free char *value_conf = NULL;
 				gs_free char *key_was = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_WAS"%s", key_base);
@@ -1208,7 +1207,7 @@ intern_config_read (const char *filename,
 				has_intern = TRUE;
 				g_key_file_set_value (keyfile_intern, group, key_base, value_set);
 			} else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
-				const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
+				const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
 				gs_free char *key_set = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_SET"%s", key_base);
 				gs_free char *value_was = NULL;
 				gs_free char *value_conf = NULL;
@@ -1252,7 +1251,7 @@ out:
 			needs_rewrite = TRUE;
 		for (g = 0; groups && groups[g]; g++) {
 			if (   g_str_has_prefix (groups[g], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)
-			    && groups[g][STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)]) {
+			    && groups[g][NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)]) {
 				g_key_file_remove_group (keyfile_intern, groups[g], NULL);
 				needs_rewrite = TRUE;
 			}
@@ -1391,7 +1390,7 @@ intern_config_write (const char *filename,
 					 * Why did this happen?? */
 					g_warn_if_reached ();
 				} else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
-					const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
+					const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
 
 					if (   _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_SET)
 					    || _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c
index 8185b8c6..2e258bd5 100644
--- a/src/nm-connection-provider.c
+++ b/src/nm-connection-provider.c
@@ -13,7 +13,7 @@
  * Copyright (C) 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-connection-provider.h"
 #include "nm-utils.h"
diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c
index 5942c5b7..934727fa 100644
--- a/src/nm-connectivity.c
+++ b/src/nm-connectivity.c
@@ -19,16 +19,16 @@
  * Copyright (C) 2011 Dan Williams <dcbw@redhat.com>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #if WITH_CONCHECK
 #include <libsoup/soup.h>
 #endif
 
-#include "nm-default.h"
 #include "nm-connectivity.h"
 #include "nm-config.h"
+#include "NetworkManagerUtils.h"
 
 G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT)
 
@@ -76,24 +76,14 @@ nm_connectivity_get_state (NMConnectivity *connectivity)
 	return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->state;
 }
 
-const char *
-nm_connectivity_state_to_string (NMConnectivityState state)
-{
-	switch (state) {
-	case NM_CONNECTIVITY_UNKNOWN:
-		return "UNKNOWN";
-	case NM_CONNECTIVITY_NONE:
-		return "NONE";
-	case NM_CONNECTIVITY_LIMITED:
-		return "LIMITED";
-	case NM_CONNECTIVITY_PORTAL:
-		return "PORTAL";
-	case NM_CONNECTIVITY_FULL:
-		return "FULL";
-	default:
-		g_return_val_if_reached ("???");
-	}
-}
+NM_UTILS_LOOKUP_STR_DEFINE (nm_connectivity_state_to_string, NMConnectivityState,
+	NM_UTILS_LOOKUP_DEFAULT_WARN ("???"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_UNKNOWN,  "UNKNOWN"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_NONE,     "NONE"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_LIMITED,  "LIMITED"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_PORTAL,   "PORTAL"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_FULL,     "FULL"),
+);
 
 static void
 update_state (NMConnectivity *self, NMConnectivityState state)
@@ -142,7 +132,7 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
 
 	if (msg->status_code == 511) {
 		_LOGD ("check for uri '%s' returned status '%d %s'; captive portal present.",
-			   uri, msg->status_code, msg->reason_phrase);
+		       uri, msg->status_code, msg->reason_phrase);
 		new_state = NM_CONNECTIVITY_PORTAL;
 	} else {
 		/* Check headers; if we find the NM-specific one we're done */
@@ -162,7 +152,7 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
 			}
 		} else {
 			_LOGI ("check for uri '%s' returned status '%d %s'; assuming captive portal.",
-				   uri, msg->status_code, msg->reason_phrase);
+			       uri, msg->status_code, msg->reason_phrase);
 			new_state = NM_CONNECTIVITY_PORTAL;
 		}
 	}
@@ -466,11 +456,10 @@ dispose (GObject *object)
 		g_clear_object (&priv->soup_session);
 	}
 
-	if (priv->check_id > 0) {
-		g_source_remove (priv->check_id);
-		priv->check_id = 0;
-	}
+	nm_clear_g_source (&priv->check_id);
 #endif
+
+	G_OBJECT_CLASS (nm_connectivity_parent_class)->dispose (object);
 }
 
 
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
new file mode 100644
index 00000000..a7d85c29
--- /dev/null
+++ b/src/nm-core-utils.c
@@ -0,0 +1,2944 @@
+/* -*- 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 2004 - 2014 Red Hat, Inc.
+ * Copyright 2005 - 2008 Novell, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-core-utils.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <resolv.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <linux/if.h>
+#include <linux/if_infiniband.h>
+#include <net/ethernet.h>
+
+#include "nm-utils.h"
+#include "nm-core-internal.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
+
+/*
+ * Some toolchains (E.G. uClibc 0.9.33 and earlier) don't export
+ * CLOCK_BOOTTIME even though the kernel supports it, so provide a
+ * local definition
+ */
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif
+
+G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int));
+int _nm_utils_testing = 0;
+
+gboolean
+nm_utils_get_testing_initialized ()
+{
+	NMUtilsTestFlags flags;
+
+	flags = (NMUtilsTestFlags) _nm_utils_testing;
+	if (flags == NM_UTILS_TEST_NONE)
+		flags = (NMUtilsTestFlags) g_atomic_int_get (&_nm_utils_testing);
+	return flags != NM_UTILS_TEST_NONE;
+}
+
+NMUtilsTestFlags
+nm_utils_get_testing ()
+{
+	NMUtilsTestFlags flags;
+
+	flags = (NMUtilsTestFlags) _nm_utils_testing;
+	if (flags != NM_UTILS_TEST_NONE) {
+		/* Flags already initialized. Return them. */
+		return flags & NM_UTILS_TEST_ALL;
+	}
+
+	/* Accessing nm_utils_get_testing() causes us to set the flags to initialized.
+	 * Detecting running tests also based on g_test_initialized(). */
+	flags = _NM_UTILS_TEST_INITIALIZED;
+	if (g_test_initialized ())
+		flags |= _NM_UTILS_TEST_GENERAL;
+
+	if (g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
+		/* Done. We set it. */
+		return flags & NM_UTILS_TEST_ALL;
+	}
+	/* It changed in the meantime (??). Re-read the value. */
+	return ((NMUtilsTestFlags) _nm_utils_testing) & NM_UTILS_TEST_ALL;
+}
+
+void
+_nm_utils_set_testing (NMUtilsTestFlags flags)
+{
+	g_assert (!NM_FLAGS_ANY (flags, ~NM_UTILS_TEST_ALL));
+
+	/* mask out everything except ALL, and always set GENERAL. */
+	flags = (flags & NM_UTILS_TEST_ALL) | (_NM_UTILS_TEST_GENERAL | _NM_UTILS_TEST_INITIALIZED);
+
+	if (!g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
+		/* We only allow setting _nm_utils_set_testing() once, before fetching the
+		 * value with nm_utils_get_testing(). */
+		g_return_if_reached ();
+	}
+}
+
+/*****************************************************************************/
+
+G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error)
+
+void
+nm_utils_error_set_cancelled (GError **error,
+                              gboolean is_disposing,
+                              const char *instance_name)
+{
+	if (is_disposing) {
+		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING,
+		             "Disposing %s instance",
+		             instance_name && *instance_name ? instance_name : "source");
+	} else {
+		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+		                     "Request cancelled");
+	}
+}
+
+gboolean
+nm_utils_error_is_cancelled (GError *error,
+                             gboolean consider_is_disposing)
+{
+	if (error) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			return TRUE;
+		if (   consider_is_disposing
+		    && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+/*****************************************************************************/
+
+static GSList *_singletons = NULL;
+static gboolean _singletons_shutdown = FALSE;
+
+static void
+_nm_singleton_instance_weak_cb (gpointer data,
+                                GObject *where_the_object_was)
+{
+	_singletons = g_slist_remove (_singletons, where_the_object_was);
+}
+
+static void __attribute__((destructor))
+_nm_singleton_instance_destroy (void)
+{
+	_singletons_shutdown = TRUE;
+
+	while (_singletons) {
+		GObject *instance = _singletons->data;
+
+		_singletons = g_slist_delete_link (_singletons, _singletons);
+
+		g_object_weak_unref (instance, _nm_singleton_instance_weak_cb, NULL);
+
+		if (instance->ref_count > 1)
+			nm_log_dbg (LOGD_CORE, "disown %s singleton (%p)", G_OBJECT_TYPE_NAME (instance), instance);
+
+		g_object_unref (instance);
+	}
+}
+
+void
+_nm_singleton_instance_register_destruction (GObject *instance)
+{
+	g_return_if_fail (G_IS_OBJECT (instance));
+
+	/* Don't allow registration after shutdown. We only destroy the singletons
+	 * once. */
+	g_return_if_fail (!_singletons_shutdown);
+
+	g_object_weak_ref (instance, _nm_singleton_instance_weak_cb, NULL);
+
+	_singletons = g_slist_prepend (_singletons, instance);
+}
+
+/*****************************************************************************/
+
+gint
+nm_utils_ascii_str_to_bool (const char *str,
+                            gint default_value)
+{
+	gsize len;
+	char *s = NULL;
+
+	if (!str)
+		return default_value;
+
+	while (str[0] && g_ascii_isspace (str[0]))
+		str++;
+
+	if (!str[0])
+		return default_value;
+
+	len = strlen (str);
+	if (g_ascii_isspace (str[len - 1])) {
+		s = g_strdup (str);
+		g_strchomp (s);
+		str = s;
+	}
+
+	if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
+		default_value = TRUE;
+	else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
+		default_value = FALSE;
+	if (s)
+		g_free (s);
+	return default_value;
+}
+
+/*****************************************************************************/
+
+/*
+ * nm_ethernet_address_is_valid:
+ * @addr: pointer to a binary or ASCII Ethernet address
+ * @len: length of @addr, or -1 if @addr is ASCII
+ *
+ * Compares an Ethernet address against known invalid addresses.
+
+ * Returns: %TRUE if @addr is a valid Ethernet address, %FALSE if it is not.
+ */
+gboolean
+nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
+{
+	guint8 invalid_addr[4][ETH_ALEN] = {
+	    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+	    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	    {0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
+	    {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}, /* prism54 dummy MAC */
+	};
+	guint8 addr_bin[ETH_ALEN];
+	guint i;
+
+	if (!addr) {
+		g_return_val_if_fail (len == -1 || len == ETH_ALEN, FALSE);
+		return FALSE;
+	}
+
+	if (len == -1) {
+		if (!nm_utils_hwaddr_aton (addr, addr_bin, ETH_ALEN))
+			return FALSE;
+		addr = addr_bin;
+	} else if (len != ETH_ALEN)
+		g_return_val_if_reached (FALSE);
+
+	/* Check for multicast address */
+	if ((((guint8 *) addr)[0]) & 0x01)
+		return FALSE;
+
+	for (i = 0; i < G_N_ELEMENTS (invalid_addr); i++) {
+		if (nm_utils_hwaddr_matches (addr, ETH_ALEN, invalid_addr[i], ETH_ALEN))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/* nm_utils_ip4_address_clear_host_address:
+ * @addr: source ip6 address
+ * @plen: prefix length of network
+ *
+ * returns: the input address, with the host address set to 0.
+ */
+in_addr_t
+nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen)
+{
+	return addr & nm_utils_ip4_prefix_to_netmask (plen);
+}
+
+/* nm_utils_ip6_address_clear_host_address:
+ * @dst: destination output buffer, will contain the network part of the @src address
+ * @src: source ip6 address
+ * @plen: prefix length of network
+ *
+ * Note: this function is self assignment safe, to update @src inplace, set both
+ * @dst and @src to the same destination.
+ */
+const struct in6_addr *
+nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen)
+{
+	g_return_val_if_fail (plen <= 128, NULL);
+	g_return_val_if_fail (src, NULL);
+	g_return_val_if_fail (dst, NULL);
+
+	if (plen < 128) {
+		guint nbytes = plen / 8;
+		guint nbits = plen % 8;
+
+		if (nbytes && dst != src)
+			memcpy (dst, src, nbytes);
+		if (nbits) {
+			dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
+			nbytes++;
+		}
+		if (nbytes <= 15)
+			memset (&dst->s6_addr[nbytes], 0, 16 - nbytes);
+	} else if (src != dst)
+		*dst = *src;
+
+	return dst;
+}
+
+void
+nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
+{
+	gsize elt_size;
+	guint index_to_delete;
+	guint i_src;
+	guint mm_src, mm_dst, mm_len;
+	gsize i_itd;
+	guint res_length;
+
+	g_return_if_fail (array);
+	if (!len)
+		return;
+	g_return_if_fail (indexes_to_delete);
+
+	elt_size = g_array_get_element_size (array);
+
+	i_itd = 0;
+	index_to_delete = indexes_to_delete[0];
+	if (index_to_delete >= array->len)
+		g_return_if_reached ();
+
+	res_length = array->len - 1;
+
+	mm_dst = index_to_delete;
+	mm_src = index_to_delete;
+	mm_len = 0;
+
+	for (i_src = index_to_delete; i_src < array->len; i_src++) {
+		if (i_src < index_to_delete)
+			mm_len++;
+		else {
+			/* we require indexes_to_delete to contain non-repeated, ascending
+			 * indexes. Otherwise we would need to presort the indexes. */
+			while (TRUE) {
+				guint dd;
+
+				if (i_itd + 1 >= len) {
+					index_to_delete = G_MAXUINT;
+					break;
+				}
+
+				dd = indexes_to_delete[++i_itd];
+				if (dd > index_to_delete) {
+					if (dd >= array->len)
+						g_warn_if_reached ();
+					else {
+						g_assert (res_length > 0);
+						res_length--;
+					}
+					index_to_delete = dd;
+					break;
+				}
+				g_warn_if_reached ();
+			}
+
+			if (mm_len) {
+				memmove (&array->data[mm_dst * elt_size],
+				         &array->data[mm_src * elt_size],
+				         mm_len * elt_size);
+				mm_dst += mm_len;
+				mm_src += mm_len + 1;
+				mm_len = 0;
+			} else
+				mm_src++;
+		}
+	}
+	if (mm_len) {
+		memmove (&array->data[mm_dst * elt_size],
+		         &array->data[mm_src * elt_size],
+		         mm_len * elt_size);
+	}
+	g_array_set_size (array, res_length);
+}
+
+int
+nm_spawn_process (const char *args, GError **error)
+{
+	GError *local = NULL;
+	gint num_args;
+	char **argv = NULL;
+	int status = -1;
+
+	g_return_val_if_fail (args != NULL, -1);
+	g_return_val_if_fail (!error || !*error, -1);
+
+	if (g_shell_parse_argv (args, &num_args, &argv, &local)) {
+		g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local);
+		g_strfreev (argv);
+	}
+
+	if (local) {
+		nm_log_warn (LOGD_CORE, "could not spawn process '%s': %s", args, local->message);
+		g_propagate_error (error, local);
+	}
+
+	return status;
+}
+
+static const char *
+_trunk_first_line (char *str)
+{
+	char *s;
+
+	s = strchr (str, '\n');
+	if (s)
+		s[0] = '\0';
+	return str;
+}
+
+int
+nm_utils_modprobe (GError **error, gboolean suppress_error_logging, const char *arg1, ...)
+{
+	gs_unref_ptrarray GPtrArray *argv = NULL;
+	int exit_status;
+	gs_free char *_log_str = NULL;
+#define ARGV_TO_STR(argv)   (_log_str ? _log_str : (_log_str = g_strjoinv (" ", (char **) argv->pdata)))
+	GError *local = NULL;
+	va_list ap;
+	NMLogLevel llevel = suppress_error_logging ? LOGL_DEBUG : LOGL_ERR;
+	gs_free char *std_out = NULL, *std_err = NULL;
+
+	g_return_val_if_fail (!error || !*error, -1);
+	g_return_val_if_fail (arg1, -1);
+
+	/* construct the argument list */
+	argv = g_ptr_array_sized_new (4);
+	g_ptr_array_add (argv, "/sbin/modprobe");
+	g_ptr_array_add (argv, (char *) arg1);
+
+	va_start (ap, arg1);
+	while ((arg1 = va_arg (ap, const char *)))
+		g_ptr_array_add (argv, (char *) arg1);
+	va_end (ap);
+
+	g_ptr_array_add (argv, NULL);
+
+	nm_log_dbg (LOGD_CORE, "modprobe: '%s'", ARGV_TO_STR (argv));
+	if (!g_spawn_sync (NULL, (char **) argv->pdata, NULL, 0, NULL, NULL, &std_out, &std_err, &exit_status, &local)) {
+		nm_log (llevel, LOGD_CORE, "modprobe: '%s' failed: %s", ARGV_TO_STR (argv), local->message);
+		g_propagate_error (error, local);
+		return -1;
+	} else if (exit_status != 0)
+		nm_log (llevel, LOGD_CORE, "modprobe: '%s' exited with error %d%s%s%s%s%s%s", ARGV_TO_STR (argv), exit_status,
+		        std_out&&*std_out ? " (" : "", std_out&&*std_out ? _trunk_first_line (std_out) : "", std_out&&*std_out ? ")" : "",
+		        std_err&&*std_err ? " (" : "", std_err&&*std_err ? _trunk_first_line (std_err) : "", std_err&&*std_err ? ")" : "");
+
+	return exit_status;
+}
+
+/**
+ * nm_utils_get_start_time_for_pid:
+ * @pid: the process identifier
+ * @out_state: return the state character, like R, S, Z. See `man 5 proc`.
+ * @out_ppid: parent process id
+ *
+ * Originally copied from polkit source (src/polkit/polkitunixprocess.c)
+ * and adjusted.
+ *
+ * Returns: the timestamp when the process started (by parsing /proc/$PID/stat).
+ * If an error occurs (e.g. the process does not exist), 0 is returned.
+ *
+ * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds)
+ **/
+guint64
+nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid)
+{
+	guint64 start_time;
+	char filename[256];
+	gs_free gchar *contents = NULL;
+	size_t length;
+	gs_strfreev gchar **tokens = NULL;
+	guint num_tokens;
+	gchar *p;
+	gchar *endp;
+	char state = '\0';
+	gint64 ppid = 0;
+
+	start_time = 0;
+	contents = NULL;
+
+	g_return_val_if_fail (pid > 0, 0);
+
+	nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid);
+
+	if (!g_file_get_contents (filename, &contents, &length, NULL))
+		goto out;
+
+	/* start time is the token at index 19 after the '(process name)' entry - since only this
+	 * field can contain the ')' character, search backwards for this to avoid malicious
+	 * processes trying to fool us
+	 */
+	p = strrchr (contents, ')');
+	if (p == NULL)
+		goto out;
+	p += 2; /* skip ') ' */
+	if (p - contents >= (int) length)
+		goto out;
+
+	state = p[0];
+
+	tokens = g_strsplit (p, " ", 0);
+
+	num_tokens = g_strv_length (tokens);
+
+	if (num_tokens < 20)
+		goto out;
+
+	if (out_ppid)
+		ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0);
+
+	errno = 0;
+	start_time = strtoull (tokens[19], &endp, 10);
+	if (*endp != '\0' || errno != 0)
+		start_time = 0;
+
+out:
+	if (out_state)
+		*out_state = state;
+	if (out_ppid)
+		*out_ppid = ppid;
+
+	return start_time;
+}
+
+/******************************************************************************************/
+
+typedef struct {
+	pid_t pid;
+	NMLogDomain log_domain;
+	union {
+		struct {
+			gint64 wait_start_us;
+			guint source_timeout_kill_id;
+		} async;
+		struct {
+			gboolean success;
+			int child_status;
+		} sync;
+	};
+	NMUtilsKillChildAsyncCb callback;
+	void *user_data;
+
+	char log_name[1]; /* variable-length object, must be last element!! */
+} KillChildAsyncData;
+
+#define LOG_NAME_FMT "kill child process '%s' (%ld)"
+#define LOG_NAME_PROCESS_FMT "kill process '%s' (%ld)"
+#define LOG_NAME_ARGS log_name,(long)pid
+
+static KillChildAsyncData *
+_kc_async_data_alloc (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data)
+{
+	KillChildAsyncData *data;
+	size_t log_name_len;
+
+	/* append the name at the end of our KillChildAsyncData. */
+	log_name_len = strlen (LOG_NAME_FMT) + 20 + strlen (log_name);
+	data = g_malloc (sizeof (KillChildAsyncData) - 1 + log_name_len);
+	g_snprintf (data->log_name, log_name_len, LOG_NAME_FMT, LOG_NAME_ARGS);
+
+	data->pid = pid;
+	data->user_data = user_data;
+	data->callback = callback;
+	data->log_domain = log_domain;
+
+	return data;
+}
+
+#define KC_EXIT_TO_STRING_BUF_SIZE 128
+static const char *
+_kc_exit_to_string (char *buf, int exit)
+#define _kc_exit_to_string(buf, exit) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_EXIT_TO_STRING_BUF_SIZE && sizeof ((buf)[0]) == 1), _kc_exit_to_string (buf, exit) )
+{
+	if (WIFEXITED (exit))
+		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "normally with status %d", WEXITSTATUS (exit));
+	else if (WIFSIGNALED (exit))
+		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "by signal %d", WTERMSIG (exit));
+	else
+		g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "with unexpected status %d", exit);
+	return buf;
+}
+
+static const char *
+_kc_signal_to_string (int sig)
+{
+	switch (sig) {
+	case 0:  return "no signal (0)";
+	case SIGKILL:  return "SIGKILL (" G_STRINGIFY (SIGKILL) ")";
+	case SIGTERM:  return "SIGTERM (" G_STRINGIFY (SIGTERM) ")";
+	default:
+		return "Unexpected signal";
+	}
+}
+
+#define KC_WAITED_TO_STRING 100
+static const char *
+_kc_waited_to_string (char *buf, gint64 wait_start_us)
+#define _kc_waited_to_string(buf, wait_start_us) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_WAITED_TO_STRING && sizeof ((buf)[0]) == 1), _kc_waited_to_string (buf, wait_start_us) )
+{
+	g_snprintf (buf, KC_WAITED_TO_STRING, " (%ld usec elapsed)", (long) (nm_utils_get_monotonic_timestamp_us () - wait_start_us));
+	return buf;
+}
+
+static void
+_kc_cb_watch_child (GPid pid, gint status, gpointer user_data)
+{
+	KillChildAsyncData *data = user_data;
+	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE], buf_wait[KC_WAITED_TO_STRING];
+
+	if (data->async.source_timeout_kill_id)
+		g_source_remove (data->async.source_timeout_kill_id);
+
+	nm_log_dbg (data->log_domain, "%s: terminated %s%s",
+	            data->log_name, _kc_exit_to_string (buf_exit, status),
+	            _kc_waited_to_string (buf_wait, data->async.wait_start_us));
+
+	if (data->callback)
+		data->callback (pid, TRUE, status, data->user_data);
+
+	g_free (data);
+}
+
+static gboolean
+_kc_cb_timeout_grace_period (void *user_data)
+{
+	KillChildAsyncData *data = user_data;
+	int ret, errsv;
+
+	data->async.source_timeout_kill_id = 0;
+
+	if ((ret = kill (data->pid, SIGKILL)) != 0) {
+		errsv = errno;
+		/* ESRCH means, process does not exist or is already a zombie. */
+		if (errsv != ESRCH) {
+			nm_log_err (LOGD_CORE | data->log_domain, "%s: kill(SIGKILL) returned unexpected return value %d: (%s, %d)",
+			            data->log_name, ret, strerror (errsv), errsv);
+		}
+	} else {
+		nm_log_dbg (data->log_domain, "%s: process not terminated after %ld usec. Sending SIGKILL signal",
+		            data->log_name, (long) (nm_utils_get_monotonic_timestamp_us () - data->async.wait_start_us));
+	}
+
+	return G_SOURCE_REMOVE;
+}
+
+static gboolean
+_kc_invoke_callback_idle (gpointer user_data)
+{
+	KillChildAsyncData *data = user_data;
+
+	if (data->sync.success) {
+		char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
+
+		nm_log_dbg (data->log_domain, "%s: invoke callback: terminated %s",
+		            data->log_name, _kc_exit_to_string (buf_exit, data->sync.child_status));
+	} else
+		nm_log_dbg (data->log_domain, "%s: invoke callback: killing child failed", data->log_name);
+
+	data->callback (data->pid, data->sync.success, data->sync.child_status, data->user_data);
+	g_free (data);
+
+	return G_SOURCE_REMOVE;
+}
+
+static void
+_kc_invoke_callback (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data, gboolean success, int child_status)
+{
+	KillChildAsyncData *data;
+
+	if (!callback)
+		return;
+
+	data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
+	data->sync.success = success;
+	data->sync.child_status = child_status;
+
+	g_idle_add (_kc_invoke_callback_idle, data);
+}
+
+/* nm_utils_kill_child_async:
+ * @pid: the process id of the process to kill
+ * @sig: signal to send initially. Set to 0 to send not signal.
+ * @log_domain: the logging domain used for logging (LOGD_NONE to suppress logging)
+ * @log_name: for logging, the name of the processes to kill
+ * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
+ * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter is ignored.
+ * @callback: (allow-none): callback after the child terminated. This function will always
+ *   be invoked asynchronously.
+ * @user_data: passed on to callback
+ *
+ * Uses g_child_watch_add(), so note the glib comment: if you obtain pid from g_spawn_async() or
+ * g_spawn_async_with_pipes() you will need to pass %G_SPAWN_DO_NOT_REAP_CHILD as flag to the spawn
+ * function for the child watching to work.
+ * Also note, that you must g_source_remove() any other child watchers for @pid because glib
+ * supports only one watcher per child.
+ **/
+void
+nm_utils_kill_child_async (pid_t pid, int sig, NMLogDomain log_domain,
+                           const char *log_name, guint32 wait_before_kill_msec,
+                           NMUtilsKillChildAsyncCb callback, void *user_data)
+{
+	int status = 0, errsv;
+	pid_t ret;
+	KillChildAsyncData *data;
+	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
+
+	g_return_if_fail (pid > 0);
+	g_return_if_fail (log_name != NULL);
+
+	/* let's see if the child already terminated... */
+	ret = waitpid (pid, &status, WNOHANG);
+	if (ret > 0) {
+		nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
+		            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
+		_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
+		return;
+	} else if (ret != 0) {
+		errsv = errno;
+		/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
+		if (errsv != ECHILD) {
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
+			            LOG_NAME_ARGS, strerror (errsv), errsv);
+			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
+			return;
+		}
+	}
+
+	/* send the first signal. */
+	if (kill (pid, sig) != 0) {
+		errsv = errno;
+		/* ESRCH means, process does not exist or is already a zombie. */
+		if (errsv != ESRCH) {
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error sending %s: %s (%d)",
+			            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
+			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
+			return;
+		}
+
+		/* let's try again with waitpid, probably there was a race... */
+		ret = waitpid (pid, &status, 0);
+		if (ret > 0) {
+			nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
+			            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
+			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
+		} else {
+			errsv = errno;
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
+			            LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
+			_kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
+		}
+		return;
+	}
+
+	data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
+	data->async.wait_start_us = nm_utils_get_monotonic_timestamp_us ();
+
+	if (sig != SIGKILL && wait_before_kill_msec > 0) {
+		data->async.source_timeout_kill_id = g_timeout_add (wait_before_kill_msec, _kc_cb_timeout_grace_period, data);
+		nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s (send SIGKILL in %ld milliseconds)...",
+		            data->log_name,  _kc_signal_to_string (sig), (long) wait_before_kill_msec);
+	} else {
+		data->async.source_timeout_kill_id = 0;
+		nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s...",
+		            data->log_name, _kc_signal_to_string (sig));
+	}
+
+	g_child_watch_add (pid, _kc_cb_watch_child, data);
+}
+
+static inline gulong
+_sleep_duration_convert_ms_to_us (guint32 sleep_duration_msec)
+{
+	if (sleep_duration_msec > 0) {
+		guint64 x = (gint64) sleep_duration_msec * (guint64) 1000L;
+
+		return x < G_MAXULONG ? (gulong) x : G_MAXULONG;
+	}
+	return G_USEC_PER_SEC / 20;
+}
+
+/* nm_utils_kill_child_sync:
+ * @pid: process id to kill
+ * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
+ * second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
+ * @log_domain: log debug information for this domain. Errors and warnings are logged both
+ * as %LOGD_CORE and @log_domain.
+ * @log_name: name of the process to kill for logging.
+ * @child_status: (out) (allow-none): return the exit status of the child, if no error occured.
+ * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
+ * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has not effect.
+ * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
+ * Set to zero, to use the default (meaning 20 wakeups per seconds).
+ *
+ * Kill a child process synchronously and wait. The function first checks if the child already terminated
+ * and if it did, return the exit status. Otherwise send one @sig signal. @sig  will always be
+ * sent unless the child already exited. If the child does not exit within @wait_before_kill_msec milliseconds,
+ * the function will send %SIGKILL and waits for the child indefinitly. If @wait_before_kill_msec is zero, no
+ * %SIGKILL signal will be sent.
+ *
+ * In case of error, errno is preserved to contain the last reason of failure.
+ **/
+gboolean
+nm_utils_kill_child_sync (pid_t pid, int sig, NMLogDomain log_domain, const char *log_name,
+                          int *child_status, guint32 wait_before_kill_msec,
+                          guint32 sleep_duration_msec)
+{
+	int status = 0, errsv = 0;
+	pid_t ret;
+	gboolean success = FALSE;
+	gboolean was_waiting = FALSE, send_kill = FALSE;
+	char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
+	char buf_wait[KC_WAITED_TO_STRING];
+	gint64 wait_start_us;
+
+	g_return_val_if_fail (pid > 0, FALSE);
+	g_return_val_if_fail (log_name != NULL, FALSE);
+
+	/* check if the child process already terminated... */
+	ret = waitpid (pid, &status, WNOHANG);
+	if (ret > 0) {
+		nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
+		            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
+		success = TRUE;
+		goto out;
+	} else if (ret != 0) {
+		errsv = errno;
+		/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
+		if (errsv != ECHILD) {
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
+			            LOG_NAME_ARGS, strerror (errsv), errsv);
+			goto out;
+		}
+	}
+
+	/* send first signal @sig */
+	if (kill (pid, sig) != 0) {
+		errsv = errno;
+		/* ESRCH means, process does not exist or is already a zombie. */
+		if (errsv != ESRCH) {
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send %s: %s (%d)",
+			            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
+		} else {
+			/* let's try again with waitpid, probably there was a race... */
+			ret = waitpid (pid, &status, 0);
+			if (ret > 0) {
+				nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
+				            LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
+				success = TRUE;
+			} else {
+				errsv = errno;
+				nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
+				            LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
+			}
+		}
+		goto out;
+	}
+
+	wait_start_us = nm_utils_get_monotonic_timestamp_us ();
+
+	/* wait for the process to terminated... */
+	if (sig != SIGKILL) {
+		gint64 wait_until, now;
+		gulong sleep_time, sleep_duration_usec;
+		int loop_count = 0;
+
+		sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
+		wait_until = wait_before_kill_msec <= 0 ? 0 : wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
+
+		while (TRUE) {
+			ret = waitpid (pid, &status, WNOHANG);
+			if (ret > 0) {
+				nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s, process %ld exited %s%s",
+				            LOG_NAME_ARGS, _kc_signal_to_string (sig), (long) ret, _kc_exit_to_string (buf_exit, status),
+				            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+				success = TRUE;
+				goto out;
+			}
+			if (ret == -1) {
+				errsv = errno;
+				/* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
+				if (errsv != ECHILD) {
+					nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s, waitpid failed with %s (%d)%s",
+					            LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
+					           was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+					goto out;
+				}
+			}
+
+			if (!wait_until)
+				break;
+
+			now = nm_utils_get_monotonic_timestamp_us ();
+			if (now >= wait_until)
+				break;
+
+			if (!was_waiting) {
+				nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting up to %ld milliseconds for process to terminate normally after sending %s...",
+				            LOG_NAME_ARGS, (long) MAX (wait_before_kill_msec, 0), _kc_signal_to_string (sig));
+				was_waiting = TRUE;
+			}
+
+			sleep_time = MIN (wait_until - now, sleep_duration_usec);
+			if (loop_count < 20) {
+				/* At the beginning we expect the process to die fast.
+				 * Limit the sleep time, the limit doubles with every iteration. */
+				sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
+				loop_count++;
+			}
+			g_usleep (sleep_time);
+		}
+
+		/* send SIGKILL, if called with @wait_before_kill_msec > 0 */
+		if (wait_until) {
+			nm_log_dbg (log_domain, LOG_NAME_FMT ": sending SIGKILL...", LOG_NAME_ARGS);
+
+			send_kill = TRUE;
+			if (kill (pid, SIGKILL) != 0) {
+				errsv = errno;
+				/* ESRCH means, process does not exist or is already a zombie. */
+				if (errsv != ESRCH) {
+					nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send SIGKILL (after sending %s), %s (%d)",
+								LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
+					goto out;
+				}
+			}
+		}
+	}
+
+	if (!was_waiting) {
+		nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting for process to terminate after sending %s%s...",
+		            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "");
+	}
+
+	/* block until the child terminates. */
+	while ((ret = waitpid (pid, &status, 0)) <= 0) {
+		errsv = errno;
+
+		if (errsv != EINTR) {
+			nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s%s, waitpid failed with %s (%d)%s",
+			            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", strerror (errsv), errsv,
+			            _kc_waited_to_string (buf_wait, wait_start_us));
+			goto out;
+		}
+	}
+
+	nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s%s, process %ld exited %s%s",
+	            LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", (long) ret,
+	            _kc_exit_to_string (buf_exit, status), _kc_waited_to_string (buf_wait, wait_start_us));
+	success = TRUE;
+out:
+	if (child_status)
+		*child_status = success ? status : -1;
+	errno = success ? 0 : errsv;
+	return success;
+}
+
+/* nm_utils_kill_process_sync:
+ * @pid: process id to kill
+ * @start_time: the start time of the process to kill (as obtained by nm_utils_get_start_time_for_pid()).
+ *   This is an optional argument, to avoid (somewhat) killing the wrong process as @pid
+ *   might get recycled. You can pass 0, to not provide this parameter.
+ * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
+ *   second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
+ * @log_domain: log debug information for this domain. Errors and warnings are logged both
+ *   as %LOGD_CORE and @log_domain.
+ * @log_name: name of the process to kill for logging.
+ * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
+ *   to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has no effect.
+ *   If @max_wait_msec is set but less then @wait_before_kill_msec, the final %SIGKILL will also
+ *   not be send.
+ * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
+ *   Set to zero, to use the default (meaning 20 wakeups per seconds).
+ * @max_wait_msec: if 0, waits indefinitely until the process is gone (or a zombie). Otherwise, this
+ *   is the maxium wait time until returning. If @max_wait_msec is non-zero but smaller then @wait_before_kill_msec,
+ *   we will not send a final %SIGKILL.
+ *
+ * Kill a non-child process synchronously and wait. This function will not return before the
+ * process with PID @pid is gone, the process is a zombie, or @max_wait_msec expires.
+ **/
+void
+nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain log_domain,
+                            const char *log_name, guint32 wait_before_kill_msec,
+                            guint32 sleep_duration_msec, guint32 max_wait_msec)
+{
+	int errsv;
+	guint64 start_time0;
+	gint64 wait_until_sigkill, now, wait_start_us, max_wait_until;
+	gulong sleep_time, sleep_duration_usec;
+	int loop_count = 0;
+	gboolean was_waiting = FALSE;
+	char buf_wait[KC_WAITED_TO_STRING];
+	char p_state;
+
+	g_return_if_fail (pid > 0);
+	g_return_if_fail (log_name != NULL);
+	g_return_if_fail (wait_before_kill_msec > 0);
+
+	start_time0 = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
+	if (start_time0 == 0) {
+		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it seems already gone",
+		            LOG_NAME_ARGS, (long int) pid);
+		return;
+	}
+	if (start_time != 0 && start_time != start_time0) {
+		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": don't kill process %ld because the start_time is unexpectedly %lu instead of %ld",
+		            LOG_NAME_ARGS, (long int) pid, (long unsigned) start_time0, (long unsigned) start_time);
+		return;
+	}
+
+	switch (p_state) {
+	case 'Z':
+	case 'x':
+	case 'X':
+		nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it is already a zombie (%c)",
+		            LOG_NAME_ARGS, (long int) pid, p_state);
+		return;
+	default:
+		break;
+	}
+
+	if (kill (pid, sig) != 0) {
+		errsv = errno;
+		/* ESRCH means, process does not exist or is already a zombie. */
+		if (errsv == ESRCH) {
+			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s because process seems gone",
+			            LOG_NAME_ARGS, _kc_signal_to_string (sig));
+		} else {
+			nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s: %s (%d)",
+			             LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
+		}
+		return;
+	}
+
+	/* wait for the process to terminated... */
+
+	wait_start_us = nm_utils_get_monotonic_timestamp_us ();
+
+	sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
+	if (sig != SIGKILL)
+		wait_until_sigkill = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
+	else
+		wait_until_sigkill = 0;
+	if (max_wait_msec > 0) {
+		max_wait_until = wait_start_us + (((gint64) max_wait_msec) * 1000L);
+		if (wait_until_sigkill > 0 && wait_until_sigkill > max_wait_msec)
+			wait_until_sigkill = 0;
+	} else
+		max_wait_until = 0;
+
+	while (TRUE) {
+		start_time = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
+
+		if (start_time != start_time0) {
+			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone after sending signal %s%s",
+			            LOG_NAME_ARGS, _kc_signal_to_string (sig),
+			            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+			return;
+		}
+		switch (p_state) {
+		case 'Z':
+		case 'x':
+		case 'X':
+			nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is a zombie (%c) after sending signal %s%s",
+			            LOG_NAME_ARGS, p_state, _kc_signal_to_string (sig),
+			            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+			return;
+		default:
+			break;
+		}
+
+		if (kill (pid, 0) != 0) {
+			errsv = errno;
+			/* ESRCH means, process does not exist or is already a zombie. */
+			if (errsv == ESRCH) {
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie after sending signal %s%s",
+				            LOG_NAME_ARGS, _kc_signal_to_string (sig),
+				            was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+			} else {
+				nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to kill(%ld, 0): %s (%d)%s",
+				             LOG_NAME_ARGS, (long int) pid, strerror (errsv), errsv,
+				             was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+			}
+			return;
+		}
+
+		sleep_time = sleep_duration_usec;
+		now = nm_utils_get_monotonic_timestamp_us ();
+
+		if (   max_wait_until != 0
+		    && now >= max_wait_until) {
+			if (wait_until_sigkill != 0) {
+				/* wait_before_kill_msec is not larger then max_wait_until but we did not yet send
+				 * SIGKILL. Although we already reached our timeout, we don't want to skip sending
+				 * the signal. Even if we don't wait for the process to disappear. */
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
+				kill (pid, SIGKILL);
+			}
+			nm_log_warn (log_domain, LOG_NAME_PROCESS_FMT ": timeout %u msec waiting for process to disappear (after sending %s)%s",
+			             LOG_NAME_ARGS, (unsigned) max_wait_until, _kc_signal_to_string (sig),
+			             was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
+			return;
+		}
+
+		if (wait_until_sigkill != 0) {
+			if (now >= wait_until_sigkill) {
+				/* Still not dead. SIGKILL now... */
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
+				if (kill (pid, SIGKILL) != 0) {
+					errsv = errno;
+					/* ESRCH means, process does not exist or is already a zombie. */
+					if (errsv != ESRCH) {
+						nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie%s",
+						            LOG_NAME_ARGS, _kc_waited_to_string (buf_wait, wait_start_us));
+					} else {
+						nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send SIGKILL (after sending %s), %s (%d)%s",
+						             LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
+						             _kc_waited_to_string (buf_wait, wait_start_us));
+					}
+					return;
+				}
+				sig = SIGKILL;
+				wait_until_sigkill = 0;
+				loop_count = 0; /* reset the loop_count. Now we really expect the process to die quickly. */
+			} else
+				sleep_time = MIN (wait_until_sigkill - now, sleep_duration_usec);
+		}
+
+		if (!was_waiting) {
+			if (wait_until_sigkill != 0) {
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear before sending KILL signal after sending %s...",
+				            LOG_NAME_ARGS, (long) wait_before_kill_msec, _kc_signal_to_string (sig));
+			} else if (max_wait_until != 0) {
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear after sending %s...",
+				            LOG_NAME_ARGS, (long) max_wait_msec, _kc_signal_to_string (sig));
+			} else {
+				nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting for process to disappear after sending %s...",
+				            LOG_NAME_ARGS, _kc_signal_to_string (sig));
+			}
+			was_waiting = TRUE;
+		}
+
+		if (loop_count < 20) {
+			/* At the beginning we expect the process to die fast.
+			 * Limit the sleep time, the limit doubles with every iteration. */
+			sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
+			loop_count++;
+		}
+		g_usleep (sleep_time);
+	}
+}
+#undef LOG_NAME_FMT
+#undef LOG_NAME_PROCESS_FMT
+#undef LOG_NAME_ARGS
+
+const char *const NM_PATHS_DEFAULT[] = {
+	PREFIX "/sbin/",
+	PREFIX "/bin/",
+	"/sbin/",
+	"/usr/sbin/",
+	"/usr/local/sbin/",
+	"/bin/",
+	"/usr/bin/",
+	"/usr/local/bin/",
+	NULL,
+};
+
+const char *
+nm_utils_find_helper(const char *progname, const char *try_first, GError **error)
+{
+	return nm_utils_file_search_in_paths (progname, try_first, NM_PATHS_DEFAULT, G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error);
+}
+
+/******************************************************************************************/
+
+#define MAC_TAG "mac:"
+#define INTERFACE_NAME_TAG "interface-name:"
+#define DEVICE_TYPE_TAG "type:"
+#define SUBCHAN_TAG "s390-subchannels:"
+#define EXCEPT_TAG "except:"
+#define MATCH_TAG_CONFIG_NM_VERSION             "nm-version:"
+#define MATCH_TAG_CONFIG_NM_VERSION_MIN         "nm-version-min:"
+#define MATCH_TAG_CONFIG_NM_VERSION_MAX         "nm-version-max:"
+#define MATCH_TAG_CONFIG_ENV                    "env:"
+
+#define _spec_has_prefix(pspec, tag) \
+	({ \
+		const char **_spec = (pspec); \
+		gboolean _has = FALSE; \
+		\
+		if (!g_ascii_strncasecmp (*_spec, (""tag), NM_STRLEN (tag))) { \
+			*_spec += NM_STRLEN (tag); \
+			_has = TRUE; \
+		} \
+		_has; \
+	})
+
+static const char *
+_match_except (const char *spec_str, gboolean *out_except)
+{
+	if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, NM_STRLEN (EXCEPT_TAG))) {
+		spec_str += NM_STRLEN (EXCEPT_TAG);
+		*out_except = TRUE;
+	} else
+		*out_except = FALSE;
+	return spec_str;
+}
+
+NMMatchSpecMatchType
+nm_match_spec_device_type (const GSList *specs, const char *device_type)
+{
+	const GSList *iter;
+	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+	if (!device_type || !*device_type)
+		return NM_MATCH_SPEC_NO_MATCH;
+
+	for (iter = specs; iter; iter = g_slist_next (iter)) {
+		const char *spec_str = iter->data;
+		gboolean except;
+
+		if (!spec_str || !*spec_str)
+			continue;
+
+		spec_str = _match_except (spec_str, &except);
+
+		if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)) != 0)
+			continue;
+
+		spec_str += NM_STRLEN (DEVICE_TYPE_TAG);
+		if (strcmp (spec_str, device_type) == 0) {
+			if (except)
+				return NM_MATCH_SPEC_NEG_MATCH;
+			match = NM_MATCH_SPEC_MATCH;
+		}
+	}
+	return match;
+}
+
+NMMatchSpecMatchType
+nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
+{
+	const GSList *iter;
+	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+	g_return_val_if_fail (hwaddr != NULL, NM_MATCH_SPEC_NO_MATCH);
+
+	for (iter = specs; iter; iter = g_slist_next (iter)) {
+		const char *spec_str = iter->data;
+		gboolean except;
+
+		if (!spec_str || !*spec_str)
+			continue;
+
+		spec_str = _match_except (spec_str, &except);
+
+		if (   !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))
+		    || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
+		    || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
+			continue;
+
+		if (!g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG)))
+			spec_str += NM_STRLEN (MAC_TAG);
+		else if (except)
+			continue;
+
+		if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) {
+			if (except)
+				return NM_MATCH_SPEC_NEG_MATCH;
+			match = NM_MATCH_SPEC_MATCH;
+		}
+	}
+	return match;
+}
+
+NMMatchSpecMatchType
+nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
+{
+	const GSList *iter;
+	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+	g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH);
+
+	for (iter = specs; iter; iter = g_slist_next (iter)) {
+		const char *spec_str = iter->data;
+		gboolean use_pattern = FALSE;
+		gboolean except;
+
+		if (!spec_str || !*spec_str)
+			continue;
+
+		spec_str = _match_except (spec_str, &except);
+
+		if (   !g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG))
+		    || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
+		    || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
+			continue;
+
+		if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))) {
+			spec_str += NM_STRLEN (INTERFACE_NAME_TAG);
+			if (spec_str[0] == '=')
+				spec_str += 1;
+			else {
+				if (spec_str[0] == '~')
+					spec_str += 1;
+				use_pattern=TRUE;
+			}
+		} else if (except)
+			continue;
+
+		if (   !strcmp (spec_str, interface_name)
+		    || (use_pattern && g_pattern_match_simple (spec_str, interface_name))) {
+			if (except)
+				return NM_MATCH_SPEC_NEG_MATCH;
+			match = NM_MATCH_SPEC_MATCH;
+		}
+	}
+	return match;
+}
+
+#define BUFSIZE 10
+
+static gboolean
+parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
+{
+	long unsigned int tmp;
+	char buf[BUFSIZE + 1];
+	const char *p = subchannels;
+	int i = 0;
+	char *pa = NULL, *pb = NULL, *pc = NULL;
+
+	g_return_val_if_fail (subchannels != NULL, FALSE);
+	g_return_val_if_fail (a != NULL, FALSE);
+	g_return_val_if_fail (*a == 0, FALSE);
+	g_return_val_if_fail (b != NULL, FALSE);
+	g_return_val_if_fail (*b == 0, FALSE);
+	g_return_val_if_fail (c != NULL, FALSE);
+	g_return_val_if_fail (*c == 0, FALSE);
+
+	/* sanity check */
+	if (!g_ascii_isxdigit (subchannels[0]))
+		return FALSE;
+
+	/* Get the first channel */
+	while (*p && (*p != ',')) {
+		if (!g_ascii_isxdigit (*p) && (*p != '.'))
+			return FALSE;  /* Invalid chars */
+		if (i >= BUFSIZE)
+			return FALSE;  /* Too long to be a subchannel */
+		buf[i++] = *p++;
+	}
+	buf[i] = '\0';
+
+	/* and grab each of its elements, there should be 3 */
+	pa = &buf[0];
+	pb = strchr (buf, '.');
+	if (pb)
+		pc = strchr (pb + 1, '.');
+	if (!pa || !pb || !pc)
+		return FALSE;
+
+	/* Split the string */
+	*pb++ = '\0';
+	*pc++ = '\0';
+
+	errno = 0;
+	tmp = strtoul (pa, NULL, 16);
+	if (errno)
+		return FALSE;
+	*a = (guint32) tmp;
+
+	errno = 0;
+	tmp = strtoul (pb, NULL, 16);
+	if (errno)
+		return FALSE;
+	*b = (guint32) tmp;
+
+	errno = 0;
+	tmp = strtoul (pc, NULL, 16);
+	if (errno)
+		return FALSE;
+	*c = (guint32) tmp;
+
+	return TRUE;
+}
+
+NMMatchSpecMatchType
+nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
+{
+	const GSList *iter;
+	guint32 a = 0, b = 0, c = 0;
+	guint32 spec_a = 0, spec_b = 0, spec_c = 0;
+	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+	g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH);
+
+	if (!specs)
+		return NM_MATCH_SPEC_NO_MATCH;
+
+	if (!parse_subchannels (subchannels, &a, &b, &c))
+		return NM_MATCH_SPEC_NO_MATCH;
+
+	for (iter = specs; iter; iter = g_slist_next (iter)) {
+		const char *spec_str = iter->data;
+		gboolean except;
+
+		if (!spec_str || !*spec_str)
+			continue;
+
+		spec_str = _match_except (spec_str, &except);
+
+		if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))) {
+			spec_str += NM_STRLEN (SUBCHAN_TAG);
+			if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) {
+				if (a == spec_a && b == spec_b && c == spec_c) {
+					if (except)
+						return NM_MATCH_SPEC_NEG_MATCH;
+					match = NM_MATCH_SPEC_MATCH;
+				}
+			}
+		}
+	}
+	return match;
+}
+
+static gboolean
+_match_config_nm_version (const char *str, const char *tag, guint cur_nm_version)
+{
+	gs_free char *s_ver = NULL;
+	gs_strfreev char **s_ver_tokens = NULL;
+	gint v_maj = -1, v_min = -1, v_mic = -1;
+	guint c_maj = -1, c_min = -1, c_mic = -1;
+	guint n_tokens;
+
+	s_ver = g_strdup (str);
+	g_strstrip (s_ver);
+
+	/* Let's be strict with the accepted format here. No funny stuff!! */
+
+	if (s_ver[strspn (s_ver, ".0123456789")] != '\0')
+		return FALSE;
+
+	s_ver_tokens = g_strsplit (s_ver, ".", -1);
+	n_tokens = g_strv_length (s_ver_tokens);
+	if (n_tokens == 0 || n_tokens > 3)
+		return FALSE;
+
+	v_maj = _nm_utils_ascii_str_to_int64 (s_ver_tokens[0], 10, 0, 0xFFFF, -1);
+	if (v_maj < 0)
+		return FALSE;
+	if (n_tokens >= 2) {
+		v_min = _nm_utils_ascii_str_to_int64 (s_ver_tokens[1], 10, 0, 0xFF, -1);
+		if (v_min < 0)
+			return FALSE;
+	}
+	if (n_tokens >= 3) {
+		v_mic = _nm_utils_ascii_str_to_int64 (s_ver_tokens[2], 10, 0, 0xFF, -1);
+		if (v_mic < 0)
+			return FALSE;
+	}
+
+	nm_decode_version (cur_nm_version, &c_maj, &c_min, &c_mic);
+
+#define CHECK_AND_RETURN_FALSE(cur, val, tag, is_last_digit) \
+	G_STMT_START { \
+		if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MIN)) { \
+			if (cur < val) \
+				return FALSE; \
+		} else if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MAX)) { \
+			if (cur > val) \
+				return FALSE; \
+		} else { \
+			if (cur != val) \
+				return FALSE; \
+		} \
+		if (!(is_last_digit)) { \
+			if (cur != val) \
+				return FALSE; \
+		} \
+	} G_STMT_END
+	if (v_mic >= 0)
+		CHECK_AND_RETURN_FALSE (c_mic, v_mic, tag, TRUE);
+	if (v_min >= 0)
+		CHECK_AND_RETURN_FALSE (c_min, v_min, tag, v_mic < 0);
+	CHECK_AND_RETURN_FALSE (c_maj, v_maj, tag, v_min < 0);
+	return TRUE;
+}
+
+NMMatchSpecMatchType
+nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env)
+{
+	const GSList *iter;
+	NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+	if (!specs)
+		return NM_MATCH_SPEC_NO_MATCH;
+
+	for (iter = specs; iter; iter = g_slist_next (iter)) {
+		const char *spec_str = iter->data;
+		gboolean except;
+		gboolean v_match;
+
+		if (!spec_str || !*spec_str)
+			continue;
+
+		spec_str = _match_except (spec_str, &except);
+
+		if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION))
+			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
+		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
+			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
+		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
+			v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
+		else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV))
+			v_match = env && env[0] && !strcmp (spec_str, env);
+		else
+			continue;
+
+		if (v_match) {
+			if (except)
+				return NM_MATCH_SPEC_NEG_MATCH;
+			match = NM_MATCH_SPEC_MATCH;
+		}
+	}
+	return match;
+}
+
+/**
+ * nm_match_spec_split:
+ * @value: the string of device specs
+ *
+ * Splits the specs from the string and returns them as individual
+ * entires in a #GSList.
+ *
+ * It does not validate any specs, it basically just does a special
+ * strsplit with ',' or ';' as separators and supporting '\\' as
+ * escape character.
+ *
+ * Leading and trailing spaces of each entry are removed. But the user
+ * can preserve them by specifying "\\s has 2 leading" or "has 2 trailing \\s".
+ *
+ * Specs can have a qualifier like "interface-name:". We still don't strip
+ * any whitespace after the colon, so "interface-name: X" matches an interface
+ * named " X".
+ *
+ * Returns: (transfer full): the list of device specs.
+ */
+GSList *
+nm_match_spec_split (const char *value)
+{
+	char *string_value, *p, *q0, *q;
+	GSList *pieces = NULL;
+	int trailing_ws;
+
+	if (!value || !*value)
+		return NULL;
+
+	/* Copied from glibs g_key_file_parse_value_as_string() function
+	 * and adjusted. */
+
+	string_value = g_new (gchar, strlen (value) + 1);
+
+	p = (gchar *) value;
+
+	/* skip over leading whitespace */
+	while (g_ascii_isspace (*p))
+		p++;
+
+	q0 = q = string_value;
+	trailing_ws = 0;
+	while (*p) {
+		if (*p == '\\') {
+			p++;
+
+			switch (*p) {
+			case 's':
+				*q = ' ';
+				break;
+			case 'n':
+				*q = '\n';
+				break;
+			case 't':
+				*q = '\t';
+				break;
+			case 'r':
+				*q = '\r';
+				break;
+			case '\\':
+				*q = '\\';
+				break;
+			case '\0':
+				break;
+			default:
+				if (NM_IN_SET (*p, ',', ';'))
+					*q = *p;
+				else {
+					*q++ = '\\';
+					*q = *p;
+				}
+				break;
+			}
+			if (*p == '\0')
+				break;
+			p++;
+			trailing_ws = 0;
+		} else {
+			*q = *p;
+			if (*p == '\0')
+				break;
+			if (g_ascii_isspace (*p)) {
+				trailing_ws++;
+				p++;
+			} else if (NM_IN_SET (*p, ',', ';')) {
+				if (q0 < q - trailing_ws)
+					pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
+				q0 = q + 1;
+				p++;
+				trailing_ws = 0;
+				while (g_ascii_isspace (*p))
+					p++;
+			} else
+				p++;
+		}
+		q++;
+	}
+
+	*q = '\0';
+	if (q0 < q - trailing_ws)
+		pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
+	g_free (string_value);
+	return g_slist_reverse (pieces);
+}
+
+/**
+ * nm_match_spec_join:
+ * @specs: the device specs to join
+ *
+ * This is based on g_key_file_parse_string_as_value(), analog to
+ * nm_match_spec_split() which is based on g_key_file_parse_value_as_string().
+ *
+ * Returns: (transfer full): a joined list of device specs that can be
+ *   split again with nm_match_spec_split(). Note that
+ *   nm_match_spec_split (nm_match_spec_join (specs)) yields the original
+ *   result (which is not true the other way around because there are multiple
+ *   ways to encode the same joined specs string).
+ */
+char *
+nm_match_spec_join (GSList *specs)
+{
+	const char *p;
+	GString *str;
+
+	str = g_string_new ("");
+
+	for (; specs; specs = specs->next) {
+		p = specs->data;
+
+		if (!p || !*p)
+			continue;
+
+		if (str->len > 0)
+			g_string_append_c (str, ',');
+
+		/* escape leading whitespace */
+		switch (*p) {
+		case ' ':
+			g_string_append (str, "\\s");
+			p++;
+			break;
+		case '\t':
+			g_string_append (str, "\\t");
+			p++;
+			break;
+		}
+
+		for (; *p; p++) {
+			switch (*p) {
+			case '\n':
+				g_string_append (str, "\\n");
+				break;
+			case '\r':
+				g_string_append (str, "\\r");
+				break;
+			case '\\':
+				g_string_append (str, "\\\\");
+				break;
+			case ',':
+				g_string_append (str, "\\,");
+				break;
+			case ';':
+				g_string_append (str, "\\;");
+				break;
+			default:
+				g_string_append_c (str, *p);
+				break;
+			}
+		}
+
+		/* escape trailing whitespaces */
+		switch (str->str[str->len - 1]) {
+		case ' ':
+			g_string_overwrite (str, str->len - 1, "\\s");
+			break;
+		case '\t':
+			g_string_overwrite (str, str->len - 1, "\\t");
+			break;
+		}
+	}
+
+	return g_string_free (str, FALSE);
+}
+
+/*****************************************************************************/
+
+char _nm_utils_to_string_buffer[];
+
+void
+nm_utils_to_string_buffer_init (char **buf, gsize *len)
+{
+	if (!*buf) {
+		*buf = _nm_utils_to_string_buffer;
+		*len = sizeof (_nm_utils_to_string_buffer);
+	}
+}
+
+gboolean
+nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len)
+{
+	nm_utils_to_string_buffer_init (buf, len);
+	if (!obj) {
+		g_strlcpy (*buf, "(null)", *len);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+void
+nm_utils_strbuf_append_c (char **buf, gsize *len, char c)
+{
+	switch (*len) {
+	case 0:
+		return;
+	case 1:
+		(*buf)[0] = '\0';
+		*len = 0;
+		(*buf)++;
+		return;
+	default:
+		(*buf)[0] = c;
+		(*buf)[1] = '\0';
+		(*len)--;
+		(*buf)++;
+		return;
+	}
+}
+
+void
+nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str)
+{
+	gsize src_len;
+
+	switch (*len) {
+	case 0:
+		return;
+	case 1:
+		if (!str || !*str) {
+			(*buf)[0] = '\0';
+			return;
+		}
+		(*buf)[0] = '\0';
+		*len = 0;
+		(*buf)++;
+		return;
+	default:
+		if (!str || !*str) {
+			(*buf)[0] = '\0';
+			return;
+		}
+		src_len = g_strlcpy (*buf, str, *len);
+		if (src_len >= *len) {
+			*buf = &(*buf)[*len];
+			*len = 0;
+		} else {
+			*buf = &(*buf)[src_len];
+			*len -= src_len;
+		}
+		return;
+	}
+}
+
+void
+nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
+{
+	char *p = *buf;
+	va_list args;
+	gint retval;
+
+	if (*len == 0)
+		return;
+
+	va_start (args, format);
+	retval = g_vsnprintf (p, *len, format, args);
+	va_end (args);
+
+	if (retval >= *len) {
+		*buf = &p[*len];
+		*len = 0;
+	} else {
+		*buf = &p[retval];
+		*len -= retval;
+	}
+}
+
+const char *
+nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
+                    gsize n_descs,
+                    unsigned flags,
+                    char *buf,
+                    gsize len)
+{
+	gsize i;
+	char *p;
+
+#if NM_MORE_ASSERTS > 10
+	nm_assert (descs);
+	nm_assert (n_descs > 0);
+	for (i = 0; i < n_descs; i++) {
+		gsize j;
+
+		nm_assert (descs[i].flag && nm_utils_is_power_of_two (descs[i].flag));
+		nm_assert (descs[i].name && descs[i].name[0]);
+		for (j = 0; j < i; j++)
+			nm_assert (descs[j].flag != descs[i].flag);
+	}
+#endif
+
+	nm_utils_to_string_buffer_init (&buf, &len);
+
+	if (!len)
+		return buf;
+
+	buf[0] = '\0';
+	if (!flags) {
+		return buf;
+	}
+
+	p = buf;
+	for (i = 0; flags && i < n_descs; i++) {
+		if (NM_FLAGS_HAS (flags, descs[i].flag)) {
+			flags &= ~descs[i].flag;
+
+			if (buf[0] != '\0')
+				nm_utils_strbuf_append_c (&p, &len, ',');
+			nm_utils_strbuf_append_str (&p, &len, descs[i].name);
+		}
+	}
+	if (flags) {
+		if (buf[0] != '\0')
+			nm_utils_strbuf_append_c (&p, &len, ',');
+		nm_utils_strbuf_append (&p, &len, "0x%x", flags);
+	}
+	return buf;
+};
+
+/*****************************************************************************/
+
+char *
+nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id)
+{
+	guint id_len;
+	gsize parent_len;
+	char *ifname;
+
+	g_return_val_if_fail (parent_iface && *parent_iface, NULL);
+
+	if (vlan_id < 10)
+		id_len = 2;
+	else if (vlan_id < 100)
+		id_len = 3;
+	else if (vlan_id < 1000)
+		id_len = 4;
+	else {
+		g_return_val_if_fail (vlan_id < 4095, NULL);
+		id_len = 5;
+	}
+
+	ifname = g_new (char, IFNAMSIZ);
+
+	parent_len = strlen (parent_iface);
+	parent_len = MIN (parent_len, IFNAMSIZ - 1 - id_len);
+	memcpy (ifname, parent_iface, parent_len);
+	g_snprintf (&ifname[parent_len], IFNAMSIZ - parent_len, ".%u", vlan_id);
+
+	return ifname;
+}
+
+/**
+ * nm_utils_read_resolv_conf_nameservers():
+ * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
+ *
+ * Reads all nameservers out of @rc_contents or /etc/resolv.conf and returns
+ * them.
+ *
+ * Returns: a #GPtrArray of 'char *' elements of each nameserver line from
+ * @contents or resolv.conf
+ */
+GPtrArray *
+nm_utils_read_resolv_conf_nameservers (const char *rc_contents)
+{
+	GPtrArray *nameservers = NULL;
+	char *contents = NULL;
+	char **lines, **iter;
+	char *p;
+
+	if (rc_contents)
+		contents = g_strdup (rc_contents);
+	else {
+		if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
+			return NULL;
+	}
+
+	nameservers = g_ptr_array_new_full (3, g_free);
+
+	lines = g_strsplit_set (contents, "\r\n", -1);
+	for (iter = lines; *iter; iter++) {
+		if (!g_str_has_prefix (*iter, "nameserver"))
+			continue;
+		p = *iter + strlen ("nameserver");
+		if (!g_ascii_isspace (*p++))
+			continue;
+		/* Skip intermediate whitespace */
+		while (g_ascii_isspace (*p))
+			p++;
+		g_strchomp (p);
+
+		g_ptr_array_add (nameservers, g_strdup (p));
+	}
+	g_strfreev (lines);
+	g_free (contents);
+
+	return nameservers;
+}
+
+/**
+ * nm_utils_read_resolv_conf_dns_options():
+ * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
+ *
+ * Reads all dns options out of @rc_contents or /etc/resolv.conf and returns
+ * them.
+ *
+ * Returns: a #GPtrArray of 'char *' elements of each option
+ */
+GPtrArray *
+nm_utils_read_resolv_conf_dns_options (const char *rc_contents)
+{
+	GPtrArray *options = NULL;
+	char *contents = NULL;
+	char **lines, **line_iter;
+	char **tokens, **token_iter;
+	char *p;
+
+	if (rc_contents)
+		contents = g_strdup (rc_contents);
+	else {
+		if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
+			return NULL;
+	}
+
+	options = g_ptr_array_new_full (3, g_free);
+
+	lines = g_strsplit_set (contents, "\r\n", -1);
+	for (line_iter = lines; *line_iter; line_iter++) {
+		if (!g_str_has_prefix (*line_iter, "options"))
+			continue;
+		p = *line_iter + strlen ("options");
+		if (!g_ascii_isspace (*p++))
+			continue;
+
+		tokens = g_strsplit (p, " ", 0);
+		for (token_iter = tokens; token_iter && *token_iter; token_iter++) {
+			g_strstrip (*token_iter);
+			if (!*token_iter[0])
+				continue;
+			g_ptr_array_add (options, g_strdup (*token_iter));
+		}
+		g_strfreev (tokens);
+	}
+	g_strfreev (lines);
+	g_free (contents);
+
+	return options;
+}
+
+int
+nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b)
+{
+	NMSettingConnection *a_s_con, *b_s_con;
+	gboolean a_ac, b_ac;
+	gint a_ap, b_ap;
+
+	a_s_con = nm_connection_get_setting_connection (*a);
+	b_s_con = nm_connection_get_setting_connection (*b);
+
+	a_ac = !!nm_setting_connection_get_autoconnect (a_s_con);
+	b_ac = !!nm_setting_connection_get_autoconnect (b_s_con);
+	if (a_ac != b_ac)
+		return ((int) b_ac) - ((int) a_ac);
+	if (!a_ac)
+		return 0;
+
+	a_ap = nm_setting_connection_get_autoconnect_priority (a_s_con);
+	b_ap = nm_setting_connection_get_autoconnect_priority (b_s_con);
+	if (a_ap != b_ap)
+		return (a_ap > b_ap) ? -1 : 1;
+
+	return 0;
+}
+
+/**************************************************************************/
+
+static gint64 monotonic_timestamp_offset_sec;
+static int monotonic_timestamp_clock_mode = 0;
+
+static void
+monotonic_timestamp_get (struct timespec *tp)
+{
+	int clock_mode = 0;
+	int err = 0;
+
+	switch (monotonic_timestamp_clock_mode) {
+	case 0:
+		/* the clock is not yet initialized (first run) */
+		err = clock_gettime (CLOCK_BOOTTIME, tp);
+		if (err == -1 && errno == EINVAL) {
+			clock_mode = 2;
+			err = clock_gettime (CLOCK_MONOTONIC, tp);
+		} else
+			clock_mode = 1;
+		break;
+	case 1:
+		/* default, return CLOCK_BOOTTIME */
+		err = clock_gettime (CLOCK_BOOTTIME, tp);
+		break;
+	case 2:
+		/* fallback, return CLOCK_MONOTONIC. Kernels prior to 2.6.39
+		 * don't support CLOCK_BOOTTIME. */
+		err = clock_gettime (CLOCK_MONOTONIC, tp);
+		break;
+	}
+
+	g_assert (err == 0); (void)err;
+	g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND);
+
+	if (G_LIKELY (clock_mode == 0))
+		return;
+
+	/* Calculate an offset for the time stamp.
+	 *
+	 * We always want positive values, because then we can initialize
+	 * a timestamp with 0 and be sure, that it will be less then any
+	 * value nm_utils_get_monotonic_timestamp_*() might return.
+	 * For this to be true also for nm_utils_get_monotonic_timestamp_s() at
+	 * early boot, we have to shift the timestamp to start counting at
+	 * least from 1 second onward.
+	 *
+	 * Another advantage of shifting is, that this way we make use of the whole 31 bit
+	 * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s()
+	 * wraps (~68 years).
+	 **/
+	monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1;
+	monotonic_timestamp_clock_mode = clock_mode;
+
+	if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
+		time_t now = time (NULL);
+		struct tm tm;
+		char s[255];
+
+		strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
+		nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
+		                       "an offset of %lld.0 seconds to %s (local time is %s)",
+		                       tp->tv_nsec, (long long) -monotonic_timestamp_offset_sec,
+		                       clock_mode == 1 ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", s);
+	}
+}
+
+/**
+ * nm_utils_get_monotonic_timestamp_ns:
+ *
+ * Returns: a monotonically increasing time stamp in nanoseconds,
+ * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
+ *
+ * The returned value will start counting at an undefined point
+ * in the past and will always be positive.
+ *
+ * All the nm_utils_get_monotonic_timestamp_*s functions return the same
+ * timestamp but in different scales (nsec, usec, msec, sec).
+ **/
+gint64
+nm_utils_get_monotonic_timestamp_ns (void)
+{
+	struct timespec tp = { 0 };
+
+	monotonic_timestamp_get (&tp);
+
+	/* Although the result will always be positive, we return a signed
+	 * integer, which makes it easier to calculate time differences (when
+	 * you want to subtract signed values).
+	 **/
+	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * NM_UTILS_NS_PER_SECOND +
+	       tp.tv_nsec;
+}
+
+/**
+ * nm_utils_get_monotonic_timestamp_us:
+ *
+ * Returns: a monotonically increasing time stamp in microseconds,
+ * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
+ *
+ * The returned value will start counting at an undefined point
+ * in the past and will always be positive.
+ *
+ * All the nm_utils_get_monotonic_timestamp_*s functions return the same
+ * timestamp but in different scales (nsec, usec, msec, sec).
+ **/
+gint64
+nm_utils_get_monotonic_timestamp_us (void)
+{
+	struct timespec tp = { 0 };
+
+	monotonic_timestamp_get (&tp);
+
+	/* Although the result will always be positive, we return a signed
+	 * integer, which makes it easier to calculate time differences (when
+	 * you want to subtract signed values).
+	 **/
+	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) G_USEC_PER_SEC) +
+	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC));
+}
+
+/**
+ * nm_utils_get_monotonic_timestamp_ms:
+ *
+ * Returns: a monotonically increasing time stamp in milliseconds,
+ * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
+ *
+ * The returned value will start counting at an undefined point
+ * in the past and will always be positive.
+ *
+ * All the nm_utils_get_monotonic_timestamp_*s functions return the same
+ * timestamp but in different scales (nsec, usec, msec, sec).
+ **/
+gint64
+nm_utils_get_monotonic_timestamp_ms (void)
+{
+	struct timespec tp = { 0 };
+
+	monotonic_timestamp_get (&tp);
+
+	/* Although the result will always be positive, we return a signed
+	 * integer, which makes it easier to calculate time differences (when
+	 * you want to subtract signed values).
+	 **/
+	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) 1000) +
+	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
+}
+
+/**
+ * nm_utils_get_monotonic_timestamp_s:
+ *
+ * Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing
+ * away sub second parts). The returned value will always be positive.
+ *
+ * This value wraps after roughly 68 years which should be fine for any
+ * practical purpose.
+ *
+ * All the nm_utils_get_monotonic_timestamp_*s functions return the same
+ * timestamp but in different scales (nsec, usec, msec, sec).
+ **/
+gint32
+nm_utils_get_monotonic_timestamp_s (void)
+{
+	struct timespec tp = { 0 };
+
+	monotonic_timestamp_get (&tp);
+	return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec);
+}
+
+typedef struct
+{
+	const char *name;
+	NMSetting *setting;
+	NMSetting *diff_base_setting;
+	GHashTable *setting_diff;
+} LogConnectionSettingData;
+
+typedef struct
+{
+	const char *item_name;
+	NMSettingDiffResult diff_result;
+} LogConnectionSettingItem;
+
+static gint
+_log_connection_sort_hashes_fcn (gconstpointer a, gconstpointer b)
+{
+	const LogConnectionSettingData *v1 = a;
+	const LogConnectionSettingData *v2 = b;
+	guint32 p1, p2;
+	NMSetting *s1, *s2;
+
+	s1 = v1->setting ? v1->setting : v1->diff_base_setting;
+	s2 = v2->setting ? v2->setting : v2->diff_base_setting;
+
+	g_assert (s1 && s2);
+
+	p1 = _nm_setting_get_setting_priority (s1);
+	p2 = _nm_setting_get_setting_priority (s2);
+
+	if (p1 != p2)
+		return p1 > p2 ? 1 : -1;
+
+	return strcmp (v1->name, v2->name);
+}
+
+static GArray *
+_log_connection_sort_hashes (NMConnection *connection, NMConnection *diff_base, GHashTable *connection_diff)
+{
+	GHashTableIter iter;
+	GArray *sorted_hashes;
+	LogConnectionSettingData setting_data;
+
+	sorted_hashes = g_array_sized_new (TRUE, FALSE, sizeof (LogConnectionSettingData), g_hash_table_size (connection_diff));
+
+	g_hash_table_iter_init (&iter, connection_diff);
+	while (g_hash_table_iter_next (&iter, (gpointer) &setting_data.name, (gpointer) &setting_data.setting_diff)) {
+		setting_data.setting = nm_connection_get_setting_by_name (connection, setting_data.name);
+		setting_data.diff_base_setting = diff_base ? nm_connection_get_setting_by_name (diff_base, setting_data.name) : NULL;
+		g_assert (setting_data.setting || setting_data.diff_base_setting);
+		g_array_append_val (sorted_hashes, setting_data);
+	}
+
+	g_array_sort (sorted_hashes, _log_connection_sort_hashes_fcn);
+	return sorted_hashes;
+}
+
+static gint
+_log_connection_sort_names_fcn (gconstpointer a, gconstpointer b)
+{
+	const LogConnectionSettingItem *v1 = a;
+	const LogConnectionSettingItem *v2 = b;
+
+	/* we want to first show the items, that disappeared, then the one that changed and
+	 * then the ones that were added. */
+
+	if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_A))
+		return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) ? -1 : 1;
+	if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_B))
+		return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) ? 1 : -1;
+	return strcmp (v1->item_name, v2->item_name);
+}
+
+static char *
+_log_connection_get_property (NMSetting *setting, const char *name)
+{
+	GValue val = G_VALUE_INIT;
+	char *s;
+
+	g_return_val_if_fail (setting, NULL);
+
+	if (   !NM_IS_SETTING_VPN (setting)
+	    && nm_setting_get_secret_flags (setting, name, NULL, NULL))
+		return g_strdup ("****");
+
+	if (!_nm_setting_get_property (setting, name, &val))
+		g_return_val_if_reached (FALSE);
+
+	if (G_VALUE_HOLDS_STRING (&val)) {
+		const char *val_s;
+
+		val_s = g_value_get_string (&val);
+		if (!val_s) {
+			/* for NULL, we want to return the unquoted string "NULL". */
+			s = g_strdup ("NULL");
+		} else {
+			char *escaped = g_strescape (val_s, "'");
+
+			s = g_strdup_printf ("'%s'", escaped);
+			g_free (escaped);
+		}
+	} else {
+		s = g_strdup_value_contents (&val);
+		if (s == NULL)
+			s = g_strdup ("NULL");
+		else {
+			char *escaped = g_strescape (s, "'");
+
+			g_free (s);
+			s = escaped;
+		}
+	}
+	g_value_unset(&val);
+	return s;
+}
+
+static void
+_log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sorted_names)
+{
+	GHashTableIter iter;
+	LogConnectionSettingItem item;
+	gpointer p;
+
+	g_array_set_size (sorted_names, 0);
+
+	g_hash_table_iter_init (&iter, setting_data->setting_diff);
+	while (g_hash_table_iter_next (&iter, (gpointer) &item.item_name, &p)) {
+		item.diff_result = GPOINTER_TO_UINT (p);
+		g_array_append_val (sorted_names, item);
+	}
+
+	g_array_sort (sorted_names, _log_connection_sort_names_fcn);
+}
+
+void
+nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix)
+{
+	GHashTable *connection_diff = NULL;
+	GArray *sorted_hashes;
+	GArray *sorted_names = NULL;
+	int i, j;
+	gboolean connection_diff_are_same;
+	gboolean print_header = TRUE;
+	gboolean print_setting_header;
+	GString *str1;
+
+	g_return_if_fail (NM_IS_CONNECTION (connection));
+	g_return_if_fail (!diff_base || (NM_IS_CONNECTION (diff_base) && diff_base != connection));
+
+	/* For VPN setting types, this is broken, because we cannot (generically) print the content of data/secrets. Bummer... */
+
+	if (!nm_logging_enabled (level, domain))
+		return;
+
+	if (!prefix)
+		prefix = "";
+	if (!name)
+		name = "";
+
+	connection_diff_are_same = nm_connection_diff (connection, diff_base, NM_SETTING_COMPARE_FLAG_EXACT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, &connection_diff);
+	if (connection_diff_are_same) {
+		if (diff_base)
+			nm_log (level, domain, "%sconnection '%s' (%p/%s and %p/%s): no difference", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base));
+		else
+			nm_log (level, domain, "%sconnection '%s' (%p/%s): no properties set", prefix, name, connection, G_OBJECT_TYPE_NAME (connection));
+		g_assert (!connection_diff);
+		return;
+	}
+
+	/* FIXME: it doesn't nicely show the content of NMSettingVpn, becuase nm_connection_diff() does not
+	 * expand the hash values. */
+
+	sorted_hashes = _log_connection_sort_hashes (connection, diff_base, connection_diff);
+	if (sorted_hashes->len <= 0)
+		goto out;
+
+	sorted_names = g_array_new (FALSE, FALSE, sizeof (LogConnectionSettingItem));
+	str1 = g_string_new (NULL);
+
+	for (i = 0; i < sorted_hashes->len; i++) {
+		LogConnectionSettingData *setting_data = &g_array_index (sorted_hashes, LogConnectionSettingData, i);
+
+		_log_connection_sort_names (setting_data, sorted_names);
+		print_setting_header = TRUE;
+		for (j = 0; j < sorted_names->len; j++) {
+			char *str_conn, *str_diff;
+			LogConnectionSettingItem *item = &g_array_index (sorted_names, LogConnectionSettingItem, j);
+
+			str_conn = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_A)
+			           ? _log_connection_get_property (setting_data->setting, item->item_name)
+			           : NULL;
+			str_diff = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_B)
+			           ? _log_connection_get_property (setting_data->diff_base_setting, item->item_name)
+			           : NULL;
+
+			if (print_header) {
+				GError *err_verify = NULL;
+				const char *path = nm_connection_get_path (connection);
+
+				if (diff_base) {
+					nm_log (level, domain, "%sconnection '%s' (%p/%s < %p/%s)%s%s%s:", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base),
+					        NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
+				} else {
+					nm_log (level, domain, "%sconnection '%s' (%p/%s):%s%s%s", prefix, name, connection, G_OBJECT_TYPE_NAME (connection),
+					        NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
+				}
+				print_header = FALSE;
+
+				if (!nm_connection_verify (connection, &err_verify)) {
+					nm_log (level, domain, "%sconnection %p does not verify: %s", prefix, connection, err_verify->message);
+					g_clear_error (&err_verify);
+				}
+			}
+#define _NM_LOG_ALIGN "-25"
+			if (print_setting_header) {
+				if (diff_base) {
+					if (setting_data->setting && setting_data->diff_base_setting)
+						g_string_printf (str1, "%p < %p", setting_data->setting, setting_data->diff_base_setting);
+					else if (setting_data->diff_base_setting)
+						g_string_printf (str1, "*missing* < %p", setting_data->diff_base_setting);
+					else
+						g_string_printf (str1, "%p < *missing*", setting_data->setting);
+					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %s ]", prefix, setting_data->name, str1->str);
+				} else
+					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %p ]", prefix, setting_data->name, setting_data->setting);
+				print_setting_header = FALSE;
+			}
+			g_string_printf (str1, "%s.%s", setting_data->name, item->item_name);
+			switch (item->diff_result & (NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B)) {
+				case NM_SETTING_DIFF_RESULT_IN_B:
+					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s < %s", prefix, str1->str, str_diff ? str_diff : "NULL");
+					break;
+				case NM_SETTING_DIFF_RESULT_IN_A:
+					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s", prefix, str1->str, str_conn ? str_conn : "NULL");
+					break;
+				default:
+					nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s < %s", prefix, str1->str, str_conn ? str_conn : "NULL", str_diff ? str_diff : "NULL");
+					break;
+#undef _NM_LOG_ALIGN
+			}
+			g_free (str_conn);
+			g_free (str_diff);
+		}
+	}
+
+	g_array_free (sorted_names, TRUE);
+	g_string_free (str1, TRUE);
+out:
+	g_hash_table_destroy (connection_diff);
+	g_array_free (sorted_hashes, TRUE);
+}
+
+/**
+ * nm_utils_monotonic_timestamp_as_boottime:
+ * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME.
+ * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if
+ * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano
+ * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc.
+ *
+ * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime().
+ * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick.
+ * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds.
+ * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp
+ * is always positive.
+ *
+ * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC.
+ **/
+gint64
+nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick)
+{
+	gint64 offset;
+
+	/* only support ns-per-tick being a multiple of 10. */
+	g_return_val_if_fail (timestamp_ns_per_tick == 1
+	                      || (timestamp_ns_per_tick > 0 &&
+	                          timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND &&
+	                          timestamp_ns_per_tick % 10 == 0),
+	                      -1);
+
+	/* Check that the timestamp is in a valid range. */
+	g_return_val_if_fail (timestamp >= 0, -1);
+
+	/* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful
+	 * value (because he has no idea what these timestamps would be). That would be a bug. */
+	g_return_val_if_fail (monotonic_timestamp_clock_mode != 0, -1);
+
+	/* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
+	offset = monotonic_timestamp_offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick);
+
+	/* check for overflow. */
+	g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64);
+
+	return timestamp - offset;
+}
+
+
+#define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/"
+#define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/"
+G_STATIC_ASSERT (sizeof (IPV4_PROPERTY_DIR) == sizeof (IPV6_PROPERTY_DIR));
+
+static const char *
+_get_property_path (const char *ifname,
+                    const char *property,
+                    gboolean ipv6)
+{
+	static char path[sizeof (IPV6_PROPERTY_DIR) + IFNAMSIZ + 32];
+	int len;
+
+	ifname = ASSERT_VALID_PATH_COMPONENT (ifname);
+	property = ASSERT_VALID_PATH_COMPONENT (property);
+
+	len = g_snprintf (path,
+	                  sizeof (path),
+	                  "%s%s/%s",
+	                  ipv6 ? IPV6_PROPERTY_DIR : IPV4_PROPERTY_DIR,
+	                  ifname,
+	                  property);
+	g_assert (len < sizeof (path) - 1);
+
+	return path;
+}
+
+/**
+ * nm_utils_ip6_property_path:
+ * @ifname: an interface name
+ * @property: a property name
+ *
+ * Returns the path to IPv6 property @property on @ifname. Note that
+ * this uses a static buffer.
+ */
+const char *
+nm_utils_ip6_property_path (const char *ifname, const char *property)
+{
+	return _get_property_path (ifname, property, TRUE);
+}
+
+/**
+ * nm_utils_ip4_property_path:
+ * @ifname: an interface name
+ * @property: a property name
+ *
+ * Returns the path to IPv4 property @property on @ifname. Note that
+ * this uses a static buffer.
+ */
+const char *
+nm_utils_ip4_property_path (const char *ifname, const char *property)
+{
+	return _get_property_path (ifname, property, FALSE);
+}
+
+gboolean
+nm_utils_is_valid_path_component (const char *name)
+{
+	const char *n;
+
+	if (name == NULL || name[0] == '\0')
+		return FALSE;
+
+	if (name[0] == '.') {
+		if (name[1] == '\0')
+			return FALSE;
+		if (name[1] == '.' && name[2] == '\0')
+			return FALSE;
+	}
+	n = name;
+	do {
+		if (*n == '/')
+			return FALSE;
+	} while (*(++n) != '\0');
+
+	return TRUE;
+}
+
+const char *
+ASSERT_VALID_PATH_COMPONENT (const char *name)
+{
+	if (G_LIKELY (nm_utils_is_valid_path_component (name)))
+		return name;
+
+	nm_log_err (LOGD_CORE, "Failed asserting path component: %s%s%s",
+	            NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
+	g_error ("FATAL: Failed asserting path component: %s%s%s",
+	         NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
+	g_assert_not_reached ();
+}
+
+gboolean
+nm_utils_is_specific_hostname (const char *name)
+{
+	if (!name)
+		return FALSE;
+	if (   strcmp (name, "(none)")
+	    && strcmp (name, "localhost")
+	    && strcmp (name, "localhost6")
+	    && strcmp (name, "localhost.localdomain")
+	    && strcmp (name, "localhost6.localdomain6"))
+		return TRUE;
+	return FALSE;
+}
+
+/******************************************************************/
+
+/* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
+static gboolean
+get_gre_eui64_u_bit (guint32 addr)
+{
+	static const struct {
+		guint32 mask;
+		guint32 result;
+	} items[] = {
+		{ 0xff000000 }, { 0x7f000000 },  /* IPv4 loopback */
+		{ 0xf0000000 }, { 0xe0000000 },  /* IPv4 multicast */
+		{ 0xffffff00 }, { 0xe0000000 },  /* IPv4 local multicast */
+		{ 0xffffffff }, { INADDR_BROADCAST },  /* limited broadcast */
+		{ 0xff000000 }, { 0x00000000 },  /* zero net */
+		{ 0xff000000 }, { 0x0a000000 },  /* private 10 (RFC3330) */
+		{ 0xfff00000 }, { 0xac100000 },  /* private 172 */
+		{ 0xffff0000 }, { 0xc0a80000 },  /* private 192 */
+		{ 0xffff0000 }, { 0xa9fe0000 },  /* IPv4 link-local */
+		{ 0xffffff00 }, { 0xc0586300 },  /* anycast 6-to-4 */
+		{ 0xffffff00 }, { 0xc0000200 },  /* test 192 */
+		{ 0xfffe0000 }, { 0xc6120000 },  /* test 198 */
+	};
+	guint i;
+
+	for (i = 0; i < G_N_ELEMENTS (items); i++) {
+		if ((addr & htonl (items[i].mask)) == htonl (items[i].result))
+			return 0x00; /* "local" scope */
+	}
+	return 0x02; /* "universal" scope */
+}
+
+/**
+ * nm_utils_get_ipv6_interface_identifier:
+ * @link_type: the hardware link type
+ * @hwaddr: the hardware address of the interface
+ * @hwaddr_len: the length (in bytes) of @hwaddr
+ * @dev_id: the device identifier, if any
+ * @out_iid: on success, filled with the interface identifier; on failure
+ * zeroed out
+ *
+ * Constructs an interface identifier in "Modified EUI-64" format which is
+ * suitable for constructing IPv6 addresses.  Note that the identifier is
+ * not obscured in any way (eg, RFC3041).
+ *
+ * Returns: %TRUE if the interface identifier could be constructed, %FALSE if
+ * if could not be constructed.
+ */
+gboolean
+nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
+                                        const guint8 *hwaddr,
+                                        guint hwaddr_len,
+                                        guint dev_id,
+                                        NMUtilsIPv6IfaceId *out_iid)
+{
+	guint32 addr;
+
+	g_return_val_if_fail (hwaddr != NULL, FALSE);
+	g_return_val_if_fail (hwaddr_len > 0, FALSE);
+	g_return_val_if_fail (out_iid != NULL, FALSE);
+
+	out_iid->id = 0;
+
+	switch (link_type) {
+	case NM_LINK_TYPE_INFINIBAND:
+		/* Use the port GUID per http://tools.ietf.org/html/rfc4391#section-8,
+		 * making sure to set the 'u' bit to 1.  The GUID is the lower 64 bits
+		 * of the IPoIB interface's hardware address.
+		 */
+		g_return_val_if_fail (hwaddr_len == INFINIBAND_ALEN, FALSE);
+		memcpy (out_iid->id_u8, hwaddr + INFINIBAND_ALEN - 8, 8);
+		out_iid->id_u8[0] |= 0x02;
+		return TRUE;
+	case NM_LINK_TYPE_GRE:
+	case NM_LINK_TYPE_GRETAP:
+		/* Hardware address is the network-endian IPv4 address */
+		g_return_val_if_fail (hwaddr_len == 4, FALSE);
+		addr = * (guint32 *) hwaddr;
+		out_iid->id_u8[0] = get_gre_eui64_u_bit (addr);
+		out_iid->id_u8[1] = 0x00;
+		out_iid->id_u8[2] = 0x5E;
+		out_iid->id_u8[3] = 0xFE;
+		memcpy (out_iid->id_u8 + 4, &addr, 4);
+		return TRUE;
+	default:
+		if (hwaddr_len == ETH_ALEN) {
+			/* Translate 48-bit MAC address to a 64-bit Modified EUI-64.  See
+			 * http://tools.ietf.org/html/rfc4291#appendix-A and the Linux
+			 * kernel's net/ipv6/addrconf.c::ipv6_generate_eui64() function.
+			 */
+			out_iid->id_u8[0] = hwaddr[0];
+			out_iid->id_u8[1] = hwaddr[1];
+			out_iid->id_u8[2] = hwaddr[2];
+			if (dev_id) {
+				out_iid->id_u8[3] = (dev_id >> 8) & 0xff;
+				out_iid->id_u8[4] = dev_id & 0xff;
+			} else {
+				out_iid->id_u8[0] ^= 0x02;
+				out_iid->id_u8[3] = 0xff;
+				out_iid->id_u8[4] = 0xfe;
+			}
+			out_iid->id_u8[5] = hwaddr[3];
+			out_iid->id_u8[6] = hwaddr[4];
+			out_iid->id_u8[7] = hwaddr[5];
+			return TRUE;
+		}
+		break;
+	}
+	return FALSE;
+}
+void
+nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
+                                            const NMUtilsIPv6IfaceId iid)
+{
+	memcpy (addr->s6_addr + 8, &iid.id_u8, 8);
+}
+
+void
+nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
+                                                 const struct in6_addr *addr)
+{
+	memcpy (iid, addr->s6_addr + 8, 8);
+}
+
+static gboolean
+_set_stable_privacy (struct in6_addr *addr,
+                     const char *ifname,
+                     const char *uuid,
+                     guint dad_counter,
+                     gchar *secret_key,
+                     gsize key_len,
+                     GError **error)
+{
+	GChecksum *sum;
+	guint8 digest[32];
+	guint32 tmp[2];
+	gsize len = sizeof (digest);
+
+	g_return_val_if_fail (key_len, FALSE);
+
+	/* Documentation suggests that this can fail.
+	 * Maybe in case of a missing algorithm in crypto library? */
+	sum = g_checksum_new (G_CHECKSUM_SHA256);
+	if (!sum) {
+		g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+		                     "Can't create a SHA256 hash");
+		return FALSE;
+	}
+
+	key_len = MIN (key_len, G_MAXUINT32);
+
+	g_checksum_update (sum, addr->s6_addr, 8);
+	g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
+	if (!uuid)
+		uuid = "";
+	g_checksum_update (sum, (const guchar *) uuid, strlen (uuid) + 1);
+	tmp[0] = htonl (dad_counter);
+	tmp[1] = htonl (key_len);
+	g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
+	g_checksum_update (sum, (const guchar *) secret_key, key_len);
+
+	g_checksum_get_digest (sum, digest, &len);
+	g_checksum_free (sum);
+
+	g_return_val_if_fail (len == 32, FALSE);
+
+	memcpy (addr->s6_addr + 8, &digest[0], 8);
+
+	return TRUE;
+}
+
+#define RFC7217_IDGEN_RETRIES 3
+/**
+ * nm_utils_ipv6_addr_set_stable_privacy:
+ *
+ * Extend the address prefix with an interface identifier using the
+ * RFC 7217 Stable Privacy mechanism.
+ *
+ * Returns: %TRUE on success, %FALSE if the address could not be generated.
+ */
+gboolean
+nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
+                                       const char *ifname,
+                                       const char *uuid,
+                                       guint dad_counter,
+                                       GError **error)
+{
+	gchar *secret_key = NULL;
+	gsize key_len = 0;
+	gboolean success = FALSE;
+
+	if (dad_counter >= RFC7217_IDGEN_RETRIES) {
+		g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+		                     "Too many DAD collisions");
+		return FALSE;
+	}
+
+	/* Let's try to load a saved secret key first. */
+	if (g_file_get_contents (NMSTATEDIR "/secret_key", &secret_key, &key_len, NULL)) {
+		if (key_len < 16) {
+			g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+			                     "Key is too short to be usable");
+			key_len = 0;
+		}
+	} else {
+		int urandom = open ("/dev/urandom", O_RDONLY);
+		mode_t key_mask;
+
+		if (urandom == -1) {
+			g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+			             "Can't open /dev/urandom: %s", strerror (errno));
+			return FALSE;
+		}
+
+		/* RFC7217 mandates the key SHOULD be at least 128 bits.
+		 * Let's use twice as much. */
+		key_len = 32;
+		secret_key = g_malloc (key_len);
+
+		key_mask = umask (0077);
+		if (read (urandom, secret_key, key_len) == key_len) {
+			if (!g_file_set_contents (NMSTATEDIR "/secret_key", secret_key, key_len, error)) {
+				g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key");
+				key_len = 0;
+			}
+		} else {
+			g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+			                     "Could not obtain a secret");
+			key_len = 0;
+		}
+		umask (key_mask);
+		close (urandom);
+	}
+
+	if (key_len) {
+		success = _set_stable_privacy (addr, ifname, uuid, dad_counter,
+		                               secret_key, key_len, error);
+	}
+
+	g_free (secret_key);
+	return success;
+}
+
+/**
+ * nm_utils_setpgid:
+ * @unused: unused
+ *
+ * This can be passed as a child setup function to the g_spawn*() family
+ * of functions, to ensure that the child is in its own process group
+ * (and thus, in some situations, will not be killed when NetworkManager
+ * is killed).
+ */
+void
+nm_utils_setpgid (gpointer unused G_GNUC_UNUSED)
+{
+	pid_t pid;
+
+	pid = getpid ();
+	setpgid (pid, pid);
+}
+
+/**
+ * nm_utils_g_value_set_strv:
+ * @value: a #GValue, initialized to store a #G_TYPE_STRV
+ * @strings: a #GPtrArray of strings
+ *
+ * Converts @strings to a #GStrv and stores it in @value.
+ */
+void
+nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings)
+{
+	char **strv;
+	int i;
+
+	strv = g_new (char *, strings->len + 1);
+	for (i = 0; i < strings->len; i++)
+		strv[i] = g_strdup (strings->pdata[i]);
+	strv[i] = NULL;
+
+	g_value_take_boxed (value, strv);
+}
+
+/*****************************************************************************/
+
+static gboolean
+debug_key_matches (const gchar *key,
+                   const gchar *token,
+                   guint        length)
+{
+	/* may not call GLib functions: see note in g_parse_debug_string() */
+	for (; length; length--, key++, token++) {
+		char k = (*key   == '_') ? '-' : g_ascii_tolower (*key  );
+		char t = (*token == '_') ? '-' : g_ascii_tolower (*token);
+
+		if (k != t)
+			return FALSE;
+	}
+
+	return *key == '\0';
+}
+
+/**
+ * nm_utils_parse_debug_string:
+ * @string: the string to parse
+ * @keys: the debug keys
+ * @nkeys: number of entires in @keys
+ *
+ * Similar to g_parse_debug_string(), but does not special
+ * case "help" or "all".
+ *
+ * Returns: the flags
+ */
+guint
+nm_utils_parse_debug_string (const char *string,
+                             const GDebugKey *keys,
+                             guint nkeys)
+{
+	guint i;
+	guint result = 0;
+	const char *q;
+
+	if (string == NULL)
+		return 0;
+
+	while (*string) {
+		q = strpbrk (string, ":;, \t");
+		if (!q)
+			q = string + strlen (string);
+
+		for (i = 0; i < nkeys; i++) {
+			if (debug_key_matches (keys[i].key, string, q - string))
+				result |= keys[i].value;
+		}
+
+		string = q;
+		if (*string)
+			string++;
+	}
+
+	return result;
+}
+
+
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
new file mode 100644
index 00000000..7a69fb19
--- /dev/null
+++ b/src/nm-core-utils.h
@@ -0,0 +1,415 @@
+/* -*- 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 2004 - 2016 Red Hat, Inc.
+ * Copyright 2005 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_CORE_UTILS_H__
+#define __NM_CORE_UTILS_H__
+
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#include "nm-default.h"
+#include "nm-connection.h"
+
+/*****************************************************************************/
+
+#define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \
+static TYPE *singleton_instance
+
+#define NM_DEFINE_SINGLETON_REGISTER(TYPE) \
+NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
+static void \
+_singleton_instance_weak_ref_cb (gpointer data, \
+                                 GObject *where_the_object_was) \
+{ \
+	nm_log_dbg (LOGD_CORE, "disposing %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
+	singleton_instance = NULL; \
+} \
+static inline void \
+nm_singleton_instance_register (void) \
+{ \
+	g_object_weak_ref (G_OBJECT (singleton_instance), _singleton_instance_weak_ref_cb, NULL); \
+	_nm_singleton_instance_register_destruction (G_OBJECT (singleton_instance)); \
+}
+
+void _nm_singleton_instance_register_destruction (GObject *instance);
+
+/* By default, the getter will assert that the singleton will be created only once. You can
+ * change this by redefining NM_DEFINE_SINGLETON_ALLOW_MULTIPLE. */
+#ifndef NM_DEFINE_SINGLETON_ALLOW_MULTIPLE
+#define NM_DEFINE_SINGLETON_ALLOW_MULTIPLE     FALSE
+#endif
+
+#define NM_DEFINE_SINGLETON_GETTER(TYPE, GETTER, GTYPE, ...) \
+NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
+NM_DEFINE_SINGLETON_REGISTER (TYPE); \
+TYPE * \
+GETTER (void) \
+{ \
+	if (G_UNLIKELY (!singleton_instance)) { \
+		static char _already_created = FALSE; \
+\
+		g_assert (!_already_created || (NM_DEFINE_SINGLETON_ALLOW_MULTIPLE)); \
+		_already_created = TRUE;\
+		singleton_instance = (g_object_new (GTYPE, ##__VA_ARGS__, NULL)); \
+		g_assert (singleton_instance); \
+		nm_singleton_instance_register (); \
+		nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
+	} \
+	return singleton_instance; \
+}
+
+/* attach @instance to the data or @owner. @owner owns a reference
+ * to @instance thus the lifetime of @instance is at least as long
+ * as that of @owner. Use this when @owner depends on @instance. */
+#define NM_UTILS_KEEP_ALIVE(owner, instance, unique_token) \
+    G_STMT_START { \
+         g_object_set_data_full (G_OBJECT (owner), \
+                                 ".nm-utils-keep-alive-" unique_token "", \
+                                 g_object_ref (instance), \
+                                 g_object_unref); \
+    } G_STMT_END
+
+/*****************************************************************************/
+
+/**
+ * NMUtilsError:
+ * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
+ *   pending aynchronous operations, the operation is cancelled with this
+ *   error reason. Depending on the usage, this might indicate a bug because
+ *   usually the target object should stay alive as long as there are pending
+ *   operations.
+ */
+typedef enum {
+	NM_UTILS_ERROR_UNKNOWN = 0,                 /*< nick=Unknown >*/
+	NM_UTILS_ERROR_CANCELLED_DISPOSING,         /*< nick=CancelledDisposing >*/
+} NMUtilsError;
+
+#define NM_UTILS_ERROR (nm_utils_error_quark ())
+GQuark nm_utils_error_quark (void);
+
+void nm_utils_error_set_cancelled (GError **error,
+                                   gboolean is_disposing,
+                                   const char *instance_name);
+gboolean nm_utils_error_is_cancelled (GError *error,
+                                      gboolean consider_is_disposing);
+
+/*****************************************************************************/
+
+gint nm_utils_ascii_str_to_bool (const char *str,
+                                 gint default_value);
+
+/*****************************************************************************/
+
+gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
+
+in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
+const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
+
+/**
+ * nm_utils_ip6_route_metric_normalize:
+ * @metric: the route metric
+ *
+ * For IPv6 route, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
+ * Thus, when comparing metric (values), we want to treat zero as NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6.
+ *
+ * Returns: @metric, if @metric is not zero, otherwise 1024.
+ */
+static inline guint32
+nm_utils_ip6_route_metric_normalize (guint32 metric)
+{
+	return metric ? metric : 1024 /*NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6*/;
+}
+
+int nm_spawn_process (const char *args, GError **error);
+
+int nm_utils_modprobe (GError **error, gboolean suppress_error_loggin, const char *arg1, ...) G_GNUC_NULL_TERMINATED;
+
+/**
+ * str_if_set:
+ * @str: input string that will be returned if @str is not %NULL
+ * @fallback: if @str is %NULL, return @fallback instead
+ *
+ * This utility function is useful when printing a string to avoid passing
+ * %NULL. E.g. printf ("%s", str_if_set (get_string(), "(none)"));
+ *
+ * Returns: either @str or @fallback, depending on whether @str is %NULL.
+ */
+static inline const char *
+str_if_set (const char *str, const char *fallback)
+{
+	return str ? str : fallback;
+}
+
+guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
+
+void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain,
+                                 const char *log_name, guint32 wait_before_kill_msec,
+                                 guint32 sleep_duration_msec, guint32 max_wait_msec);
+
+typedef void (*NMUtilsKillChildAsyncCb) (pid_t pid, gboolean success, int child_status, void *user_data);
+void nm_utils_kill_child_async (pid_t pid, int sig, guint64 log_domain, const char *log_name,
+                                guint32 wait_before_kill_msec,
+                                NMUtilsKillChildAsyncCb callback, void *user_data);
+gboolean nm_utils_kill_child_sync (pid_t pid, int sig, guint64 log_domain, const char *log_name,
+                                   int *child_status, guint32 wait_before_kill_msec,
+                                   guint32 sleep_duration_msec);
+
+const char *nm_utils_find_helper (const char *progname,
+                                  const char *try_first,
+                                  GError **error);
+
+typedef enum {
+	NM_MATCH_SPEC_NO_MATCH  = 0,
+	NM_MATCH_SPEC_MATCH     = 1,
+	NM_MATCH_SPEC_NEG_MATCH = 2,
+} NMMatchSpecMatchType;
+
+NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char *device_type);
+NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
+NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
+NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
+NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
+GSList *nm_match_spec_split (const char *value);
+char *nm_match_spec_join (GSList *specs);
+
+extern char _nm_utils_to_string_buffer[2096];
+
+void     nm_utils_to_string_buffer_init (char **buf, gsize *len);
+gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
+
+/*****************************************************************************/
+
+typedef struct {
+	unsigned flag;
+	const char *name;
+} NMUtilsFlags2StrDesc;
+
+#define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
+
+#define _NM_UTILS_FLAGS2STR_DEFINE(scope, fcn_name, flags_type, ...) \
+scope const char * \
+fcn_name (flags_type flags, char *buf, gsize len) \
+{ \
+	static const NMUtilsFlags2StrDesc descs[] = { \
+		__VA_ARGS__ \
+	}; \
+	G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
+	return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
+};
+
+#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
+	_NM_UTILS_FLAGS2STR_DEFINE (, fcn_name, flags_type, __VA_ARGS__)
+#define NM_UTILS_FLAGS2STR_DEFINE_STATIC(fcn_name, flags_type, ...) \
+	_NM_UTILS_FLAGS2STR_DEFINE (static, fcn_name, flags_type, __VA_ARGS__)
+
+const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
+                                gsize n_descs,
+                                unsigned flags,
+                                char *buf,
+                                gsize len);
+
+/*****************************************************************************/
+
+#define NM_UTILS_ENUM2STR(v, n)     (void) 0; case v: s = ""n""; break; (void) 0
+#define NM_UTILS_ENUM2STR_IGNORE(v) (void) 0; case v: break; (void) 0
+
+#define _NM_UTILS_ENUM2STR_DEFINE(scope, fcn_name, lookup_type, int_fmt, ...) \
+scope const char * \
+fcn_name (lookup_type val, char *buf, gsize len) \
+{ \
+	nm_utils_to_string_buffer_init (&buf, &len); \
+	if (len) { \
+		const char *s = NULL; \
+		switch (val) { \
+			(void) 0, \
+			__VA_ARGS__ \
+			(void) 0; \
+		}; \
+		if (s) \
+			g_strlcpy (buf, s, len); \
+		else \
+			g_snprintf (buf, len, "(%"int_fmt")", val); \
+	} \
+	return buf; \
+}
+
+#define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
+	_NM_UTILS_ENUM2STR_DEFINE (, fcn_name, lookup_type, "d", __VA_ARGS__)
+#define NM_UTILS_ENUM2STR_DEFINE_STATIC(fcn_name, lookup_type, ...) \
+	_NM_UTILS_ENUM2STR_DEFINE (static, fcn_name, lookup_type, "d", __VA_ARGS__)
+
+/*****************************************************************************/
+
+#define NM_UTILS_LOOKUP_DEFAULT(v)      return (v)
+#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v)
+#define NM_UTILS_LOOKUP_ITEM(v, n)     (void) 0; case v: return (n); (void) 0
+#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"")
+#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0
+
+#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
+scope result_type \
+fcn_name (lookup_type val) \
+{ \
+	switch (val) { \
+		(void) 0, \
+		__VA_ARGS__ \
+		(void) 0; \
+	}; \
+	{ unknown_val; } \
+}
+
+#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
+	_NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
+#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
+	_NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
+
+/* Call the string-lookup-table function @fcn_name. If the function returns
+ * %NULL, the numeric index is converted to string using a alloca() buffer.
+ * Beware: this macro uses alloca(). */
+#define NM_UTILS_LOOKUP_STR(fcn_name, idx) \
+	({ \
+		typeof (idx) _idx = (idx); \
+		const char *_s; \
+		\
+		_s = fcn_name (_idx); \
+		if (!_s) { \
+			_s = g_alloca (30); \
+			\
+			g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
+		} \
+		_s; \
+	})
+
+/*****************************************************************************/
+
+static inline void
+_nm_utils_strbuf_init (char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
+{
+	NM_SET_OUT (p_buf_len, len);
+	NM_SET_OUT (p_buf_ptr, buf);
+	buf[0] = '\0';
+}
+
+#define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len) \
+	G_STMT_START { \
+		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) > sizeof (char *)); \
+		_nm_utils_strbuf_init ((buf), sizeof (buf), (p_buf_ptr), (p_buf_len)); \
+	} G_STMT_END
+void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) __attribute__((__format__ (__printf__, 3, 4)));
+void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
+void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
+
+const char *nm_utils_get_ip_config_method (NMConnection *connection,
+                                           GType         ip_setting_type);
+
+char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id);
+
+GPtrArray *nm_utils_read_resolv_conf_nameservers (const char *rc_contents);
+GPtrArray *nm_utils_read_resolv_conf_dns_options (const char *rc_contents);
+
+int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b);
+
+void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
+
+#define NM_UTILS_NS_PER_SECOND  ((gint64) 1000000000)
+gint64 nm_utils_get_monotonic_timestamp_ns (void);
+gint64 nm_utils_get_monotonic_timestamp_us (void);
+gint64 nm_utils_get_monotonic_timestamp_ms (void);
+gint32 nm_utils_get_monotonic_timestamp_s (void);
+gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns);
+
+gboolean    nm_utils_is_valid_path_component (const char *name);
+const char *ASSERT_VALID_PATH_COMPONENT (const char *name);
+const char *nm_utils_ip6_property_path (const char *ifname, const char *property);
+const char *nm_utils_ip4_property_path (const char *ifname, const char *property);
+
+gboolean nm_utils_is_specific_hostname (const char *name);
+
+/* IPv6 Interface Identifer helpers */
+
+/**
+ * NMUtilsIPv6IfaceId:
+ * @id: convenience member for validity checking; never use directly
+ * @id_u8: the 64-bit Interface Identifier
+ *
+ * Holds a 64-bit IPv6 Interface Identifier.  The IID is a sequence of bytes
+ * and should not normally be treated as a %guint64, but this is done for
+ * convenience of validity checking and initialization.
+ */
+struct _NMUtilsIPv6IfaceId {
+	union {
+		guint64 id;
+		guint8  id_u8[8];
+	};
+};
+
+#define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } }
+
+gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
+                                                 const guint8 *hwaddr,
+                                                 guint len,
+                                                 guint dev_id,
+                                                 NMUtilsIPv6IfaceId *out_iid);
+
+void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
+                                                 const NMUtilsIPv6IfaceId iid);
+
+gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
+                                                const char *ifname,
+                                                const char *uuid,
+                                                guint dad_counter,
+                                                GError **error);
+
+void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
+                                                      const struct in6_addr *addr);
+
+void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
+
+void nm_utils_setpgid (gpointer unused);
+
+typedef enum {
+	NM_UTILS_TEST_NONE                              = 0,
+
+	/* Internal flag, marking that either nm_utils_get_testing() or _nm_utils_set_testing() was called. */
+	_NM_UTILS_TEST_INITIALIZED                      = (1LL << 0),
+
+	/* Indicate that test mode is enabled in general. Explicitly calling _nm_utils_set_testing() will always set this flag. */
+	_NM_UTILS_TEST_GENERAL                          = (1LL << 1),
+
+	/* Don't check the owner of keyfiles during testing. */
+	NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK            = (1LL << 2),
+
+	_NM_UTILS_TEST_LAST,
+	NM_UTILS_TEST_ALL                               = (((_NM_UTILS_TEST_LAST - 1) << 1) - 1) & ~(_NM_UTILS_TEST_INITIALIZED),
+} NMUtilsTestFlags;
+
+gboolean nm_utils_get_testing_initialized (void);
+NMUtilsTestFlags nm_utils_get_testing (void);
+void _nm_utils_set_testing (NMUtilsTestFlags flags);
+
+void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings);
+
+guint nm_utils_parse_debug_string (const char *string,
+                                   const GDebugKey *keys,
+                                   guint nkeys);
+
+#endif /* __NM_CORE_UTILS_H__ */
diff --git a/src/nm-dcb.c b/src/nm-dcb.c
index 109e56e5..d8f3d3e7 100644
--- a/src/nm-dcb.c
+++ b/src/nm-dcb.c
@@ -18,12 +18,11 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/wait.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dcb.h"
 #include "nm-platform.h"
 #include "NetworkManagerUtils.h"
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index a27cb287..e2c4eefe 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -19,11 +19,10 @@
  */
 
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-default-route-manager.h"
 #include "nm-device.h"
 #include "nm-vpn-connection.h"
diff --git a/src/nm-dhcp4-config.c b/src/nm-dhcp4-config.c
index 00b9949b..26c6ab0b 100644
--- a/src/nm-dhcp4-config.c
+++ b/src/nm-dhcp4-config.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2008 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-dhcp4-config.h"
 #include "nm-utils.h"
diff --git a/src/nm-dhcp6-config.c b/src/nm-dhcp6-config.c
index 8aa8c2e0..4311ee98 100644
--- a/src/nm-dhcp6-config.c
+++ b/src/nm-dhcp6-config.c
@@ -18,11 +18,10 @@
  * Copyright (C) 2008 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-dhcp6-config.h"
 #include "nm-utils.h"
diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c
index dad48520..c0238fc5 100644
--- a/src/nm-dispatcher.c
+++ b/src/nm-dispatcher.c
@@ -19,12 +19,11 @@
  * Copyright (C) 2005 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "nm-dispatcher.h"
 #include "nm-dispatcher-api.h"
 #include "NetworkManagerUtils.h"
@@ -58,7 +57,7 @@ enum {
 };
 
 static Monitor monitors[3] = {
-#define MONITORS_INIT_SET(INDEX, USE, SCRIPT_DIR)   [INDEX] = { .dir_len = STRLEN (SCRIPT_DIR), .dir = SCRIPT_DIR, .description = ("" USE), .has_scripts = TRUE }
+#define MONITORS_INIT_SET(INDEX, USE, SCRIPT_DIR)   [INDEX] = { .dir_len = NM_STRLEN (SCRIPT_DIR), .dir = SCRIPT_DIR, .description = ("" USE), .has_scripts = TRUE }
 	MONITORS_INIT_SET (MONITOR_INDEX_DEFAULT,  "default",  NMD_SCRIPT_DIR_DEFAULT),
 	MONITORS_INIT_SET (MONITOR_INDEX_PRE_UP,   "pre-up",   NMD_SCRIPT_DIR_PRE_UP),
 	MONITORS_INIT_SET (MONITOR_INDEX_PRE_DOWN, "pre-down", NMD_SCRIPT_DIR_PRE_DOWN),
diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c
index 1d087f52..66d54bdf 100644
--- a/src/nm-enum-types.c
+++ b/src/nm-enum-types.c
@@ -23,6 +23,7 @@
 #include "nm-dhcp-systemd.h" 
 #include "nm-device.h" 
 #include "nm-lldp-listener.h" 
+#include "nm-arping-manager.h" 
 #include "nm-device-ethernet-utils.h" 
 #include "nm-device-factory.h" 
 #include "nm-device-generic.h" 
@@ -97,6 +98,7 @@
 #include "nm-session-monitor.h" 
 #include "nm-sleep-monitor.h" 
 #include "nm-types.h" 
+#include "nm-core-utils.h" 
 #include "NetworkManagerUtils.h" 
 #include "wifi-utils-wext.h"
 
@@ -121,6 +123,26 @@ nm_vlan_error_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_unman_flag_op_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_UNMAN_FLAG_OP_SET_MANAGED, "NM_UNMAN_FLAG_OP_SET_MANAGED", "set-managed" },
+        { NM_UNMAN_FLAG_OP_SET_UNMANAGED, "NM_UNMAN_FLAG_OP_SET_UNMANAGED", "set-unmanaged" },
+        { NM_UNMAN_FLAG_OP_FORGET, "NM_UNMAN_FLAG_OP_FORGET", "forget" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMUnmanFlagOp"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_dhcp_state_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
diff --git a/src/nm-enum-types.h b/src/nm-enum-types.h
index 4a85d966..6bfc3ebc 100644
--- a/src/nm-enum-types.h
+++ b/src/nm-enum-types.h
@@ -12,6 +12,8 @@
 G_BEGIN_DECLS
 GType nm_vlan_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_VLAN_ERROR (nm_vlan_error_get_type ())
+GType nm_unman_flag_op_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_UNMAN_FLAG_OP (nm_unman_flag_op_get_type ())
 GType nm_dhcp_state_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ())
 GType nm_dns_ip_config_type_get_type (void) G_GNUC_CONST;
diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c
index ca3187e8..b6d30aab 100644
--- a/src/nm-exported-object.c
+++ b/src/nm-exported-object.c
@@ -18,14 +18,13 @@
  * Copyright 2014-2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdarg.h>
 #include <string.h>
 
 #include "nm-exported-object.h"
 #include "nm-bus-manager.h"
-#include "nm-default.h"
 
 static GHashTable *prefix_counters;
 static gboolean quitting = FALSE;
@@ -538,6 +537,7 @@ nm_exported_object_export (NMExportedObject *self)
 	NMExportedObjectPrivate *priv;
 	const char *class_export_path, *p;
 	GType type;
+	char *path;
 
 	g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL);
 	priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
@@ -568,12 +568,9 @@ nm_exported_object_export (NMExportedObject *self)
 			g_hash_table_insert (prefix_counters, g_strdup (class_export_path), counter);
 		}
 
-		priv->path = g_strdup_printf (class_export_path, (*counter)++);
+		path = g_strdup_printf (class_export_path, (*counter)++);
 	} else
-		priv->path = g_strdup (class_export_path);
-
-	_LOGT ("export: \"%s\"", priv->path);
-	g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (self), priv->path);
+		path = g_strdup (class_export_path);
 
 	type = G_OBJECT_TYPE (self);
 	while (type != NM_TYPE_EXPORTED_OBJECT) {
@@ -581,6 +578,10 @@ nm_exported_object_export (NMExportedObject *self)
 		type = g_type_parent (type);
 	}
 
+	priv->path = path;
+	_LOGT ("export: \"%s\"", priv->path);
+	g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (self), priv->path);
+
 	/* Important: priv->path and priv->interfaces must not change while
 	 * the object is registered. */
 
diff --git a/src/nm-firewall-manager.c b/src/nm-firewall-manager.c
index 5e5248a9..7babff3c 100644
--- a/src/nm-firewall-manager.c
+++ b/src/nm-firewall-manager.c
@@ -18,13 +18,12 @@
  * Copyright (C) 2011 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-firewall-manager.h"
 
 #include <string.h>
 
-#include "nm-default.h"
-#include "nm-firewall-manager.h"
-#include "gsystem-local-alloc.h"
 #include "NetworkManagerUtils.h"
 
 #define NM_FIREWALL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 069a68f8..cc59835f 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <glib-unix.h>
 #include <getopt.h>
@@ -36,7 +36,6 @@
  * Forward declare if_nametoindex. */
 extern unsigned int if_nametoindex (const char *__ifname);
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-linux-platform.h"
 #include "nm-dhcp-manager.h"
@@ -135,7 +134,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da
 	NMIP6Config *existing;
 	NMIP6Config *ip6_config;
 	static int system_support = -1;
-	guint ifa_flags = 0x00;
+	guint32 ifa_flags = 0x00;
 	int i;
 
 	if (system_support == -1) {
@@ -192,7 +191,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da
 			if (address.preferred > address.lifetime)
 				address.preferred = address.lifetime;
 			address.source = NM_IP_CONFIG_SOURCE_RDISC;
-			address.flags = ifa_flags;
+			address.n_ifa_flags = ifa_flags;
 
 			nm_ip6_config_add_address (ip6_config, &address);
 		}
@@ -334,8 +333,8 @@ ip6_address_changed (NMPlatform *platform,
                      NMPlatformSignalChangeType change_type,
                      NMRDisc *rdisc)
 {
-	if (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED)
-	    || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE))
+	if (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
+	    || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE))
 		nm_rdisc_dad_failed (rdisc, &addr->address);
 }
 
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 78e7fb78..9c2557f9 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -19,21 +19,19 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-ip4-config.h"
 
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-ip4-config.h"
-
-#include "nm-default.h"
 #include "nm-utils.h"
 #include "nm-platform.h"
+#include "nm-platform-utils.h"
 #include "NetworkManagerUtils.h"
-#include "nm-core-internal.h"
 #include "nm-route-manager.h"
 #include "nm-core-internal.h"
-#include "nm-macros-internal.h"
 
 #include "nmdbus-ip4-config.h"
 
@@ -66,8 +64,7 @@ typedef struct _NMIP4ConfigPrivate {
 G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32));
 G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
 
-enum {
-	PROP_0,
+NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
 	PROP_IFINDEX,
 	PROP_ADDRESS_DATA,
 	PROP_ADDRESSES,
@@ -79,11 +76,7 @@ enum {
 	PROP_SEARCHES,
 	PROP_DNS_OPTIONS,
 	PROP_WINS_SERVERS,
-
-	LAST_PROP
-};
-static GParamSpec *obj_properties[LAST_PROP] = { NULL, };
-#define _NOTIFY(config, prop)    G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END
+);
 
 NMIP4Config *
 nm_ip4_config_new (int ifindex)
@@ -190,6 +183,73 @@ routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b,
 	       (!consider_gateway_and_metric || (a->gateway == b->gateway && a->metric == b->metric));
 }
 
+/*****************************************************************************/
+
+static gint
+_addresses_sort_cmp_get_prio (in_addr_t addr)
+{
+	if (nmp_utils_ip4_address_is_link_local (addr))
+		return 0;
+	return 1;
+}
+
+static gint
+_addresses_sort_cmp (gconstpointer a, gconstpointer b)
+{
+	gint p1, p2, c;
+	const NMPlatformIP4Address *a1 = a, *a2 = b;
+
+	/* Sort by address type. For example link local will
+	 * be sorted *after* a global address. */
+	p1 = _addresses_sort_cmp_get_prio (a1->address);
+	p2 = _addresses_sort_cmp_get_prio (a2->address);
+	if (p1 != p2)
+		return p1 > p2 ? -1 : 1;
+
+	/* Sort the addresses based on their source. */
+	if (a1->source != a2->source)
+		return a1->source > a2->source ? -1 : 1;
+
+	if ((a1->label[0] == '\0') != (a2->label[0] == '\0'))
+		return (a1->label[0] == '\0') ? -1 : 1;
+
+	/* finally sort addresses lexically */
+	c = memcmp (&a1->address, &a2->address, sizeof (a2->address));
+	return c != 0 ? c : memcmp (a1, a2, sizeof (*a1));
+}
+
+gboolean
+nm_ip4_config_addresses_sort (NMIP4Config *self)
+{
+	NMIP4ConfigPrivate *priv;
+	size_t data_len = 0;
+	char *data_pre = NULL;
+	gboolean changed;
+
+	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
+
+	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+	if (priv->addresses->len > 1) {
+		data_len = priv->addresses->len * g_array_get_element_size (priv->addresses);
+		data_pre = g_new (char, data_len);
+		memcpy (data_pre, priv->addresses->data, data_len);
+
+		g_array_sort (priv->addresses, _addresses_sort_cmp);
+
+		changed = memcmp (data_pre, priv->addresses->data, data_len) != 0;
+		g_free (data_pre);
+
+		if (changed) {
+			_notify (self, PROP_ADDRESS_DATA);
+			_notify (self, PROP_ADDRESSES);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/*****************************************************************************/
+
 NMIP4Config *
 nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
 {
@@ -257,17 +317,17 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
 	 */
 	if (priv->addresses->len && priv->has_gateway && capture_resolv_conf) {
 		if (nm_ip4_config_capture_resolv_conf (priv->nameservers, priv->dns_options, NULL))
-			_NOTIFY (config, PROP_NAMESERVERS);
+			_notify (config, PROP_NAMESERVERS);
 	}
 
 	/* actually, nobody should be connected to the signal, just to be sure, notify */
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
-	_NOTIFY (config, PROP_ROUTES);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ADDRESSES);
+	_notify (config, PROP_ROUTES);
 	if (   priv->gateway != old_gateway
 	    || priv->has_gateway != old_has_gateway)
-		_NOTIFY (config, PROP_GATEWAY);
+		_notify (config, PROP_GATEWAY);
 
 	return config;
 }
@@ -1319,7 +1379,7 @@ nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway)
 	if (priv->gateway != gateway || !priv->has_gateway) {
 		priv->gateway = gateway;
 		priv->has_gateway = TRUE;
-		_NOTIFY (config, PROP_GATEWAY);
+		_notify (config, PROP_GATEWAY);
 	}
 }
 
@@ -1331,7 +1391,7 @@ nm_ip4_config_unset_gateway (NMIP4Config *config)
 	if (priv->has_gateway) {
 		priv->gateway = 0;
 		priv->has_gateway = FALSE;
-		_NOTIFY (config, PROP_GATEWAY);
+		_notify (config, PROP_GATEWAY);
 	}
 }
 
@@ -1378,8 +1438,8 @@ nm_ip4_config_reset_addresses (NMIP4Config *config)
 
 	if (priv->addresses->len != 0) {
 		g_array_set_size (priv->addresses, 0);
-		_NOTIFY (config, PROP_ADDRESS_DATA);
-		_NOTIFY (config, PROP_ADDRESSES);
+		_notify (config, PROP_ADDRESS_DATA);
+		_notify (config, PROP_ADDRESSES);
 	}
 }
 
@@ -1436,8 +1496,8 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
 
 	g_array_append_val (priv->addresses, *new);
 NOTIFY:
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ADDRESSES);
 }
 
 void
@@ -1448,8 +1508,8 @@ nm_ip4_config_del_address (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->addresses->len);
 
 	g_array_remove_index (priv->addresses, i);
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ADDRESSES);
 }
 
 guint
@@ -1484,8 +1544,8 @@ nm_ip4_config_reset_routes (NMIP4Config *config)
 
 	if (priv->routes->len != 0) {
 		g_array_set_size (priv->routes, 0);
-		_NOTIFY (config, PROP_ROUTE_DATA);
-		_NOTIFY (config, PROP_ROUTES);
+		_notify (config, PROP_ROUTE_DATA);
+		_notify (config, PROP_ROUTES);
 	}
 }
 
@@ -1528,8 +1588,8 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
 	g_array_append_val (priv->routes, *new);
 	g_array_index (priv->routes, NMPlatformIP4Route, priv->routes->len - 1).ifindex = priv->ifindex;
 NOTIFY:
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ROUTES);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ROUTES);
 }
 
 void
@@ -1540,8 +1600,8 @@ nm_ip4_config_del_route (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->routes->len);
 
 	g_array_remove_index (priv->routes, i);
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ROUTES);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ROUTES);
 }
 
 guint
@@ -1599,7 +1659,7 @@ nm_ip4_config_reset_nameservers (NMIP4Config *config)
 
 	if (priv->nameservers->len != 0) {
 		g_array_set_size (priv->nameservers, 0);
-		_NOTIFY (config, PROP_NAMESERVERS);
+		_notify (config, PROP_NAMESERVERS);
 	}
 }
 
@@ -1616,7 +1676,7 @@ nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new)
 			return;
 
 	g_array_append_val (priv->nameservers, new);
-	_NOTIFY (config, PROP_NAMESERVERS);
+	_notify (config, PROP_NAMESERVERS);
 }
 
 void
@@ -1627,7 +1687,7 @@ nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->nameservers->len);
 
 	g_array_remove_index (priv->nameservers, i);
-	_NOTIFY (config, PROP_NAMESERVERS);
+	_notify (config, PROP_NAMESERVERS);
 }
 
 guint32
@@ -1655,7 +1715,7 @@ nm_ip4_config_reset_domains (NMIP4Config *config)
 
 	if (priv->domains->len != 0) {
 		g_ptr_array_set_size (priv->domains, 0);
-		_NOTIFY (config, PROP_DOMAINS);
+		_notify (config, PROP_DOMAINS);
 	}
 }
 
@@ -1673,7 +1733,7 @@ nm_ip4_config_add_domain (NMIP4Config *config, const char *domain)
 			return;
 
 	g_ptr_array_add (priv->domains, g_strdup (domain));
-	_NOTIFY (config, PROP_DOMAINS);
+	_notify (config, PROP_DOMAINS);
 }
 
 void
@@ -1684,7 +1744,7 @@ nm_ip4_config_del_domain (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->domains->len);
 
 	g_ptr_array_remove_index (priv->domains, i);
-	_NOTIFY (config, PROP_DOMAINS);
+	_notify (config, PROP_DOMAINS);
 }
 
 guint32
@@ -1712,7 +1772,7 @@ nm_ip4_config_reset_searches (NMIP4Config *config)
 
 	if (priv->searches->len != 0) {
 		g_ptr_array_set_size (priv->searches, 0);
-		_NOTIFY (config, PROP_SEARCHES);
+		_notify (config, PROP_SEARCHES);
 	}
 }
 
@@ -1745,7 +1805,7 @@ nm_ip4_config_add_search (NMIP4Config *config, const char *new)
 	}
 
 	g_ptr_array_add (priv->searches, search);
-	_NOTIFY (config, PROP_SEARCHES);
+	_notify (config, PROP_SEARCHES);
 }
 
 void
@@ -1756,7 +1816,7 @@ nm_ip4_config_del_search (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->searches->len);
 
 	g_ptr_array_remove_index (priv->searches, i);
-	_NOTIFY (config, PROP_SEARCHES);
+	_notify (config, PROP_SEARCHES);
 }
 
 guint32
@@ -1784,7 +1844,7 @@ nm_ip4_config_reset_dns_options (NMIP4Config *config)
 
 	if (priv->dns_options->len != 0) {
 		g_ptr_array_set_size (priv->dns_options, 0);
-		_NOTIFY (config, PROP_DNS_OPTIONS);
+		_notify (config, PROP_DNS_OPTIONS);
 	}
 }
 
@@ -1802,7 +1862,7 @@ nm_ip4_config_add_dns_option (NMIP4Config *config, const char *new)
 			return;
 
 	g_ptr_array_add (priv->dns_options, g_strdup (new));
-	_NOTIFY (config, PROP_DNS_OPTIONS);
+	_notify (config, PROP_DNS_OPTIONS);
 }
 
 void
@@ -1813,7 +1873,7 @@ nm_ip4_config_del_dns_option(NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->dns_options->len);
 
 	g_ptr_array_remove_index (priv->dns_options, i);
-	_NOTIFY (config, PROP_DNS_OPTIONS);
+	_notify (config, PROP_DNS_OPTIONS);
 }
 
 guint32
@@ -1925,7 +1985,7 @@ nm_ip4_config_reset_wins (NMIP4Config *config)
 
 	if (priv->wins->len != 0) {
 		g_array_set_size (priv->wins, 0);
-		_NOTIFY (config, PROP_WINS_SERVERS);
+		_notify (config, PROP_WINS_SERVERS);
 	}
 }
 
@@ -1942,7 +2002,7 @@ nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins)
 			return;
 
 	g_array_append_val (priv->wins, wins);
-	_NOTIFY (config, PROP_WINS_SERVERS);
+	_notify (config, PROP_WINS_SERVERS);
 }
 
 void
@@ -1953,7 +2013,7 @@ nm_ip4_config_del_wins (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->wins->len);
 
 	g_array_remove_index (priv->wins, i);
-	_NOTIFY (config, PROP_WINS_SERVERS);
+	_notify (config, PROP_WINS_SERVERS);
 }
 
 guint32
@@ -2430,7 +2490,7 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
 		                      G_PARAM_READABLE |
 		                      G_PARAM_STATIC_STRINGS);
 
-	g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (config_class),
 	                                        NMDBUS_TYPE_IP4_CONFIG_SKELETON,
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 514ba802..02bc8b07 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -98,6 +98,7 @@ void nm_ip4_config_del_address (NMIP4Config *config, guint i);
 guint nm_ip4_config_get_num_addresses (const NMIP4Config *config);
 const NMPlatformIP4Address *nm_ip4_config_get_address (const NMIP4Config *config, guint i);
 gboolean nm_ip4_config_address_exists (const NMIP4Config *config, const NMPlatformIP4Address *address);
+gboolean nm_ip4_config_addresses_sort (NMIP4Config *config);
 
 /* Routes */
 void nm_ip4_config_reset_routes (NMIP4Config *config);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index fd63dcb4..6d83bd53 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -19,20 +19,18 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-ip6-config.h"
 
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
-#include "nm-ip6-config.h"
-
 #include "nm-utils.h"
 #include "nm-platform.h"
 #include "nm-route-manager.h"
 #include "nm-core-internal.h"
 #include "NetworkManagerUtils.h"
-#include "nm-macros-internal.h"
 
 #include "nmdbus-ip6-config.h"
 
@@ -55,8 +53,7 @@ typedef struct _NMIP6ConfigPrivate {
 } NMIP6ConfigPrivate;
 
 
-enum {
-	PROP_0,
+NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config,
 	PROP_IFINDEX,
 	PROP_ADDRESS_DATA,
 	PROP_ADDRESSES,
@@ -67,12 +64,7 @@ enum {
 	PROP_DOMAINS,
 	PROP_SEARCHES,
 	PROP_DNS_OPTIONS,
-
-	LAST_PROP
-};
-static GParamSpec *obj_properties[LAST_PROP] = { NULL, };
-#define _NOTIFY(config, prop)    G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END
-
+);
 
 NMIP6Config *
 nm_ip6_config_new (int ifindex)
@@ -83,6 +75,18 @@ nm_ip6_config_new (int ifindex)
 	                                     NULL);
 }
 
+NMIP6Config *
+nm_ip6_config_new_cloned (const NMIP6Config *src)
+{
+	NMIP6Config *new;
+
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (src), NULL);
+
+	new = nm_ip6_config_new (nm_ip6_config_get_ifindex (src));
+	nm_ip6_config_replace (new, src, NULL);
+	return new;
+}
+
 int
 nm_ip6_config_get_ifindex (const NMIP6Config *config)
 {
@@ -218,8 +222,8 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
 
 	/* tentative addresses are always sorted back... */
 	/* sort tentative addresses after non-tentative. */
-	tent1 = (a1->flags & IFA_F_TENTATIVE);
-	tent2 = (a2->flags & IFA_F_TENTATIVE);
+	tent1 = (a1->n_ifa_flags & IFA_F_TENTATIVE);
+	tent2 = (a2->n_ifa_flags & IFA_F_TENTATIVE);
 	if (tent1 != tent2)
 		return tent1 ? 1 : -1;
 
@@ -230,20 +234,20 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
 	if (p1 != p2)
 		return p1 > p2 ? -1 : 1;
 
-	ipv6_privacy1 = !!(a1->flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY));
-	ipv6_privacy2 = !!(a2->flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY));
+	ipv6_privacy1 = !!(a1->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY));
+	ipv6_privacy2 = !!(a2->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY));
 	if (ipv6_privacy1 || ipv6_privacy2) {
 		gboolean prefer_temp = ((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR;
 		gboolean public1 = TRUE, public2 = TRUE;
 
 		if (ipv6_privacy1) {
-			if (a1->flags & IFA_F_TEMPORARY)
+			if (a1->n_ifa_flags & IFA_F_TEMPORARY)
 				public1 = prefer_temp;
 			else
 				public1 = !prefer_temp;
 		}
 		if (ipv6_privacy2) {
-			if (a2->flags & IFA_F_TEMPORARY)
+			if (a2->n_ifa_flags & IFA_F_TEMPORARY)
 				public2 = prefer_temp;
 			else
 				public2 = !prefer_temp;
@@ -258,8 +262,8 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
 		return a1->source > a2->source ? -1 : 1;
 
 	/* sort permanent addresses before non-permanent. */
-	perm1 = (a1->flags & IFA_F_PERMANENT);
-	perm2 = (a2->flags & IFA_F_PERMANENT);
+	perm1 = (a1->n_ifa_flags & IFA_F_PERMANENT);
+	perm2 = (a2->n_ifa_flags & IFA_F_PERMANENT);
 	if (perm1 != perm2)
 		return perm1 ? -1 : 1;
 
@@ -290,8 +294,8 @@ nm_ip6_config_addresses_sort (NMIP6Config *self, NMSettingIP6ConfigPrivacy use_t
 		g_free (data_pre);
 
 		if (changed) {
-			_NOTIFY (self, PROP_ADDRESS_DATA);
-			_NOTIFY (self, PROP_ADDRESSES);
+			_notify (self, PROP_ADDRESS_DATA);
+			_notify (self, PROP_ADDRESSES);
 			return TRUE;
 		}
 	}
@@ -372,13 +376,13 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
 
 	/* actually, nobody should be connected to the signal, just to be sure, notify */
 	if (notify_nameservers)
-		_NOTIFY (config, PROP_NAMESERVERS);
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ROUTES);
+		_notify (config, PROP_NAMESERVERS);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ADDRESSES);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ROUTES);
 	if (!IN6_ARE_ADDR_EQUAL (&priv->gateway, &old_gateway))
-		_NOTIFY (config, PROP_GATEWAY);
+		_notify (config, PROP_GATEWAY);
 
 	return config;
 }
@@ -713,7 +717,7 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6
 		const NMPlatformIP6Address *item = nm_ip6_config_get_address (config, i);
 
 		if (item->plen <= plen && same_prefix (&item->address, network, item->plen) &&
-		    !(item->flags & IFA_F_NOPREFIXROUTE))
+		    !(item->n_ifa_flags & IFA_F_NOPREFIXROUTE))
 			return TRUE;
 	}
 
@@ -968,8 +972,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
 	const NMPlatformIP6Address *dst_addr, *src_addr;
 	const NMPlatformIP6Route *dst_route, *src_route;
 
-	g_return_val_if_fail (src != NULL, FALSE);
-	g_return_val_if_fail (dst != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (src), FALSE);
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (dst), FALSE);
 	g_return_val_if_fail (src != dst, FALSE);
 
 #if NM_MORE_ASSERTS
@@ -1231,7 +1235,7 @@ nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway)
 			return;
 		memset (&priv->gateway, 0, sizeof (priv->gateway));
 	}
-	_NOTIFY (config, PROP_GATEWAY);
+	_notify (config, PROP_GATEWAY);
 }
 
 const struct in6_addr *
@@ -1259,8 +1263,8 @@ nm_ip6_config_reset_addresses (NMIP6Config *config)
 
 	if (priv->addresses->len != 0) {
 		g_array_set_size (priv->addresses, 0);
-		_NOTIFY (config, PROP_ADDRESS_DATA);
-		_NOTIFY (config, PROP_ADDRESSES);
+		_notify (config, PROP_ADDRESS_DATA);
+		_notify (config, PROP_ADDRESSES);
 	}
 }
 
@@ -1317,8 +1321,8 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
 
 	g_array_append_val (priv->addresses, *new);
 NOTIFY:
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ADDRESSES);
 }
 
 void
@@ -1329,8 +1333,8 @@ nm_ip6_config_del_address (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->addresses->len);
 
 	g_array_remove_index (priv->addresses, i);
-	_NOTIFY (config, PROP_ADDRESS_DATA);
-	_NOTIFY (config, PROP_ADDRESSES);
+	_notify (config, PROP_ADDRESS_DATA);
+	_notify (config, PROP_ADDRESSES);
 }
 
 guint
@@ -1356,6 +1360,29 @@ nm_ip6_config_address_exists (const NMIP6Config *config,
 	return _addresses_get_index (config, needle) >= 0;
 }
 
+const NMPlatformIP6Address *
+nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolean linklocal)
+{
+	NMIP6ConfigPrivate *priv;
+	guint i;
+
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+	linklocal = !!linklocal;
+
+	for (i = 0; i < priv->addresses->len; i++) {
+		const NMPlatformIP6Address *addr = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
+
+		if (   ((!!IN6_IS_ADDR_LINKLOCAL (&addr->address)) == linklocal)
+		    && !(addr->n_ifa_flags & IFA_F_TENTATIVE))
+			return addr;
+	}
+
+	return NULL;
+}
+
 /******************************************************************/
 
 void
@@ -1365,8 +1392,8 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
 
 	if (priv->routes->len != 0) {
 		g_array_set_size (priv->routes, 0);
-		_NOTIFY (config, PROP_ROUTE_DATA);
-		_NOTIFY (config, PROP_ROUTES);
+		_notify (config, PROP_ROUTE_DATA);
+		_notify (config, PROP_ROUTES);
 	}
 }
 
@@ -1409,8 +1436,8 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
 	g_array_append_val (priv->routes, *new);
 	g_array_index (priv->routes, NMPlatformIP6Route, priv->routes->len - 1).ifindex = priv->ifindex;
 NOTIFY:
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ROUTES);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ROUTES);
 }
 
 void
@@ -1421,8 +1448,8 @@ nm_ip6_config_del_route (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->routes->len);
 
 	g_array_remove_index (priv->routes, i);
-	_NOTIFY (config, PROP_ROUTE_DATA);
-	_NOTIFY (config, PROP_ROUTES);
+	_notify (config, PROP_ROUTE_DATA);
+	_notify (config, PROP_ROUTES);
 }
 
 guint
@@ -1512,7 +1539,7 @@ nm_ip6_config_reset_nameservers (NMIP6Config *config)
 
 	if (priv->nameservers->len != 0) {
 		g_array_set_size (priv->nameservers, 0);
-		_NOTIFY (config, PROP_NAMESERVERS);
+		_notify (config, PROP_NAMESERVERS);
 	}
 }
 
@@ -1529,7 +1556,7 @@ nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *new)
 			return;
 
 	g_array_append_val (priv->nameservers, *new);
-	_NOTIFY (config, PROP_NAMESERVERS);
+	_notify (config, PROP_NAMESERVERS);
 }
 
 void
@@ -1540,7 +1567,7 @@ nm_ip6_config_del_nameserver (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->nameservers->len);
 
 	g_array_remove_index (priv->nameservers, i);
-	_NOTIFY (config, PROP_NAMESERVERS);
+	_notify (config, PROP_NAMESERVERS);
 }
 
 guint32
@@ -1568,7 +1595,7 @@ nm_ip6_config_reset_domains (NMIP6Config *config)
 
 	if (priv->domains->len != 0) {
 		g_ptr_array_set_size (priv->domains, 0);
-		_NOTIFY (config, PROP_DOMAINS);
+		_notify (config, PROP_DOMAINS);
 	}
 }
 
@@ -1586,7 +1613,7 @@ nm_ip6_config_add_domain (NMIP6Config *config, const char *domain)
 			return;
 
 	g_ptr_array_add (priv->domains, g_strdup (domain));
-	_NOTIFY (config, PROP_DOMAINS);
+	_notify (config, PROP_DOMAINS);
 }
 
 void
@@ -1597,7 +1624,7 @@ nm_ip6_config_del_domain (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->domains->len);
 
 	g_ptr_array_remove_index (priv->domains, i);
-	_NOTIFY (config, PROP_DOMAINS);
+	_notify (config, PROP_DOMAINS);
 }
 
 guint32
@@ -1625,7 +1652,7 @@ nm_ip6_config_reset_searches (NMIP6Config *config)
 
 	if (priv->searches->len != 0) {
 		g_ptr_array_set_size (priv->searches, 0);
-		_NOTIFY (config, PROP_SEARCHES);
+		_notify (config, PROP_SEARCHES);
 	}
 }
 
@@ -1658,7 +1685,7 @@ nm_ip6_config_add_search (NMIP6Config *config, const char *new)
 	}
 
 	g_ptr_array_add (priv->searches, search);
-	_NOTIFY (config, PROP_SEARCHES);
+	_notify (config, PROP_SEARCHES);
 }
 
 void
@@ -1669,7 +1696,7 @@ nm_ip6_config_del_search (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->searches->len);
 
 	g_ptr_array_remove_index (priv->searches, i);
-	_NOTIFY (config, PROP_SEARCHES);
+	_notify (config, PROP_SEARCHES);
 }
 
 guint32
@@ -1697,7 +1724,7 @@ nm_ip6_config_reset_dns_options (NMIP6Config *config)
 
 	if (priv->dns_options->len != 0) {
 		g_ptr_array_set_size (priv->dns_options, 0);
-		_NOTIFY (config, PROP_DNS_OPTIONS);
+		_notify (config, PROP_DNS_OPTIONS);
 	}
 }
 
@@ -1715,7 +1742,7 @@ nm_ip6_config_add_dns_option (NMIP6Config *config, const char *new)
 			return;
 
 	g_ptr_array_add (priv->dns_options, g_strdup (new));
-	_NOTIFY (config, PROP_DNS_OPTIONS);
+	_notify (config, PROP_DNS_OPTIONS);
 }
 
 void
@@ -1726,7 +1753,7 @@ nm_ip6_config_del_dns_option (NMIP6Config *config, guint i)
 	g_return_if_fail (i < priv->dns_options->len);
 
 	g_ptr_array_remove_index (priv->dns_options, i);
-	_NOTIFY (config, PROP_DNS_OPTIONS);
+	_notify (config, PROP_DNS_OPTIONS);
 }
 
 guint32
@@ -2164,7 +2191,7 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
 		                    G_PARAM_READABLE |
 		                    G_PARAM_STATIC_STRINGS);
 
-	g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (config_class),
 	                                        NMDBUS_TYPE_IP6_CONFIG_SKELETON,
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 3ee83701..5ca64ac3 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -66,6 +66,7 @@ GType nm_ip6_config_get_type (void);
 
 
 NMIP6Config * nm_ip6_config_new (int ifindex);
+NMIP6Config * nm_ip6_config_new_cloned (const NMIP6Config *src);
 
 int nm_ip6_config_get_ifindex (const NMIP6Config *config);
 
@@ -96,10 +97,10 @@ void nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address
 void nm_ip6_config_del_address (NMIP6Config *config, guint i);
 guint nm_ip6_config_get_num_addresses (const NMIP6Config *config);
 const NMPlatformIP6Address *nm_ip6_config_get_address (const NMIP6Config *config, guint i);
+const NMPlatformIP6Address *nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolean linklocal);
 gboolean nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address *address);
 gboolean nm_ip6_config_addresses_sort (NMIP6Config *config, NMSettingIP6ConfigPrivacy use_temporary);
 
-
 /* Routes */
 void nm_ip6_config_reset_routes (NMIP6Config *config);
 void nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *route);
diff --git a/src/nm-logging.c b/src/nm-logging.c
index 60ccb5cb..5bb3660f 100644
--- a/src/nm-logging.c
+++ b/src/nm-logging.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <dlfcn.h>
 #include <syslog.h>
@@ -32,15 +32,50 @@
 #include <strings.h>
 #include <string.h>
 
+#if defined (NO_SYSTEMD_JOURNAL) && defined (SYSTEMD_JOURNAL)
+#undef SYSTEMD_JOURNAL
+#define SYSTEMD_JOURNAL 0
+#endif
+
 #if SYSTEMD_JOURNAL
 #define SD_JOURNAL_SUPPRESS_LOCATION
 #include <systemd/sd-journal.h>
 #endif
 
-#include "nm-default.h"
 #include "nm-errors.h"
-#include "NetworkManagerUtils.h"
-#include "nm-linux-platform.h"
+#include "nm-core-utils.h"
+
+typedef enum {
+	LOG_FORMAT_FLAG_NONE                                = 0,
+	LOG_FORMAT_FLAG_TIMESTAMP_DEBUG                     = (1LL << 0),
+	LOG_FORMAT_FLAG_TIMESTAMP_INFO                      = (1LL << 1),
+	LOG_FORMAT_FLAG_TIMESTAMP_ERROR                     = (1LL << 2),
+	LOG_FORMAT_FLAG_LOCATION_DEBUG                      = (1LL << 3),
+	LOG_FORMAT_FLAG_LOCATION_INFO                       = (1LL << 4),
+	LOG_FORMAT_FLAG_LOCATION_ERROR                      = (1LL << 5),
+	LOG_FORMAT_FLAG_ALIGN_LOCATION                      = (1LL << 6),
+
+	_LOG_FORMAT_FLAG_TIMESTAMP                          = LOG_FORMAT_FLAG_TIMESTAMP_DEBUG |
+	                                                      LOG_FORMAT_FLAG_TIMESTAMP_INFO |
+	                                                      LOG_FORMAT_FLAG_TIMESTAMP_ERROR,
+	_LOG_FORMAT_FLAG_LOCATION                           = LOG_FORMAT_FLAG_LOCATION_DEBUG |
+	                                                      LOG_FORMAT_FLAG_LOCATION_INFO |
+	                                                      LOG_FORMAT_FLAG_LOCATION_ERROR,
+
+	_LOG_FORMAT_FLAG_LEVEL_DEBUG                        = LOG_FORMAT_FLAG_TIMESTAMP_DEBUG |
+	                                                      LOG_FORMAT_FLAG_LOCATION_DEBUG,
+	_LOG_FORMAT_FLAG_LEVEL_INFO                         = LOG_FORMAT_FLAG_TIMESTAMP_INFO |
+	                                                      LOG_FORMAT_FLAG_LOCATION_INFO,
+	_LOG_FORMAT_FLAG_LEVEL_ERROR                        = LOG_FORMAT_FLAG_TIMESTAMP_ERROR |
+	                                                      LOG_FORMAT_FLAG_LOCATION_ERROR,
+
+	_LOG_FORMAT_FLAG_SYSLOG                             = _LOG_FORMAT_FLAG_TIMESTAMP |
+	                                                      LOG_FORMAT_FLAG_LOCATION_DEBUG |
+	                                                      LOG_FORMAT_FLAG_LOCATION_ERROR |
+	                                                      LOG_FORMAT_FLAG_ALIGN_LOCATION,
+} LogFormatFlags;
+
+void (*_nm_logging_clear_platform_logging_cache) (void);
 
 static void
 nm_log_handler (const gchar *log_domain,
@@ -58,18 +93,18 @@ typedef struct {
 	const char *level_str;
 	int syslog_level;
 	GLogLevelFlags g_log_level;
-	gboolean full_details;
+	LogFormatFlags log_format_level;
 } LogLevelDesc;
 
 static struct {
 	NMLogLevel log_level;
 	NMLogDomain logging[_LOGL_N_REAL];
 	gboolean logging_set_up;
+	LogFormatFlags log_format_flags;
 	enum {
 		LOG_BACKEND_GLIB,
 		LOG_BACKEND_SYSLOG,
 		LOG_BACKEND_JOURNAL,
-		LOG_BACKEND_JOURNAL_SYSLOG_STYLE,
 	} log_backend;
 	char *logging_domains_to_string;
 	const LogLevelDesc level_desc[_LOGL_N];
@@ -82,13 +117,13 @@ static struct {
 	.log_level = LOGL_INFO,
 	.log_backend = LOG_BACKEND_GLIB,
 	.level_desc = {
-		[LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG,   G_LOG_LEVEL_DEBUG,   TRUE  },
-		[LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_INFO,    G_LOG_LEVEL_DEBUG,   TRUE  },
-		[LOGL_INFO]  = { "INFO",  "<info>",  LOG_INFO,    G_LOG_LEVEL_MESSAGE, FALSE },
-		[LOGL_WARN]  = { "WARN",  "<warn>",  LOG_WARNING, G_LOG_LEVEL_WARNING, FALSE },
-		[LOGL_ERR]   = { "ERR",   "<error>", LOG_ERR,     G_LOG_LEVEL_WARNING, TRUE  },
-		[_LOGL_OFF]  = { "OFF",   NULL,      0,           0,                   FALSE },
-		[_LOGL_KEEP] = { "KEEP",  NULL,      0,           0,                   FALSE },
+		[LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG,   G_LOG_LEVEL_DEBUG,   _LOG_FORMAT_FLAG_LEVEL_DEBUG },
+		[LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_INFO,    G_LOG_LEVEL_DEBUG,   _LOG_FORMAT_FLAG_LEVEL_DEBUG },
+		[LOGL_INFO]  = { "INFO",  "<info>",  LOG_INFO,    G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_INFO },
+		[LOGL_WARN]  = { "WARN",  "<warn>",  LOG_WARNING, G_LOG_LEVEL_WARNING, _LOG_FORMAT_FLAG_LEVEL_INFO },
+		[LOGL_ERR]   = { "ERR",   "<error>", LOG_ERR,     G_LOG_LEVEL_WARNING, _LOG_FORMAT_FLAG_LEVEL_ERROR },
+		[_LOGL_OFF]  = { "OFF",   NULL,      0,           0,                   0 },
+		[_LOGL_KEEP] = { "KEEP",  NULL,      0,           0,                   0 },
 	},
 	.domain_desc = {
 		{ LOGD_PLATFORM,  "PLATFORM" },
@@ -149,8 +184,14 @@ static char *_domains_to_string (gboolean include_level_override);
 static void
 _ensure_initialized (void)
 {
-	if (G_UNLIKELY (!global.logging_set_up))
+	if (G_UNLIKELY (!global.logging_set_up)) {
+		int errsv = errno;
+
 		nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL);
+
+		/* must ensure that errno is not modified. */
+		errno = errsv;
+	}
 }
 
 static gboolean
@@ -297,11 +338,12 @@ nm_logging_setup (const char  *level,
 		global.logging[i] = new_logging[i];
 
 	if (   had_platform_debug
+	    && _nm_logging_clear_platform_logging_cache
 	    && !nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
 		/* when debug logging is enabled, platform will cache all access to
 		 * sysctl. When the user disables debug-logging, we want to clear that
 		 * cache right away. */
-		_nm_linux_platform_sysctl_clear_cache ();
+		_nm_logging_clear_platform_logging_cache ();
 	}
 
 	if (unrecognized)
@@ -419,6 +461,7 @@ nm_logging_enabled (NMLogLevel level, NMLogDomain domain)
 	if ((guint) level >= G_N_ELEMENTS (global.logging))
 		g_return_val_if_reached (FALSE);
 
+	/* This function is guaranteed not to modify errno. */
 	_ensure_initialized ();
 
 	return !!(global.logging[level] & domain);
@@ -448,7 +491,7 @@ _iovec_set_string (struct iovec *iov, gboolean *iov_free, int i, const char *str
 	iov[i].iov_len = len;
 	iov_free[i] = FALSE;
 }
-#define _iovec_set_literal_string(iov, iov_free, i, str) _iovec_set_string ((iov), (iov_free), (i), (""str""), STRLEN (str))
+#define _iovec_set_literal_string(iov, iov_free, i, str) _iovec_set_string ((iov), (iov_free), (i), (""str""), NM_STRLEN (str))
 #endif
 
 void
@@ -463,7 +506,9 @@ _nm_log_impl (const char *file,
 {
 	va_list args;
 	char *msg;
-	char *fullmsg = NULL;
+	char *fullmsg;
+	char s_buf_timestamp[64];
+	char s_buf_location[1024];
 	GTimeVal tv;
 
 	if ((guint) level >= G_N_ELEMENTS (global.logging))
@@ -485,10 +530,55 @@ _nm_log_impl (const char *file,
 	msg = g_strdup_vprintf (fmt, args);
 	va_end (args);
 
+	if (NM_FLAGS_ANY (global.log_format_flags, global.level_desc[level].log_format_level & _LOG_FORMAT_FLAG_TIMESTAMP)) {
+		g_get_current_time (&tv);
+		nm_sprintf_buf (s_buf_timestamp, " [%ld.%06ld]", tv.tv_sec, tv.tv_usec);
+	} else
+		s_buf_timestamp[0] = '\0';
+
+	s_buf_location[0] = '\0';
+	if (NM_FLAGS_ANY (global.log_format_flags, global.level_desc[level].log_format_level & _LOG_FORMAT_FLAG_LOCATION)) {
+#define MAX_LEN_FILE 37
+#define MAX_LEN_FUNC 26
+		gsize l = sizeof (s_buf_location);
+		char *p = s_buf_location, *p_buf;
+		gsize len;
+		char s_buf[MAX (MAX_LEN_FILE, MAX_LEN_FUNC) + 30];
+
+		if (file) {
+			if (NM_FLAGS_HAS (global.log_format_flags, LOG_FORMAT_FLAG_ALIGN_LOCATION)) {
+				/* left-align the "[file:line]" string, but truncate from left to MAX_LEN_FILE chars. */
+				len = strlen (file);
+				nm_sprintf_buf (s_buf, "[%s:%u]",
+				                len > MAX_LEN_FILE ? &file[len - MAX_LEN_FILE] : file,
+				                line);
+				len = strlen (s_buf);
+				if (len > MAX_LEN_FILE) {
+					p_buf = &s_buf[len - MAX_LEN_FILE];
+					p_buf[0] = '[';
+				} else
+					p_buf = s_buf;
+				nm_utils_strbuf_append (&p, &l, " %-"G_STRINGIFY (MAX_LEN_FILE)"s", p_buf);
+			} else
+				nm_utils_strbuf_append (&p, &l, " [%s:%u]", file, line);
+		}
+		if (func) {
+			if (NM_FLAGS_HAS (global.log_format_flags, LOG_FORMAT_FLAG_ALIGN_LOCATION)) {
+				/* left-align the "func():" string, but truncate from left to MAX_LEN_FUNC chars. */
+				len = strlen (func);
+				nm_sprintf_buf (s_buf, "%s():",
+				                len > MAX_LEN_FUNC ? &func[len - MAX_LEN_FUNC] : func);
+				len = strlen (s_buf);
+				nm_utils_strbuf_append (&p, &l, " %-"G_STRINGIFY (MAX_LEN_FUNC)"s",
+				                        len > MAX_LEN_FUNC ? &s_buf[len - MAX_LEN_FUNC] : s_buf);
+			} else
+				nm_utils_strbuf_append (&p, &l, " %s():", func);
+		}
+	}
+
 	switch (global.log_backend) {
 #if SYSTEMD_JOURNAL
 	case LOG_BACKEND_JOURNAL:
-	case LOG_BACKEND_JOURNAL_SYSLOG_STYLE:
 		{
 			gint64 now, boottime;
 #define _NUM_MAX_FIELDS_SYSLOG_FACILITY 10
@@ -501,12 +591,12 @@ _nm_log_impl (const char *file,
 			boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
 
 			_iovec_set_format (iov, iov_free, i_field++, "PRIORITY=%d", global.level_desc[level].syslog_level);
-			if (   global.log_backend == LOG_BACKEND_JOURNAL_SYSLOG_STYLE
-			    && global.level_desc[level].full_details) {
-				g_get_current_time (&tv);
-				_iovec_set_format (iov, iov_free, i_field++, "MESSAGE=%-7s [%ld.%06ld] [%s:%u] %s(): %s", global.level_desc[level].level_str, tv.tv_sec, tv.tv_usec, file, line, func, msg);
-			} else
-				_iovec_set_format (iov, iov_free, i_field++, "MESSAGE=%-7s %s", global.level_desc[level].level_str, msg);
+			_iovec_set_format (iov, iov_free, i_field++, "MESSAGE="
+			                   "%-7s%s%s %s",
+			                   global.level_desc[level].level_str,
+			                   s_buf_timestamp,
+			                   s_buf_location,
+			                   msg);
 			_iovec_set_literal_string (iov, iov_free, i_field++, "SYSLOG_IDENTIFIER=" G_LOG_DOMAIN);
 			_iovec_set_format (iov, iov_free, i_field++, "SYSLOG_PID=%ld", (long) getpid ());
 			{
@@ -552,8 +642,8 @@ _nm_log_impl (const char *file,
 					_iovec_set_format (iov, iov_free, i_field++, "NM_LOG_DOMAINS=%s", s_domain_1);
 			}
 			_iovec_set_format (iov, iov_free, i_field++, "NM_LOG_LEVEL=%s", global.level_desc[level].name);
-			_iovec_set_format (iov, iov_free, i_field++, "CODE_FUNC=%s", func);
-			_iovec_set_format (iov, iov_free, i_field++, "CODE_FILE=%s", file);
+			_iovec_set_format (iov, iov_free, i_field++, "CODE_FUNC=%s", func ?: "");
+			_iovec_set_format (iov, iov_free, i_field++, "CODE_FILE=%s", file ?: "");
 			_iovec_set_format (iov, iov_free, i_field++, "CODE_LINE=%u", line);
 			_iovec_set_format (iov, iov_free, i_field++, "TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NS_PER_SECOND), (long long) ((now % NM_UTILS_NS_PER_SECOND) / 1000));
 			_iovec_set_format (iov, iov_free, i_field++, "TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NS_PER_SECOND), (long long) ((boottime % NM_UTILS_NS_PER_SECOND) / 1000));
@@ -573,21 +663,21 @@ _nm_log_impl (const char *file,
 		break;
 #endif
 	default:
-		if (global.level_desc[level].full_details) {
-			g_get_current_time (&tv);
-			fullmsg = g_strdup_printf ("%-7s [%ld.%06ld] [%s:%u] %s(): %s", global.level_desc[level].level_str, tv.tv_sec, tv.tv_usec, file, line, func, msg);
-		} else
-			fullmsg = g_strdup_printf ("%-7s %s", global.level_desc[level].level_str, msg);
+		fullmsg = g_strdup_printf ("%-7s%s%s %s",
+		                           global.level_desc[level].level_str,
+		                           s_buf_timestamp,
+		                           s_buf_location,
+		                           msg);
 
 		if (global.log_backend == LOG_BACKEND_SYSLOG)
 			syslog (global.level_desc[level].syslog_level, "%s", fullmsg);
 		else
 			g_log (G_LOG_DOMAIN, global.level_desc[level].g_log_level, "%s", fullmsg);
+		g_free (fullmsg);
 		break;
 	}
 
 	g_free (msg);
-	g_free (fullmsg);
 }
 
 /************************************************************************/
@@ -625,7 +715,6 @@ nm_log_handler (const gchar *log_domain,
 	switch (global.log_backend) {
 #if SYSTEMD_JOURNAL
 	case LOG_BACKEND_JOURNAL:
-	case LOG_BACKEND_JOURNAL_SYSLOG_STYLE:
 		{
 			gint64 now, boottime;
 
@@ -654,6 +743,8 @@ nm_log_handler (const gchar *log_domain,
 void
 nm_logging_syslog_openlog (const char *logging_backend)
 {
+	LogFormatFlags log_format_flags;
+
 	if (global.log_backend != LOG_BACKEND_GLIB)
 		g_return_if_reached ();
 
@@ -663,12 +754,14 @@ nm_logging_syslog_openlog (const char *logging_backend)
 	if (strcmp (logging_backend, "debug") == 0) {
 		global.log_backend = LOG_BACKEND_SYSLOG;
 		openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER);
+		log_format_flags = _LOG_FORMAT_FLAG_SYSLOG;
 #if SYSTEMD_JOURNAL
 	} else if (strcmp (logging_backend, "syslog") != 0) {
-		if (strcmp (logging_backend, "journal-syslog-style") != 0)
-			global.log_backend = LOG_BACKEND_JOURNAL;
+		if (strcmp (logging_backend, "journal-syslog-style") == 0)
+			log_format_flags = _LOG_FORMAT_FLAG_SYSLOG;
 		else
-			global.log_backend = LOG_BACKEND_JOURNAL_SYSLOG_STYLE;
+			log_format_flags = _LOG_FORMAT_FLAG_TIMESTAMP;
+		global.log_backend = LOG_BACKEND_JOURNAL;
 
 		/* ensure we read a monotonic timestamp. Reading the timestamp the first
 		 * time causes a logging message. We don't want to do that during _nm_log_impl. */
@@ -676,9 +769,12 @@ nm_logging_syslog_openlog (const char *logging_backend)
 #endif
 	} else {
 		global.log_backend = LOG_BACKEND_SYSLOG;
+		log_format_flags = _LOG_FORMAT_FLAG_SYSLOG;
 		openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON);
 	}
 
+	global.log_format_flags = log_format_flags;
+
 	g_log_set_handler (G_LOG_DOMAIN,
 	                   G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
 	                   nm_log_handler,
diff --git a/src/nm-logging.h b/src/nm-logging.h
index 19b965f8..97102770 100644
--- a/src/nm-logging.h
+++ b/src/nm-logging.h
@@ -26,11 +26,6 @@
 #error nm-test-utils.h must be included as last header
 #endif
 
-#include "nm-logging.h"
-
-#include "nm-default.h"
-#include "nm-macros-internal.h"
-
 /* Log domains */
 typedef enum  { /*< skip >*/
 	LOGD_NONE       = 0LL,
@@ -189,15 +184,23 @@ void     nm_logging_syslog_openlog (const char *logging_backend);
 #define _LOGW_ENABLED(...)  _NMLOG_ENABLED (LOGL_WARN , ##__VA_ARGS__)
 #define _LOGE_ENABLED(...)  _NMLOG_ENABLED (LOGL_ERR  , ##__VA_ARGS__)
 
+#define _LOGT_err(errsv, ...) _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_err(errsv, ...) _NMLOG_err (errsv, LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_err(errsv, ...) _NMLOG_err (errsv, LOGL_INFO , __VA_ARGS__)
+#define _LOGW_err(errsv, ...) _NMLOG_err (errsv, LOGL_WARN , __VA_ARGS__)
+#define _LOGE_err(errsv, ...) _NMLOG_err (errsv, LOGL_ERR  , __VA_ARGS__)
+
 /* _LOGT() and _LOGt() both log with level TRACE, but the latter is disabled by default,
  * unless building with --with-more-logging. */
 #ifdef NM_MORE_LOGGING
-#define _LOGt_ENABLED(...)  _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
-#define _LOGt(...)          _NMLOG (LOGL_TRACE, __VA_ARGS__)
+#define _LOGt_ENABLED(...)    _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOGt(...)            _NMLOG (LOGL_TRACE, __VA_ARGS__)
+#define _LOGt_err(errsv, ...) _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__)
 #else
 /* still call the logging macros to get compile time checks, but they will be optimized out. */
-#define _LOGt_ENABLED(...)  ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
-#define _LOGt(...)          G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+#define _LOGt_ENABLED(...)    ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
+#define _LOGt(...)            G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+#define _LOGt_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
 #endif
 
 /*****************************************************************************/
@@ -206,32 +209,42 @@ void     nm_logging_syslog_openlog (const char *logging_backend);
  * use. As with the _LOGD() macro familiy above, the exact implementation
  * depends on the file that uses them.
  * Still, it encourages a common pattern to have the common set of macros
- * like _LOG2D(), _LOG2I(), etc. and have _LOG2T() which by default
+ * like _LOG2D(), _LOG2I(), etc. and have _LOG2t() which by default
  * is disabled at compile time. */
 
 #define _NMLOG2_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG2_DOMAIN)) )
 
-#define _LOG2t(...)          _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
+#define _LOG2T(...)          _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
 #define _LOG2D(...)          _NMLOG2 (LOGL_DEBUG, __VA_ARGS__)
 #define _LOG2I(...)          _NMLOG2 (LOGL_INFO , __VA_ARGS__)
 #define _LOG2W(...)          _NMLOG2 (LOGL_WARN , __VA_ARGS__)
 #define _LOG2E(...)          _NMLOG2 (LOGL_ERR  , __VA_ARGS__)
 
-#define _LOG2t_ENABLED(...)  _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOG2T_ENABLED(...)  _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
 #define _LOG2D_ENABLED(...)  _NMLOG2_ENABLED (LOGL_DEBUG, ##__VA_ARGS__)
 #define _LOG2I_ENABLED(...)  _NMLOG2_ENABLED (LOGL_INFO , ##__VA_ARGS__)
 #define _LOG2W_ENABLED(...)  _NMLOG2_ENABLED (LOGL_WARN , ##__VA_ARGS__)
 #define _LOG2E_ENABLED(...)  _NMLOG2_ENABLED (LOGL_ERR  , ##__VA_ARGS__)
 
+#define _LOG2T_err(errsv, ...) _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__)
+#define _LOG2D_err(errsv, ...) _NMLOG2_err (errsv, LOGL_DEBUG, __VA_ARGS__)
+#define _LOG2I_err(errsv, ...) _NMLOG2_err (errsv, LOGL_INFO , __VA_ARGS__)
+#define _LOG2W_err(errsv, ...) _NMLOG2_err (errsv, LOGL_WARN , __VA_ARGS__)
+#define _LOG2E_err(errsv, ...) _NMLOG2_err (errsv, LOGL_ERR  , __VA_ARGS__)
+
 #ifdef NM_MORE_LOGGING
-#define _LOG2T_ENABLED(...)  _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
-#define _LOG2T(...)          _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
+#define _LOG2t_ENABLED(...)    _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOG2t(...)            _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
+#define _LOG2t_err(errsv, ...) _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__)
 #else
 /* still call the logging macros to get compile time checks, but they will be optimized out. */
-#define _LOG2T_ENABLED(...)  ( FALSE && (_NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
-#define _LOG2T(...)          G_STMT_START { if (FALSE) { _NMLOG2 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+#define _LOG2t_ENABLED(...)    ( FALSE && (_NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
+#define _LOG2t(...)            G_STMT_START { if (FALSE) { _NMLOG2 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+#define _LOG2t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
 #endif
 
+extern void (*_nm_logging_clear_platform_logging_cache) (void);
+
 /*****************************************************************************/
 
 #endif /* __NETWORKMANAGER_LOGGING_H__ */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index ffc89ec0..7f414e8f 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <fcntl.h>
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "nm-default.h"
 #include "nm-manager.h"
 #include "nm-bus-manager.h"
 #include "nm-vpn-manager.h"
@@ -833,9 +832,9 @@ remove_device (NMManager *manager,
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
 
 	nm_log_dbg (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)",
-	            nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device));
+	            nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE));
 
-	if (allow_unmanage && nm_device_get_managed (device)) {
+	if (allow_unmanage && nm_device_get_managed (device, FALSE)) {
 		NMActRequest *req = nm_device_get_act_request (device);
 		gboolean unmanage = FALSE;
 
@@ -853,9 +852,9 @@ remove_device (NMManager *manager,
 
 		if (unmanage) {
 			if (quitting)
-				nm_device_set_unmanaged_quitting (device);
+				nm_device_set_unmanaged_by_quitting (device);
 			else
-				nm_device_set_unmanaged_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
+				nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
 		} else if (quitting && nm_config_get_configure_and_quit (nm_config_get ())) {
 			nm_device_spawn_iface_helper (device);
 		}
@@ -896,7 +895,7 @@ nm_manager_get_state (NMManager *manager)
 /***************************/
 
 static NMDevice *
-find_parent_device_for_connection (NMManager *self, NMConnection *connection)
+find_parent_device_for_connection (NMManager *self, NMConnection *connection, NMDeviceFactory *cached_factory)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 	NMDeviceFactory *factory;
@@ -907,9 +906,12 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection)
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
-	factory = nm_device_factory_manager_find_factory_for_connection (connection);
-	if (!factory)
-		return NULL;
+	if (!cached_factory) {
+		factory = nm_device_factory_manager_find_factory_for_connection (connection);
+		if (!factory)
+			return NULL;
+	} else
+		factory = cached_factory;
 
 	parent_name = nm_device_factory_get_connection_parent (factory, connection);
 	if (!parent_name)
@@ -948,24 +950,24 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection)
 }
 
 /**
- * get_virtual_iface_name:
+ * nm_manager_get_connection_iface:
  * @self: the #NMManager
- * @connection: the #NMConnection representing a virtual interface
+ * @connection: the #NMConnection to get the interface for
  * @out_parent: on success, the parent device if any
  * @error: an error if determining the virtual interface name failed
  *
  * Given @connection, returns the interface name that the connection
- * would represent if it is a virtual connection.  %NULL is returned and
- * @error is set if the connection is not virtual, or if the name could
- * not be determined.
+ * would need to use when activated. %NULL is returned if the name
+ * is not specified in connection or a the name for a virtual device
+ * could not be generated.
  *
  * Returns: the expected interface name (caller takes ownership), or %NULL
  */
-static char *
-get_virtual_iface_name (NMManager *self,
-                        NMConnection *connection,
-                        NMDevice **out_parent,
-                        GError **error)
+char *
+nm_manager_get_connection_iface (NMManager *self,
+                                 NMConnection *connection,
+                                 NMDevice **out_parent,
+                                 GError **error)
 {
 	NMDeviceFactory *factory;
 	char *iface = NULL;
@@ -974,15 +976,6 @@ get_virtual_iface_name (NMManager *self,
 	if (out_parent)
 		*out_parent = NULL;
 
-	if (!nm_connection_is_virtual (connection)) {
-		g_set_error (error,
-		             NM_MANAGER_ERROR,
-		             NM_MANAGER_ERROR_FAILED,
-		             "NetworkManager plugin for '%s' unavailable",
-		             nm_connection_get_connection_type (connection));
-		return NULL;
-	}
-
 	factory = nm_device_factory_manager_find_factory_for_connection (connection);
 	if (!factory) {
 		g_set_error (error,
@@ -993,18 +986,28 @@ get_virtual_iface_name (NMManager *self,
 		return NULL;
 	}
 
-	parent = find_parent_device_for_connection (self, connection);
-	iface = nm_device_factory_get_virtual_iface_name (factory,
-	                                                  connection,
-	                                                  parent ? nm_device_get_ip_iface (parent) : NULL);
-	if (!iface) {
-		g_set_error_literal (error,
-		                     NM_MANAGER_ERROR,
-		                     NM_MANAGER_ERROR_UNKNOWN_DEVICE,
-		                     "failed to determine virtual interface name");
-		return NULL;
+	if (   !out_parent
+	    && !NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_connection_iface) {
+		/* optimization. Shortcut lookup of the partent device. */
+		iface = g_strdup (nm_connection_get_interface_name (connection));
+		if (!iface) {
+			g_set_error (error,
+			             NM_MANAGER_ERROR,
+			             NM_MANAGER_ERROR_FAILED,
+			             "failed to determine interface name: error determine name for %s",
+			             nm_connection_get_connection_type (connection));
+		}
+		return iface;
 	}
 
+	parent = find_parent_device_for_connection (self, connection, factory);
+	iface = nm_device_factory_get_connection_iface (factory,
+	                                                connection,
+	                                                parent ? nm_device_get_ip_iface (parent) : NULL,
+	                                                error);
+	if (!iface)
+		return NULL;
+
 	if (out_parent)
 		*out_parent = parent;
 	return iface;
@@ -1025,7 +1028,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 	NMDeviceFactory *factory;
-	GSList *connections, *iter;
+	gs_free_slist GSList *connections = NULL;
+	GSList *iter;
 	gs_free char *iface = NULL;
 	NMDevice *device = NULL, *parent = NULL;
 	GError *error = NULL;
@@ -1033,7 +1037,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
 	g_return_val_if_fail (NM_IS_MANAGER (self), NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
-	iface = get_virtual_iface_name (self, connection, &parent, &error);
+	iface = nm_manager_get_connection_iface (self, connection, &parent, &error);
 	if (!iface) {
 		nm_log_warn (LOGD_DEVICE, "(%s) can't get a name of a virtual device: %s",
 		             nm_connection_get_id (connection), error->message);
@@ -1045,9 +1049,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
 	for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
 		NMDevice *candidate = iter->data;
 
-		if (   g_strcmp0 (nm_device_get_iface (candidate), iface) == 0
-		    && nm_device_check_connection_compatible (candidate, connection)) {
-
+		if (nm_device_check_connection_compatible (candidate, connection)) {
 			if (nm_device_is_real (candidate)) {
 				nm_log_dbg (LOGD_DEVICE, "(%s) already created virtual interface name %s",
 				            nm_connection_get_id (connection), iface);
@@ -1133,10 +1135,12 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device)
 		NMConnection *candidate = iter->data;
 		NMDevice *parent;
 
-		parent = find_parent_device_for_connection (self, candidate);
+		parent = find_parent_device_for_connection (self, candidate, NULL);
 		if (parent == device)
 			connection_changed (priv->settings, candidate, self);
 	}
+
+	g_slist_free (connections);
 }
 
 static void
@@ -1181,7 +1185,7 @@ system_unmanaged_devices_changed_cb (NMSettings *settings,
 
 	unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
 	for (iter = priv->devices; iter; iter = g_slist_next (iter))
-		nm_device_set_unmanaged_flags_by_device_spec (NM_DEVICE (iter->data), unmanaged_specs);
+		nm_device_set_unmanaged_by_user_config (NM_DEVICE (iter->data), unmanaged_specs);
 }
 
 static void
@@ -1592,6 +1596,8 @@ get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_gen
 	matched = NM_SETTINGS_CONNECTION (nm_utils_match_connection (connections,
 	                                                             connection,
 	                                                             nm_device_has_carrier (device),
+	                                                             nm_device_get_ip4_route_metric (device),
+	                                                             nm_device_get_ip6_route_metric (device),
 	                                                             match_connection_filter,
 	                                                             device));
 	if (matched) {
@@ -1672,14 +1678,6 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn
 }
 
 static gboolean
-can_start_device (NMManager *self, NMDevice *device)
-{
-	return    nm_device_is_real (device)
-	       && !manager_sleeping (self)
-	       && !nm_device_get_unmanaged_flags (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT);
-}
-
-static gboolean
 recheck_assume_connection (NMManager *self, NMDevice *device)
 {
 	NMSettingsConnection *connection;
@@ -1692,7 +1690,7 @@ recheck_assume_connection (NMManager *self, NMDevice *device)
 	if (nm_device_get_is_nm_owned (device))
 		return FALSE;
 
-	if (!can_start_device (self, device))
+	if (!nm_device_get_managed (device, FALSE))
 		return FALSE;
 
 	state = nm_device_get_state (device);
@@ -1719,13 +1717,6 @@ recheck_assume_connection (NMManager *self, NMDevice *device)
 			nm_device_state_changed (device,
 			                         NM_DEVICE_STATE_UNAVAILABLE,
 			                         NM_DEVICE_STATE_REASON_CONFIG_FAILED);
-
-			/* Return default-unmanaged devices to their original state */
-			if (nm_device_get_unmanaged_flags (device, NM_UNMANAGED_DEFAULT)) {
-				nm_device_state_changed (device,
-				                         NM_DEVICE_STATE_UNMANAGED,
-				                         NM_DEVICE_STATE_REASON_CONFIG_FAILED);
-			}
 		}
 
 		if (generated) {
@@ -1787,26 +1778,31 @@ device_realized (NMDevice *device,
                  GParamSpec *pspec,
                  NMManager *self)
 {
-	int ifindex;
-
 	/* Emit D-Bus signals */
 	g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
 	g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
+}
 
-	/* Loopback device never gets managed */
-	ifindex = nm_device_get_ifindex (device);
-	if (ifindex > 0 && nm_platform_link_get_type (NM_PLATFORM_GET, ifindex) == NM_LINK_TYPE_LOOPBACK)
+static void
+_device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink *plink)
+{
+	g_return_if_fail (NM_IS_MANAGER (self));
+	g_return_if_fail (NM_IS_DEVICE (device));
+
+	nm_device_realize_finish (device, plink);
+
+	if (!nm_device_get_managed (device, FALSE))
 		return;
 
-	if (!can_start_device (self, device))
+	if (recheck_assume_connection (self, device))
 		return;
 
-	if (   !recheck_assume_connection (self, device)
-	    && nm_device_get_managed (device)) {
-		nm_device_state_changed (device,
-		                         NM_DEVICE_STATE_UNAVAILABLE,
-		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
-	}
+	/* if we failed to assume a connection for the managed device, but the device
+	 * is still unavailable. Set UNAVAILABLE state again, this time with NOW_MANAGED. */
+	nm_device_state_changed (device,
+	                         NM_DEVICE_STATE_UNAVAILABLE,
+	                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
+	nm_device_emit_recheck_auto_activate (device);
 }
 
 /**
@@ -1823,7 +1819,6 @@ add_device (NMManager *self, NMDevice *device, GError **error)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 	const char *iface, *type_desc;
-	const GSList *unmanaged_specs;
 	RfKillType rtype;
 	GSList *iter, *remove = NULL;
 	int ifindex;
@@ -1833,7 +1828,7 @@ add_device (NMManager *self, NMDevice *device, GError **error)
 	ifindex = nm_device_get_ifindex (device);
 	if (ifindex > 0 && nm_manager_get_device_by_ifindex (self, ifindex)) {
 		g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
-		             "A device with ifindex %d already exits", ifindex);
+		             "A device with ifindex %d already exists", ifindex);
 		return FALSE;
 	}
 
@@ -1906,19 +1901,15 @@ add_device (NMManager *self, NMDevice *device, GError **error)
 	type_desc = nm_device_get_type_desc (device);
 	g_assert (type_desc);
 
-	unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
-	nm_device_set_unmanaged_flags_initial (device,
-	                                       NM_UNMANAGED_USER,
-	                                       nm_device_spec_match_list (device, unmanaged_specs));
-	nm_device_set_unmanaged_flags_initial (device,
-	                                       NM_UNMANAGED_INTERNAL,
-	                                       manager_sleeping (self));
+	nm_device_set_unmanaged_by_user_config (device, nm_settings_get_unmanaged_specs (priv->settings));
+
+	nm_device_set_unmanaged_flags (device,
+	                               NM_UNMANAGED_SLEEPING,
+	                               manager_sleeping (self));
 
 	dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device));
 	nm_log_info (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path);
 
-	nm_device_finish_init (device);
-
 	nm_settings_device_added (priv->settings, device);
 	g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device);
 	g_object_notify (G_OBJECT (self), NM_MANAGER_ALL_DEVICES);
@@ -1945,11 +1936,14 @@ factory_device_added_cb (NMDeviceFactory *factory,
                          NMDevice *device,
                          gpointer user_data)
 {
+	NMManager *self = user_data;
 	GError *error = NULL;
 
+	g_return_if_fail (NM_IS_MANAGER (self));
+
 	if (nm_device_realize_start (device, NULL, NULL, &error)) {
-		add_device (NM_MANAGER (user_data), device, NULL);
-		nm_device_realize_finish (device, NULL);
+		add_device (self, device, NULL);
+		_device_realize_finish (self, device, NULL);
 	} else {
 		nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s",
 		             nm_device_get_iface (device), error->message);
@@ -2021,7 +2015,7 @@ platform_link_added (NMManager *self,
 			return;
 		} else if (nm_device_realize_start (candidate, plink, &compatible, &error)) {
 			/* Success */
-			nm_device_realize_finish (candidate, plink);
+			_device_realize_finish (self, candidate, plink);
 			return;
 		}
 
@@ -2070,7 +2064,7 @@ platform_link_added (NMManager *self,
 			nm_device_set_nm_plugin_missing (device, TRUE);
 		if (nm_device_realize_start (device, plink, NULL, &error)) {
 			add_device (self, device, NULL);
-			nm_device_realize_finish (device, plink);
+			_device_realize_finish (self, device, plink);
 		} else {
 			nm_log_warn (LOGD_DEVICE, "%s: failed to realize device: %s",
 			             plink->name, error->message);
@@ -2569,21 +2563,6 @@ ensure_master_active_connection (NMManager *self,
 			return master_ac;
 		}
 
-		/* Device described by master_connection may be a virtual one that's
-		 * not created yet.
-		 */
-		if (!found_device && nm_connection_is_virtual (NM_CONNECTION (master_connection))) {
-			master_ac = nm_manager_activate_connection (self,
-			                                            master_connection,
-			                                            NULL,
-			                                            NULL,
-			                                            subject,
-			                                            error);
-			if (!master_ac)
-				g_prefix_error (error, "%s", "Master device activation failed: ");
-			return master_ac;
-		}
-
 		g_set_error (error,
 		             NM_MANAGER_ERROR,
 		             NM_MANAGER_ERROR_UNKNOWN_DEVICE,
@@ -2792,7 +2771,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
 	if (!nm_device_is_real (device)) {
 		NMDevice *parent;
 
-		parent = find_parent_device_for_connection (self, (NMConnection *) connection);
+		parent = find_parent_device_for_connection (self, (NMConnection *) connection, NULL);
 		if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) {
 			g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device));
 			return FALSE;
@@ -2857,6 +2836,16 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
 	if (existing)
 		nm_device_steal_connection (existing, connection);
 
+	/* when creating the software device, it can happen that the device is
+	 * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet
+	 * get the udev event. At this point, we can no longer delay the activation
+	 * and force the device to be managed. */
+	nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
+
+	nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
+
+	g_return_val_if_fail (nm_device_get_managed (device, FALSE), FALSE);
+
 	if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
 		nm_device_state_changed (device,
 		                         NM_DEVICE_STATE_UNAVAILABLE,
@@ -3229,7 +3218,7 @@ validate_activation_request (NMManager *self,
 			char *iface;
 
 			/* Look for an existing device with the connection's interface name */
-			iface = get_virtual_iface_name (self, connection, NULL, error);
+			iface = nm_manager_get_connection_iface (self, connection, NULL, error);
 			if (!iface)
 				goto error;
 
@@ -3817,7 +3806,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
 			if (suspending && device_is_wake_on_lan (device))
 				continue;
 
-			nm_device_set_unmanaged_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
+			nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
 		}
 	} else {
 		nm_log_info (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling");
@@ -3832,7 +3821,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
 				if (nm_device_is_software (device))
 					continue;
 				if (device_is_wake_on_lan (device))
-					nm_device_set_unmanaged_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
+					nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
 			}
 		}
 
@@ -3868,7 +3857,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
 
 			nm_device_set_autoconnect (device, TRUE);
 
-			nm_device_set_unmanaged_flags (device, NM_UNMANAGED_INTERNAL, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
+			nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
 		}
 	}
 
@@ -4428,6 +4417,8 @@ nm_manager_stop (NMManager *self)
 	/* Remove all devices */
 	while (priv->devices)
 		remove_device (self, NM_DEVICE (priv->devices->data), TRUE, TRUE);
+
+	_active_connection_cleanup (self);
 }
 
 static gboolean
@@ -4439,9 +4430,6 @@ handle_firmware_changed (gpointer user_data)
 
 	priv->fw_changed_id = 0;
 
-	if (manager_sleeping (self))
-		return FALSE;
-
 	/* Try to re-enable devices with missing firmware */
 	for (iter = priv->devices; iter; iter = iter->next) {
 		NMDevice *candidate = NM_DEVICE (iter->data);
@@ -5044,16 +5032,20 @@ NM_DEFINE_SINGLETON_REGISTER (NMManager);
 NMManager *
 nm_manager_get (void)
 {
-	g_assert (singleton_instance);
+	g_return_val_if_fail (singleton_instance, NULL);
 	return singleton_instance;
 }
 
 NMConnectionProvider *
 nm_connection_provider_get (void)
 {
-	g_assert (singleton_instance);
-	g_assert (NM_MANAGER_GET_PRIVATE (singleton_instance)->settings);
-	return NM_CONNECTION_PROVIDER (NM_MANAGER_GET_PRIVATE (singleton_instance)->settings);
+	NMConnectionProvider *p;
+
+	g_return_val_if_fail (singleton_instance, NULL);
+
+	p = NM_CONNECTION_PROVIDER (NM_MANAGER_GET_PRIVATE (singleton_instance)->settings);
+	g_return_val_if_fail (p, NULL);
+	return p;
 }
 
 NMManager *
@@ -5064,7 +5056,7 @@ nm_manager_setup (const char *state_file,
 {
 	NMManager *self;
 
-	g_assert (singleton_instance == NULL);
+	g_return_val_if_fail (!singleton_instance, singleton_instance);
 
 	self = g_object_new (NM_TYPE_MANAGER,
 	                     NM_MANAGER_NETWORKING_ENABLED, initial_net_enabled,
diff --git a/src/nm-manager.h b/src/nm-manager.h
index 2935d2a2..97830201 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -101,6 +101,11 @@ const GSList *      nm_manager_get_devices             (NMManager *manager);
 NMDevice *          nm_manager_get_device_by_ifindex   (NMManager *manager,
                                                         int ifindex);
 
+char *              nm_manager_get_connection_iface (NMManager *self,
+                                                     NMConnection *connection,
+                                                     NMDevice **out_parent,
+                                                     GError **error);
+
 NMActiveConnection *nm_manager_activate_connection     (NMManager *manager,
                                                         NMSettingsConnection *connection,
                                                         const char *specific_object,
@@ -113,4 +118,5 @@ gboolean            nm_manager_deactivate_connection   (NMManager *manager,
                                                         NMDeviceStateReason reason,
                                                         GError **error);
 
+
 #endif /* __NETWORKMANAGER_MANAGER_H__ */
diff --git a/src/nm-multi-index.c b/src/nm-multi-index.c
index 47cd9810..6ae54a98 100644
--- a/src/nm-multi-index.c
+++ b/src/nm-multi-index.c
@@ -18,15 +18,12 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
-
 #include "nm-default.h"
+
 #include "nm-multi-index.h"
 
 #include <string.h>
 
-#include "nm-macros-internal.h"
-
 struct NMMultiIndex {
 	NMMultiIndexFuncEqual equal_fcn;
 	NMMultiIndexFuncClone clone_fcn;
@@ -111,7 +108,7 @@ _values_data_get_data (ValuesData *values_data,
  * @out_len: (allow-none): output the number of values
  *   that are returned.
  *
- * Returns: (transfer-none): %NULL if there are no values
+ * Returns: (transfer none): %NULL if there are no values
  *   or a %NULL terminated array of pointers.
  */
 void *const*
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 05f7edf4..68e50a1c 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -19,15 +19,13 @@
  * Copyright (C) 2007 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <netdb.h>
 
-
-#include "nm-default.h"
 #include "nm-policy.h"
 #include "NetworkManagerUtils.h"
 #include "nm-activation-request.h"
diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c
index 76703b20..16742656 100644
--- a/src/nm-rfkill-manager.c
+++ b/src/nm-rfkill-manager.c
@@ -18,13 +18,12 @@
  * Copyright (C) 2009 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <gudev/gudev.h>
 
 #include "nm-rfkill-manager.h"
-#include "nm-default.h"
 
 typedef struct {
 	GUdevClient *client;
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 5af0b917..84811d5a 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
@@ -26,7 +26,6 @@
 #include "nm-platform.h"
 #include "nmp-object.h"
 #include "nm-core-internal.h"
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 
 /* if within half a second after adding an IP address a matching device-route shows
@@ -134,7 +133,7 @@ static const VTableIP vtable_v4, vtable_v6;
             if ((self) != singleton_instance) \
                 g_snprintf (__prefix, sizeof (__prefix), "%s%c[%p]", _NMLOG_PREFIX_NAME, __ch, (self)); \
             else \
-                __prefix[STRLEN (_NMLOG_PREFIX_NAME)] = __ch; \
+                __prefix[NM_STRLEN (_NMLOG_PREFIX_NAME)] = __ch; \
             _nm_log ((level), (__domain), 0, \
                      "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
                      __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
@@ -633,7 +632,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 		 * causes the route on the unmanaged device to be replaced).
 		 * Still, that is not much different then from messing with unmanaged routes when
 		 * the effective and the intended metrics equal. The rules is: NM will leave routes
-		 * on unmanged devices alone, unless they conflict with what NM wants to configure.
+		 * on unmanaged devices alone, unless they conflict with what NM wants to configure.
 		 ***************************************************************************/
 
 		g_array_set_size (ipx_routes->effective_metrics, ipx_routes->entries->len);
diff --git a/src/nm-session-monitor.c b/src/nm-session-monitor.c
index 461195b0..d8b046e6 100644
--- a/src/nm-session-monitor.c
+++ b/src/nm-session-monitor.c
@@ -19,14 +19,13 @@
  * Author: Matthias Clasen
  * Author: Pavel Å imerda <psimerda@redhat.com>
  */
-#include "config.h"
+#include "nm-default.h"
 
 #include <pwd.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
 
-#include "nm-default.h"
 #include "nm-session-monitor.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/nm-sleep-monitor-systemd.c b/src/nm-sleep-monitor-systemd.c
index 12db56b2..064a7035 100644
--- a/src/nm-sleep-monitor-systemd.c
+++ b/src/nm-sleep-monitor-systemd.c
@@ -17,14 +17,13 @@
  * Author: Matthias Clasen <mclasen@redhat.com>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <gio/gunixfdlist.h>
 
-#include "nm-default.h"
 #include "nm-core-internal.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/nm-sleep-monitor-upower.c b/src/nm-sleep-monitor-upower.c
index c65609cf..5f0ff245 100644
--- a/src/nm-sleep-monitor-upower.c
+++ b/src/nm-sleep-monitor-upower.c
@@ -17,12 +17,12 @@
  * Author: Matthias Clasen <mclasen@redhat.com>
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
-#include "nm-default.h"
+
 #include "nm-core-internal.h"
 
 #include "nm-sleep-monitor.h"
diff --git a/src/nm-types.h b/src/nm-types.h
index 7934fcbb..0fda9216 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -35,6 +35,7 @@ typedef struct _NMAuthSubject        NMAuthSubject;
 typedef struct _NMBusManager         NMBusManager;
 typedef struct _NMConfig             NMConfig;
 typedef struct _NMConfigData         NMConfigData;
+typedef struct _NMArpingManager      NMArpingManager;
 typedef struct _NMConnectionProvider NMConnectionProvider;
 typedef struct _NMConnectivity       NMConnectivity;
 typedef struct _NMDefaultRouteManager NMDefaultRouteManager;
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index a4eae902..68b72b19 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -18,7 +18,9 @@
  * Copyright (C) 2012–2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-fake-platform.h"
 
 #include <errno.h>
 #include <unistd.h>
@@ -27,10 +29,9 @@
 #include <linux/rtnetlink.h>
 
 #include "nm-utils.h"
+
+#include "nm-core-utils.h"
 #include "nmp-object.h"
-#include "NetworkManagerUtils.h"
-#include "nm-fake-platform.h"
-#include "nm-default.h"
 
 #include "nm-test-utils.h"
 
@@ -173,10 +174,10 @@ link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name)
 		strcpy (device->link.name, name);
 	switch (device->link.type) {
 	case NM_LINK_TYPE_DUMMY:
-		device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
+		device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
 		break;
 	default:
-		device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
+		device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
 		break;
 	}
 }
@@ -440,9 +441,9 @@ link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
 		g_error ("Unexpected device type: %d", device->link.type);
 	}
 
-	if (   NM_FLAGS_HAS (device->link.flags, IFF_UP) != !!up
+	if (   NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) != !!up
 	    || device->link.connected != connected) {
-		device->link.flags = NM_FLAGS_ASSIGN (device->link.flags, IFF_UP, up);
+		device->link.n_ifi_flags = NM_FLAGS_ASSIGN (device->link.n_ifi_flags, IFF_UP, up);
 		device->link.connected = connected;
 		link_changed (platform, device, TRUE);
 	}
@@ -460,8 +461,8 @@ link_set_down (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	if (NM_FLAGS_HAS (device->link.flags, IFF_UP) || device->link.connected) {
-		device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_UP);
+	if (NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) || device->link.connected) {
+		device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_UP);
 		device->link.connected = FALSE;
 
 		link_changed (platform, device, TRUE);
@@ -480,7 +481,7 @@ link_set_arp (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
+	device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
 
 	link_changed (platform, device, TRUE);
 
@@ -497,7 +498,7 @@ link_set_noarp (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
+	device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
 
 	link_changed (platform, device, TRUE);
 
@@ -509,7 +510,8 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t
 {
 	NMFakePlatformLink *device = link_get (platform, ifindex);
 
-	if (   len == 0
+	if (   !device
+	    || len == 0
 	    || len > NM_UTILS_HWADDR_LEN_MAX
 	    || !addr)
 		g_return_val_if_reached (FALSE);
@@ -611,7 +613,7 @@ link_enslave (NMPlatform *platform, int master, int slave)
 		device->link.master = master;
 
 		if (NM_IN_SET (master_device->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) {
-			device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_UP);
+			device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_UP);
 			device->link.connected = TRUE;
 		}
 
@@ -937,7 +939,8 @@ ip6_address_add (NMPlatform *platform,
                  int plen,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
-                 guint32 preferred, guint flags)
+                 guint32 preferred,
+                 guint32 flags)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	NMPlatformIP6Address address;
@@ -952,7 +955,7 @@ ip6_address_add (NMPlatform *platform,
 	address.timestamp = nm_utils_get_monotonic_timestamp_s ();
 	address.lifetime = lifetime;
 	address.preferred = preferred;
-	address.flags = flags;
+	address.n_ifa_flags = flags;
 
 	for (i = 0; i < priv->ip6_addresses->len; i++) {
 		NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f73c228b..196e75cb 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -17,7 +17,9 @@
  *
  * Copyright (C) 2012-2015 Red Hat, Inc.
  */
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-linux-platform.h"
 
 #include <errno.h>
 #include <unistd.h>
@@ -42,22 +44,21 @@
 #include <netlink/route/route.h>
 #include <gudev/gudev.h>
 
+#include "nm-utils.h"
 #include "nm-core-internal.h"
-#include "NetworkManagerUtils.h"
-#include "nm-linux-platform.h"
+#include "nm-setting-vlan.h"
+
+#include "nm-core-utils.h"
+#include "nmp-object.h"
 #include "nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
-#include "nm-utils.h"
-#include "nm-default.h"
 #include "wifi/wifi-utils.h"
 #include "wifi/wifi-utils-wext.h"
-#include "nmp-object.h"
-
-/* This is only included for the translation of VLAN flags */
-#include "nm-setting-vlan.h"
 
 #define VLAN_FLAG_MVRP 0x8
 
+/* nm-internal error codes for libnl. Make sure they don't overlap. */
+#define _NLE_NM_NOBUFS 500
+
 /*********************************************************************************************/
 
 #define IFQDISCSIZ                      32
@@ -115,8 +116,26 @@
 #define _NMLOG_PREFIX_NAME                "platform-linux"
 #define _NMLOG_DOMAIN                     LOGD_PLATFORM
 #define _NMLOG2_DOMAIN                    LOGD_PLATFORM
-#define _NMLOG(level, ...)                _LOG(level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
-#define _NMLOG2(level, ...)               _LOG(level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+#define _NMLOG(level, ...)                _LOG     (       level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
+#define _NMLOG_err(errsv, level, ...)     _LOG_err (errsv, level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
+#define _NMLOG2(level, ...)               _LOG     (       level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+#define _NMLOG2_err(errsv, level, ...)    _LOG_err (errsv, level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+
+
+#define _LOG_print(__level, __domain, __errsv, self, ...) \
+    G_STMT_START { \
+        char __prefix[32]; \
+        const char *__p_prefix = _NMLOG_PREFIX_NAME; \
+        const void *const __self = (self); \
+        \
+        if (__self && __self != nm_platform_try_get ()) { \
+            g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \
+            __p_prefix = __prefix; \
+        } \
+        _nm_log (__level, __domain, __errsv, \
+                 "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
+                 __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+    } G_STMT_END
 
 #define _LOG(level, domain, self, ...) \
     G_STMT_START { \
@@ -124,20 +143,30 @@
         const NMLogDomain __domain = (domain); \
         \
         if (nm_logging_enabled (__level, __domain)) { \
-            char __prefix[32]; \
-            const char *__p_prefix = _NMLOG_PREFIX_NAME; \
-            const void *const __self = (self); \
+            _LOG_print (__level, __domain, 0, self, __VA_ARGS__); \
+        } \
+    } G_STMT_END
+
+#define _LOG_err(errsv, level, domain, self, ...) \
+    G_STMT_START { \
+        const NMLogLevel __level = (level); \
+        const NMLogDomain __domain = (domain); \
+        \
+        if (nm_logging_enabled (__level, __domain)) { \
+            int __errsv = (errsv); \
             \
-            if (__self && __self != nm_platform_try_get ()) { \
-                g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \
-                __p_prefix = __prefix; \
-            } \
-            _nm_log (__level, __domain, 0, \
-                     "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
-                     __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+            /* The %m format specifier (GNU extension) would alread allow you to specify the error
+             * message conveniently (and nm_log would get that right too). But we don't want to depend
+             * on that, so instead append the message at the end.
+             * Currently users are expected not to use %m in the format string. */ \
+            _LOG_print (__level, __domain, __errsv, self, \
+                        _NM_UTILS_MACRO_FIRST (__VA_ARGS__) ": %s (%d)" \
+                        _NM_UTILS_MACRO_REST (__VA_ARGS__), \
+                        g_strerror (__errsv), __errsv); \
         } \
     } G_STMT_END
 
+
 #define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s"
 
 /******************************************************************
@@ -257,17 +286,6 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
  * Various utilities
  ******************************************************************/
 
-const NMIPAddr nm_ip_addr_zero = NMIPAddrInit;
-
-#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
-#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
-
-static gboolean
-ip4_address_is_link_local (in_addr_t addr)
-{
-	return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK;
-}
-
 static guint
 _nm_ip_config_source_to_rtprot (NMIPConfigSource source)
 {
@@ -579,7 +597,7 @@ _lookup_cached_link (const NMPCache *cache, int ifindex, gboolean *completed_fro
 	if (!*completed_from_cache) {
 		obj = ifindex > 0 && cache ? nmp_cache_lookup_link (cache, ifindex) : NULL;
 
-		if (obj && !obj->_link.netlink.is_in_netlink)
+		if (obj && obj->_link.netlink.is_in_netlink)
 			*link_cached = obj;
 		else
 			*link_cached = NULL;
@@ -605,8 +623,8 @@ _linktype_read_devtype (const char *sysfs_path)
 		end = strpbrk (cont, "\r\n");
 		if (end)
 			*end++ = '\0';
-		if (strncmp (cont, DEVTYPE_PREFIX, STRLEN (DEVTYPE_PREFIX)) == 0) {
-			cont += STRLEN (DEVTYPE_PREFIX);
+		if (strncmp (cont, DEVTYPE_PREFIX, NM_STRLEN (DEVTYPE_PREFIX)) == 0) {
+			cont += NM_STRLEN (DEVTYPE_PREFIX);
 			memmove (contents, cont, strlen (cont) + 1);
 			return contents;
 		}
@@ -732,13 +750,19 @@ _linktype_get_type (NMPlatform *platform,
 		if (wifi_utils_is_wifi (ifname, sysfs_path))
 			return NM_LINK_TYPE_WIFI;
 
-		/* Standard wired ethernet interfaces don't report an rtnl_link_type, so
-		 * only allow fallback to Ethernet if no type is given.  This should
-		 * prevent future virtual network drivers from being treated as Ethernet
-		 * when they should be Generic instead.
-		 */
-		if (arptype == ARPHRD_ETHER && !kind && !devtype)
-			return NM_LINK_TYPE_ETHERNET;
+		if (arptype == ARPHRD_ETHER) {
+			/* Standard wired ethernet interfaces don't report an rtnl_link_type, so
+			 * only allow fallback to Ethernet if no type is given.  This should
+			 * prevent future virtual network drivers from being treated as Ethernet
+			 * when they should be Generic instead.
+			 */
+			if (!kind && !devtype)
+				return NM_LINK_TYPE_ETHERNET;
+			/* The USB gadget interfaces behave and look like ordinary ethernet devices
+			 * aside from the DEVTYPE. */
+			if (!g_strcmp0 (devtype, "gadget"))
+				return NM_LINK_TYPE_ETHERNET;
+		}
 	}
 
 	return NM_LINK_TYPE_UNKNOWN;
@@ -1464,8 +1488,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
 		nl_info_data = li[IFLA_INFO_DATA];
 	}
 
-	obj->link.flags = ifi->ifi_flags;
-	obj->link.connected = NM_FLAGS_HAS (obj->link.flags, IFF_LOWER_UP);
+	obj->link.n_ifi_flags = ifi->ifi_flags;
+	obj->link.connected = NM_FLAGS_HAS (obj->link.n_ifi_flags, IFF_LOWER_UP);
 	obj->link.arptype = ifi->ifi_type;
 
 	obj->link.type = _linktype_get_type (platform,
@@ -1473,7 +1497,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
 	                                     nl_info_kind,
 	                                     obj->link.ifindex,
 	                                     obj->link.name,
-	                                     obj->link.flags,
+	                                     obj->link.n_ifi_flags,
 	                                     obj->link.arptype,
 	                                     completed_from_cache,
 	                                     &link_cached,
@@ -1650,9 +1674,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
 	obj->ip_address.source = NM_IP_CONFIG_SOURCE_KERNEL;
 
 	if (!is_v4) {
-		obj->ip6_address.flags = tb[IFA_FLAGS]
-		                         ? nla_get_u32 (tb[IFA_FLAGS])
-		                         : ifa->ifa_flags;
+		obj->ip6_address.n_ifa_flags = tb[IFA_FLAGS]
+		                               ? nla_get_u32 (tb[IFA_FLAGS])
+		                               : ifa->ifa_flags;
 	}
 
 	if (is_v4) {
@@ -2329,8 +2353,8 @@ static gboolean
 _support_kernel_extended_ifa_flags_get (void)
 {
 	if (_support_kernel_extended_ifa_flags_still_undecided ()) {
-		_LOG2W ("support: kernel-extended-ifa-flags: unable to detect kernel support for handling IPv6 temporary addresses. Assume none");
-		_support_kernel_extended_ifa_flags = 0;
+		_LOG2W ("support: kernel-extended-ifa-flags: unable to detect kernel support for handling IPv6 temporary addresses. Assume support");
+		_support_kernel_extended_ifa_flags = 1;
 	}
 	return _support_kernel_extended_ifa_flags;
 }
@@ -2427,8 +2451,11 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *path, const char *va
 static gboolean
 sysctl_set (NMPlatform *platform, const char *path, const char *value)
 {
-	int fd, len, nwrote, tries;
+	int fd, tries;
+	gssize nwrote;
+	gsize len;
 	char *actual;
+	gs_free char *actual_free = NULL;
 
 	g_return_val_if_fail (path != NULL, FALSE);
 	g_return_val_if_fail (value != NULL, FALSE);
@@ -2458,10 +2485,16 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
 	 * sysctl support partial writes so the LF must be added to the string we're
 	 * about to write.
 	 */
-	actual = g_strdup_printf ("%s\n", value);
+	len = strlen (value) + 1;
+	if (len > 512)
+		actual = actual_free = g_malloc (len + 1);
+	else
+		actual = g_alloca (len + 1);
+	memcpy (actual, value, len - 1);
+	actual[len - 1] = '\n';
+	actual[len] = '\0';
 
 	/* Try to write the entire value three times if a partial write occurs */
-	len = strlen (actual);
 	for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) {
 		nwrote = write (fd, actual, len);
 		if (nwrote == -1) {
@@ -2480,15 +2513,14 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
 		       path, value);
 	}
 
-	g_free (actual);
 	close (fd);
 	return (nwrote == len);
 }
 
 static GSList *sysctl_clear_cache_list;
 
-void
-_nm_linux_platform_sysctl_clear_cache (void)
+static void
+_nm_logging_clear_platform_logging_cache_impl (void)
 {
 	while (sysctl_clear_cache_list) {
 		NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (sysctl_clear_cache_list->data);
@@ -2508,6 +2540,7 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co
 	const char *prev_value = NULL;
 
 	if (!priv->sysctl_get_prev_values) {
+		_nm_logging_clear_platform_logging_cache = _nm_logging_clear_platform_logging_cache_impl;
 		sysctl_clear_cache_list = g_slist_prepend (sysctl_clear_cache_list, platform);
 		priv->sysctl_get_prev_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	} else
@@ -2798,13 +2831,23 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
 
 static void
 delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
-                                                  WaitForNlResponseResult result)
+                                                  WaitForNlResponseResult fallback_result)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 
 	if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
-		while (priv->delayed_action.list_wait_for_nl_response->len > 0)
-			delayed_action_wait_for_nl_response_complete (platform, priv->delayed_action.list_wait_for_nl_response->len - 1, result);
+		while (priv->delayed_action.list_wait_for_nl_response->len > 0) {
+			const DelayedActionWaitForNlResponseData *data;
+			guint idx = priv->delayed_action.list_wait_for_nl_response->len - 1;
+			WaitForNlResponseResult r;
+
+			data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx);
+
+			/* prefer the result that we already have. */
+			r = data->seq_result ? : fallback_result;
+
+			delayed_action_wait_for_nl_response_complete (platform, idx, r);
+		}
 	}
 	nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
 	nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
@@ -3190,9 +3233,9 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 			if (   ops_type == NMP_CACHE_OPS_UPDATED
 			    && old && new /* <-- nonsensical, make coverity happy */
 			    && old->_link.netlink.is_in_netlink
-			    && NM_FLAGS_HAS (old->link.flags, IFF_LOWER_UP)
+			    && NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP)
 			    && new->_link.netlink.is_in_netlink
-			    && !NM_FLAGS_HAS (new->link.flags, IFF_LOWER_UP)) {
+			    && !NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP)) {
 				delayed_action_schedule (platform,
 				                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES |
 				                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES,
@@ -3235,6 +3278,19 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 				                         DELAYED_ACTION_TYPE_REFRESH_LINK,
 				                         GINT_TO_POINTER (new->link.ifindex));
 			}
+			if (   new->link.type == NM_LINK_TYPE_ETHERNET
+			    && new->link.addr.len == 0) {
+				/* Due to a kernel bug, we sometimes receive spurious NEWLINK
+				 * messages after a wifi interface has disappeared. Since the
+				 * link is not present anymore we can't determine its type and
+				 * thus it will show up as a Ethernet one, with no address
+				 * specified.  Request the link again to check if it really
+				 * exists.  https://bugzilla.redhat.com/show_bug.cgi?id=1302037
+				 */
+				delayed_action_schedule (platform,
+				                         DELAYED_ACTION_TYPE_REFRESH_LINK,
+				                         GINT_TO_POINTER (new->link.ifindex));
+			}
 		}
 		{
 			/* on enslave/release, we also refresh the master. */
@@ -3243,8 +3299,8 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 
 			changed_master =    (new && new->_link.netlink.is_in_netlink && new->link.master > 0 ? new->link.master : 0)
 			                 != (old && old->_link.netlink.is_in_netlink && old->link.master > 0 ? old->link.master : 0);
-			changed_connected =    (new && new->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (new->link.flags, IFF_LOWER_UP) : 2)
-			                    != (old && old->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (old->link.flags, IFF_LOWER_UP) : 2);
+			changed_connected =    (new && new->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP) : 2)
+			                    != (old && old->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP) : 2);
 
 			if (changed_master || changed_connected) {
 				ifindex1 = (old && old->_link.netlink.is_in_netlink && old->link.master > 0) ? old->link.master : 0;
@@ -3455,7 +3511,7 @@ event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResu
 }
 
 static void
-event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
+event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_events)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	nm_auto_nmpobj NMPObject *obj = NULL;
@@ -3471,6 +3527,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
 	if (_support_kernel_extended_ifa_flags_still_undecided () && msghdr->nlmsg_type == RTM_NEWADDR)
 		_support_kernel_extended_ifa_flags_detect (msg);
 
+	if (!handle_events)
+		return;
+
 	if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK, RTM_DELADDR, RTM_DELROUTE)) {
 		/* The event notifies about a deleted object. We don't need to initialize all
 		 * fields of the object. */
@@ -4684,7 +4743,6 @@ link_vlan_change (NMPlatform *platform,
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	const NMPObject *obj_cache;
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
-	unsigned flags;
 	const NMPObjectLnkVlan *lnk;
 	guint new_n_ingress_map = 0;
 	guint new_n_egress_map = 0;
@@ -4702,7 +4760,6 @@ link_vlan_change (NMPlatform *platform,
 	}
 
 	lnk = obj_cache->_link.netlink.lnk ? &obj_cache->_link.netlink.lnk->_lnk_vlan : NULL;
-	flags = obj_cache->link.flags;
 
 	flags_set &= flags_mask;
 
@@ -4821,6 +4878,7 @@ tun_add (NMPlatform *platform, const char *name, gboolean tap,
 	if (out_link)
 		*out_link = obj ? &obj->link : NULL;
 
+	close (fd);
 	return !!obj;
 }
 
@@ -5139,7 +5197,7 @@ ip4_address_add (NMPlatform *platform,
 	                             plen,
 	                             &peer_addr,
 	                             0,
-	                             ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
+	                             nmp_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
 	                             lifetime,
 	                             preferred,
 	                             label);
@@ -5156,7 +5214,7 @@ ip6_address_add (NMPlatform *platform,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
-                 guint flags)
+                 guint32 flags)
 {
 	NMPObject obj_id;
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
@@ -5492,8 +5550,7 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	struct nl_sock *sk = priv->nlh;
-	int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0;
-	unsigned char *buf = NULL;
+	int n, err = 0, multipart = 0, interrupted = 0;
 	struct nlmsghdr *hdr;
 	WaitForNlResponseResult seq_result;
 
@@ -5503,34 +5560,44 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
 	initialize the variable. Thomas Graf.
 	*/
 	struct sockaddr_nl nla = {0};
-	struct nl_msg *msg = NULL;
-	struct ucred *creds = NULL;
+	nm_auto_free struct ucred *creds = NULL;
+	nm_auto_free unsigned char *buf = NULL;
 
 continue_reading:
+	g_clear_pointer (&buf, free);
+	g_clear_pointer (&creds, free);
 	errno = 0;
 	n = nl_recv (sk, &nla, &buf, &creds);
 
-	/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
-	if (n == 0 && errno == EAGAIN) {
-		/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
-		 * workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
-		G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
-		n = -NLE_AGAIN;
+	switch (n) {
+	case 0:
+		/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
+		if (errno == EAGAIN) {
+			/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
+			 * workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
+			G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
+			n = -NLE_AGAIN;
+		}
+		break;
+	case -NLE_NOMEM:
+		if (errno == ENOBUFS) {
+			/* we are very much interested in a overrun of the receive buffer.
+			 * nl_recv() maps all kinds of errors to NLE_NOMEM, so check also
+			 * for errno explicitly. And if so, hack our own return code to signal
+			 * the overrun. */
+			n = -_NLE_NM_NOBUFS;
+		}
+		break;
 	}
 
 	if (n <= 0)
 		return n;
 
-	if (!handle_events) {
-		/* we read until failure or there is nothing to read (EAGAIN). */
-		goto continue_reading;
-	}
-
 	hdr = (struct nlmsghdr *) buf;
 	while (nlmsg_ok (hdr, n)) {
+		nm_auto_nlmsg struct nl_msg *msg = NULL;
 		gboolean abort_parsing = FALSE;
 
-		nlmsg_free (msg);
 		msg = nlmsg_convert (hdr);
 		if (!msg) {
 			err = -NLE_NOMEM;
@@ -5539,13 +5606,13 @@ continue_reading:
 
 		nlmsg_set_proto (msg, NETLINK_ROUTE);
 		nlmsg_set_src (msg, &nla);
-		nrecv++;
 
 		if (!creds || creds->pid) {
 			if (creds)
-				_LOGD ("netlink: recvmsg: received non-kernel message (pid %d)", creds->pid);
+				_LOGT ("netlink: recvmsg: received non-kernel message (pid %d)", creds->pid);
 			else
-				_LOGD ("netlink: recvmsg: received message without credentials");
+				_LOGT ("netlink: recvmsg: received message without credentials");
+			err = 0;
 			goto stop;
 		}
 
@@ -5618,42 +5685,35 @@ continue_reading:
 			/* Valid message (not checking for MULTIPART bit to
 			 * get along with broken kernels. NL_SKIP has no
 			 * effect on this.  */
-			event_valid_msg (platform, msg);
+
+			event_valid_msg (platform, msg, handle_events);
+
 			seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
 		}
 
 		event_seq_check (platform, msg, seq_result);
-		err = 0;
-		hdr = nlmsg_next (hdr, &n);
 
 		if (abort_parsing)
-			goto out;
-	}
+			goto stop;
 
-	nlmsg_free (msg);
-	free (buf);
-	free (creds);
-	buf = NULL;
-	msg = NULL;
-	creds = NULL;
+		err = 0;
+		hdr = nlmsg_next (hdr, &n);
+	}
 
 	if (multipart) {
 		/* Multipart message not yet complete, continue reading */
 		goto continue_reading;
 	}
 stop:
-	err = 0;
+	if (!handle_events) {
+		/* when we don't handle events, we want to drain all messages from the socket
+		 * without handling the messages (but still check for sequence numbers).
+		 * Repeat reading. */
+		goto continue_reading;
+	}
 out:
-	nlmsg_free (msg);
-	free (buf);
-	free (creds);
-
 	if (interrupted)
 		err = -NLE_DUMP_INTR;
-
-	if (!err)
-		err = nrecv;
-
 	return err;
 }
 
@@ -5687,12 +5747,10 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
 				case -NLE_DUMP_INTR:
 					_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
 					break;
-				case -NLE_NOMEM:
+				case -_NLE_NM_NOBUFS:
 					_LOGI ("netlink: read: too many netlink events. Need to resynchronize platform cache");
-					/* Drain the event queue, we've lost events and are out of sync anyway and we'd
-					 * like to free up some space. We'll read in the status synchronously. */
-					delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
 					event_handler_recvmsgs (platform, FALSE);
+					delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
 					delayed_action_schedule (platform,
 					                         DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
 					                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
@@ -5728,9 +5786,10 @@ after_read:
 				i++;
 
 				if (   data_next.seq_number == 0
-				    || data_next.timeout_abs_ns > data->timeout_abs_ns)
+				    || data_next.timeout_abs_ns > data->timeout_abs_ns) {
 					data_next.seq_number = data->seq_number;
 					data_next.timeout_abs_ns = data->timeout_abs_ns;
+				}
 			}
 		}
 
@@ -5916,14 +5975,8 @@ constructed (GObject *_object)
 	nle = nl_socket_set_nonblocking (priv->nlh);
 	g_assert (!nle);
 
-	/* The default buffer size wasn't enough for the testsuites. It might just
-	 * as well happen with NetworkManager itself. For now let's hope 128KB is
-	 * good enough.
-	 *
-	 * FIXME: it's unclear that this is still actually needed. The testsuite
-	 * certainly doesn't fail for me. Maybe it can be removed.
-	 */
-	nle = nl_socket_set_buffer_size (priv->nlh, 131072, 0);
+	/* use 8 MB for receive socket kernel queue. */
+	nle = nl_socket_set_buffer_size (priv->nlh, 8*1024*1024, 0);
 	g_assert (!nle);
 
 	nle = nl_socket_add_memberships (priv->nlh,
diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h
index 81f9c738..a9e2cd82 100644
--- a/src/platform/nm-linux-platform.h
+++ b/src/platform/nm-linux-platform.h
@@ -50,6 +50,4 @@ GType nm_linux_platform_get_type (void);
 
 void nm_linux_platform_setup (void);
 
-void _nm_linux_platform_sysctl_clear_cache (void);
-
 #endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 953ac8c5..0f2656f2 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -18,6 +18,8 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
+#include "nm-default.h"
+
 #include "nm-platform-utils.h"
 
 #include <string.h>
@@ -30,10 +32,9 @@
 #include <linux/version.h>
 
 #include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "nm-default.h"
 #include "nm-setting-wired.h"
 
+#include "nm-core-utils.h"
 
 /******************************************************************
  * ethtool
@@ -142,7 +143,8 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
 		struct ethtool_perm_addr e;
 		guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1];
 	} edata;
-	guint zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
+	static const guint8 zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
+	static guint8 ones[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
 
 	if (!ifname)
 		return FALSE;
@@ -161,6 +163,12 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
 	if (memcmp (edata.e.data, zeros, edata.e.size) == 0)
 		return FALSE;
 
+	/* Some drivers return a permanent address of all ones. Reject that too */
+	if (G_UNLIKELY (ones[0] != 0xFF))
+		memset (ones, 0xFF, sizeof (ones));
+	if (memcmp (edata.e.data, ones, edata.e.size) == 0)
+		return FALSE;
+
 	memcpy (buf, edata.e.data, edata.e.size);
 	*length = edata.e.size;
 	return TRUE;
@@ -408,6 +416,15 @@ out:
  * utils
  ******************************************************************/
 
+#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
+#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
+
+gboolean
+nmp_utils_ip4_address_is_link_local (in_addr_t addr)
+{
+	return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK;
+}
+
 /**
  * Takes a pair @timestamp and @duration, and returns the remaining duration based
  * on the new timestamp @now.
@@ -496,13 +513,13 @@ gboolean
 nmp_utils_device_exists (const char *name)
 {
 #define SYS_CLASS_NET "/sys/class/net/"
-	char sysdir[STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
+	char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
 
 	if (   !name
 	    || strlen (name) >= IFNAMSIZ
 	    || !nm_utils_is_valid_path_component (name))
 		g_return_val_if_reached (FALSE);
 
-	strcpy (&sysdir[STRLEN (SYS_CLASS_NET)], name);
+	strcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name);
 	return g_file_test (sysdir, G_FILE_TEST_EXISTS);
 }
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index 3769a8e1..a9d29c04 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -21,8 +21,6 @@
 #ifndef __NM_PLATFORM_UTILS_H__
 #define __NM_PLATFORM_UTILS_H__
 
-#include "config.h"
-
 #include <gudev/gudev.h>
 
 #include "nm-platform.h"
@@ -69,4 +67,6 @@ gboolean nmp_utils_lifetime_get (guint32 timestamp,
 
 gboolean nmp_utils_device_exists (const char *name);
 
+gboolean nmp_utils_ip4_address_is_link_local (in_addr_t addr);
+
 #endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 3bb44e1a..e3126442 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -18,7 +18,9 @@
  * Copyright (C) 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-platform.h"
 
 #include <stdlib.h>
 #include <errno.h>
@@ -32,15 +34,19 @@
 #include <linux/if_tun.h>
 #include <linux/if_tunnel.h>
 
-#include "NetworkManagerUtils.h"
 #include "nm-utils.h"
-#include "nm-platform.h"
+#include "nm-core-internal.h"
+
+#include "nm-core-utils.h"
+#include "nm-enum-types.h"
 #include "nm-platform-utils.h"
 #include "nmp-object.h"
-#include "NetworkManagerUtils.h"
-#include "nm-default.h"
-#include "nm-enum-types.h"
-#include "nm-core-internal.h"
+
+/*****************************************************************************/
+
+const NMIPAddr nm_ip_addr_zero = NMIPAddrInit;
+
+/*****************************************************************************/
 
 #define ADDRESS_LIFETIME_PADDING 5
 
@@ -181,39 +187,26 @@ nm_platform_try_get (void)
 /******************************************************************/
 
 /**
- * nm_platform_error_to_string:
+ * _nm_platform_error_to_string:
  * @error_code: the error code to stringify.
  *
  * Returns: A string representation of the error.
  * For negative numbers, this function interprets
  * the code as -errno.
+ * For invalid (positive) numbers it returns NULL.
  */
-const char *
-nm_platform_error_to_string (NMPlatformError error)
-{
-	switch (error) {
-	case NM_PLATFORM_ERROR_SUCCESS:
-		return "success";
-	case NM_PLATFORM_ERROR_BUG:
-		return "bug";
-	case NM_PLATFORM_ERROR_UNSPECIFIED:
-		return "unspecified";
-	case NM_PLATFORM_ERROR_NOT_FOUND:
-		return "not-found";
-	case NM_PLATFORM_ERROR_EXISTS:
-		return "exists";
-	case NM_PLATFORM_ERROR_WRONG_TYPE:
-		return "wrong-type";
-	case NM_PLATFORM_ERROR_NOT_SLAVE:
-		return "not-slave";
-	case NM_PLATFORM_ERROR_NO_FIRMWARE:
-		return "no-firmware";
-	default:
-		if (error < 0)
-			return g_strerror (- ((int) error));
-		return "unknown";
-	}
-}
+NM_UTILS_LOOKUP_STR_DEFINE (_nm_platform_error_to_string, NMPlatformError,
+	NM_UTILS_LOOKUP_DEFAULT ( val < 0 ? g_strerror (- ((int) val)) : NULL ),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_SUCCESS,     "success"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_BUG,         "bug"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_UNSPECIFIED, "unspecified"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NOT_FOUND,   "not-found"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_EXISTS,      "exists"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_WRONG_TYPE,  "wrong-type"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NOT_SLAVE,   "not-slave"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NO_FIRMWARE, "no-firmware"),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_PLATFORM_ERROR_MININT),
+);
 
 /******************************************************************/
 
@@ -811,13 +804,13 @@ nm_platform_link_refresh (NMPlatform *self, int ifindex)
 	return TRUE;
 }
 
-static guint32
+static guint
 _link_get_flags (NMPlatform *self, int ifindex)
 {
 	const NMPlatformLink *pllink;
 
 	pllink = nm_platform_link_get (self, ifindex);
-	return pllink ? pllink->flags : IFF_NOARP;
+	return pllink ? pllink->n_ifi_flags : IFF_NOARP;
 }
 
 /**
@@ -2147,7 +2140,8 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe
 gboolean
 nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname, NMPlatformTunProperties *props)
 {
-	char *path, *val;
+	char path[256];
+	char *val;
 	gboolean success = TRUE;
 
 	_CHECK_SELF (self, klass, FALSE);
@@ -2160,11 +2154,9 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 
 	if (!ifname || !nm_utils_iface_valid_name (ifname))
 		return FALSE;
-	ifname = ASSERT_VALID_PATH_COMPONENT (ifname);
 
-	path = g_strdup_printf ("/sys/class/net/%s/owner", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/owner", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		props->owner = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
 		if (errno)
@@ -2173,9 +2165,8 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 	} else
 		success = FALSE;
 
-	path = g_strdup_printf ("/sys/class/net/%s/group", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/group", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		props->group = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
 		if (errno)
@@ -2184,9 +2175,8 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 	} else
 		success = FALSE;
 
-	path = g_strdup_printf ("/sys/class/net/%s/tun_flags", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/tun_flags", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		gint64 flags;
 
@@ -2461,7 +2451,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
                              struct in6_addr peer_address,
                              guint32 lifetime,
                              guint32 preferred,
-                             guint flags)
+                             guint32 flags)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
@@ -2480,7 +2470,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
 		addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */
 		addr.lifetime = lifetime;
 		addr.preferred = preferred;
-		addr.flags = flags;
+		addr.n_ifa_flags = flags;
 
 		_LOGD ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr, NULL, 0));
 	}
@@ -2701,7 +2691,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
 
 		if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,
 		                                  known_address->plen, known_address->peer_address,
-		                                  lifetime, preferred, known_address->flags))
+		                                  lifetime, preferred, known_address->n_ifa_flags))
 			return FALSE;
 	}
 
@@ -2978,19 +2968,19 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 		return buf;
 
 	str_flags = g_string_new (NULL);
-	if (NM_FLAGS_HAS (link->flags, IFF_NOARP))
+	if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_NOARP))
 		g_string_append (str_flags, "NOARP,");
-	if (NM_FLAGS_HAS (link->flags, IFF_UP))
+	if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_UP))
 		g_string_append (str_flags, "UP");
 	else
 		g_string_append (str_flags, "DOWN");
 	if (link->connected)
 		g_string_append (str_flags, ",LOWER_UP");
 
-	if (link->flags) {
+	if (link->n_ifi_flags) {
 		char str_flags_buf[64];
 
-		nm_platform_link_flags2str (link->flags, str_flags_buf, sizeof (str_flags_buf));
+		nm_platform_link_flags2str (link->n_ifi_flags, str_flags_buf, sizeof (str_flags_buf));
 		g_string_append_printf (str_flags, ";%s", str_flags_buf);
 	}
 
@@ -3006,21 +2996,6 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	else
 		parent[0] = 0;
 
-	if (link->inet6_addr_gen_mode_inv) {
-		switch (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv)) {
-			case 0:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode eui64");
-				break;
-			case 1:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode none");
-				break;
-			default:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode %d", _nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv));
-				break;
-		}
-	} else
-		str_addrmode[0] = '\0';
-
 	if (link->addr.len)
 		str_addr = nm_utils_hwaddr_ntoa (link->addr.data, MIN (link->addr.len, sizeof (link->addr.data)));
 	if (link->inet6_token.is_valid)
@@ -3036,10 +3011,10 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	            " mtu %d"
 	            "%s" /* master */
 	            " arp %u" /* arptype */
-	            "%s%s" /* link->type */
+	            " %s" /* link->type */
 	            "%s%s" /* kind */
 	            "%s" /* is-in-udev */
-	            "%s" /* addr-gen-mode */
+	            "%s%s" /* addr-gen-mode */
 	            "%s%s" /* addr */
 	            "%s%s" /* inet6_token */
 	            "%s%s" /* driver */
@@ -3050,12 +3025,12 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	            str_flags->str,
 	            link->mtu, master,
 	            link->arptype,
-	            str_link_type ? " " : "",
 	            str_if_set (str_link_type, "???"),
-	            link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "",
+	            link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "?",
 	            link->kind && g_strcmp0 (str_link_type, link->kind) ? link->kind : "",
 	            link->initialized ? " init" : " not-init",
-	            str_addrmode,
+	            link->inet6_addr_gen_mode_inv ? " addrgenmode " : "",
+	            link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv), str_addrmode, sizeof (str_addrmode)) : "",
 	            str_addr ? " addr " : "",
 	            str_addr ? str_addr : "",
 	            str_inet6_token ? " inet6token " : "",
@@ -3444,6 +3419,7 @@ NM_UTILS_ENUM2STR_DEFINE (nm_platform_link_inet6_addrgenmode2str, guint8,
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_NONE, "none"),
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"),
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"),
+	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_RANDOM, "random"),
 );
 
 NM_UTILS_FLAGS2STR_DEFINE (nm_platform_addr_flags2str, unsigned,
@@ -3503,11 +3479,11 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu
 
 	_to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev));
 
-	nm_platform_addr_flags2str (address->flags, &s_flags[STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - STRLEN (S_FLAGS_PREFIX));
-	if (s_flags[STRLEN (S_FLAGS_PREFIX)] == '\0')
+	nm_platform_addr_flags2str (address->n_ifa_flags, &s_flags[NM_STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - NM_STRLEN (S_FLAGS_PREFIX));
+	if (s_flags[NM_STRLEN (S_FLAGS_PREFIX)] == '\0')
 		s_flags[0] = '\0';
 	else
-		memcpy (s_flags, S_FLAGS_PREFIX, STRLEN (S_FLAGS_PREFIX));
+		memcpy (s_flags, S_FLAGS_PREFIX, NM_STRLEN (S_FLAGS_PREFIX));
 
 	str_lft_p = _lifetime_to_string (address->timestamp,
 	                                 address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
@@ -3708,7 +3684,7 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
 	_CMP_FIELD_STR (a, b, name);
 	_CMP_FIELD (a, b, master);
 	_CMP_FIELD (a, b, parent);
-	_CMP_FIELD (a, b, flags);
+	_CMP_FIELD (a, b, n_ifi_flags);
 	_CMP_FIELD (a, b, connected);
 	_CMP_FIELD (a, b, mtu);
 	_CMP_FIELD_BOOL (a, b, initialized);
@@ -3871,7 +3847,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
 	_CMP_FIELD (a, b, timestamp);
 	_CMP_FIELD (a, b, lifetime);
 	_CMP_FIELD (a, b, preferred);
-	_CMP_FIELD (a, b, flags);
+	_CMP_FIELD (a, b, n_ifa_flags);
 	return 0;
 }
 
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 8ac129a0..b94c440a 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -27,11 +27,11 @@
 #include <linux/if_link.h>
 
 #include "nm-dbus-interface.h"
-#include "nm-default.h"
-#include "NetworkManagerUtils.h"
-#include "nm-setting-vlan.h"
 #include "nm-core-types-internal.h"
 
+#include "nm-core-utils.h"
+#include "nm-setting-vlan.h"
+
 #define NM_TYPE_PLATFORM            (nm_platform_get_type ())
 #define NM_PLATFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
 #define NM_PLATFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PLATFORM, NMPlatformClass))
@@ -61,6 +61,7 @@ typedef struct _NMPlatform NMPlatform;
 #define NM_IN6_ADDR_GEN_MODE_EUI64             0    /* IN6_ADDR_GEN_MODE_EUI64 */
 #define NM_IN6_ADDR_GEN_MODE_NONE              1    /* IN6_ADDR_GEN_MODE_NONE */
 #define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY    2    /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
+#define NM_IN6_ADDR_GEN_MODE_RANDOM            3    /* IN6_ADDR_GEN_MODE_RANDOM */
 
 #define NM_IFF_MULTI_QUEUE                     0x0100 /* IFF_MULTI_QUEUE */
 
@@ -118,7 +119,6 @@ struct _NMPlatformLink {
 	/* NMPlatform initializes this field with a static string. */
 	const char *driver;
 
-	gboolean initialized;
 	int master;
 
 	/* rtnl_link_get_link(), IFLA_LINK.
@@ -126,6 +126,11 @@ struct _NMPlatformLink {
 	 * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */
 	int parent;
 
+	/* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */
+	guint n_ifi_flags;
+
+	guint mtu;
+
 	/* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */
 	guint32 arptype;
 
@@ -146,15 +151,11 @@ struct _NMPlatformLink {
 	 * initialized with memset(0) has and unset value.*/
 	guint8 inet6_addr_gen_mode_inv;
 
-	/* IFF_* flags as u32. Note that ifi_flags in 'struct ifinfomsg' is declared as 'unsigned',
-	 * but libnl stores the flag internally as u32.  */
-	guint32 flags;
-
-	/* @connected is mostly identical to (@flags & IFF_UP). Except for bridge/bond masters,
+	/* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters,
 	 * where we coerce the link as disconnect if it has no slaves. */
-	gboolean connected;
+	bool connected:1;
 
-	guint mtu;
+	bool initialized:1;
 };
 
 typedef enum { /*< skip >*/
@@ -268,7 +269,7 @@ struct _NMPlatformIP6Address {
 	__NMPlatformIPAddress_COMMON;
 	struct in6_addr address;
 	struct in6_addr peer_address;
-	guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
+	guint32 n_ifa_flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
 };
 
 typedef union {
@@ -362,16 +363,16 @@ extern const NMPlatformVTableRoute nm_platform_vtable_route_v4;
 extern const NMPlatformVTableRoute nm_platform_vtable_route_v6;
 
 typedef struct {
+	in_addr_t local;
+	in_addr_t remote;
 	int parent_ifindex;
 	guint16 input_flags;
 	guint16 output_flags;
 	guint32 input_key;
 	guint32 output_key;
-	in_addr_t local;
-	in_addr_t remote;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
+	bool path_mtu_discovery:1;
 } NMPlatformLnkGre;
 
 typedef struct {
@@ -380,42 +381,42 @@ typedef struct {
 } NMPlatformLnkInfiniband;
 
 typedef struct {
-	int parent_ifindex;
 	struct in6_addr local;
 	struct in6_addr remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tclass;
 	guint8 encap_limit;
-	guint flow_label;
 	guint8 proto;
+	guint flow_label;
 } NMPlatformLnkIp6Tnl;
 
 typedef struct {
-	int parent_ifindex;
 	in_addr_t local;
 	in_addr_t remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
+	bool path_mtu_discovery:1;
 } NMPlatformLnkIpIp;
 
 typedef struct {
 	guint mode;
-	gboolean no_promisc;
-	gboolean tap;
+	bool no_promisc:1;
+	bool tap:1;
 } NMPlatformLnkMacvlan;
 
 typedef NMPlatformLnkMacvlan NMPlatformLnkMacvtap;
 
 typedef struct {
-	int parent_ifindex;
 	in_addr_t local;
 	in_addr_t remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
-	guint16 flags;
 	guint8 proto;
+	bool path_mtu_discovery:1;
+	guint16 flags;
 } NMPlatformLnkSit;
 
 typedef struct {
@@ -425,33 +426,33 @@ typedef struct {
 } NMPlatformLnkVlan;
 
 typedef struct {
-	int parent_ifindex;
-	guint32 id;
-	in_addr_t group;
-	in_addr_t local;
 	struct in6_addr group6;
 	struct in6_addr local6;
-	guint8 tos;
-	guint8 ttl;
-	gboolean learning;
+	in_addr_t group;
+	in_addr_t local;
+	int parent_ifindex;
+	guint32 id;
 	guint32 ageing;
 	guint32 limit;
 	guint16 dst_port;
 	guint16 src_port_min;
 	guint16 src_port_max;
-	gboolean proxy;
-	gboolean rsc;
-	gboolean l2miss;
-	gboolean l3miss;
+	guint8 tos;
+	guint8 ttl;
+	bool learning:1;
+	bool proxy:1;
+	bool rsc:1;
+	bool l2miss:1;
+	bool l3miss:1;
 } NMPlatformLnkVxlan;
 
 typedef struct {
 	gint64 owner;
 	gint64 group;
 	const char *mode;
-	gboolean no_pi;
-	gboolean vnet_hdr;
-	gboolean multi_queue;
+	bool no_pi:1;
+	bool vnet_hdr:1;
+	bool multi_queue:1;
 } NMPlatformTunProperties;
 
 /******************************************************************/
@@ -593,7 +594,7 @@ typedef struct {
 	                             struct in6_addr peer_address,
 	                             guint32 lifetime,
 	                             guint32 preferred_lft,
-	                             guint flags);
+	                             guint32 flags);
 	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
 	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
 	const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
@@ -666,7 +667,8 @@ _nm_platform_uint8_inv (guint8 scope)
 
 const char *nm_link_type_to_string (NMLinkType link_type);
 
-const char *nm_platform_error_to_string (NMPlatformError error);
+const char *_nm_platform_error_to_string (NMPlatformError error);
+#define nm_platform_error_to_string(error) NM_UTILS_LOOKUP_STR (_nm_platform_error_to_string, error)
 
 gboolean nm_platform_sysctl_set (NMPlatform *self, const char *path, const char *value);
 char *nm_platform_sysctl_get (NMPlatform *self, const char *path);
@@ -859,7 +861,7 @@ gboolean nm_platform_ip6_address_add (NMPlatform *self,
                                       struct in6_addr peer_address,
                                       guint32 lifetime,
                                       guint32 preferred_lft,
-                                      guint flags);
+                                      guint32 flags);
 gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
 gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
 gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 892fd9dd..b7b04490 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -18,16 +18,17 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nmp-object.h"
 
 #include <unistd.h>
 
-#include "nm-default.h"
-#include "nmp-object.h"
-#include "nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
 #include "nm-utils.h"
 
+#include "nm-core-utils.h"
+#include "nm-platform-utils.h"
+
 /*********************************************************************************************/
 
 #define _NMLOG_DOMAIN LOGD_PLATFORM
@@ -1256,7 +1257,7 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m
 
 	/* if native IFF_LOWER_UP is down, link.connected must also be down
 	 * regardless of the slaves. */
-	if (!NM_FLAGS_HAS (master->link.flags, IFF_LOWER_UP))
+	if (!NM_FLAGS_HAS (master->link.n_ifi_flags, IFF_LOWER_UP))
 		return !!master->link.connected;
 
 	if (potential_slave && NMP_OBJECT_GET_TYPE (potential_slave) != NMP_OBJECT_TYPE_LINK)
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index ab1cc2fe..7758798f 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -21,15 +21,11 @@
 #ifndef __NMP_OBJECT_H__
 #define __NMP_OBJECT_H__
 
-#include "config.h"
-
-#include "nm-platform.h"
-#include "nm-multi-index.h"
-#include "nm-macros-internal.h"
-
 #include <netlink/netlink.h>
 #include <gudev/gudev.h>
 
+#include "nm-platform.h"
+#include "nm-multi-index.h"
 
 typedef enum { /*< skip >*/
 	NMP_OBJECT_TO_STRING_ID,
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index 5cc3114c..3af34be4 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -1,9 +1,28 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <syslog.h>
 
-#include "nm-default.h"
 #include "nm-linux-platform.h"
 
 #include "nm-test-utils.h"
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index 566bb479..3b52a7be 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include "test-common.h"
 
@@ -255,7 +275,8 @@ test_ip4_address_peer (void)
 	/* Add/delete notification */
 	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, NULL);
 	accept_signal (address_added);
-	g_assert ((a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)));
+	a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer);
+	g_assert (a);
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
 
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
@@ -263,7 +284,8 @@ test_ip4_address_peer (void)
 	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, NULL);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
-	g_assert ((a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)));
+	a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
+	g_assert (a);
 
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
 
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 9e624a02..6ad24478 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include "test-common.h"
 
@@ -25,7 +45,7 @@ test_cleanup_internal (void)
 	int preferred = NM_PLATFORM_LIFETIME_PERMANENT;
 	int metric = 20;
 	int mss = 1000;
-	guint flags = 0;
+	guint32 flags = 0;
 
 	inet_pton (AF_INET, "192.0.2.1", &addr4);
 	inet_pton (AF_INET, "192.0.3.0", &network4);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 09a57f87..268a5c92 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <sys/mount.h>
 #include <sched.h>
@@ -39,7 +59,7 @@ add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCall
 	data->ifindex = ifindex;
 	data->ifname = ifname;
 
-	g_assert (data->handler_id >= 0);
+	g_assert (data->handler_id > 0);
 
 	return data;
 }
@@ -544,7 +564,7 @@ _ip_address_add (gboolean external_command,
                  guint32 lifetime,
                  guint32 preferred,
                  const char *label,
-                 guint flags)
+                 guint32 flags)
 {
 	gint64 end_time;
 
@@ -1008,7 +1028,7 @@ nmtstp_ip6_address_add (gboolean external_command,
                         struct in6_addr peer_address,
                         guint32 lifetime,
                         guint32 preferred,
-                        guint flags)
+                        guint32 flags)
 {
 	_ip_address_add (external_command,
 	                 FALSE,
@@ -1262,7 +1282,7 @@ nmtstp_link_set_updown (gboolean external_command,
 		plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
 		g_assert (plink);
 
-		if (NM_FLAGS_HAS (plink->flags, IFF_UP) == !!up)
+		if (NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP) == !!up)
 			break;
 
 		/* for internal command, we expect not to reach this line.*/
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 8b496262..3fa5ad50 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <sched.h>
 
@@ -290,9 +310,17 @@ test_slave (int master, int type, SignalData *master_changed)
 	ensure_no_signal (link_removed);
 	g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex));
 	g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0);
-	accept_signals (link_added, 0, 1);
-	accept_signals (link_changed, 1, 3);
-	accept_signals (link_removed, 0, 1);
+	if (link_changed->received_count > 0) {
+		accept_signals (link_added, 0, 1);
+		accept_signals (link_changed, 1, 3);
+		accept_signals (link_removed, 0, 1);
+	} else {
+		/* Due to https://bugzilla.redhat.com/show_bug.cgi?id=1285719 , kernel might send a
+		 * wrong RTM_DELLINK message so that we instead see an removed+added signal. */
+		accept_signal (link_added);
+		ensure_no_signal (link_changed);
+		accept_signal (link_removed);
+	}
 	accept_signals (master_changed, 1, 2);
 
 	ensure_no_signal (master_changed);
diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c
index eba2383b..3b44abb8 100644
--- a/src/platform/tests/test-nmp-object.c
+++ b/src/platform/tests/test-nmp-object.c
@@ -18,10 +18,10 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "nmp-object.h"
-
 #include "nm-default.h"
 
+#include "nmp-object.h"
+
 #include "nm-test-utils.h"
 
 struct {
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 60a0c15c..f5fa024b 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -1,10 +1,31 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * 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 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <linux/rtnetlink.h>
 
+#include "nm-core-utils.h"
 #include "test-common.h"
+
 #include "nm-test-utils.h"
-#include "NetworkManagerUtils.h"
 
 #define DEVICE_NAME "nm-test-device"
 
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index e05104f3..79f217a8 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -20,7 +20,7 @@
  * Copyright (C) 2011 Intel Corporation. All rights reserved.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
@@ -32,7 +32,6 @@
 #include <netlink/msg.h>
 #include <linux/nl80211.h>
 
-#include "nm-default.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-nl80211.h"
 #include "nm-platform.h"
diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c
index 96bcf53d..029601e4 100644
--- a/src/platform/wifi/wifi-utils-wext.c
+++ b/src/platform/wifi/wifi-utils-wext.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
@@ -28,8 +28,6 @@
 #include <unistd.h>
 #include <math.h>
 
-
-#include "nm-default.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-wext.h"
 #include "nm-utils.h"
@@ -315,7 +313,7 @@ wext_qual_to_percent (const struct iw_quality *qual,
 			noise = qual->noise - 0x100;
 		else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID))
 			noise = max_qual->noise - 0x100;
-		noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM);
+		noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM - 1);
 
 		/* A sort of signal-to-noise ratio calculation */
 		level_percent = (int) (100 - 70 * (((double)max_level - (double)level) /
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index 5f2f61b0..38e5a054 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -19,13 +19,12 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "wifi-utils.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-nl80211.h"
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 10bc0fec..1578e595 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -42,7 +42,6 @@
 #include <linux/if.h>
 #include <linux/if_ppp.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-ppp-manager.h"
 #include "nm-platform.h"
@@ -66,8 +65,8 @@ typedef struct {
 	NMActRequestGetSecretsCallId secrets_id;
 	const char *secrets_setting_name;
 
-	guint32 ppp_watch_id;
-	guint32 ppp_timeout_handler;
+	guint ppp_watch_id;
+	guint ppp_timeout_handler;
 
 	/* Monitoring */
 	char *ip_iface;
diff --git a/src/ppp-manager/nm-pppd-plugin.c b/src/ppp-manager/nm-pppd-plugin.c
index 1f1016ae..be4dd185 100644
--- a/src/ppp-manager/nm-pppd-plugin.c
+++ b/src/ppp-manager/nm-pppd-plugin.c
@@ -20,6 +20,7 @@
  */
 
 #include "config.h"
+#define ___CONFIG_H__
 
 #include <string.h>
 #include <pppd/pppd.h>
diff --git a/src/rdisc/nm-fake-rdisc.c b/src/rdisc/nm-fake-rdisc.c
index 001fd938..6a1585b3 100644
--- a/src/rdisc/nm-fake-rdisc.c
+++ b/src/rdisc/nm-fake-rdisc.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
@@ -26,8 +26,6 @@
 #include "nm-fake-rdisc.h"
 #include "nm-rdisc-private.h"
 
-#include "nm-default.h"
-
 #define _NMLOG_PREFIX_NAME                "rdisc-fake"
 
 typedef struct {
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
index 46000994..06863462 100644
--- a/src/rdisc/nm-lndp-rdisc.c
+++ b/src/rdisc/nm-lndp-rdisc.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
@@ -30,7 +30,6 @@
 #include "nm-rdisc-private.h"
 
 #include "NetworkManagerUtils.h"
-#include "nm-default.h"
 #include "nm-platform.h"
 
 #define _NMLOG_PREFIX_NAME                "rdisc-lndp"
diff --git a/src/rdisc/nm-rdisc.c b/src/rdisc/nm-rdisc.c
index 6133ae28..82aece30 100644
--- a/src/rdisc/nm-rdisc.c
+++ b/src/rdisc/nm-rdisc.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <arpa/inet.h>
@@ -27,7 +27,6 @@
 #include "nm-rdisc.h"
 #include "nm-rdisc-private.h"
 
-#include "nm-default.h"
 #include "nm-utils.h"
 
 #include <nm-setting-ip6-config.h>
diff --git a/src/rdisc/tests/test-rdisc-fake.c b/src/rdisc/tests/test-rdisc-fake.c
index ad045cff..00a98dca 100644
--- a/src/rdisc/tests/test-rdisc-fake.c
+++ b/src/rdisc/tests/test-rdisc-fake.c
@@ -18,14 +18,13 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <syslog.h>
 
 #include "nm-rdisc.h"
 #include "nm-fake-rdisc.h"
-#include "nm-default.h"
 
 #include "nm-fake-platform.h"
 
diff --git a/src/rdisc/tests/test-rdisc-linux.c b/src/rdisc/tests/test-rdisc-linux.c
index b93c50a7..bbdb5fb8 100644
--- a/src/rdisc/tests/test-rdisc-linux.c
+++ b/src/rdisc/tests/test-rdisc-linux.c
@@ -18,14 +18,13 @@
  * Copyright (C) 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <syslog.h>
 
 #include "nm-rdisc.h"
 #include "nm-lndp-rdisc.h"
-#include "nm-default.h"
 
 #include "nm-linux-platform.h"
 
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index ee1c6202..bc09e031 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -18,12 +18,11 @@
  * Copyright (C) 2010 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <pwd.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-agent-manager.h"
 #include "nm-secret-agent.h"
diff --git a/src/settings/nm-inotify-helper.c b/src/settings/nm-inotify-helper.c
index 681933cd..ce15246c 100644
--- a/src/settings/nm-inotify-helper.c
+++ b/src/settings/nm-inotify-helper.c
@@ -18,14 +18,13 @@
  * (C) Copyright 2008 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <unistd.h>
 #include <string.h>
 #include <sys/inotify.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "nm-inotify-helper.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c
index 89e84c26..bfa7b506 100644
--- a/src/settings/nm-secret-agent.c
+++ b/src/settings/nm-secret-agent.c
@@ -18,12 +18,11 @@
  * Copyright (C) 2010 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/types.h>
 #include <pwd.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-secret-agent.h"
 #include "nm-bus-manager.h"
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index f7e5002c..a1695b34 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -19,11 +19,10 @@
  * Copyright 2008 - 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dbus-interface.h"
 #include "nm-settings-connection.h"
 #include "nm-session-monitor.h"
@@ -1716,10 +1715,10 @@ get_update_modify_permission (NMConnection *old, NMConnection *new)
 }
 
 static void
-impl_settings_connection_update_helper (NMSettingsConnection *self,
-                                        GDBusMethodInvocation *context,
-                                        GVariant *new_settings,
-                                        gboolean save_to_disk)
+settings_connection_update_helper (NMSettingsConnection *self,
+                                   GDBusMethodInvocation *context,
+                                   GVariant *new_settings,
+                                   gboolean save_to_disk)
 {
 	NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
 	NMAuthSubject *subject = NULL;
@@ -1790,7 +1789,7 @@ impl_settings_connection_update (NMSettingsConnection *self,
                                  GDBusMethodInvocation *context,
                                  GVariant *new_settings)
 {
-	impl_settings_connection_update_helper (self, context, new_settings, TRUE);
+	settings_connection_update_helper (self, context, new_settings, TRUE);
 }
 
 static void
@@ -1798,7 +1797,7 @@ impl_settings_connection_update_unsaved (NMSettingsConnection *self,
                                          GDBusMethodInvocation *context,
                                          GVariant *new_settings)
 {
-	impl_settings_connection_update_helper (self, context, new_settings, FALSE);
+	settings_connection_update_helper (self, context, new_settings, FALSE);
 }
 
 static void
@@ -1807,7 +1806,7 @@ impl_settings_connection_save (NMSettingsConnection *self,
 {
 	/* Do nothing if the connection is already synced with disk */
 	if (nm_settings_connection_get_unsaved (self))
-		impl_settings_connection_update_helper (self, context, NULL, TRUE);
+		settings_connection_update_helper (self, context, NULL, TRUE);
 	else
 		g_dbus_method_invocation_return_value (context, NULL);
 }
diff --git a/src/settings/nm-settings-plugin.c b/src/settings/nm-settings-plugin.c
index 0bce8957..2023bc17 100644
--- a/src/settings/nm-settings-plugin.c
+++ b/src/settings/nm-settings-plugin.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "nm-settings-plugin.h"
 #include "nm-settings-connection.h"
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index f6f8c374..ee48e711 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -23,7 +23,7 @@
  * (C) Copyright 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
@@ -36,33 +36,32 @@
 #include <selinux/selinux.h>
 #endif
 
-#include <nm-dbus-interface.h>
-#include <nm-connection.h>
-#include <nm-setting-8021x.h>
-#include <nm-setting-bluetooth.h>
-#include <nm-setting-cdma.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-gsm.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-olpc-mesh.h>
-#include <nm-setting-ppp.h>
-#include <nm-setting-pppoe.h>
-#include <nm-setting-serial.h>
-#include <nm-setting-vpn.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-adsl.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-setting-bond.h>
-#include <nm-utils.h>
+#include "nm-dbus-interface.h"
+#include "nm-connection.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-bluetooth.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-olpc-mesh.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-adsl.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-bond.h"
+#include "nm-utils.h"
 #include "nm-core-internal.h"
 
 #include "nm-device-ethernet.h"
 #include "nm-settings.h"
 #include "nm-settings-connection.h"
 #include "nm-settings-plugin.h"
-#include "nm-default.h"
 #include "nm-bus-manager.h"
 #include "nm-auth-utils.h"
 #include "nm-auth-subject.h"
@@ -489,7 +488,7 @@ read_hostname_gentoo (const char *path)
 		if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
 			continue;
 		if (g_str_has_prefix (all_lines[i], "hostname=")) {
-			tmp = &all_lines[i][STRLEN ("hostname=")];
+			tmp = &all_lines[i][NM_STRLEN ("hostname=")];
 			result = g_shell_unquote (tmp, NULL);
 			break;
 		}
@@ -516,7 +515,7 @@ hostname_is_dynamic (void)
 		if (str) {
 			g_strstrip (str);
 			if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME="))
-				dynamic = strcmp (&str[STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0;
+				dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0;
 			g_free (str);
 		}
 	}
@@ -1533,10 +1532,11 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname)
 	gboolean ret;
 	gs_free_error GError *error = NULL;
 	const char *file = priv->hostname.file;
+	gs_free char *link_path = NULL;
 	gs_unref_variant GVariant *var = NULL;
+	struct stat file_stat;
 #if HAVE_SELINUX
 	security_context_t se_ctx_prev = NULL, se_ctx = NULL;
-	struct stat file_stat = { .st_mode = 0 };
 	mode_t st_mode = 0;
 #endif
 
@@ -1554,6 +1554,15 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname)
 		return !error;
 	}
 
+	/* If the hostname file is a symbolic link, follow it to find where the
+	 * real file is located, otherwise g_file_set_contents will attempt to
+	 * replace the link with a plain file.
+	 */
+	if (   lstat (file, &file_stat) == 0
+	    && S_ISLNK (file_stat.st_mode)
+	    && (link_path = g_file_read_link (file, NULL)))
+		file = link_path;
+
 #if HAVE_SELINUX
 	/* Get default context for hostname file and set it for fscreate */
 	if (stat (file, &file_stat) == 0)
@@ -1871,7 +1880,7 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
 	/* If the device isn't managed or it already has a default wired connection,
 	 * ignore it.
 	 */
-	if (   !nm_device_get_managed (device)
+	if (   !nm_device_get_managed (device, FALSE)
 	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG)
 	    || have_connection_for_device (self, device))
 		return;
diff --git a/src/settings/plugins/ibft/nm-ibft-connection.c b/src/settings/plugins/ibft/nm-ibft-connection.c
index c6a9054e..95495b5c 100644
--- a/src/settings/plugins/ibft/nm-ibft-connection.c
+++ b/src/settings/plugins/ibft/nm-ibft-connection.c
@@ -18,7 +18,7 @@
  * Copyright 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <net/ethernet.h>
diff --git a/src/settings/plugins/ibft/plugin.c b/src/settings/plugins/ibft/plugin.c
index 555725d1..6f9b8c82 100644
--- a/src/settings/plugins/ibft/plugin.c
+++ b/src/settings/plugins/ibft/plugin.c
@@ -18,7 +18,7 @@
  * Copyright 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <unistd.h>
@@ -26,9 +26,8 @@
 
 #include <gmodule.h>
 
-#include <nm-setting-connection.h>
+#include "nm-setting-connection.h"
 
-#include "nm-default.h"
 #include "nm-settings-plugin.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/settings/plugins/ibft/reader.c b/src/settings/plugins/ibft/reader.c
index 195c2641..c39d875c 100644
--- a/src/settings/plugins/ibft/reader.c
+++ b/src/settings/plugins/ibft/reader.c
@@ -18,7 +18,7 @@
  * Copyright 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -31,7 +31,6 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include "nm-default.h"
 #include "nm-core-internal.h"
 #include "nm-platform.h"
 #include "NetworkManagerUtils.h"
@@ -138,14 +137,14 @@ read_ibft_blocks (const char *iscsiadm_path,
 		if (!*iter[0])
 			continue;
 
-		if (!g_ascii_strncasecmp (*iter, TAG_BEGIN, STRLEN (TAG_BEGIN))) {
+		if (!g_ascii_strncasecmp (*iter, TAG_BEGIN, NM_STRLEN (TAG_BEGIN))) {
 			if (block_lines) {
 				PARSE_WARNING ("malformed iscsiadm record: missing END RECORD.");
 				g_ptr_array_unref (block_lines);
 			}
 			/* Start new record */
 			block_lines = g_ptr_array_new_full (15, g_free);
-		} else if (!g_ascii_strncasecmp (*iter, TAG_END, STRLEN (TAG_END))) {
+		} else if (!g_ascii_strncasecmp (*iter, TAG_END, NM_STRLEN (TAG_END))) {
 			if (block_lines) {
 				if (block_lines->len)
 					blocks = g_slist_prepend (blocks, block_lines);
diff --git a/src/settings/plugins/ibft/tests/test-ibft.c b/src/settings/plugins/ibft/tests/test-ibft.c
index c7aef050..a9085478 100644
--- a/src/settings/plugins/ibft/tests/test-ibft.c
+++ b/src/settings/plugins/ibft/tests/test-ibft.c
@@ -18,7 +18,7 @@
  * Copyright 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -33,7 +33,6 @@
 #include "NetworkManagerUtils.h"
 
 #include "reader.h"
-#include "nm-default.h"
 
 #include "nm-test-utils.h"
 
diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
index 336d9d66..2ee5a0b9 100644
--- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
+++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
@@ -18,25 +18,23 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
 #include <glib/gstdio.h>
 
-#include <nm-dbus-interface.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-gsm.h>
-#include <nm-setting-cdma.h>
-#include <nm-setting-pppoe.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-setting-8021x.h>
+#include "nm-dbus-interface.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-8021x.h"
 #include "nm-platform.h"
 
-#include "nm-default.h"
-
 #include "common.h"
 #include "nm-config.h"
 #include "nm-ifcfg-connection.h"
@@ -518,6 +516,9 @@ dispose (GObject *object)
 
 	g_clear_object (&priv->inotify_helper);
 
+	g_clear_pointer (&priv->unmanaged_spec, g_free);
+	g_clear_pointer (&priv->unrecognized_spec, g_free);
+
 	G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->dispose (object);
 }
 
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index 5afc46d6..d28e3bf6 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -21,7 +21,7 @@
  * Copyright (C) 2007 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <unistd.h>
@@ -33,7 +33,6 @@
 
 #include "nm-setting-connection.h"
 
-#include "nm-default.h"
 #include "common.h"
 #include "plugin.h"
 #include "nm-settings-plugin.h"
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index bcb726aa..ca512fc6 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -18,7 +18,7 @@
  * Copyright 2008 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -31,25 +31,24 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include <nm-connection.h>
-#include <nm-dbus-interface.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-vlan.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-8021x.h>
-#include <nm-setting-bond.h>
-#include <nm-setting-team.h>
-#include <nm-setting-team-port.h>
-#include <nm-setting-bridge.h>
-#include <nm-setting-bridge-port.h>
-#include <nm-setting-dcb.h>
-#include <nm-setting-generic.h>
-#include "nm-default.h"
+#include "nm-connection.h"
+#include "nm-dbus-interface.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-team.h"
+#include "nm-setting-team-port.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-bridge-port.h"
+#include "nm-setting-dcb.h"
+#include "nm-setting-generic.h"
 #include "nm-core-internal.h"
-#include <nm-utils.h>
+#include "nm-utils.h"
 
 #include "nm-platform.h"
 #include "NetworkManagerUtils.h"
@@ -600,8 +599,11 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError *
 			}
 		}
 		dest = g_match_info_fetch (match_info, 1);
-		if (!strcmp (dest, "default"))
-			strcpy (dest,  "0.0.0.0");
+		if (!strcmp (dest, "default")) {
+			g_match_info_free (match_info);
+			PARSE_WARNING ("ignoring manual default route: '%s' (%s)", *iter, filename);
+			continue;
+		}
 		if (!nm_utils_ipaddr_valid (AF_INET, dest)) {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Invalid IP4 route destination address '%s'", dest);
@@ -924,6 +926,7 @@ make_ip4_setting (shvarFile *ifcfg,
 	shvarFile *network_ifcfg;
 	shvarFile *route_ifcfg;
 	gboolean never_default = FALSE;
+	gint64 timeout;
 
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
 
@@ -970,12 +973,7 @@ make_ip4_setting (shvarFile *ifcfg,
 		else
 			method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
 	} else if (!g_ascii_strcasecmp (value, "autoip")) {
-		g_free (value);
-		g_object_set (s_ip4,
-		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
-		              NM_SETTING_IP_CONFIG_NEVER_DEFAULT, never_default,
-		              NULL);
-		return NM_SETTING (s_ip4);
+		method = NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL;
 	} else if (!g_ascii_strcasecmp (value, "shared")) {
 		int idx;
 
@@ -1036,7 +1034,7 @@ make_ip4_setting (shvarFile *ifcfg,
 
 		g_object_set (s_ip4,
 		              NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, svGetValueBoolean (ifcfg, "DHCP_SEND_HOSTNAME", TRUE),
-		              NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT, svGetValueInt64 (ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXUINT32, 0),
+		              NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, svGetValueInt64 (ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0),
 		              NULL);
 
 		value = svGetValue (ifcfg, "DHCP_CLIENT_ID", FALSE);
@@ -1199,6 +1197,11 @@ make_ip4_setting (shvarFile *ifcfg,
 		}
 	}
 
+	timeout = svGetValueInt64 (ifcfg, "ARPING_WAIT", 10, -1,
+	                           NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX / 1000, -1);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT,
+	              (gint) (timeout <= 0 ? timeout : timeout * 1000), NULL);
+
 	return NM_SETTING (s_ip4);
 
 done:
@@ -2810,7 +2813,7 @@ eap_ttls_reader (const char *eap_method,
 		           || !strcmp (*iter, "eap-gtc")) {
 			if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error))
 				goto done;
-			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + STRLEN ("eap-")), NULL);
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + NM_STRLEN ("eap-")), NULL);
 		} else {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
@@ -3142,8 +3145,7 @@ make_wpa_setting (shvarFile *ifcfg,
 		g_free (allow_rsn);
 	}
 
-	/* coverity[dereference] */
-	if (!strcmp (value, "WPA-PSK")) {
+	if (wpa_psk) {
 		NMSettingSecretFlags psk_flags;
 
 		psk_flags = read_secret_flags (ifcfg, "WPA_PSK_FLAGS");
@@ -3163,7 +3165,7 @@ make_wpa_setting (shvarFile *ifcfg,
 			g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
 		else
 			g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL);
-	} else if (!strcmp (value, "WPA-EAP") || !strcmp (value, "IEEE8021X")) {
+	} else if (wpa_eap || ieee8021x) {
 		/* Adhoc mode is mutually exclusive with any 802.1x-based authentication */
 		if (adhoc) {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -3324,6 +3326,7 @@ make_wireless_setting (shvarFile *ifcfg,
 	char *value = NULL;
 	gint64 chan = 0;
 	NMSettingMacRandomization mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER;
+	NMSettingWirelessPowersave powersave = NM_SETTING_WIRELESS_POWERSAVE_DEFAULT;
 
 	s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
 
@@ -3501,9 +3504,28 @@ make_wireless_setting (shvarFile *ifcfg,
 	              svGetValueBoolean (ifcfg, "SSID_HIDDEN", FALSE),
 	              NULL);
 
+	value = svGetValueFull (ifcfg, "POWERSAVE", FALSE);
+	if (value) {
+		if (!strcmp (value, "default"))
+			powersave = NM_SETTING_WIRELESS_POWERSAVE_DEFAULT;
+		else if (!strcmp (value, "ignore"))
+			powersave = NM_SETTING_WIRELESS_POWERSAVE_IGNORE;
+		else if (!strcmp (value, "disable") || !strcmp (value, "no"))
+			powersave = NM_SETTING_WIRELESS_POWERSAVE_DISABLE;
+		else if (!strcmp (value, "enable") || !strcmp (value, "yes"))
+			powersave = NM_SETTING_WIRELESS_POWERSAVE_ENABLE;
+		else {
+			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+			             "Invalid POWERSAVE value '%s'", value);
+			g_free (value);
+			goto error;
+		}
+		g_free (value);
+	}
+
 	g_object_set (s_wireless,
 	              NM_SETTING_WIRELESS_POWERSAVE,
-	              svGetValueBoolean (ifcfg, "POWERSAVE", FALSE) ? 1 : 0,
+	              powersave,
 	              NULL);
 
 	value = svGetValueFull (ifcfg, "MAC_ADDRESS_RANDOMIZATION", FALSE);
@@ -3517,6 +3539,7 @@ make_wireless_setting (shvarFile *ifcfg,
 		else {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Invalid MAC_ADDRESS_RANDOMIZATION value '%s'", value);
+			g_free (value);
 			goto error;
 		}
 		g_free (value);
@@ -4624,7 +4647,7 @@ make_vlan_setting (shvarFile *ifcfg,
 	char *end = NULL;
 	gint vlan_id = -1;
 	guint32 vlan_flags = 0;
-	gint gvrp;
+	gint gvrp, reorder_hdr;
 
 	value = svGetValue (ifcfg, "VLAN_ID", FALSE);
 	if (value) {
@@ -4699,8 +4722,7 @@ make_vlan_setting (shvarFile *ifcfg,
 	g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, parent, NULL);
 	g_clear_pointer (&parent, g_free);
 
-	if (svGetValueBoolean (ifcfg, "REORDER_HDR", FALSE))
-		vlan_flags |= NM_VLAN_FLAG_REORDER_HEADERS;
+	vlan_flags |= NM_VLAN_FLAG_REORDER_HEADERS;
 
 	gvrp = svGetValueBoolean (ifcfg, "GVRP", -1);
 	if (gvrp > 0)
@@ -4708,13 +4730,26 @@ make_vlan_setting (shvarFile *ifcfg,
 
 	value = svGetValue (ifcfg, "VLAN_FLAGS", FALSE);
 	if (value) {
-		/* Prefer GVRP variable; only take VLAN_FLAG=GVRP when GVRP is not specified */
-		if (g_strstr_len (value, -1, "GVRP") && gvrp == -1)
-			vlan_flags |= NM_VLAN_FLAG_GVRP;
-		if (g_strstr_len (value, -1, "LOOSE_BINDING"))
-			vlan_flags |= NM_VLAN_FLAG_LOOSE_BINDING;
+		gs_strfreev char **strv = NULL;
+		char **ptr;
+
+		strv = g_strsplit_set (value, ", ", 0);
+
+		for (ptr = strv; ptr && *ptr; ptr++) {
+			if (nm_streq (*ptr, "GVRP") && gvrp == -1)
+				vlan_flags |= NM_VLAN_FLAG_GVRP;
+			if (nm_streq (*ptr, "LOOSE_BINDING"))
+				vlan_flags |=  NM_VLAN_FLAG_LOOSE_BINDING;
+			if (nm_streq (*ptr, "NO_REORDER_HDR"))
+				vlan_flags &= ~NM_VLAN_FLAG_REORDER_HEADERS;
+		}
 	}
 
+	reorder_hdr = svGetValueBoolean (ifcfg, "REORDER_HDR", -1);
+	if (   reorder_hdr != -1
+	    && reorder_hdr != NM_FLAGS_HAS (vlan_flags, NM_VLAN_FLAG_REORDER_HEADERS))
+		PARSE_WARNING ("REORDER_HDR key is deprecated, use VLAN_FLAGS");
+
 	if (svGetValueBoolean (ifcfg, "MVRP", FALSE))
 		vlan_flags |= NM_VLAN_FLAG_MVRP;
 
diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c
index 43068c67..4e756349 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/settings/plugins/ifcfg-rh/shvar.c
@@ -23,7 +23,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -37,7 +37,6 @@
 #include "shvar.h"
 
 #include "nm-core-internal.h"
-#include "nm-default.h"
 
 #define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, "    " msg)
 
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
index a1b414fd..36e52af4 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
@@ -12,6 +12,7 @@ EXTRA_DIST = \
 	ifcfg-test-wired-shared-plus-ip \
 	ifcfg-test-wired-dhcp-send-hostname \
 	ifcfg-test-wired-dhcp6-only \
+	ifcfg-test-wired-autoip \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
 	ifcfg-test-wired-global-gateway-ignore \
@@ -106,6 +107,7 @@ EXTRA_DIST = \
 	ifcfg-test-vlan-only-device \
 	ifcfg-test-vlan-physdev \
 	ifcfg-test-vlan-reorder-hdr-1 \
+	ifcfg-test-vlan-reorder-hdr-2 \
 	ifcfg-test-vlan-flags-1 \
 	ifcfg-test-vlan-flags-2 \
 	ifcfg-test-wifi-wep-no-keys \
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
index cae7067e..2152961c 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
@@ -408,6 +408,7 @@ EXTRA_DIST = \
 	ifcfg-test-wired-shared-plus-ip \
 	ifcfg-test-wired-dhcp-send-hostname \
 	ifcfg-test-wired-dhcp6-only \
+	ifcfg-test-wired-autoip \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
 	ifcfg-test-wired-global-gateway-ignore \
@@ -502,6 +503,7 @@ EXTRA_DIST = \
 	ifcfg-test-vlan-only-device \
 	ifcfg-test-vlan-physdev \
 	ifcfg-test-vlan-reorder-hdr-1 \
+	ifcfg-test-vlan-reorder-hdr-2 \
 	ifcfg-test-vlan-flags-1 \
 	ifcfg-test-vlan-flags-2 \
 	ifcfg-test-wifi-wep-no-keys \
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2
index 3b536a66..2c01be71 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2
@@ -3,7 +3,6 @@ TYPE=Vlan
 DEVICE=super-vlan
 VLAN_ID=44
 PHYSDEV=eth9
-REORDER_HDR=no
 VLAN_FLAGS="GVRP LOOSE_BINDING"
 ONBOOT=yes
 BOOTPROTO=static
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface
index ccd75d7f..d8d9193f 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface
@@ -2,7 +2,6 @@ VLAN=yes
 TYPE=Vlan
 DEVICE=vlan43
 PHYSDEV=eth9
-REORDER_HDR=0
 VLAN_FLAGS=GVRP,LOOSE_BINDING
 VLAN_INGRESS_PRIORITY_MAP=0:1,2:5
 VLAN_EGRESS_PRIORITY_MAP=12:3,14:7,3:1
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1
index ca38f839..0dc53971 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1
@@ -3,5 +3,4 @@ TYPE=Vlan
 DEVICE=vlan0.3
 PHYSDEV=eth0
 VLAN_ID=3
-REORDER_HDR=1
-
+REORDER_HDR=0
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2
new file mode 100644
index 00000000..d98a9d36
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2
@@ -0,0 +1,6 @@
+VLAN=yes
+TYPE=Vlan
+DEVICE=vlan0.3
+PHYSDEV=eth0
+VLAN_ID=3
+VLAN_FLAGS="LOOSE_BINDING,NO_REORDER_HDR"
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip
new file mode 100644
index 00000000..dc47126c
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip
@@ -0,0 +1,5 @@
+TYPE=Ethernet
+DEVICE=eth0
+BOOTPROTO=autoip
+IPV4_FAILURE_FATAL=yes
+PEERDNS=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
index 68f236af..5a0f6451 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -39,14 +39,7 @@ test_get_ifcfg_name (const char *desc,
 	const char *result;
 
 	result = utils_get_ifcfg_name (path, only_ifcfg);
-	if (expected == NULL) {
-		ASSERT (result == NULL, desc, "unexpected valid ifcfg name '%s'", result);
-	} else {
-		ASSERT (result != NULL, desc, "failed to create ifcfg name for '%s'", path);
-
-		ASSERT (strcmp (result, expected) == 0,
-		        desc, "unexpected ifcfg name '%s' created for '%s'", result, path);
-	}
+	g_assert_cmpstr (result, ==, expected);
 }
 
 static void
@@ -57,14 +50,7 @@ test_get_ifcfg_path (const char *desc,
 	char *result;
 
 	result = utils_get_ifcfg_path (path);
-	if (expected == NULL) {
-		ASSERT (result == NULL, desc, "unexpected valid ifcfg name '%s'", result);
-	} else {
-		ASSERT (result != NULL, desc, "failed to create ifcfg name for '%s'", path);
-
-		ASSERT (strcmp (result, expected) == 0,
-		        desc, "unexpected ifcfg name '%s' created for '%s'", result, path);
-	}
+	g_assert_cmpstr (result, ==, expected);
 	g_free (result);
 }
 
@@ -76,14 +62,7 @@ test_get_keys_path (const char *desc,
 	char *result;
 
 	result = utils_get_keys_path (path);
-	if (expected == NULL) {
-		ASSERT (result == NULL, desc, "unexpected valid extra path '%s'", result);
-	} else {
-		ASSERT (result != NULL, desc, "failed to create extra path for '%s'", path);
-
-		ASSERT (strcmp (result, expected) == 0,
-		        desc, "unexpected extra path '%s' created for '%s'", result, path);
-	}
+	g_assert_cmpstr (result, ==, expected);
 	g_free (result);
 }
 
@@ -95,14 +74,7 @@ test_get_route_path (const char *desc,
 	char *result;
 
 	result = utils_get_route_path (path);
-	if (expected == NULL) {
-		ASSERT (result == NULL, desc, "unexpected valid extra path '%s'", result);
-	} else {
-		ASSERT (result != NULL, desc, "failed to create extra path for '%s'", path);
-
-		ASSERT (strcmp (result, expected) == 0,
-		        desc, "unexpected extra path '%s' created for '%s'", result, path);
-	}
+	g_assert_cmpstr (result, ==, expected);
 	g_free (result);
 }
 
@@ -112,7 +84,7 @@ test_ignored (const char *desc, const char *path, gboolean expected_ignored)
 	gboolean result;
 
 	result = utils_should_ignore_file (path, FALSE);
-	ASSERT (result == expected_ignored, desc, "unexpected ignore result for path '%s'", path);
+	g_assert (result == expected_ignored);
 }
 
 static void
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index b7a887d0..8ca5c8bb 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -30,22 +30,22 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <nm-utils.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-8021x.h>
-#include <nm-setting-pppoe.h>
-#include <nm-setting-ppp.h>
-#include <nm-setting-vpn.h>
-#include <nm-setting-gsm.h>
-#include <nm-setting-cdma.h>
-#include <nm-setting-serial.h>
-#include <nm-setting-vlan.h>
-#include <nm-setting-dcb.h>
+#include "nm-utils.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-dcb.h"
 #include "nm-core-internal.h"
 
 #include "NetworkManagerUtils.h"
@@ -54,36 +54,99 @@
 #include "reader.h"
 #include "writer.h"
 #include "utils.h"
-#include "nm-default.h"
 
 #include "nm-test-utils.h"
 
-typedef struct {
-	const char *name;
-	const NMSettingMacRandomization value;
-	const char *write_expected;
-} WifiMacRandomData;
+/*****************************************************************************/
+
+static NMConnection *
+_connection_from_file (const char *filename,
+                       const char *network_file,
+                       const char *test_type,
+                       char **out_unhandled)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_assert (!out_unhandled || !*out_unhandled);
+
+	connection = connection_from_file_test (filename, network_file, test_type, out_unhandled, &error);
+	g_assert_no_error (error);
+
+	if (out_unhandled && *out_unhandled)
+		nmtst_assert_connection_verifies (connection);
+	else
+		nmtst_assert_connection_verifies_without_normalization (connection);
+	return connection;
+}
 
-#if 0
 static void
-connection_diff (NMConnection *a, NMConnection *b)
+_connection_from_file_fail (const char *filename,
+                            const char *network_file,
+                            const char *test_type,
+                            GError **error)
 {
-	GHashTable *hash;
-	GHashTableIter iter, siter;
-	const char *setting_name, *key;
-	GHashTable *setting_hash = NULL;
+	NMConnection *connection;
+	GError *local = NULL;
+	char *unhandled = NULL;
+	char **p_unhandled = (nmtst_get_rand_int () % 2) ? &unhandled : NULL;
 
-	if (!nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &hash)) {
-		g_hash_table_iter_init (&iter, hash);
-		while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) {
-			g_hash_table_iter_init (&siter, setting_hash);
-			while (g_hash_table_iter_next (&siter, (gpointer) &key, NULL))
-				g_message (":: %s :: %s", setting_name,key);
-		}
-		g_hash_table_destroy (hash);
-	}
+	connection = connection_from_file_test (filename, network_file, test_type, p_unhandled, &local);
+
+	g_assert (!connection);
+	g_assert (local);
+	g_assert (!p_unhandled || !*p_unhandled);
+	g_propagate_error (error, local);
+}
+
+static void
+_writer_new_connection (NMConnection *connection,
+                        const char *ifcfg_dir,
+                        char **out_filename)
+{
+	gboolean success;
+	GError *error = NULL;
+	char *filename = NULL;
+
+	g_assert (NM_IS_CONNECTION (connection));
+	g_assert (ifcfg_dir);
+
+	success = writer_new_connection (connection,
+	                                 ifcfg_dir,
+	                                 &filename,
+	                                 &error);
+	nmtst_assert_success (success, error);
+	g_assert (filename && filename[0]);
+
+	if (out_filename)
+		*out_filename = filename;
+	else
+		g_free (filename);
 }
-#endif
+
+static void
+_writer_new_connection_fail (NMConnection *connection,
+                             const char *ifcfg_dir,
+                             GError **error)
+{
+	gboolean success;
+	GError *local = NULL;
+	char *filename = NULL;
+
+	g_assert (NM_IS_CONNECTION (connection));
+	g_assert (ifcfg_dir);
+
+	success = writer_new_connection (connection,
+	                                 ifcfg_dir,
+	                                 &filename,
+	                                 &local);
+	nmtst_assert_no_success (success, local);
+	g_assert (!filename);
+
+	g_propagate_error (error, local);
+}
+
+/*****************************************************************************/
 
 static gboolean
 verify_cert_or_key (NMSetting8021x *s_compare,
@@ -193,26 +256,17 @@ test_read_basic (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	const char *expected_id = "System test-minimal";
-	guint64 expected_timestamp = 0;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-minimal",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-minimal",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
-	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-minimal");
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
 	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
@@ -252,22 +306,15 @@ test_read_miscellaneous_variables (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	char *expected_mac_blacklist[3] = { "00:16:41:11:22:88", "00:16:41:11:22:99", "6a:5d:5a:fa:dd:f0" };
 	int mac_blacklist_num, i;
 	guint64 expected_timestamp = 0;
-	gboolean success;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*invalid MAC in HWADDR_BLACKLIST 'XX:aa:invalid'*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-misc-variables",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-misc-variables",
+	                                    NULL, TYPE_ETHERNET, NULL);
 	g_test_assert_expected_messages ();
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
@@ -302,28 +349,18 @@ test_read_variables_corner_cases (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	const char *expected_zone = "'";
-	const char *expected_id = "\"";
-	guint64 expected_timestamp = 0;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-variables-corner-cases-1",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-variables-corner-cases-1",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
-	g_assert_cmpstr (nm_setting_connection_get_zone (s_con), ==, expected_zone);
-	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "\"");
+	g_assert_cmpstr (nm_setting_connection_get_zone (s_con), ==, "'");
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
 	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
@@ -351,26 +388,17 @@ test_read_unmanaged (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	char *unhandled_spec = NULL;
-	GError *error = NULL;
-	const char *expected_id = "System test-nm-controlled";
 	guint64 expected_timestamp = 0;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled",
-	                                        NULL, TYPE_ETHERNET,
-	                                        &unhandled_spec,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled",
+	                                    NULL, TYPE_ETHERNET,
+	                                    &unhandled_spec);
 	g_assert_cmpstr (unhandled_spec, ==, "unmanaged:mac:00:11:22:33:f8:9f");
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-nm-controlled");
 	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
 	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
@@ -384,26 +412,17 @@ test_read_unmanaged_unrecognized (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	gs_free char *unhandled_spec = NULL;
-	GError *error = NULL;
-	const char *expected_id = "PigeonNet";
 	guint64 expected_timestamp = 0;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled-unrecognized",
-	                                        NULL, NULL,
-	                                        &unhandled_spec,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled-unrecognized",
+	                                    NULL, NULL,
+	                                    &unhandled_spec);
 	g_assert_cmpstr (unhandled_spec, ==, "unmanaged:interface-name:ipoac0");
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "PigeonNet");
 	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
 
 	g_object_unref (connection);
@@ -415,35 +434,24 @@ test_read_unrecognized (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	gs_free char *unhandled_spec = NULL;
-	GError *error = NULL;
-	const char *expected_id = "U Can't Touch This";
 	guint64 expected_timestamp = 0;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-unrecognized",
-	                                        NULL, NULL,
-	                                        &unhandled_spec,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-unrecognized",
+	                                    NULL, NULL,
+	                                    &unhandled_spec);
 	g_assert_cmpstr (unhandled_spec, ==, "unrecognized:mac:00:11:22:33");
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "U Can't Touch This");
 	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
 
 	g_object_unref (connection);
 }
 
 static void
-test_read_wired_static (const char *file,
-                        const char *expected_id,
-                        gboolean expect_ip6)
+test_read_wired_static (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
@@ -451,20 +459,19 @@ test_read_wired_static (const char *file,
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0xee };
 	NMIPAddress *ip4_addr;
 	NMIPAddress *ip6_addr;
-	gboolean success;
+	const char *file, *expected_id;
+	gpointer expect_ip6_p;
 
-	connection = connection_from_file_test (file, NULL, TYPE_ETHERNET,
-	                                        &unmanaged, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_test_data_unpack (test_data, &file, &expected_id, &expect_ip6_p);
+
+	g_assert (expected_id);
+
+	connection = _connection_from_file (file, NULL, TYPE_ETHERNET,
+	                                    &unmanaged);
 	g_assert_cmpstr (unmanaged, ==, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
@@ -511,7 +518,7 @@ test_read_wired_static (const char *file,
 	/* ===== IPv6 SETTING ===== */
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	g_assert (s_ip6);
-	if (expect_ip6) {
+	if (GPOINTER_TO_INT (expect_ip6_p)) {
 		g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
 		g_assert (nm_setting_ip_config_get_may_fail (s_ip6));
 
@@ -550,7 +557,6 @@ test_read_wired_static_no_prefix (gconstpointer user_data)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	NMIPAddress *ip4_addr;
 	char *file, *expected_id;
 
@@ -559,12 +565,8 @@ test_read_wired_static_no_prefix (gconstpointer user_data)
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*missing PREFIX, assuming*");
-	connection = connection_from_file_test (file, NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
+	connection = _connection_from_file (file, NULL, TYPE_ETHERNET, NULL);
 	g_test_assert_expected_messages ();
-	g_assert_no_error (error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
@@ -589,8 +591,6 @@ test_read_wired_static_no_prefix (gconstpointer user_data)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_DHCP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp"
-
 static void
 test_read_wired_dhcp (void)
 {
@@ -599,135 +599,39 @@ test_read_wired_dhcp (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0xee };
-	const char *tmp;
-	const char *expected_id = "System test-wired-dhcp";
-	const char *expected_dhcp_hostname = "foobar";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_DHCP,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-dhcp-read", "failed to read %s: %s", TEST_IFCFG_WIRED_DHCP, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-dhcp-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_DHCP, error->message);
+	const char *mac;
 
-	ASSERT (unmanaged == NULL,
-	        "wired-dhcp-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_DHCP);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-dhcp",
+	                                    NULL, TYPE_ETHERNET,
+	                                    &unmanaged);
+	g_assert (unmanaged == NULL);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-dhcp-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-dhcp-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-dhcp-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == 0,
-	        "wired-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "wired-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-dhcp");
+	g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-dhcp-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* MAC address */
 	mac = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (mac != NULL,
-	        "wired-dhcp-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "wired-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	tmp = nm_setting_ip_config_get_dhcp_hostname (s_ip4);
-	ASSERT (tmp != NULL,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DHCP_HOSTNAME);
-	ASSERT (strcmp (tmp, expected_dhcp_hostname) == 0,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DHCP_HOSTNAME);
-
-	ASSERT (nm_setting_ip_config_get_ignore_auto_dns (s_ip4) == TRUE,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS);
-
-	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 0), "4.2.2.1") == 0,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 1), "4.2.2.2") == 0,
-	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
-	        TEST_IFCFG_WIRED_DHCP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+	g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip4), ==, "foobar");
+	g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+	g_assert_cmpuint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "4.2.2.1");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "4.2.2.2");
 
 	g_object_unref (connection);
 }
@@ -738,19 +642,11 @@ test_read_wired_dhcp_plus_ip (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	GError *error = NULL;
 	NMIPAddress *ip4_addr;
 	NMIPAddress *ip6_addr;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -814,13 +710,10 @@ test_read_wired_shared_plus_ip (void)
 {
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	NMIPAddress *ip4_addr;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-shared-plus-ip",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-shared-plus-ip",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -848,14 +741,12 @@ test_read_wired_global_gateway (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	NMIPAddress *ip4_addr;
 	char *unmanaged = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway",
-	                                        TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway",
-	                                        TYPE_ETHERNET, &unmanaged, &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway",
+	                                    TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway",
+	                                    TYPE_ETHERNET, &unmanaged);
 	g_assert (unmanaged == NULL);
 
 	/* ===== CONNECTION SETTING ===== */
@@ -892,15 +783,14 @@ test_read_wired_global_gateway_ignore (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	char *unmanaged = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*ignoring GATEWAY (/etc/sysconfig/network) for * because the connection has no static addresses");
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway-ignore",
-	                                        TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway-ignore",
-	                                        TYPE_ETHERNET, &unmanaged, &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway-ignore",
+	                                    TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway-ignore",
+	                                    TYPE_ETHERNET, &unmanaged);
+	g_test_assert_expected_messages ();
 	g_assert (unmanaged == NULL);
 
 	/* ===== CONNECTION SETTING ===== */
@@ -931,13 +821,10 @@ test_read_wired_obsolete_gateway_n (void)
 {
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	NMIPAddress *ip4_addr;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-obsolete-gateway-n",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-obsolete-gateway-n",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -963,12 +850,10 @@ test_read_wired_never_default (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-never-default",
-	                                        TEST_IFCFG_DIR"/network-scripts/network-test-wired-never-default",
-	                                        TYPE_ETHERNET, NULL, &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-never-default",
+	                                    TEST_IFCFG_DIR"/network-scripts/network-test-wired-never-default",
+	                                    TYPE_ETHERNET, NULL);
 
 	/* ===== WIRED SETTING ===== */
 	g_assert (nm_connection_get_setting_wired (connection));
@@ -989,221 +874,67 @@ test_read_wired_never_default (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_DEFROUTE_NO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-defroute-no"
-
 static void
 test_read_wired_defroute_no (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-defroute-no";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_DEFROUTE_NO,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-defroute-no-read", "failed to read %s: %s", TEST_IFCFG_WIRED_DEFROUTE_NO, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-defroute-no-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_DEFROUTE_NO, error->message);
 
-	ASSERT (unmanaged == NULL,
-	        "wired-defroute-no-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_DEFROUTE_NO);
-
-	/* ===== CONNECTION SETTING ===== */
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-defroute-no",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (unmanaged == NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-defroute-no-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-defroute-no-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-defroute-no-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* ===== WIRED SETTING ===== */
-
-	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-defroute-no-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-defroute-no");
 
-	/* ===== IPv4 SETTING ===== */
+	g_assert (nm_connection_get_setting_wired (connection));
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-defroute-no-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wired-defroute-no-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip4) == TRUE,
-	        "wired-defroute-no-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
-
-	/* ===== IPv6 SETTING ===== */
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip_config_get_never_default (s_ip4));
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "wired-defroute-no-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0,
-	        "wired-defroute-no-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip6) == TRUE,
-	        "wired-defroute-no-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip_config_get_never_default (s_ip6));
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes"
-#define TEST_NETWORK_WIRED_DEFROUTE_NO_GATEWAYDEV_YES TEST_IFCFG_DIR"/network-scripts/network-test-wired-defroute-no-gatewaydev-yes"
-
 static void
 test_read_wired_defroute_no_gatewaydev_yes (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-defroute-no-gatewaydev-yes";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	                                        TEST_NETWORK_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-defroute-no-gatewaydev-yes-read",
-	        "failed to read %s: %s",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-defroute-no-gatewaydev-yes-verify",
-	        "failed to verify %s: %s",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify",
-	        "failed to verify %s: unexpected unmanaged value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES);
 
-	/* ===== CONNECTION SETTING ===== */
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes",
+	                                    TEST_IFCFG_DIR"/network-scripts/network-test-wired-defroute-no-gatewaydev-yes",
+	                                    TYPE_ETHERNET,
+	                                    &unmanaged);
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-defroute-no-gatewaydev-yes-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* ===== WIRED SETTING ===== */
-
-	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-defroute-no-gatewaydev-yes");
 
-	/* ===== IPv4 SETTING ===== */
+	g_assert (nm_connection_get_setting_wired (connection));
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip4) == FALSE,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
-
-	/* ===== IPv6 SETTING ===== */
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip_config_get_never_default (s_ip4) == FALSE);
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip6) == FALSE,
-	        "wired-defroute-no-gatewaydev-yes-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DEFROUTE_NO_GATEWAYDEV_YES,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip_config_get_never_default (s_ip6) == FALSE);
 
 	g_object_unref (connection);
 }
@@ -1215,12 +946,10 @@ test_read_wired_static_routes (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
 	NMIPRoute *ip4_route;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	nmtst_assert_connection_verifies_without_normalization (connection);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
@@ -1256,8 +985,6 @@ test_read_wired_static_routes (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes-legacy"
-
 static void
 test_read_wired_static_routes_legacy (void)
 {
@@ -1266,82 +993,31 @@ test_read_wired_static_routes_legacy (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
 	NMIPRoute *ip4_route;
-	const char *expected_id = "System test-wired-static-routes-legacy";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-
-	ASSERT (connection != NULL,
-	        "wired-static-routes-legacy-read",
-	        "failed to read %s: %s",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-static-routes-legacy-verify", "failed to verify %s: %s",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, error->message);
 
-	ASSERT (unmanaged == NULL,
-	        "wired-static-routes-legacy-verify",
-	        "failed to verify %s: unexpected unmanaged value",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes-legacy",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-static-routes-legacy-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-static-routes-legacy-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-static-routes-legacy-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-static-routes-legacy");
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-static-routes-legacy-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
 
 	/* Routes */
-	ASSERT (nm_setting_ip_config_get_num_routes (s_ip4) == 3,
-	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_ROUTES);
+	g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 3);
 
 	/* Route #1 */
 	ip4_route = nm_setting_ip_config_get_route (s_ip4, 0);
@@ -1371,82 +1047,45 @@ test_read_wired_static_routes_legacy (void)
 }
 
 static void
-test_read_wired_ipv4_manual (const char *file, const char *expected_id)
+test_read_wired_ipv4_manual (gconstpointer data)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
 	NMIPAddress *ip4_addr;
+	const char *file, *expected_id;
 
-	connection = connection_from_file_test (file,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-ipv4-manual-read", "failed to read %s: %s", file, error->message);
+	nmtst_test_data_unpack (data, &file, &expected_id);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-ipv4-manual-verify", "failed to verify %s: %s", file, error->message);
+	g_assert (expected_id);
 
-	ASSERT (unmanaged == NULL,
-	        "wired-ipv4-manual-verify", "failed to verify %s: unexpected unmanaged value", file);
+	connection = _connection_from_file (file,
+	                                    NULL,
+	                                    TYPE_ETHERNET,
+	                                    &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-ipv4-manual-verify-connection", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-ipv4-manual-verify-connection", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-ipv4-manual-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-ipv4-manual-verify-wired", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-ipv4-manual-verify-ip4", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-ipv4-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
 
 	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 3,
-		"wired-ipv4-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-		file,
-		NM_SETTING_IP4_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 3);
 
 	/* Address #1 */
 	ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
@@ -1469,8 +1108,6 @@ test_read_wired_ipv4_manual (const char *file, const char *expected_id)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_IPV6_MANUAL TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-manual"
-
 static void
 test_read_wired_ipv6_manual (void)
 {
@@ -1480,151 +1117,51 @@ test_read_wired_ipv6_manual (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-ipv6-manual";
 	NMIPAddress *ip6_addr;
 	NMIPRoute *ip6_route;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*ignoring manual default route*");
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_IPV6_MANUAL,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-manual",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
 	g_test_assert_expected_messages ();
-
-	ASSERT (connection != NULL,
-	        "wired-ipv6-manual-read", "failed to read %s: %s", TEST_IFCFG_WIRED_IPV6_MANUAL, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-ipv6-manual-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_IPV6_MANUAL, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-ipv6-manual-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_IPV6_MANUAL);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-ipv6-manual-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-ipv6-manual-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-ipv6-manual-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-ipv6-manual");
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-ipv6-manual-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	g_assert (s_ip4);
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
 
 	/* DNS search domains */
-	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip4) == 3,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip4, 0);
-	ASSERT (tmp != NULL,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (strcmp (tmp, "lorem.com") == 0,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip4, 1);
-	ASSERT (tmp != NULL,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (strcmp (tmp, "ipsum.org") == 0,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip4, 2);
-	ASSERT (tmp != NULL,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (strcmp (tmp, "dolor.edu") == 0,
-	        "wired-ipv6-manual-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip4), ==, 3);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 0), ==, "lorem.com");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 1), ==, "ipsum.org");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 2), ==, "dolor.edu");
 
 	/* ===== IPv6 SETTING ===== */
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip6) == FALSE,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
-
-	ASSERT (nm_setting_ip_config_get_may_fail (s_ip6) == TRUE,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_MAY_FAIL);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
+	g_assert (!nm_setting_ip_config_get_never_default (s_ip6));
+	g_assert (nm_setting_ip_config_get_may_fail (s_ip6));
 
 	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip6) == 3,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 3);
 
 	/* Address #1 */
 	ip6_addr = nm_setting_ip_config_get_address (s_ip6, 0);
@@ -1662,39 +1199,18 @@ test_read_wired_ipv6_manual (void)
 	g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, 777);
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip6) == 2,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 0), "1:2:3:4::a") == 0,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 1), "1:2:3:4::b") == 0,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value #2",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_DNS);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "1:2:3:4::a");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 1), ==, "1:2:3:4::b");
 
 	/* DNS domains - none as domains are stuffed to 'ipv4' setting */
-	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip6) == 0,
-	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 0);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_IPV6_ONLY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only"
-#define TEST_IFCFG_WIRED_IPV6_ONLY_1 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only-1"
-
 static void
-test_read_wired_ipv6_only (const char *file, const char *expected_id)
+test_read_wired_ipv6_only (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
@@ -1702,91 +1218,44 @@ test_read_wired_ipv6_only (const char *file, const char *expected_id)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
 	NMIPAddress *ip6_addr;
 	const char *method;
+	const char *file, *expected_id;
 
-	connection = connection_from_file_test (file,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-ipv6-only-read", "failed to read %s: %s", file, error->message);
+	nmtst_test_data_unpack (test_data, &file, &expected_id);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-ipv6-only-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_IPV6_ONLY, error->message);
+	g_assert (expected_id);
 
-	ASSERT (unmanaged == NULL,
-	        "wired-ipv6-only-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_IPV6_MANUAL);
+	connection = _connection_from_file (file, NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-ipv6-only-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-ipv6-only-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-ipv6-only-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-ipv6-only-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-ipv6-only-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	g_assert (s_ip4);
 
 	method = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
-	        "wired-ipv6-only-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert_cmpstr (method, ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
 
 	/* ===== IPv6 SETTING ===== */
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "wired-ipv6-only-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
 
 	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip6) == 1,
-		"wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 1);
 
 	/* Address #1 */
 	ip6_addr = nm_setting_ip_config_get_address (s_ip6, 0);
@@ -1795,17 +1264,8 @@ test_read_wired_ipv6_only (const char *file, const char *expected_id)
 	g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 56);
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip6) == 1,
-	        "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 0), "1:2:3:4::a") == 0,
-		"wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP_CONFIG_DNS);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 1);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "1:2:3:4::a");
 
 	/* DNS domains should be in IPv6, because IPv4 is disabled */
 	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 3);
@@ -1816,8 +1276,6 @@ test_read_wired_ipv6_only (const char *file, const char *expected_id)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_DHCP6_ONLY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp6-only"
-
 static void
 test_read_wired_dhcp6_only (void)
 {
@@ -1827,89 +1285,57 @@ test_read_wired_dhcp6_only (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-dhcp6-only";
 	const char *method;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_DHCP6_ONLY,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-dhcp6-only-read", "failed to read %s: %s", TEST_IFCFG_WIRED_DHCP6_ONLY, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-dhcp6-only-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_DHCP6_ONLY, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-dhcp6-only-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_DHCP6_ONLY);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp6-only", NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-dhcp6-only-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-dhcp6-only-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-dhcp6-only-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-dhcp6-only");
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-dhcp6-only-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-dhcp6-only-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	g_assert (s_ip4);
 
 	method = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
-	        "wired-dhcp6-only-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert_cmpstr (method, ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
 
 	/* ===== IPv6 SETTING ===== */
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "wired-dhcp6-only-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0,
-	        "wired-dhcp6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_DHCP6_ONLY,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DHCP);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_ONBOOT_NO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-onboot-no"
+static void
+test_read_wired_autoip (void)
+{
+	gs_unref_object NMConnection *connection = NULL;
+	NMSettingIPConfig *s_ip4;
+	char *unmanaged = NULL;
+
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-autoip",
+	                                    NULL, TYPE_ETHERNET,
+	                                    &unmanaged);
+	g_assert (unmanaged == NULL);
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL);
+	g_assert (!nm_setting_ip_config_get_may_fail (s_ip4));
+	g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+}
 
 static void
 test_read_onboot_no (void)
@@ -1917,58 +1343,26 @@ test_read_onboot_no (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	char *unmanaged = NULL;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_ONBOOT_NO,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "onboot-no-read", "failed to read %s: %s", TEST_IFCFG_ONBOOT_NO, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "onboot-no-verify", "failed to verify %s: %s", TEST_IFCFG_ONBOOT_NO, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "onboot-no-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_ONBOOT_NO);
-
-	/* ===== CONNECTION SETTING ===== */
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-onboot-no", NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "onboot-no-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_ONBOOT_NO,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == FALSE,
-	        "onboot-no-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_ONBOOT_NO,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (!nm_setting_connection_get_autoconnect (s_con));
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_NOIP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-noip"
-
 static void
 test_read_noip (void)
 {
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_NOIP,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
-	g_assert_no_error (error);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-noip", NULL, TYPE_ETHERNET, NULL);
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	g_assert (s_ip4);
@@ -1983,8 +1377,7 @@ test_read_noip (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2"
-#define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
+#define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT TEST_IFCFG_DIR "/network-scripts/test_ca_cert.pem"
 
 static void
 test_read_wired_8021x_peap_mschapv2 (void)
@@ -1996,141 +1389,36 @@ test_read_wired_8021x_peap_mschapv2 (void)
 	NMSetting8021x *tmp_8021x;
 	char *unmanaged = NULL;
 	GError *error = NULL;
-	const char *tmp;
-	const char *expected_identity = "David Smith";
-	const char *expected_anon_identity = "somebody";
-	const char *expected_password = "foobar baz";
 	gboolean success = FALSE;
 	const char *expected_ca_cert_path;
 	const char *read_ca_cert_path;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-8021x-peap-mschapv2-read", "failed to read %s: %s", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-8021x-peap-mschapv2-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-8021x-peap-mschapv2-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-8021x-peap-mschapv2-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-8021x-peap-mschapv2-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wired-8021x-peap-mschapv2-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
-	ASSERT (s_8021x != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME);
+	g_assert (s_8021x);
 
-	/* EAP methods */
-	ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	ASSERT (strcmp (tmp, "peap") == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-
-	/* Identity */
-	tmp = nm_setting_802_1x_get_identity (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-	ASSERT (strcmp (tmp, expected_identity) == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-
-	/* Anonymous Identity */
-	tmp = nm_setting_802_1x_get_anonymous_identity (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
-	ASSERT (strcmp (tmp, expected_anon_identity) == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
-
-	/* Password */
-	tmp = nm_setting_802_1x_get_password (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PASSWORD);
-	ASSERT (strcmp (tmp, expected_password) == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PASSWORD);
-
-	/* PEAP version */
-	tmp = nm_setting_802_1x_get_phase1_peapver (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE1_PEAPVER);
-	ASSERT (strcmp (tmp, "1") == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE1_PEAPVER);
-
-	/* PEAP Label */
-	tmp = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE1_PEAPLABEL);
-	ASSERT (strcmp (tmp, "1") == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE1_PEAPLABEL);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "peap");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "David Smith");
+	g_assert_cmpstr (nm_setting_802_1x_get_anonymous_identity (s_8021x), ==, "somebody");
+	g_assert_cmpstr (nm_setting_802_1x_get_password (s_8021x), ==, "foobar baz");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase1_peapver (s_8021x), ==, "1");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase1_peaplabel (s_8021x), ==, "1");
 
 	/* CA Cert */
 	tmp_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
@@ -2140,61 +1428,35 @@ test_read_wired_8021x_peap_mschapv2 (void)
 	                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                         NULL,
 	                                         &error);
-	ASSERT (success == TRUE,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not load CA certificate",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_CA_CERT);
+	g_assert_no_error (error);
+	g_assert (success == TRUE);
+
 	expected_ca_cert_path = nm_setting_802_1x_get_ca_cert_path (tmp_8021x);
-	ASSERT (expected_ca_cert_path != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: failed to get CA certificate",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_CA_CERT);
+	g_assert (expected_ca_cert_path);
 
 	read_ca_cert_path = nm_setting_802_1x_get_ca_cert_path (s_8021x);
-	ASSERT (read_ca_cert_path != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_CA_CERT);
-
-	ASSERT (strcmp (read_ca_cert_path, expected_ca_cert_path) == 0,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s certificate path",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_CA_CERT);
+	g_assert (read_ca_cert_path);
+
+	g_assert_cmpstr (read_ca_cert_path, ==, expected_ca_cert_path);
 
 	g_object_unref (tmp_8021x);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_8021X_TLS_AGENT TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-tls-agent"
-#define TEST_IFCFG_WIRED_8021X_TLS_ALWAYS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-tls-always"
-
 static void
-test_read_wired_8021x_tls_secret_flags (const char *ifcfg, NMSettingSecretFlags expected_flags)
+test_read_wired_8021x_tls_secret_flags (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMSettingWired *s_wired;
 	NMSetting8021x *s_8021x;
-	GError *error = NULL;
-	const char *expected_identity = "David Smith";
-	gboolean success = FALSE;
 	char *dirname, *tmp;
+	const char *ifcfg;
+	gpointer expected_flags_p;
 
-	connection = connection_from_file_test (ifcfg,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
+	nmtst_test_data_unpack (test_data, &ifcfg, &expected_flags_p);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (ifcfg, NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== WIRED SETTING ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -2205,8 +1467,8 @@ test_read_wired_8021x_tls_secret_flags (const char *ifcfg, NMSettingSecretFlags
 	g_assert (s_8021x);
 	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
 	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "tls");
-	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, expected_identity);
-	g_assert_cmpint (nm_setting_802_1x_get_private_key_password_flags (s_8021x), ==, expected_flags);
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "David Smith");
+	g_assert_cmpint (nm_setting_802_1x_get_private_key_password_flags (s_8021x), ==, GPOINTER_TO_INT (expected_flags_p));
 
 	dirname = g_path_get_dirname (ifcfg);
 	tmp = g_build_path ("/", dirname, "test_ca_cert.pem", NULL);
@@ -2229,17 +1491,12 @@ test_read_write_802_1X_subj_matches (void)
 	NMConnection *connection, *reread;
 	NMSetting8021x *s_8021x;
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*missing IEEE_8021X_CA_CERT*peap*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1X-subj-matches",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1X-subj-matches",
+	                                    NULL, TYPE_ETHERNET, NULL);
 	g_test_assert_expected_messages ();
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
@@ -2257,33 +1514,18 @@ test_read_write_802_1X_subj_matches (void)
 	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 0), ==, "x.yourdomain.tld");
 	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 1), ==, "y.yourdomain.tld");
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
-	/* re-read the connection for comparison */
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*missing IEEE_8021X_CA_CERT*peap*");
-	reread = connection_from_file_test (written, NULL, TYPE_ETHERNET, NULL,
-	                                    &error);
+	reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL);
 	g_test_assert_expected_messages ();
 	unlink (written);
 	g_free (written);
 
-	g_assert_no_error (error);
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	/* Check 802.1X stuff of the re-read connection. */
 	s_8021x = nm_connection_get_setting_802_1x (reread);
@@ -2310,20 +1552,13 @@ test_read_802_1x_ttls_eapgtc (void)
 {
 	NMConnection *connection;
 	NMSetting8021x *s_8021x;
-	GError *error = NULL;
-	gboolean success;
 
 	/* Test that EAP-* inner methods are correctly read into the
 	 * NMSetting8021x::autheap property.
 	 */
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
@@ -2340,76 +1575,32 @@ test_read_802_1x_ttls_eapgtc (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_ALIASES_GOOD TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem0"
-
 static void
 test_read_wired_aliases_good (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System aliasem0";
 	int expected_num_addresses = 4;
 	const char *expected_address[4] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99" };
 	const char *expected_label[4] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99" };
-	const char *expected_gateway = "192.168.1.1";
 	int i, j;
 
-	connection = connection_from_file_test (TEST_IFCFG_ALIASES_GOOD,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "aliases-good-read", "failed to read %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "aliases-good-verify", "failed to verify %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem0",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "aliases-good-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "aliases-good-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "aliases-good-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System aliasem0");
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "aliases-good-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == expected_num_addresses,
-	        "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_ALIASES_GOOD,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, expected_num_addresses);
 
 	/* Addresses */
 	for (i = 0; i < expected_num_addresses; i++) {
@@ -2441,14 +1632,10 @@ test_read_wired_aliases_good (void)
 	}
 
 	/* Gateway */
-	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, expected_gateway);
+	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
 
-	for (i = 0; i < expected_num_addresses; i++) {
-		ASSERT (expected_address[i] == NULL,
-		        "aliases-good-verify-ip4", "failed to verify %s: did not find IP4 address %s",
-		        TEST_IFCFG_ALIASES_GOOD,
-		        expected_address[i]);
-	}
+	for (i = 0; i < expected_num_addresses; i++)
+		g_assert (!expected_address[i]);
 
 	g_object_unref (connection);
 }
@@ -2459,64 +1646,26 @@ test_read_wired_aliases_bad (const char *base, const char *expected_id)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
 	NMIPAddress *ip4_addr;
 
-	connection = connection_from_file_test (base,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_test_assert_expected_messages ();
-	ASSERT (connection != NULL,
-	        "aliases-bad-read", "failed to read %s: %s", base, error->message);
+	g_assert (expected_id);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "aliases-bad-verify", "failed to verify %s: %s", base, error->message);
+	connection = _connection_from_file (base, NULL, TYPE_ETHERNET, NULL);
+	g_test_assert_expected_messages ();
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "aliases-bad-verify-connection", "failed to verify %s: missing %s setting",
-	        base,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "aliases-bad-verify-connection", "failed to verify %s: missing %s / %s key",
-	        base,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "aliases-bad-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        base,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "aliases-bad-verify-ip4", "failed to verify %s: missing %s setting",
-	        base,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        base,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 1,
-	        "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        base,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
 
 	/* Addresses */
 	ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
@@ -2531,28 +1680,22 @@ test_read_wired_aliases_bad (const char *base, const char *expected_id)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_ALIASES_BAD_1  TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem1"
-
 static void
 test_read_wired_aliases_bad_1 (void)
 {
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*aliasem1:1*has no DEVICE*");
-	test_read_wired_aliases_bad (TEST_IFCFG_ALIASES_BAD_1, "System aliasem1");
+	test_read_wired_aliases_bad (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem1", "System aliasem1");
 }
 
-#define TEST_IFCFG_ALIASES_BAD_2  TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem2"
-
 static void
 test_read_wired_aliases_bad_2 (void)
 {
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*aliasem2:1*has invalid DEVICE*");
-	test_read_wired_aliases_bad (TEST_IFCFG_ALIASES_BAD_2, "System aliasem2");
+	test_read_wired_aliases_bad (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem2", "System aliasem2");
 }
 
-#define TEST_IFCFG_DNS_OPTIONS TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dns-options"
-
 static void
 test_read_dns_options (void)
 {
@@ -2560,17 +1703,11 @@ test_read_dns_options (void)
 	NMSettingIPConfig *s_ip4, *s_ip6;
 	char *unmanaged = NULL;
 	const char *option;
-	GError *error = NULL;
 	const char *options[] = { "ndots:3", "single-request-reopen", "inet6" };
 	guint32 i, options_len = sizeof (options) / sizeof (options[0]);
 
-	connection = connection_from_file_test (TEST_IFCFG_DNS_OPTIONS,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dns-options",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
 	g_assert_cmpstr (unmanaged, ==, NULL);
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -2610,7 +1747,6 @@ test_write_dns_options (void)
 	char *uuid;
 	NMIPAddress *addr;
 	NMIPAddress *addr6;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 
@@ -2671,25 +1807,13 @@ test_write_dns_options (void)
 	nm_setting_ip_config_add_dns_option (s_ip4, "debug");
 	nm_setting_ip_config_add_dns_option (s_ip6, "timeout:3");
 
-	g_assert (nm_connection_verify (connection, &error));
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert (success);
-	g_assert (testfile);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
 	/* RES_OPTIONS is copied to both IPv4 and IPv6 settings */
@@ -2701,17 +1825,13 @@ test_write_dns_options (void)
 	nm_setting_ip_config_add_dns_option (s_ip6, "debug");
 	nm_setting_ip_config_add_dns_option (s_ip6, "timeout:3");
 
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_WIFI_OPEN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open"
-
 static void
 test_read_wifi_open (void)
 {
@@ -2720,137 +1840,48 @@ test_read_wifi_open (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4, *s_ip6;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	const char *expected_id = "System blahblah (test-wifi-open)";
-	guint64 expected_timestamp = 0;
 	const char *expected_ssid = "blahblah";
-	const char *expected_mode = "infrastructure";
-	const guint32 expected_channel = 1;
-
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_OPEN,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-open-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN, error->message);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-open-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-open",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-open-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-open-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-open-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-open)");
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
 	 * depending on where the tests are run.
 	 */
 
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "wifi-open-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "wifi-open-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
-
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 	g_assert_cmpint (nm_setting_connection_get_autoconnect_priority (s_con), ==, -1);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* MAC address */
 	mac = nm_setting_wireless_get_mac_address (s_wireless);
-	ASSERT (mac != NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
-
-	ASSERT (nm_setting_wireless_get_mtu (s_wireless) == 0,
-	        "wifi-open-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MTU);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
+
+	g_assert_cmpint (nm_setting_wireless_get_mtu (s_wireless), ==, 0);
 
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	
-	ASSERT (nm_setting_wireless_get_bssid (s_wireless) == NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-
-	ASSERT (nm_setting_wireless_get_channel (s_wireless) == expected_channel,
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_CHANNEL);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
+
+	g_assert (!nm_setting_wireless_get_bssid (s_wireless));
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "infrastructure");
+	g_assert_cmpint (nm_setting_wireless_get_channel (s_wireless), ==, 1);
 
 	/* ===== WiFi SECURITY SETTING ===== */
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -2859,20 +1890,9 @@ test_read_wifi_open (void)
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-open-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
+	g_assert (s_ip4);
 	g_assert_cmpint (nm_setting_ip_config_get_route_metric (s_ip4), ==, 104);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-open-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	g_assert( s_ip6);
@@ -2881,242 +1901,95 @@ test_read_wifi_open (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_OPEN_AUTO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-auto"
-
 static void
 test_read_wifi_open_auto (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System blahblah (test-wifi-open-auto)";
-	const char *expected_mode = "infrastructure";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_OPEN_AUTO,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-open-auto-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_AUTO, error->message);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-open-auto-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_AUTO, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-open-auto",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-open-auto-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-open-auto-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-open-auto-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-open-auto)");
 
 	/* ===== WIRELESS SETTING ===== */
-
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-open-auto-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
-
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-open-auto-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-open-auto-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_AUTO,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
+	g_assert (s_wireless);
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "infrastructure");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_OPEN_SSID_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-hex"
-
 static void
 test_read_wifi_open_ssid_hex (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
-	const char *expected_id = "System blahblah (test-wifi-open-ssid-hex)";
 	const char *expected_ssid = "blahblah";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-open-ssid-hex-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-open-ssid-hex-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-open-ssid-hex",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-open-ssid-hex-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-open-ssid-hex)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_SSID_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
 
 	g_object_unref (connection);
 }
 
 static void
-test_read_wifi_open_ssid_bad (const char *file, const char *test)
+test_read_wifi_open_ssid_bad (gconstpointer data)
 {
-	NMConnection *connection;
-	GError *error = NULL;
-
-	connection = connection_from_file_test (file,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection == NULL, test, "unexpected success reading %s", file);
-	g_clear_error (&error);
-
+	_connection_from_file_fail ((const char *) data, NULL, TYPE_WIRELESS, NULL);
 }
 
-#define TEST_IFCFG_WIFI_OPEN_SSID_QUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-quoted"
-
 static void
 test_read_wifi_open_ssid_quoted (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
-	const char *expected_id = "System foo\"bar\\ (test-wifi-open-ssid-quoted)";
 	const char *expected_ssid = "foo\"bar\\";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-open-ssid-quoted-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-open-ssid-quoted-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-open-ssid-quoted",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System foo\"bar\\ (test-wifi-open-ssid-quoted)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep"
-
 static void
 test_read_wifi_wep (void)
 {
@@ -3125,243 +1998,75 @@ test_read_wifi_wep (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	const char *expected_id = "System blahblah (test-wifi-wep)";
-	guint64 expected_timestamp = 0;
 	const char *expected_ssid = "blahblah";
-	const char *expected_mode = "infrastructure";
-	const guint32 expected_channel = 1;
-	const char *expected_wep_key0 = "0123456789abcdef0123456789";
 	NMWepKeyType key_type;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wep-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wep)");
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
 	 * depending on where the tests are run.
 	 */
 
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "wifi-wep-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "wifi-wep-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* MAC address */
 	mac = nm_setting_wireless_get_mac_address (s_wireless);
-	ASSERT (mac != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 
 	/* MTU */
-	ASSERT (nm_setting_wireless_get_mtu (s_wireless) == 0,
-	        "wifi-wep-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MTU);
+	g_assert_cmpint (nm_setting_wireless_get_mtu (s_wireless), ==, 0);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-
-	/* BSSID */
-	ASSERT (nm_setting_wireless_get_bssid (s_wireless) == NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-
-	/* Mode */
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-
-	/* Channel */
-	ASSERT (nm_setting_wireless_get_channel (s_wireless) == expected_channel,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_CHANNEL);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
+
+	g_assert (!nm_setting_wireless_get_bssid (s_wireless));
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "infrastructure");
+	g_assert_cmpint (nm_setting_wireless_get_channel (s_wireless), ==, 1);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
+	g_assert_cmpstr (nm_setting_wireless_security_get_auth_alg (s_wsec), ==, "shared");
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
 
-	/* WEP key type */
 	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
-	ASSERT (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected WEP key type %d",
-	        TEST_IFCFG_WIFI_WEP,
-	        key_type);
-
-	/* WEP key index 0 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-	ASSERT (strcmp (tmp, expected_wep_key0) == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-
-	/* WEP key index 1 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 1);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
-
-	/* WEP key index 2 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 2);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
-
-	/* WEP key index 3 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 3);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
-
-	/* WEP Authentication mode */
-	tmp = nm_setting_wireless_security_get_auth_alg (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-	ASSERT (strcmp (tmp, "shared") == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+	g_assert (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY);
+
+	g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "0123456789abcdef0123456789");
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 3));
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wep-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wep-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP_ADHOC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-adhoc"
-
 static void
 test_read_wifi_wep_adhoc (void)
 {
@@ -3370,225 +2075,68 @@ test_read_wifi_wep_adhoc (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
-	const char *expected_id = "System blahblah (test-wifi-wep-adhoc)";
 	const char *expected_ssid = "blahblah";
-	const char *expected_mode = "adhoc";
-	const char *expected_wep_key0 = "0123456789abcdef0123456789";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_ADHOC,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-adhoc-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_ADHOC, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-adhoc-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_ADHOC, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-adhoc",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-adhoc-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-adhoc-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wep-adhoc-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wep-adhoc)");
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
 	 * depending on where the tests are run.
 	 */
 
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == FALSE,
-	        "wifi-wep-adhoc-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (!nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-
-	/* BSSID */
-	ASSERT (nm_setting_wireless_get_bssid (s_wireless) == NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-
-	/* Mode */
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-
-	/* Channel */
-	ASSERT (nm_setting_wireless_get_channel (s_wireless) == 11,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_CHANNEL);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
+
+	g_assert (!nm_setting_wireless_get_bssid (s_wireless));
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "adhoc");
+	g_assert_cmpint (nm_setting_wireless_get_channel (s_wireless), ==, 11);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
+	g_assert (!nm_setting_wireless_security_get_auth_alg (s_wsec));
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
 
-	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
-
-	/* WEP key index 0 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-	ASSERT (strcmp (tmp, expected_wep_key0) == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-
-	/* WEP key index 1 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 1);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
-
-	/* WEP key index 2 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 2);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
-
-	/* WEP key index 3 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 3);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
-
-	/* WEP Authentication mode */
-	tmp = nm_setting_wireless_security_get_auth_alg (s_wsec);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+	g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "0123456789abcdef0123456789");
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 3));
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* Ignore auto DNS */
-	ASSERT (nm_setting_ip_config_get_ignore_auto_dns (s_ip4) == TRUE,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS);
+	g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 0), "4.2.2.1") == 0,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 1), "4.2.2.2") == 0,
-	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "4.2.2.1");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "4.2.2.2");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP_PASSPHRASE TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-passphrase"
-
 static void
 test_read_wifi_wep_passphrase (void)
 {
@@ -3596,110 +2144,34 @@ test_read_wifi_wep_passphrase (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_wep_key0 = "foobar222blahblah";
-	NMWepKeyType key_type;
-
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-passphrase-read", "failed to read %s: %s",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE, error->message);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-passphrase-verify", "failed to verify %s: %s",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-passphrase",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-passphrase-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_PASSPHRASE);
+	g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "foobar222blahblah");
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 3));
 
-	/* WEP key type */
-	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
-	ASSERT (key_type == NM_WEP_KEY_TYPE_PASSPHRASE,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected WEP key type %d",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        key_type);
-
-	/* WEP key index 0 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-	ASSERT (strcmp (tmp, expected_wep_key0) == 0,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-
-	/* WEP key index 1 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 1);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
-
-	/* WEP key index 2 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 2);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
-
-	/* WEP key index 3 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 3);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
-
-	g_object_unref (connection);
-}
-
-#define TEST_IFCFG_WIFI_WEP_40_ASCII TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-40-ascii"
+	g_object_unref (connection);
+}
 
 static void
 test_read_wifi_wep_40_ascii (void)
@@ -3708,108 +2180,38 @@ test_read_wifi_wep_40_ascii (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_wep_key0 = "Lorem";
 	NMWepKeyType key_type;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_40_ASCII,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-40-ascii-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_40_ASCII, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-40-ascii-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_40_ASCII, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-40-ascii",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-40-ascii-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
 
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
+	g_assert (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY);
 
-	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+	g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "Lorem");
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 3));
 
-	/* WEP key type */
-	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
-	ASSERT (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected WEP key type %d",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        key_type);
-
-	/* WEP key index 0 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-	ASSERT (strcmp (tmp, expected_wep_key0) == 0,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-
-	/* WEP key index 1 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 1);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
-
-	/* WEP key index 2 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 2);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
-
-	/* WEP key index 3 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 3);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
-
-	g_object_unref (connection);
-}
-
-#define TEST_IFCFG_WIFI_WEP_104_ASCII TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-104-ascii"
+	g_object_unref (connection);
+}
 
 static void
 test_read_wifi_wep_104_ascii (void)
@@ -3818,108 +2220,38 @@ test_read_wifi_wep_104_ascii (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_wep_key0 = "LoremIpsumSit";
 	NMWepKeyType key_type;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_104_ASCII,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-104-ascii-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_104_ASCII, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-104-ascii-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_104_ASCII, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-104-ascii",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-104-ascii-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
 
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
+	g_assert (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY);
 
-	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+	g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "LoremIpsumSit");
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2));
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 3));
 
-	/* WEP key type */
-	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
-	ASSERT (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected WEP key type %d",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        key_type);
-
-	/* WEP key index 0 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-	ASSERT (strcmp (tmp, expected_wep_key0) == 0,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
-
-	/* WEP key index 1 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 1);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
-
-	/* WEP key index 2 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 2);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
-
-	/* WEP key index 3 */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 3);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
-
-	g_object_unref (connection);
-}
-
-#define TEST_IFCFG_WIFI_LEAP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-leap"
+	g_object_unref (connection);
+}
 
 static void
 test_read_wifi_leap (void)
@@ -3928,133 +2260,45 @@ test_read_wifi_leap (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System blahblah (test-wifi-leap)";
-	const char *expected_identity = "Bill Smith";
-	const char *expected_password = "foobarblah";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_LEAP,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-leap-read", "failed to read %s: %s", TEST_IFCFG_WIFI_LEAP, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-leap-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_LEAP, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-leap",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-leap-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-leap-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-leap-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-leap)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "ieee8021x");
+	g_assert_cmpstr (nm_setting_wireless_security_get_auth_alg (s_wsec), ==, "leap");
+	g_assert_cmpstr (nm_setting_wireless_security_get_leap_username (s_wsec), ==, "Bill Smith");
+	g_assert_cmpstr (nm_setting_wireless_security_get_leap_password (s_wsec), ==, "foobarblah");
 
-	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "ieee8021x") == 0,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* WEP Authentication mode */
-	tmp = nm_setting_wireless_security_get_auth_alg (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-	ASSERT (strcmp (tmp, "leap") == 0,
-	        "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-
-	/* LEAP Username */
-	tmp = nm_setting_wireless_security_get_leap_username (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
-	ASSERT (strcmp (tmp, expected_identity) == 0,
-	        "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
-
-	/* LEAP Password */
-	tmp = nm_setting_wireless_security_get_leap_password (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
-	ASSERT (strcmp (tmp, expected_password) == 0,
-	        "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
-
-	g_object_unref (connection);
-}
-
-#define TEST_IFCFG_WIFI_LEAP_AGENT TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-leap-agent"
-#define TEST_IFCFG_WIFI_LEAP_ALWAYS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-leap-always-ask"
-
-static void
-test_read_wifi_leap_secret_flags (const char *file, NMSettingSecretFlags expected_flags)
+	g_object_unref (connection);
+}
+
+static void
+test_read_wifi_leap_secret_flags (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *expected_identity = "Bill Smith";
-	gboolean success;
+	const char *file;
+	gpointer expected_flags_p;
 
-	connection = connection_from_file_test (file,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
+	nmtst_test_data_unpack (test_data, &file, &expected_flags_p);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (file, NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== WIRELESS SETTING ===== */
 	s_wifi = nm_connection_get_setting_wireless (connection);
@@ -4066,16 +2310,14 @@ test_read_wifi_leap_secret_flags (const char *file, NMSettingSecretFlags expecte
 
 	g_assert (g_strcmp0 (nm_setting_wireless_security_get_key_mgmt (s_wsec), "ieee8021x") == 0);
 	g_assert (g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap") == 0);
-	g_assert (g_strcmp0 (nm_setting_wireless_security_get_leap_username (s_wsec), expected_identity) == 0);
+	g_assert (g_strcmp0 (nm_setting_wireless_security_get_leap_username (s_wsec), "Bill Smith") == 0);
 	/* password blank as it's not system-owned */
-	g_assert (nm_setting_wireless_security_get_leap_password_flags (s_wsec) == expected_flags);
+	g_assert (nm_setting_wireless_security_get_leap_password_flags (s_wsec) == GPOINTER_TO_INT (expected_flags_p));
 	g_assert (nm_setting_wireless_security_get_leap_password (s_wsec) == NULL);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk"
-
 static void
 test_read_wifi_wpa_psk (void)
 {
@@ -4084,18 +2326,10 @@ test_read_wifi_wpa_psk (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	const char *expected_id = "System blahblah (test-wifi-wpa-psk)";
-	guint64 expected_timestamp = 0;
 	const char *expected_ssid = "blahblah";
-	const char *expected_mode = "infrastructure";
-	const guint32 expected_channel = 1;
-	const char *expected_key_mgmt = "wpa-psk";
-	const char *expected_psk = "I wonder what the king is doing tonight?";
 	guint32 n, i;
 	gboolean found_pair_tkip = FALSE;
 	gboolean found_pair_ccmp = FALSE;
@@ -4106,204 +2340,70 @@ test_read_wifi_wpa_psk (void)
 	gboolean found_proto_wpa = FALSE;
 	gboolean found_proto_rsn = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-psk-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wpa-psk)");
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
 	 * depending on where the tests are run.
 	 */
 
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
-	/* MAC address */
 	mac = nm_setting_wireless_get_mac_address (s_wireless);
-	ASSERT (mac != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MAC_ADDRESS);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 
-	/* MTU */
-	ASSERT (nm_setting_wireless_get_mtu (s_wireless) == 0,
-	        "wifi-wpa-psk-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MTU);
+	g_assert_cmpint (nm_setting_wireless_get_mtu (s_wireless), ==, 0);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-
-	/* BSSID */
-	ASSERT (nm_setting_wireless_get_bssid (s_wireless) == NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-
-	/* Mode */
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-
-	/* Channel */
-	ASSERT (nm_setting_wireless_get_channel (s_wireless) == expected_channel,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_CHANNEL);
+	g_assert (ssid);
+	g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid));
+
+	g_assert (!nm_setting_wireless_get_bssid (s_wireless));
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "infrastructure");
+	g_assert_cmpint (nm_setting_wireless_get_channel (s_wireless), ==, 1);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* Key management */
-	tmp = nm_setting_wireless_security_get_key_mgmt (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-	ASSERT (strcmp (tmp, expected_key_mgmt) == 0,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* PSK */
-	tmp = nm_setting_wireless_security_get_psk (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-	ASSERT (strcmp (tmp, expected_psk) == 0,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-
-	/* WEP Authentication mode */
-	tmp = nm_setting_wireless_security_get_auth_alg (s_wsec);
-	ASSERT (tmp == NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "I wonder what the king is doing tonight?");
+	g_assert (!nm_setting_wireless_security_get_auth_alg (s_wsec));
 
 	/* Pairwise ciphers */
 	n = nm_setting_wireless_security_get_num_pairwise (s_wsec);
-	ASSERT (n == 2,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+	g_assert_cmpint (n, ==, 2);
 	for (i = 0; i < n; i++) {
-		tmp = nm_setting_wireless_security_get_pairwise (s_wsec, i);
-		ASSERT (tmp, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing pairwise cipher",
-		        TEST_IFCFG_WIFI_WPA_PSK);
+		const char * tmp = nm_setting_wireless_security_get_pairwise (s_wsec, i);
+		g_assert (tmp);
 		if (strcmp (tmp, "tkip") == 0)
 			found_pair_tkip = TRUE;
 		else if (strcmp (tmp, "ccmp") == 0)
 			found_pair_ccmp = TRUE;
 	}
-	ASSERT (found_pair_tkip, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing pairwise TKIP cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
-	ASSERT (found_pair_ccmp, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing pairwise CCMP cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
+	g_assert (found_pair_tkip);
+	g_assert (found_pair_ccmp);
 
 	/* Group ciphers */
 	n = nm_setting_wireless_security_get_num_groups (s_wsec);
-	ASSERT (n == 4,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_GROUP);
+	g_assert_cmpint (n, ==, 4);
 	for (i = 0; i < n; i++) {
-		tmp = nm_setting_wireless_security_get_group (s_wsec, i);
-		ASSERT (tmp, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing group cipher",
-		        TEST_IFCFG_WIFI_WPA_PSK);
+		const char *tmp = nm_setting_wireless_security_get_group (s_wsec, i);
+		g_assert (tmp);
 		if (strcmp (tmp, "tkip") == 0)
 			found_group_tkip = TRUE;
 		else if (strcmp (tmp, "ccmp") == 0)
@@ -4313,57 +2413,34 @@ test_read_wifi_wpa_psk (void)
 		else if (strcmp (tmp, "wep104") == 0)
 			found_group_wep104 = TRUE;
 	}
-	ASSERT (found_group_tkip, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing group TKIP cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
-	ASSERT (found_group_ccmp, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing group CCMP cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
-	ASSERT (found_group_wep40, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing group WEP-40 cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
-	ASSERT (found_group_wep104, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing group WEP-104 cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK);
+	g_assert (found_group_tkip);
+	g_assert (found_group_ccmp);
+	g_assert (found_group_wep40);
+	g_assert (found_group_wep104);
 
 	/* Protocols */
 	n = nm_setting_wireless_security_get_num_protos (s_wsec);
-	ASSERT (n == 2,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PROTO);
+	g_assert_cmpint (n, ==, 2);
 	for (i = 0; i < n; i++) {
-		tmp = nm_setting_wireless_security_get_proto (s_wsec, i);
-		ASSERT (tmp, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing protocol",
-		        TEST_IFCFG_WIFI_WPA_PSK);
+		const char *tmp = nm_setting_wireless_security_get_proto (s_wsec, i);
+		g_assert (tmp);
 		if (strcmp (tmp, "wpa") == 0)
 			found_proto_wpa = TRUE;
 		else if (strcmp (tmp, "rsn") == 0)
 			found_proto_rsn = TRUE;
 	}
-	ASSERT (found_proto_wpa, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing protoocl WPA",
-	        TEST_IFCFG_WIFI_WPA_PSK);
-	ASSERT (found_proto_rsn, "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing protocol RSN",
-	        TEST_IFCFG_WIFI_WPA_PSK);
+	g_assert (found_proto_wpa);
+	g_assert (found_proto_rsn);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wpa-psk-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wpa-psk-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK_2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-2"
-
 static void
 test_read_wifi_wpa_psk_2 (void)
 {
@@ -4371,77 +2448,30 @@ test_read_wifi_wpa_psk_2 (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System ipsum (test-wifi-wpa-psk-2)";
-	const char *expected_psk = "They're really saying I love you. >>`<< \\";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK_2,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-2-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK_2, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-psk-2-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK_2, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-2",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-2-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-2-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wpa-psk-2-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System ipsum (test-wifi-wpa-psk-2)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* PSK */
-	tmp = nm_setting_wireless_security_get_psk (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-	ASSERT (strcmp (tmp, expected_psk) == 0,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "They're really saying I love you. >>`<< \\");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted"
-
 static void
 test_read_wifi_wpa_psk_unquoted (void)
 {
@@ -4449,100 +2479,41 @@ test_read_wifi_wpa_psk_unquoted (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System blahblah (test-wifi-wpa-psk-unquoted)";
-	const char *expected_psk = "54336845e2f3f321c4c7";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-unquoted-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-psk-unquoted-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-unquoted-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-unquoted-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wpa-psk-unquoted-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wpa-psk-unquoted)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* PSK */
-	tmp = nm_setting_wireless_security_get_psk (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-	ASSERT (strcmp (tmp, expected_psk) == 0,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "54336845e2f3f321c4c7");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2"
-
 static void
 test_read_wifi_wpa_psk_unquoted2 (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
-
 	/* Ensure a quoted 64-character WPA passphrase will fail since passphrases
 	 * must be between 8 and 63 ASCII characters inclusive per the WPA spec.
 	 */
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED2,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection == NULL,
-	        "wifi-wpa-psk-unquoted-read", "unexpected success reading %s", TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED2);
-	g_clear_error (&error);
-
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2",
+	                            NULL, TYPE_WIRELESS, NULL);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK_ADHOC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc"
-
 static void
 test_read_wifi_wpa_psk_adhoc (void)
 {
@@ -4551,163 +2522,48 @@ test_read_wifi_wpa_psk_adhoc (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System blahblah (test-wifi-wpa-psk-adhoc)";
-	const char *expected_mode = "adhoc";
-	const char *expected_key_mgmt = "wpa-none";
-	const char *expected_psk = "I wonder what the king is doing tonight?";
-	const char *expected_group = "ccmp";
-	const char *expected_proto = "wpa";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-adhoc-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK_ADHOC, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-psk-adhoc-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK_ADHOC, error->message);
+
+	connection = _connection_from_file(TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc",
+	                                   NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-adhoc-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wpa-psk-adhoc-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wpa-psk-adhoc)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
-
-	/* Mode */
-	tmp = nm_setting_wireless_get_mode (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
-	ASSERT (strcmp (tmp, expected_mode) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_MODE);
+	g_assert (s_wireless);
+
+	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "adhoc");
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-none");
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "I wonder what the king is doing tonight?");
 
-	/* Key management */
-	tmp = nm_setting_wireless_security_get_key_mgmt (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-	ASSERT (strcmp (tmp, expected_key_mgmt) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* PSK */
-	tmp = nm_setting_wireless_security_get_psk (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-	ASSERT (strcmp (tmp, expected_psk) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-
-	/* Pairwise cipher: unused in adhoc mode */
-	ASSERT (nm_setting_wireless_security_get_num_pairwise (s_wsec) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
-
-	/* Group cipher */
-	ASSERT (nm_setting_wireless_security_get_num_groups (s_wsec) == 1,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_GROUP);
-
-	tmp = nm_setting_wireless_security_get_group (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing group cipher",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC);
-	ASSERT (strcmp (tmp, expected_group) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_GROUP);
+	/* Pairwise cipher is unused in adhoc mode */
+	g_assert_cmpint (nm_setting_wireless_security_get_num_pairwise (s_wsec), ==, 0);
 
-	/* Protocols */
-	ASSERT (nm_setting_wireless_security_get_num_protos (s_wsec) == 1,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PROTO);
-	tmp = nm_setting_wireless_security_get_proto (s_wsec, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing proto",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC);
-	ASSERT (strcmp (tmp, expected_proto) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PROTO);
+	g_assert_cmpint (nm_setting_wireless_security_get_num_groups (s_wsec), ==, 1);
+	g_assert_cmpstr (nm_setting_wireless_security_get_group (s_wsec, 0), ==, "ccmp");
+
+	g_assert_cmpint (nm_setting_wireless_security_get_num_protos (s_wsec), ==, 1);
+	g_assert_cmpstr (nm_setting_wireless_security_get_proto (s_wsec, 0), ==, "wpa");
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wpa-psk-adhoc-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wpa-psk-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_PSK_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-hex"
-
 static void
 test_read_wifi_wpa_psk_hex (void)
 {
@@ -4716,129 +2572,47 @@ test_read_wifi_wpa_psk_hex (void)
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	GError *error = NULL;
-	const char *tmp;
 	GBytes *ssid;
-	const char *expected_id = "System blahblah (test-wifi-wpa-psk-hex)";
 	const char *expected_ssid = "blahblah";
-	const char *expected_key_mgmt = "wpa-psk";
-	const char *expected_psk = "1da190379817bc360dda52e85c388c439a21ea5c7bf819c64e9da051807deae6";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-hex-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK_HEX, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-psk-hex-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK_HEX, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-hex",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-hex-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-hex-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wpa-psk-hex-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah (test-wifi-wpa-psk-hex)");
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
-	/* SSID */
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (g_bytes_get_size (ssid) == strlen (expected_ssid),
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
-	ASSERT (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
+	g_assert (ssid);
+	g_assert_cmpint (g_bytes_get_size (ssid), ==, strlen (expected_ssid));
+	g_assert (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
-	/* Key management */
-	tmp = nm_setting_wireless_security_get_key_mgmt (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-	ASSERT (strcmp (tmp, expected_key_mgmt) == 0,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-
-	/* PSK */
-	tmp = nm_setting_wireless_security_get_psk (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
-	ASSERT (strcmp (tmp, expected_psk) == 0,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_PSK);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "1da190379817bc360dda52e85c388c439a21ea5c7bf819c64e9da051807deae6");
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wpa-psk-hex-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wpa-psk-hex-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_EAP_TLS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-eap-tls"
-#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
-#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem"
-#define TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem"
+#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT TEST_IFCFG_DIR "/network-scripts/test_ca_cert.pem"
+#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT TEST_IFCFG_DIR "/network-scripts/test1_key_and_cert.pem"
+#define TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY TEST_IFCFG_DIR "/network-scripts/test1_key_and_cert.pem"
 
 static void
 test_read_wifi_wpa_eap_tls (void)
@@ -4848,86 +2622,29 @@ test_read_wifi_wpa_eap_tls (void)
 	NMSettingIPConfig *s_ip4;
 	NMSetting8021x *s_8021x;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp, *password;
-	const char *expected_identity = "Bill Smith";
 	const char *expected_privkey_password = "test1";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-eap-tls-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TLS, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-eap-tls-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TLS, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wifi-wpa-eap-tls-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WPA_EAP_TLS);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-eap-tls",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-eap-tls-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wpa-eap-tls-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wpa-eap-tls-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
-	ASSERT (s_8021x != NULL,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME);
-
-	/* EAP methods */
-	ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	ASSERT (strcmp (tmp, "tls") == 0,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-
-	/* Identity */
-	tmp = nm_setting_802_1x_get_identity (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-	ASSERT (strcmp (tmp, expected_identity) == 0,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
+	g_assert (s_8021x);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "tls");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "Bill Smith");
 
 	/* CA Cert */
 	verify_cert_or_key (s_8021x,
@@ -4942,18 +2659,7 @@ test_read_wifi_wpa_eap_tls (void)
 	                    NM_SETTING_802_1X_CLIENT_CERT);
 
 	/* Private Key Password */
-	password = nm_setting_802_1x_get_private_key_password (s_8021x);
-	ASSERT (password != NULL,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
-
-	ASSERT (strcmp (password, expected_privkey_password) == 0,
-	        "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+	g_assert_cmpstr (nm_setting_802_1x_get_private_key_password (s_8021x), ==, expected_privkey_password);
 
 	/* Private key */
 	verify_cert_or_key (s_8021x,
@@ -4964,8 +2670,6 @@ test_read_wifi_wpa_eap_tls (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls"
-#define TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
 /* Also use TLS defines from the previous test */
 
 static void
@@ -4976,92 +2680,38 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	NMSettingIPConfig *s_ip4;
 	NMSetting8021x *s_8021x;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp, *password;
-	const char *expected_identity = "Chuck Shumer";
 	const char *expected_privkey_password = "test1";
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wpa-eap-ttls-tls-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wpa-eap-ttls-tls-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wifi-wpa-eap-ttls-tls-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls",
+	                                    NULL, TYPE_WIRELESS, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wpa-eap-ttls-tls-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
-	ASSERT (s_8021x != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME);
-
-	/* EAP methods */
-	ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	ASSERT (strcmp (tmp, "ttls") == 0,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
+	g_assert (s_8021x);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "ttls");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "Chuck Shumer");
 
 	/* CA Cert */
 	verify_cert_or_key (s_8021x,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS_CA_CERT,
+	                    TEST_IFCFG_DIR "/network-scripts/test_ca_cert.pem",
 	                    NULL,
 	                    NM_SETTING_802_1X_CA_CERT);
 
 	/* Inner auth method */
-	tmp = nm_setting_802_1x_get_phase2_autheap (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_AUTHEAP);
-	ASSERT (strcmp (tmp, "tls") == 0,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_AUTHEAP);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_autheap (s_8021x), ==, "tls");
 
 	/* Inner CA Cert */
 	verify_cert_or_key (s_8021x,
@@ -5076,18 +2726,7 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	                    NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 
 	/* Inner Private Key Password */
-	password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
-	ASSERT (password != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
-
-	ASSERT (strcmp (password, expected_privkey_password) == 0,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_private_key_password (s_8021x), ==, expected_privkey_password);
 
 	/* Inner private key */
 	verify_cert_or_key (s_8021x,
@@ -5095,24 +2734,9 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	                    expected_privkey_password,
 	                    NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
 
-	/* Identity */
-	tmp = nm_setting_802_1x_get_identity (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-	ASSERT (strcmp (tmp, expected_identity) == 0,
-	        "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_DYNAMIC_WEP_LEAP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-dynamic-wep-leap"
-
 static void
 test_read_wifi_dynamic_wep_leap (void)
 {
@@ -5120,20 +2744,9 @@ test_read_wifi_dynamic_wep_leap (void)
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSetting8021x *s_8021x;
-	gboolean success;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_DYNAMIC_WEP_LEAP,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-dynamic-wep-leap",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== WIRELESS SETTING ===== */
 
@@ -5171,9 +2784,6 @@ test_read_wifi_dynamic_wep_leap (void)
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap"
-#define TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
-
 static void
 test_read_wifi_wep_eap_ttls_chap (void)
 {
@@ -5183,139 +2793,44 @@ test_read_wifi_wep_eap_ttls_chap (void)
 	NMSettingIPConfig *s_ip4;
 	NMSetting8021x *s_8021x;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_password = "foobar baz";
-	const char *expected_identity = "David Smith";
-	const char *expected_key_mgmt = "ieee8021x";
-
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-eap-ttls-chap-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-eap-ttls-chap-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, error->message);
 
-	ASSERT (unmanaged == NULL,
-	        "wifi-wep-eap-ttls-chap-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap",
+	                                    NULL, TYPE_WIRELESS, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "wifi-wep-eap-ttls-chap-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* ===== 802.1x SETTING ===== */
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME);
-
-	/* Key management */
-	tmp = nm_setting_wireless_security_get_key_mgmt (s_wsec);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-	ASSERT (strcmp (tmp, expected_key_mgmt) == 0,
-	        "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "ieee8021x");
 
 	/* ===== 802.1x SETTING ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
-	ASSERT (s_8021x != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME);
+	g_assert (s_8021x);
 
 	/* EAP methods */
-	ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
-	ASSERT (strcmp (tmp, "ttls") == 0,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_EAP);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "ttls");
 
 	/* CA Cert */
 	verify_cert_or_key (s_8021x,
-	                    TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP_CA_CERT,
+	                    TEST_IFCFG_DIR "/network-scripts/test_ca_cert.pem",
 	                    NULL,
 	                    NM_SETTING_802_1X_CA_CERT);
 
-	/* Inner auth method */
-	tmp = nm_setting_802_1x_get_phase2_auth (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s eap method",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_AUTH);
-	ASSERT (strcmp (tmp, "chap") == 0,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PHASE2_AUTH);
-
-	/* Password */
-	tmp = nm_setting_802_1x_get_identity (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-	ASSERT (strcmp (tmp, expected_identity) == 0,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_IDENTITY);
-
-	/* Password */
-	tmp = nm_setting_802_1x_get_password (s_8021x);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PASSWORD);
-	ASSERT (strcmp (tmp, expected_password) == 0,
-	        "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	        NM_SETTING_802_1X_SETTING_NAME,
-	        NM_SETTING_802_1X_PASSWORD);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_auth (s_8021x), ==, "chap");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "David Smith");
+	g_assert_cmpstr (nm_setting_802_1x_get_password (s_8021x), ==, "foobar baz");
 
 	g_object_unref (connection);
 }
@@ -5326,17 +2841,9 @@ test_read_wired_wake_on_lan (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	gboolean success;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-wake-on-lan",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-wake-on-lan",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -5363,17 +2870,9 @@ test_read_wifi_hidden (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
-	gboolean success;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-hidden",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-hidden",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -5393,7 +2892,6 @@ test_write_wifi_hidden (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	shvarFile *f;
 	GBytes *ssid;
@@ -5427,17 +2925,11 @@ test_write_wifi_hidden (void)
 
 	g_bytes_unref (ssid);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -5450,21 +2942,10 @@ test_write_wifi_hidden (void)
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_WIRELESS,
-	                                    NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -5474,26 +2955,23 @@ test_write_wifi_hidden (void)
 static void
 test_read_wifi_mac_random (gconstpointer user_data)
 {
-	const WifiMacRandomData *test_data = user_data;
 	NMConnection *connection;
 	NMSettingWireless *s_wifi;
-	gboolean success;
-	GError *error = NULL;
 	char *path;
+	const char *name;
+	gpointer value_p;
+	NMSettingMacRandomization value;
 
-	path = g_strdup_printf (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-mac-random-%s", test_data->name);
-	connection = connection_from_file_test (path, NULL, TYPE_WIRELESS, NULL, &error);
-	g_free (path);
-	g_assert_no_error (error);
-	g_assert (connection);
+	nmtst_test_data_unpack (user_data, &name, &value_p);
+	value = GPOINTER_TO_INT (value_p);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	path = g_strdup_printf (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-mac-random-%s", name);
+	connection = _connection_from_file (path, NULL, TYPE_WIRELESS, NULL);
+	g_free (path);
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
-	g_assert_cmpint (nm_setting_wireless_get_mac_address_randomization (s_wifi), ==, test_data->value);
+	g_assert_cmpint (nm_setting_wireless_get_mac_address_randomization (s_wifi), ==, value);
 
 	g_object_unref (connection);
 }
@@ -5501,16 +2979,22 @@ test_read_wifi_mac_random (gconstpointer user_data)
 static void
 test_write_wifi_mac_random (gconstpointer user_data)
 {
-	const WifiMacRandomData *test_data = user_data;
 	NMConnection *connection, *reread;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	shvarFile *f;
 	GBytes *ssid;
 	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	const char *name, *write_expected;
+	gpointer value_p;
+	NMSettingMacRandomization value;
+
+	nmtst_test_data_unpack (user_data, &name, &value_p, &write_expected);
+	value = GPOINTER_TO_INT (value_p);
+
+	g_assert (write_expected);
 
 	connection = nm_simple_connection_new ();
 
@@ -5519,7 +3003,7 @@ test_write_wifi_mac_random (gconstpointer user_data)
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
-	val = g_strdup_printf ("Test Write WiFi MAC %s", test_data->name);
+	val = g_strdup_printf ("Test Write WiFi MAC %s", name);
 	g_object_set (s_con,
 	              NM_SETTING_CONNECTION_ID, val,
 	              NM_SETTING_CONNECTION_UUID, uuid,
@@ -5536,21 +3020,15 @@ test_write_wifi_mac_random (gconstpointer user_data)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, test_data->value,
+	              NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, value,
 	              NULL);
 	g_bytes_unref (ssid);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-		                             TEST_SCRATCH_DIR "/network-scripts/",
-		                             &testfile,
-		                             &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -5558,24 +3036,14 @@ test_write_wifi_mac_random (gconstpointer user_data)
 
 	/* re-read the file to check that what key was written. */
 	val = svGetValue (f, "MAC_ADDRESS_RANDOMIZATION", FALSE);
-	g_assert_cmpstr (val, ==, test_data->write_expected);
+	g_assert_cmpstr (val, ==, write_expected);
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_WIRELESS, NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -5590,7 +3058,6 @@ test_write_wired_wake_on_lan (void)
 	NMSettingWired *s_wired;
 	NMSettingWiredWakeOnLan wol;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	shvarFile *f;
 
@@ -5621,17 +3088,11 @@ test_write_wired_wake_on_lan (void)
 	              NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, "00:00:00:11:22:33",
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -5645,21 +3106,10 @@ test_write_wired_wake_on_lan (void)
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_ETHERNET,
-	                                    NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -5672,17 +3122,9 @@ test_read_wifi_band_a (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
-	gboolean success;
-	GError *error = NULL;
-
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-a",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-a",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -5702,7 +3144,6 @@ test_write_wifi_band_a (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	shvarFile *f;
 	GBytes *ssid;
@@ -5736,17 +3177,11 @@ test_write_wifi_band_a (void)
 
 	g_bytes_unref (ssid);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -5759,21 +3194,10 @@ test_write_wifi_band_a (void)
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_WIRELESS,
-	                                    NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -5783,31 +3207,23 @@ test_write_wifi_band_a (void)
 static void
 test_read_wifi_band_a_channel_mismatch (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert (connection == NULL);
+	_connection_from_file_fail (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch",
+	                            NULL, TYPE_WIRELESS, &error);
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
-	g_clear_error (&error);
 }
 
 static void
 test_read_wifi_band_bg_channel_mismatch (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch",
-	                                        NULL, TYPE_WIRELESS, NULL, &error);
-	g_assert (connection == NULL);
+	_connection_from_file_fail (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch",
+	                            NULL, TYPE_WIRELESS, &error);
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
-	g_clear_error (&error);
 }
 
-#define TEST_IFCFG_WIRED_QETH_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-qeth-static"
-
 static void
 test_read_wired_qeth_static (void)
 {
@@ -5816,156 +3232,48 @@ test_read_wired_qeth_static (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-qeth-static";
-	const char *mac;
-	const char *expected_channel0 = "0.0.0600";
-	const char *expected_channel1 = "0.0.0601";
-	const char *expected_channel2 = "0.0.0602";
 	const char * const *subchannels;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_QETH_STATIC,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wired-qeth-static-read", "failed to read %s: %s", TEST_IFCFG_WIRED_QETH_STATIC, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-qeth-static-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_QETH_STATIC, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-qeth-static-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_QETH_STATIC);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-qeth-static",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-qeth-static-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-qeth-static-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-qeth-static-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-qeth-static");
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
-	/* MAC address */
-	mac = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (mac == NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s / %s key",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
+	g_assert (!nm_setting_wired_get_mac_address (s_wired));
 
 	/* Subchannels */
 	subchannels = nm_setting_wired_get_s390_subchannels (s_wired);
-	ASSERT (subchannels != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_S390_SUBCHANNELS);
-	ASSERT (subchannels[0] && subchannels[1] && subchannels[2] && !subchannels[3],
-	        "wired-qeth-static-verify-wired", "failed to verify %s: invalid %s / %s key (not 3 elements)",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_S390_SUBCHANNELS);
-
-	ASSERT (strcmp (subchannels[0], expected_channel0) == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #0",
-	        TEST_IFCFG_WIRED_QETH_STATIC);
-	ASSERT (strcmp (subchannels[1], expected_channel1) == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #1",
-	        TEST_IFCFG_WIRED_QETH_STATIC);
-	ASSERT (strcmp (subchannels[2], expected_channel2) == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #2",
-	        TEST_IFCFG_WIRED_QETH_STATIC);
-
-	/* Nettype */
-	tmp = nm_setting_wired_get_s390_nettype (s_wired);
-	ASSERT (tmp != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_S390_NETTYPE);
-	ASSERT (strcmp (tmp, "qeth") == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_S390_NETTYPE);
-
-	/* port name */
-	tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "portname");
-	ASSERT (tmp != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'portname'",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
-	ASSERT (strcmp (tmp, "OSAPORT") == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'portname' value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
-
-	/* port number */
-	tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "portno");
-	ASSERT (tmp != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'portno'",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
-	ASSERT (strcmp (tmp, "0") == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'portno' value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
-
-	/* layer */
-	tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "layer2");
-	ASSERT (tmp != NULL,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'layer2'",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
-	ASSERT (strcmp (tmp, "1") == 0,
-	        "wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'layer2' value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (subchannels);
+	g_assert (subchannels[0] && subchannels[1] && subchannels[2] && !subchannels[3]);
+
+	g_assert_cmpstr (subchannels[0], ==, "0.0.0600");
+	g_assert_cmpstr (subchannels[1], ==, "0.0.0601");
+	g_assert_cmpstr (subchannels[2], ==, "0.0.0602");
+
+	g_assert_cmpstr (nm_setting_wired_get_s390_nettype (s_wired), ==, "qeth");
+	g_assert_cmpstr (nm_setting_wired_get_s390_option_by_key (s_wired, "portname"), ==, "OSAPORT");
+	g_assert_cmpstr (nm_setting_wired_get_s390_option_by_key (s_wired, "portno"), ==, "0");
+	g_assert_cmpstr (nm_setting_wired_get_s390_option_by_key (s_wired, "layer2"), ==, "1");
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-qeth-static-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-qeth-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_QETH_STATIC,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIRED_CTC_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ctc-static"
-
 static void
 test_read_wired_ctc_static (void)
 {
@@ -5973,31 +3281,16 @@ test_read_wired_ctc_static (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	char *unmanaged = NULL;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System test-wired-ctc-static";
-	const char *expected_channel0 = "0.0.1b00";
-	const char *expected_channel1 = "0.0.1b01";
 	const char * const *subchannels;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_CTC_STATIC,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        &unmanaged,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ctc-static",
+	                                    NULL, TYPE_ETHERNET, &unmanaged);
 	g_assert (unmanaged == NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con != NULL);
-	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-ctc-static");
 
 	/* ===== WIRED SETTING ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -6010,22 +3303,15 @@ test_read_wired_ctc_static (void)
 	g_assert (subchannels != NULL);
 	g_assert (subchannels[0] && subchannels[1] && !subchannels[2]);
 
-	g_assert_cmpstr (subchannels[0], ==, expected_channel0);
-	g_assert_cmpstr (subchannels[1], ==, expected_channel1);
+	g_assert_cmpstr (subchannels[0], ==, "0.0.1b00");
+	g_assert_cmpstr (subchannels[1], ==, "0.0.1b01");
 
-	/* Nettype */
 	g_assert_cmpstr (nm_setting_wired_get_s390_nettype (s_wired), ==, "ctc");
-
-	/* port name */
-	tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot");
-	g_assert (tmp != NULL);
-	g_assert_cmpstr (tmp, ==, "0");
+	g_assert_cmpstr (nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot"), ==, "0");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP_NO_KEYS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-no-keys"
-
 static void
 test_read_wifi_wep_no_keys (void)
 {
@@ -6033,42 +3319,16 @@ test_read_wifi_wep_no_keys (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "System foobar (test-wifi-wep-no-keys)";
 	NMWepKeyType key_type;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "wifi-wep-no-keys-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_NO_KEYS, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wifi-wep-no-keys-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_NO_KEYS, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-no-keys",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wifi-wep-no-keys-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-no-keys-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wifi-wep-no-keys-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System foobar (test-wifi-wep-no-keys)");
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
@@ -6078,135 +3338,79 @@ test_read_wifi_wep_no_keys (void)
 	/* ===== WIRELESS SETTING ===== */
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
+	g_assert (s_wireless);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	ASSERT (s_wsec != NULL,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	g_assert (s_wsec);
 
 	/* Key management */
-	ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "none") == 0,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none");
 
 	/* WEP key index */
-	ASSERT (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) == 0,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+	g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0);
 
 	/* WEP key type */
 	key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec);
-	ASSERT (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: unexpected WEP key type %d",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        key_type);
+	g_assert (key_type == NM_WEP_KEY_TYPE_UNKNOWN || key_type == NM_WEP_KEY_TYPE_KEY);
 
 	/* WEP key index 0; we don't expect it to be filled */
-	tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
-	ASSERT (tmp == NULL,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+	g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 0));
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_PERMISSIONS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-permissions"
-
 static void
 test_read_permissions (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	gboolean success;
-	GError *error = NULL;
 	guint32 num;
 	const char *tmp;
 
-	connection = connection_from_file_test (TEST_IFCFG_PERMISSIONS,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "permissions-read", "failed to read %s: %s", TEST_IFCFG_PERMISSIONS, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "permissions-verify", "failed to verify %s: %s", TEST_IFCFG_PERMISSIONS, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-permissions",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "permissions-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_PERMISSIONS,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
 	num = nm_setting_connection_get_num_permissions (s_con);
-	ASSERT (num == 3,
-	        "permissions-verify-permissions", "unexpected number of permissions (%d, expected 3)",
-	        num);
+	g_assert_cmpint (num, ==, 3);
 
 	/* verify each permission */
 	tmp = NULL;
 	success = nm_setting_connection_get_permission (s_con, 0, NULL, &tmp, NULL);
-	ASSERT (success == TRUE,
-	        "permissions-verify-permissions", "unexpected failure getting permission #1");
-	ASSERT (strcmp (tmp, "dcbw") == 0,
-	        "permissions-verify-permissions", "unexpected permission #1");
+	g_assert (success);
+	g_assert_cmpstr (tmp, ==, "dcbw");
 
 	tmp = NULL;
 	success = nm_setting_connection_get_permission (s_con, 1, NULL, &tmp, NULL);
-	ASSERT (success == TRUE,
-	        "permissions-verify-permissions", "unexpected failure getting permission #2");
-	ASSERT (strcmp (tmp, "ssmith") == 0,
-	        "permissions-verify-permissions", "unexpected permission #2");
+	g_assert (success);
+	g_assert_cmpstr (tmp, ==, "ssmith");
 
 	tmp = NULL;
 	success = nm_setting_connection_get_permission (s_con, 2, NULL, &tmp, NULL);
-	ASSERT (success == TRUE,
-	        "permissions-verify-permissions", "unexpected failure getting permission #3");
-	ASSERT (strcmp (tmp, "johnny5") == 0,
-	        "permissions-verify-permissions", "unexpected permission #3");
+	g_assert (success);
+	g_assert_cmpstr (tmp, ==, "johnny5");
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_WIFI_WEP_AGENT_KEYS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-agent-keys"
-
 static void
 test_read_wifi_wep_agent_keys (void)
 {
 	NMConnection *connection;
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
-	GError *error = NULL;
 	NMWepKeyType key_type;
-	gboolean success;
 	NMSettingSecretFlags flags;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIFI_WEP_AGENT_KEYS,
-	                                        NULL,
-	                                        TYPE_WIRELESS,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection != NULL);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wep-agent-keys",
+	                                    NULL, TYPE_WIRELESS, NULL);
 
 	/* Ensure the connection is still marked for wifi security even though
 	 * we don't have any WEP keys because they are agent owned.
@@ -6244,21 +3448,10 @@ test_write_wired_static (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4, *reread_s_ip4;
 	NMSettingIPConfig *s_ip6, *reread_s_ip6;
-	static const char *mac = "31:33:33:37:be:cd";
-	guint32 mtu = 1492;
 	char *uuid;
-	const char *dns1 = "4.2.2.1";
-	const char *dns2 = "4.2.2.2";
-	const char *dns_search1 = "foobar.com";
-	const char *dns_search2 = "lab.foobar.com";
-	const char *dns_search3 = "foobar6.com";
-	const char *dns_search4 = "lab6.foobar.com";
-	const char *dns6_1 = "fade:0102:0103::face";
-	const char *dns6_2 = "cafe:ffff:eeee:dddd:cccc:bbbb:aaaa:feed";
 	NMIPAddress *addr;
 	NMIPAddress *addr6;
 	NMIPRoute *route6;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *route6file = NULL;
@@ -6283,8 +3476,8 @@ test_write_wired_static (void)
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	g_object_set (s_wired,
-	              NM_SETTING_WIRED_MAC_ADDRESS, mac,
-	              NM_SETTING_WIRED_MTU, mtu,
+	              NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd",
+	              NM_SETTING_WIRED_MTU, (guint32) 1492,
 	              NULL);
 
 	/* IP4 setting */
@@ -6308,11 +3501,11 @@ test_write_wired_static (void)
 	nm_setting_ip_config_add_address (s_ip4, addr);
 	nm_ip_address_unref (addr);
 
-	nm_setting_ip_config_add_dns (s_ip4, dns1);
-	nm_setting_ip_config_add_dns (s_ip4, dns2);
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.1");
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.2");
 
-	nm_setting_ip_config_add_dns_search (s_ip4, dns_search1);
-	nm_setting_ip_config_add_dns_search (s_ip4, dns_search2);
+	nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com");
+	nm_setting_ip_config_add_dns_search (s_ip4, "lab.foobar.com");
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
@@ -6354,47 +3547,26 @@ test_write_wired_static (void)
 	nm_ip_route_unref (route6);
 
 	/* DNS servers */
-	nm_setting_ip_config_add_dns (s_ip6, dns6_1);
-	nm_setting_ip_config_add_dns (s_ip6, dns6_2);
+	nm_setting_ip_config_add_dns (s_ip6, "fade:0102:0103::face");
+	nm_setting_ip_config_add_dns (s_ip6, "cafe:ffff:eeee:dddd:cccc:bbbb:aaaa:feed");
 
 	/* DNS domains */
-	nm_setting_ip_config_add_dns_search (s_ip6, dns_search3);
-	nm_setting_ip_config_add_dns_search (s_ip6, dns_search4);
+	nm_setting_ip_config_add_dns_search (s_ip6, "foobar6.com");
+	nm_setting_ip_config_add_dns_search (s_ip6, "lab6.foobar.com");
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-static-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-static-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wired-static-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	/* reread will be normalized, so we must normalize connection too. */
 	nm_connection_normalize (connection, NULL, NULL, NULL);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-static-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-static-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	/* FIXME: currently DNS domains from IPv6 setting are stored in 'DOMAIN' key in ifcfg-file 
+	/* FIXME: currently DNS domains from IPv6 setting are stored in 'DOMAIN' key in ifcfg-file
 	 * However after re-reading they are dropped into IPv4 setting.
 	 * So, in order to comparison succeeded, move DNS domains back to IPv6 setting.
 	 */
@@ -6429,8 +3601,6 @@ test_write_wired_dhcp (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -6464,9 +3634,7 @@ test_write_wired_dhcp (void)
 	              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-dhcp-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
@@ -6477,37 +3645,14 @@ test_write_wired_dhcp (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-dhcp-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wired-dhcp-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-dhcp-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-dhcp-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-dhcp-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -6519,39 +3664,19 @@ test_write_wired_dhcp_plus_ip (void)
 {
 	NMConnection *connection, *reread;
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (written, NULL, TYPE_ETHERNET, NULL,
-	                                    &error);
+	reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL);
 	unlink (written);
 	g_free (written);
 
-	g_assert_no_error (error);
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -6565,14 +3690,9 @@ test_read_write_wired_dhcp_send_hostname (void)
 	NMSettingIPConfig *s_ip6;
 	const char * dhcp_hostname = "kamil-patka";
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-send-hostname",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-send-hostname",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* Check dhcp-hostname and dhcp-send-hostname */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -6588,30 +3708,15 @@ test_read_write_wired_dhcp_send_hostname (void)
 	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, dhcp_hostname, NULL);
 	g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, dhcp_hostname, NULL);
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (written, NULL, TYPE_ETHERNET, NULL,
-	                                    &error);
+	reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL);
 	unlink (written);
 	g_free (written);
 
-	g_assert_no_error (error);
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	/* Check dhcp-hostname and dhcp-send-hostname from the re-read connection. */
 	s_ip4 = nm_connection_get_setting_ip4_config (reread);
@@ -6635,11 +3740,8 @@ test_write_wired_static_ip6_only (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	static const char *mac = "31:33:33:37:be:cd";
 	char *uuid;
-	const char *dns6 = "fade:0102:0103::face";
 	NMIPAddress *addr6;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 
@@ -6662,7 +3764,7 @@ test_write_wired_static_ip6_only (void)
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
-	g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
+	g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", NULL);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -6687,43 +3789,18 @@ test_write_wired_static_ip6_only (void)
 	nm_ip_address_unref (addr6);
 
 	/* DNS server */
-	nm_setting_ip_config_add_dns (s_ip6, dns6);
-
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-static-ip6-only-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nm_setting_ip_config_add_dns (s_ip6, "fade:0102:0103::face");
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-static-ip6-only-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wired-static-ip6-only-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-static-ip6-only-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-static-ip6-only-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-static-ip6-only-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -6747,11 +3824,8 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	static const char *mac = "31:33:33:37:be:cd";
 	char *uuid;
-	const char *dns6 = "fade:0102:0103::face";
 	NMIPAddress *addr6;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *id = NULL;
@@ -6779,7 +3853,7 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
-	g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
+	g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", NULL);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -6805,32 +3879,17 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 	nm_ip_address_unref (addr6);
 
 	/* DNS server */
-	nm_setting_ip_config_add_dns (s_ip6, dns6);
+	nm_setting_ip_config_add_dns (s_ip6, "fade:0102:0103::face");
 
-	g_assert (nm_connection_verify (connection, &error));
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	{
 		/* re-read the file to check that what key was written. */
@@ -6851,7 +3910,7 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 	g_assert (addr6);
 
 	/* assert that the gateway was written and reloaded as expected */
-	if (!gateway6) {
+	if (!gateway6 || !strcmp (gateway6, "::")) {
 		g_assert (nm_setting_ip_config_get_gateway (s_ip6) == NULL);
 		g_assert (written_ifcfg_gateway == NULL);
 	} else {
@@ -6866,8 +3925,6 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-static-routes-legacy"
-
 static void
 test_read_write_static_routes_legacy (void)
 {
@@ -6878,114 +3935,52 @@ test_read_write_static_routes_legacy (void)
 	char *testfile = NULL;
 	char *routefile = NULL;
 	char *route6file = NULL;
-	gboolean success;
-	GError *error = NULL;
 	const char *tmp;
 
-	connection = connection_from_file_test (TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "read-write-static-routes-legacy-read", "failed to read %s: %s",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "read-write-static-routes-legacy-verify", "failed to verify %s: %s",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-static-routes-legacy",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "read-write-static-routes-legacy-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
 	/* ID */
 	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "read-write-static-routes-legacy-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (tmp);
 
 	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "read_write-static-routes-legacy-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
 
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "read-write-static-routes-legacy-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_never_default (s_ip4) == FALSE,
-	        "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+
+	g_assert (!nm_setting_ip_config_get_never_default (s_ip4));
 
 	/* Save the ifcfg; use a special different scratch dir to ensure that
 	 * we can clean up after the written connection in both the original
 	 * source tree and for 'make distcheck'.
 	 */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/tmp",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "read-write-static-routes-legacy-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "read-write-static-routes-legacy-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/tmp",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 	routefile = utils_get_route_path (testfile);
 	unlink (routefile);
 	route6file = utils_get_route6_path (testfile);
 	unlink (route6file);
 
-	ASSERT (reread != NULL,
-	        "read-write-static-routes-legacy-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "read-write-static-routes-legacy-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "read-write-static-routes-legacy-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (routefile);
@@ -7003,16 +3998,9 @@ test_write_wired_static_routes (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	static const char *mac = "31:33:33:37:be:cd";
-	guint32 mtu = 1492;
 	char *uuid;
-	const char *dns1 = "4.2.2.1";
-	const char *dns2 = "4.2.2.2";
-	const char *dns_search1 = "foobar.com";
-	const char *dns_search2 = "lab.foobar.com";
 	NMIPAddress *addr;
 	NMIPRoute *route;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *routefile = NULL;
@@ -7037,8 +4025,8 @@ test_write_wired_static_routes (void)
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	g_object_set (s_wired,
-	              NM_SETTING_WIRED_MAC_ADDRESS, mac,
-	              NM_SETTING_WIRED_MTU, mtu,
+	              NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd",
+	              NM_SETTING_WIRED_MTU, (guint32) 1492,
 	              NULL);
 
 	/* IP4 setting */
@@ -7071,11 +4059,11 @@ test_write_wired_static_routes (void)
 	nm_setting_ip_config_add_route (s_ip4, route);
 	nm_ip_route_unref (route);
 
-	nm_setting_ip_config_add_dns (s_ip4, dns1);
-	nm_setting_ip_config_add_dns (s_ip4, dns2);
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.1");
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.2");
 
-	nm_setting_ip_config_add_dns_search (s_ip4, dns_search1);
-	nm_setting_ip_config_add_dns_search (s_ip4, dns_search2);
+	nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com");
+	nm_setting_ip_config_add_dns_search (s_ip4, "lab.foobar.com");
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
@@ -7086,44 +4074,19 @@ test_write_wired_static_routes (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-static-routes-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-static-routes-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wired-static-routes-write", "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-static-routes-write-reread", "failed to read %s: %s", testfile, error->message);
-
 	routefile = utils_get_route_path (testfile);
 	unlink (routefile);
 
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-static-routes-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-static-routes-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (routefile);
@@ -7196,53 +4159,26 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 
 	nm_setting_802_1x_add_eap_method (s_8021x, "peap");
 
-	success = nm_setting_802_1x_set_ca_cert (s_8021x, 
+	success = nm_setting_802_1x_set_ca_cert (s_8021x,
 	                                         TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
 	                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                         NULL,
 	                                         &error);
-	ASSERT (success == TRUE,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_success (success, error);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write-reread", "failed to read %s: %s", testfile, error->message);
-
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-dhcp-8021x-peap-mschapv2write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-dhcp-8021x-peap-mschapv2write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -7250,31 +4186,8 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 	g_object_unref (reread);
 }
 
-#if 0
-static GByteArray *
-file_to_byte_array (const char *filename)
-{
-	char *contents;
-	GByteArray *array = NULL;
-	gsize length = 0;
-
-	if (g_file_get_contents (filename, &contents, &length, NULL)) {
-		array = g_byte_array_sized_new (length);
-		g_byte_array_append (array, (guint8 *) contents, length);
-		g_assert (array->len == length);
-		g_free (contents);
-	}
-	return array;
-}
-#endif
-
-#define TEST_IFCFG_WIRED_TLS_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
-#define TEST_IFCFG_WIRED_TLS_CLIENT_CERT TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem"
-#define TEST_IFCFG_WIRED_TLS_PRIVATE_KEY TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem"
-
 static void
-test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
-                            NMSettingSecretFlags flags)
+test_write_wired_8021x_tls (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMConnection *reread;
@@ -7291,6 +4204,13 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	const char *pw;
 	char *tmp;
+	gpointer scheme_p, flags_p;
+	NMSetting8021xCKScheme scheme;
+	NMSettingSecretFlags flags;
+
+	nmtst_test_data_unpack (test_data, &scheme_p, &flags_p);
+	scheme = GPOINTER_TO_INT (scheme_p);
+	flags = GPOINTER_TO_INT (flags_p);
 
 	connection = nm_simple_connection_new ();
 	g_assert (connection != NULL);
@@ -7339,7 +4259,7 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 
 	/* CA cert */
 	success = nm_setting_802_1x_set_ca_cert (s_8021x,
-	                                         TEST_IFCFG_WIRED_TLS_CA_CERT,
+	                                         TEST_IFCFG_DIR "/network-scripts/test_ca_cert.pem",
 	                                         scheme,
 	                                         &format,
 	                                         &error);
@@ -7350,7 +4270,7 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	/* Client cert */
 	format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	success = nm_setting_802_1x_set_client_cert (s_8021x,
-	                                             TEST_IFCFG_WIRED_TLS_CLIENT_CERT,
+	                                             TEST_IFCFG_DIR "/network-scripts/test1_key_and_cert.pem",
 	                                             scheme,
 	                                             &format,
 	                                             &error);
@@ -7361,7 +4281,7 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	/* Private key */
 	format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	success = nm_setting_802_1x_set_private_key (s_8021x,
-	                                             TEST_IFCFG_WIRED_TLS_PRIVATE_KEY,
+	                                             TEST_IFCFG_DIR "/network-scripts/test1_key_and_cert.pem",
 	                                             "test1",
 	                                             scheme,
 	                                             &format,
@@ -7373,48 +4293,17 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	/* Set secret flags */
 	g_object_set (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, flags, NULL);
 
-	/* Verify finished connection */
-	success = nm_connection_verify (connection, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify connection: %s", error->message);
-	}
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to write connection: %s", error->message);
-	}
-	g_assert (success);
-	g_assert (testfile != NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify %s: %s", testfile, error->message);
-	}
-	g_assert (success);
-
 	/* Ensure the reread connection's certificates and private key are paths; no
 	 * matter what scheme was used in the original connection they will be read
 	 * back in as paths.
@@ -7452,7 +4341,7 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 			g_object_set (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, NULL, NULL);
 		}
 
-		g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+		nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 	}
 
 	/* Clean up created certs and keys */
@@ -7489,21 +4378,17 @@ test_write_wired_aliases (void)
 	const char *ip[] = { "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" };
 	const char *label[] = { NULL, "alias0:2", NULL, "alias0:3" };
 	NMIPAddress *addr;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	shvarFile *ifcfg;
 	int i, j;
 
 	connection = nm_simple_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-aliases-write", "failed to allocate new connection");
+	g_assert (connection);
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-aliases-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -7516,16 +4401,12 @@ test_write_wired_aliases (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-aliases-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-	        "wired-aliases-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -7543,9 +4424,7 @@ test_write_wired_aliases (void)
 		nm_ip_address_unref (addr);
 	}
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-aliases-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
 	/* Create some pre-existing alias files, to make sure they get overwritten / deleted. */
 	ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":2");
@@ -7553,63 +4432,35 @@ test_write_wired_aliases (void)
 	svSetValue (ifcfg, "IPADDR", "192.168.1.2", FALSE);
 	svWriteFile (ifcfg, 0644, NULL);
 	svCloseFile (ifcfg);
-	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
-	        "wired-aliases-write", "failed to write extra alias file");
+	g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS));
 
 	ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":5");
 	svSetValue (ifcfg, "DEVICE", "alias0:5", FALSE);
 	svSetValue (ifcfg, "IPADDR", "192.168.1.5", FALSE);
 	svWriteFile (ifcfg, 0644, NULL);
 	svCloseFile (ifcfg);
-	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
-	        "wired-aliases-write", "failed to write extra alias file");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-aliases-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS));
 
-	ASSERT (testfile != NULL,
-	        "wired-aliases-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	/* Re-check the alias files */
-	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
-	        "wired-aliases-write", "saving failed to write ifcfg-alias0:2");
-	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":3", G_FILE_TEST_EXISTS),
-	        "wired-aliases-write", "saving failed to write ifcfg-alias0:3");
-	ASSERT (!g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
-	        "wired-aliases-write", "saving failed to delete unused ifcfg-alias0:5");
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS));
+	g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":3", G_FILE_TEST_EXISTS));
+	g_assert (!g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS));
+
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 	unlink (TEST_SCRATCH_ALIAS_BASE ":2");
 	unlink (TEST_SCRATCH_ALIAS_BASE ":3");
 
-	ASSERT (reread != NULL,
-	        "wired-aliases-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-aliases-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
 	/* nm_connection_compare() is not guaranteed to succeed, because the
 	 * aliases get read back in essentially random order. So just
 	 * verify the aliases manually.
 	 */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == num_addresses,
-	        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        testfile,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == num_addresses);
 
 	/* Addresses */
 	for (i = 0; i < num_addresses; i++) {
@@ -7634,12 +4485,8 @@ test_write_wired_aliases (void)
 		ip[j] = NULL;
 	}
 
-	for (i = 0; i < num_addresses; i++) {
-		ASSERT (ip[i] == 0,
-		        "wired-aliases-write-verify-ip4", "failed to verify %s: did not find IP4 address 0x%08x",
-		        testfile,
-		        ip[i]);
-	}
+	for (i = 0; i < num_addresses; i++)
+		g_assert (!ip[i]);
 
 	/* Gateway */
 	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "1.1.1.1");
@@ -7657,7 +4504,6 @@ test_write_gateway (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	shvarFile *f;
 	NMIPAddress *addr;
@@ -7700,17 +4546,11 @@ test_write_gateway (void)
 	nm_setting_ip_config_add_address (s_ip4, addr);
 	nm_ip_address_unref (addr);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -7756,21 +4596,10 @@ test_write_gateway (void)
 
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_WIRELESS,
-	                                    NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -7788,14 +4617,10 @@ test_write_wifi_open (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	GBytes *ssid;
 	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
-	const char *bssid = "11:22:33:44:55:66";
-	guint32 channel = 9, mtu = 1345;
-	const char *mac = "aa:bb:cc:dd:ee:ff";
 	shvarFile *ifcfg;
 	char *tmp;
 
@@ -7822,12 +4647,12 @@ test_write_wifi_open (void)
 
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
-	              NM_SETTING_WIRELESS_BSSID, bssid,
-	              NM_SETTING_WIRELESS_MAC_ADDRESS, mac,
+	              NM_SETTING_WIRELESS_BSSID, "11:22:33:44:55:66",
+	              NM_SETTING_WIRELESS_MAC_ADDRESS, "aa:bb:cc:dd:ee:ff",
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
 	              NM_SETTING_WIRELESS_BAND, "bg",
-	              NM_SETTING_WIRELESS_CHANNEL, channel,
-	              NM_SETTING_WIRELESS_MTU, mtu,
+	              NM_SETTING_WIRELESS_CHANNEL, (guint32) 9,
+	              NM_SETTING_WIRELESS_MTU, (guint32) 1345,
 	              NULL);
 
 	g_bytes_unref (ssid);
@@ -7847,32 +4672,13 @@ test_write_wifi_open (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-open-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-open-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wifi-open-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 
 	/* Now make sure that the ESSID item isn't double-quoted (rh #606518) */
 	ifcfg = svOpenFile (testfile, &error);
@@ -7880,25 +4686,16 @@ test_write_wifi_open (void)
 	g_assert (ifcfg != NULL);
 
 	tmp = svGetValue (ifcfg, "ESSID", TRUE);
-	ASSERT (tmp != NULL,
-	        "wifi-open-write-reread", "failed to read ESSID key from %s", testfile);
+	g_assert (tmp);
 
-	ASSERT (strncmp (tmp, "\"\"", 2) != 0,
-	        "wifi-open-write-reread", "unexpected ESSID double-quote in %s", testfile);
+	g_assert (strncmp (tmp, "\"\"", 2) != 0);
 
 	g_free (tmp);
 	svCloseFile (ifcfg);
 
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-open-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-open-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-open-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -7915,8 +4712,6 @@ test_write_wifi_open_hex_ssid (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	GBytes *ssid;
 	const unsigned char ssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
@@ -7964,41 +4759,16 @@ test_write_wifi_open_hex_ssid (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-open-hex-ssid-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-open-hex-ssid-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-open-hex-ssid-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-open-hex-ssid-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-open-hex-ssid-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-open-hex-ssid-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -8016,8 +4786,6 @@ test_write_wifi_wep (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
@@ -8081,50 +4849,22 @@ test_write_wifi_wep (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wep-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wep-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wifi-wep-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-wep-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-wep-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-wep-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wep-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wep-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wep-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8143,7 +4883,6 @@ test_write_wifi_wep_adhoc (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
@@ -8151,7 +4890,6 @@ test_write_wifi_wep_adhoc (void)
 	const char *ssid_data = "blahblah";
 	struct stat statbuf;
 	NMIPAddress *addr;
-	const char *dns1 = "4.2.2.1";
 
 	connection = nm_simple_connection_new ();
 
@@ -8203,7 +4941,7 @@ test_write_wifi_wep_adhoc (void)
 	nm_setting_ip_config_add_address (s_ip4, addr);
 	nm_ip_address_unref (addr);
 
-	nm_setting_ip_config_add_dns (s_ip4, dns1);
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.1");
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
@@ -8214,50 +4952,22 @@ test_write_wifi_wep_adhoc (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wep-adhoc-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wep-adhoc-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wifi-wep-adhoc-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-wep-adhoc-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-wep-adhoc-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-wep-adhoc-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wep-adhoc-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wep-adhoc-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wep-adhoc-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8276,8 +4986,6 @@ test_write_wifi_wep_passphrase (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
@@ -8339,50 +5047,22 @@ test_write_wifi_wep_passphrase (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wep-passphrase-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wep-passphrase-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-wep-passphrase-write", "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-wep-passphrase-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-wep-passphrase-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-wep-passphrase-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wep-passphrase-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wep-passphrase-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wep-passphrase-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8401,8 +5081,6 @@ test_write_wifi_wep_40_ascii (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
@@ -8466,50 +5144,22 @@ test_write_wifi_wep_40_ascii (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wep-40-ascii-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wep-40-ascii-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-wep-40-ascii-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-wep-40-ascii-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-wep-40-ascii-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-wep-40-ascii-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wep-40-ascii-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wep-40-ascii-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wep-40-ascii-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8528,8 +5178,6 @@ test_write_wifi_wep_104_ascii (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
@@ -8593,50 +5241,23 @@ test_write_wifi_wep_104_ascii (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wep-104-ascii-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wep-104-ascii-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-wep-104-ascii-write", "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-wep-104-ascii-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-wep-104-ascii-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-wep-104-ascii-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wep-104-ascii-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wep-104-ascii-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
 
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wep-104-ascii-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8655,8 +5276,6 @@ test_write_wifi_leap (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
@@ -8717,50 +5336,22 @@ test_write_wifi_leap (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-leap-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-leap-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wifi-leap-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
-	ASSERT (stat (keyfile, &statbuf) == 0,
-	        "wifi-leap-write-reread", "couldn't stat() '%s'", keyfile);
-	ASSERT (S_ISREG (statbuf.st_mode),
-	        "wifi-leap-write-reread", "keyfile '%s' wasn't a normal file", keyfile);
-	ASSERT ((statbuf.st_mode & 0077) == 0,
-	        "wifi-leap-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile);
+	g_assert_cmpint (stat (keyfile, &statbuf), ==, 0);
+	g_assert (S_ISREG (statbuf.st_mode));
+	g_assert_cmpint ((statbuf.st_mode & 0077), ==, 0);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-leap-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-leap-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-leap-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8769,7 +5360,7 @@ test_write_wifi_leap (void)
 }
 
 static void
-test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
+test_write_wifi_leap_secret_flags (gconstpointer data)
 {
 	NMConnection *connection;
 	NMConnection *reread;
@@ -8779,12 +5370,11 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
 	const char *ssid_data = "blahblah";
+	NMSettingSecretFlags flags = GPOINTER_TO_UINT (data);
 
 	connection = nm_simple_connection_new ();
 	g_assert (connection);
@@ -8843,47 +5433,24 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
-	g_assert_no_error (error);
-
 	/* No key should be written out since the secret is not system owned */
 	keyfile = utils_get_keys_path (testfile);
 	g_assert (g_file_test (keyfile, G_FILE_TEST_EXISTS) == FALSE);
 
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
 	/* Remove the LEAP password from the original connection since it wont' be
 	 * in the reread connection, as the password is not system owned.
 	 */
 	g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, NULL, NULL);
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -8892,12 +5459,7 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 }
 
 static void
-test_write_wifi_wpa_psk (const char *name,
-                         const char *test_name,
-                         gboolean wep_group,
-                         gboolean wpa,
-                         gboolean wpa2,
-                         const char *psk)
+test_write_wifi_wpa_psk (gconstpointer test_data)
 {
 	NMConnection *connection;
 	NMConnection *reread;
@@ -8906,15 +5468,19 @@ test_write_wifi_wpa_psk (const char *name,
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	char *uuid, *tmp;
-	gboolean success;
-	GError *error = NULL;
+	char *uuid;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
 	const char *ssid_data = "blahblah";
+	struct {
+		const char *name, *psk;
+		gpointer wep_group_p, wpa_p, wpa2_p;
+	} args;
+
+	nmtst_test_data_unpack (test_data, &args.name, &args.wep_group_p, &args.wpa_p, &args.wpa2_p, &args.psk);
 
-	g_return_if_fail (psk != NULL);
+	g_assert (args.psk);
 
 	connection = nm_simple_connection_new ();
 
@@ -8924,7 +5490,7 @@ test_write_wifi_wpa_psk (const char *name,
 
 	uuid = nm_utils_uuid_generate ();
 	g_object_set (s_con,
-	              NM_SETTING_CONNECTION_ID, name,
+	              NM_SETTING_CONNECTION_ID, args.name,
 	              NM_SETTING_CONNECTION_UUID, uuid,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
 	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
@@ -8950,19 +5516,19 @@ test_write_wifi_wpa_psk (const char *name,
 
 	g_object_set (s_wsec,
 	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
-	              NM_SETTING_WIRELESS_SECURITY_PSK, psk,
+	              NM_SETTING_WIRELESS_SECURITY_PSK, args.psk,
 	              NULL);
 
-	if (wep_group) {
+	if (GPOINTER_TO_INT (args.wep_group_p)) {
 		nm_setting_wireless_security_add_group (s_wsec, "wep40");
 		nm_setting_wireless_security_add_group (s_wsec, "wep104");
 	}
-	if (wpa) {
+	if (GPOINTER_TO_INT (args.wpa_p)) {
 		nm_setting_wireless_security_add_proto (s_wsec, "wpa");
 		nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
 		nm_setting_wireless_security_add_group (s_wsec, "tkip");
 	}
-	if (wpa2) {
+	if (GPOINTER_TO_INT (args.wpa2_p)) {
 		nm_setting_wireless_security_add_proto (s_wsec, "rsn");
 		nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp");
 		nm_setting_wireless_security_add_group (s_wsec, "ccmp");
@@ -8983,46 +5549,19 @@ test_write_wifi_wpa_psk (const char *name,
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        test_name, "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        test_name, "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        test_name, "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	tmp = g_strdup_printf ("%s-reread", test_name);
-	ASSERT (reread != NULL,
-	        tmp, "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        tmp, "failed to verify %s: %s", testfile, error->message);
-	g_free (tmp);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        test_name, "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -9041,14 +5580,12 @@ test_write_wifi_wpa_psk_adhoc (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
 	GBytes *ssid;
 	const char *ssid_data = "blahblah";
 	NMIPAddress *addr;
-	const char *dns1 = "4.2.2.1";
 
 	connection = nm_simple_connection_new ();
 
@@ -9107,7 +5644,7 @@ test_write_wifi_wpa_psk_adhoc (void)
 	nm_setting_ip_config_add_address (s_ip4, addr);
 	nm_ip_address_unref (addr);
 
-	nm_setting_ip_config_add_dns (s_ip4, dns1);
+	nm_setting_ip_config_add_dns (s_ip4, "4.2.2.1");
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
@@ -9118,44 +5655,19 @@ test_write_wifi_wpa_psk_adhoc (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wpa-psk-adhoc-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-psk-adhoc-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	ASSERT (testfile != NULL,
-	        "wifi-wpa-psk-adhoc-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wpa-psk-adhoc-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wpa-psk-adhoc-write-reread", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wpa-psk-adhoc-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -9232,18 +5744,14 @@ test_write_wifi_wpa_eap_tls (void)
 	                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                         NULL,
 	                                         &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-tls-write", "failed to set CA certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
+	nmtst_assert_success (success, error);
 
 	success = nm_setting_802_1x_set_client_cert (s_8021x,
 	                                             TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
 	                                             NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                             NULL,
 	                                             &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-tls-write", "failed to set client certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message);
+	nmtst_assert_success (success, error);
 
 	success = nm_setting_802_1x_set_private_key (s_8021x,
 	                                             TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
@@ -9251,9 +5759,7 @@ test_write_wifi_wpa_eap_tls (void)
 	                                             NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                             NULL,
 	                                             &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-tls-write", "failed to set private key '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message);
+	nmtst_assert_success (success, error);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -9270,44 +5776,19 @@ test_write_wifi_wpa_eap_tls (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wpa-eap-tls-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-tls-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-wpa-eap-tls-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wpa-eap-tls-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wpa-eap-tls-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wpa-eap-tls-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -9388,9 +5869,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                         NULL,
 	                                         &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to set CA certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
+	nmtst_assert_success (success, error);
 
 	/* Phase 2 TLS stuff */
 
@@ -9400,9 +5879,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	                                                NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                                NULL,
 	                                                &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to set inner CA certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
+	nmtst_assert_success (success, error);
 
 	/* phase2 client cert */
 	success = nm_setting_802_1x_set_phase2_client_cert (s_8021x,
@@ -9410,9 +5887,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	                                                    NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                                    NULL,
 	                                                    &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to set inner client certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message);
+	nmtst_assert_success (success, error);
 
 	/* phase2 private key */
 	success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
@@ -9421,9 +5896,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	                                                    NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                                    NULL,
 	                                                    &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to set private key '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message);
+	nmtst_assert_success (success, error);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -9440,44 +5913,19 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wpa-eap-ttls-tls-write-reread", "failed to read %s: %s", testfile, error->message);
-
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wpa-eap-ttls-tls-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wpa-eap-ttls-tls-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -9562,10 +6010,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
 	                                         NULL,
 	                                         &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to set CA certificate '%s': %s",
-	        TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
-
+	nmtst_assert_success (success, error);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -9582,44 +6027,19 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	ASSERT (testfile != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write-reread", "failed to read %s: %s", testfile, error->message);
-
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wifi-wpa-eap-ttls-mschapv2-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_free (keyfile);
@@ -9715,39 +6135,20 @@ test_write_wifi_wpa_then_open (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
-	g_assert (reread);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (reread);
 
+	nmtst_connection_normalize (connection);
+
 	/* Now change the connection to open and recheck */
 	nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
 
@@ -9765,29 +6166,14 @@ test_write_wifi_wpa_then_open (void)
 	g_free (keyfile);
 	keyfile = NULL;
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read it for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-
-	g_assert (reread);
 
 	/* No keyfile since it's an open connection this time */
 	keyfile = utils_get_keys_path (testfile);
 	g_assert (g_file_test (keyfile, G_FILE_TEST_EXISTS) == FALSE);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	unlink (testfile);
 	g_free (testfile);
@@ -9839,8 +6225,7 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	              NULL);
 	g_free (uuid);
 	g_strfreev (perms);
-	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 1,
-                "test_write_wifi_wpa_then_wep_with_perms", "unexpected failure adding valid user permisson");
+	g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1);
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
@@ -9891,39 +6276,20 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (reread);
 
+	nmtst_connection_normalize (connection);
+
 	/* Now change the connection to WEP and recheck */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
 	g_assert (s_wsec);
@@ -9947,28 +6313,13 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	g_free (keyfile);
 	keyfile = NULL;
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read it for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
-
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 
+	nmtst_connection_normalize (connection);
 	success = nm_connection_compare (connection, reread,
 	                                 NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
 	                                 NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS);
-
-	ASSERT (success,
-	        "test_write_wifi_wpa_then_wep_with_perms", "failed to compare connections");
+	g_assert (success);
 
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
@@ -9993,7 +6344,6 @@ test_write_wifi_dynamic_wep_leap (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	char *keyfile = NULL;
@@ -10067,40 +6417,18 @@ test_write_wifi_dynamic_wep_leap (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
-	g_assert_no_error (error);
-	g_assert (reread);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 
 	keyfile = utils_get_keys_path (testfile);
 	unlink (keyfile);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	/* Check and make sure that an "old-school" LEAP (Network EAP) connection
 	 * did not get written.  Check first that the auth alg is not set to "LEAP"
@@ -10137,8 +6465,6 @@ test_write_wired_qeth_dhcp (void)
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
 	char **subchans;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -10189,42 +6515,16 @@ test_write_wired_qeth_dhcp (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	/* Verify */
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-qeth-dhcp-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "wired-qeth-dhcp-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "wired-qeth-dhcp-write", "didn't get ifcfg file path back after writing connection");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "wired-qeth-dhcp-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "wired-qeth-dhcp-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-qeth-dhcp-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -10242,7 +6542,6 @@ test_write_wired_ctc_dhcp (void)
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
 	char **subchans;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 	shvarFile *ifcfg;
@@ -10293,19 +6592,11 @@ test_write_wired_ctc_dhcp (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	/* Verify */
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile != NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	/* Ensure the CTCPROT item gets written out as it's own option */
 	ifcfg = svOpenFile (testfile, &error);
@@ -10324,24 +6615,10 @@ test_write_wired_ctc_dhcp (void)
 
 	svCloseFile (ifcfg);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	g_assert (reread);
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -10358,8 +6635,6 @@ test_write_permissions (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -10402,42 +6677,16 @@ test_write_permissions (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	/* Verify */
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "permissions-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "permissions-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "permissions-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "permissions-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "permissions-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "permissions-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -10457,8 +6706,6 @@ test_write_wifi_wep_agent_keys (void)
 	char *uuid;
 	const char *str_ssid = "foobarbaz";
 	GBytes *ssid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -10517,38 +6764,15 @@ test_write_wifi_wep_agent_keys (void)
 	              NULL);
 	nm_setting_wireless_security_set_wep_key (s_wsec, 0, "asdfdjaslfjasd;flasjdfl;aksdf");
 
-	/* Verify */
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile != NULL);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_WIRELESS,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
 	unlink (testfile);
 
-	g_assert_no_error (error);
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
 	/* Remove the WEP key from the original, because it should not have been
 	 * written out to disk as it was agent-owned.  The new connection should
 	 * not have any WEP keys set.
@@ -10559,9 +6783,7 @@ test_write_wifi_wep_agent_keys (void)
 	              NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_UNKNOWN,
 	              NULL);
 
-	/* Compare original and reread */
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -10578,9 +6800,7 @@ test_write_wired_pppoe (void)
 	NMSettingPppoe *s_pppoe;
 	NMSettingPpp *s_ppp;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
-	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
 
@@ -10623,17 +6843,11 @@ test_write_wired_pppoe (void)
 	s_ppp = (NMSettingPpp *) nm_setting_ppp_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_ppp));
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wired-pppoe-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == FALSE,
-	        "wired-pppoe-write", "unexpected success writing connection to disk");
+	_writer_new_connection_fail (connection,
+	                             TEST_SCRATCH_DIR "/network-scripts/",
+	                             NULL);
 
 	g_object_unref (connection);
 	g_clear_error (&error);
@@ -10647,9 +6861,7 @@ test_write_vpn (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingVpn *s_vpn;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
-	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
 
@@ -10686,24 +6898,18 @@ test_write_vpn (void)
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "vpn-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == FALSE,
-	        "vpn-write", "unexpected success writing connection to disk");
+	_writer_new_connection_fail (connection,
+	                             TEST_SCRATCH_DIR "/network-scripts/",
+	                             NULL);
 
 	g_object_unref (connection);
 	g_clear_error (&error);
 }
 
 static void
-test_write_mobile_broadband (gboolean gsm)
+test_write_mobile_broadband (gconstpointer data)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
@@ -10713,9 +6919,8 @@ test_write_mobile_broadband (gboolean gsm)
 	NMSettingPpp *s_ppp;
 	NMSettingSerial *s_serial;
 	char *uuid;
-	gboolean success;
 	GError *error = NULL;
-	char *testfile = NULL;
+	gboolean gsm = GPOINTER_TO_UINT (data);
 
 	connection = nm_simple_connection_new ();
 
@@ -10769,24 +6974,16 @@ test_write_mobile_broadband (gboolean gsm)
 	s_ppp = (NMSettingPpp *) nm_setting_ppp_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_ppp));
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "mobile-broadband-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == FALSE,
-	        "mobile-broadband-write", "unexpected success writing connection to disk");
+	_writer_new_connection_fail (connection,
+	                             TEST_SCRATCH_DIR "/network-scripts/",
+	                             NULL);
 
 	g_object_unref (connection);
 	g_clear_error (&error);
 }
 
-#define TEST_IFCFG_BRIDGE_MAIN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bridge-main"
-
 static void
 test_read_bridge_main (void)
 {
@@ -10794,16 +6991,9 @@ test_read_bridge_main (void)
 	NMSettingBridge *s_bridge;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_BRIDGE_MAIN,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
-	g_assert_no_error (error);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bridge-main",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "br0");
 
@@ -10839,7 +7029,6 @@ test_write_bridge_main (void)
 	char *uuid;
 	NMIPAddress *addr;
 	static const char *mac = "31:33:33:37:be:cd";
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 
@@ -10897,56 +7086,29 @@ test_write_bridge_main (void)
 
 	nmtst_assert_connection_verifies_without_normalization (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert (success);
-	g_assert_cmpstr (testfile, !=, NULL);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_BRIDGE,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_BRIDGE, NULL);
 	unlink (testfile);
 
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert_no_error (error);
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_BRIDGE_COMPONENT TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bridge-component"
-
 static void
 test_read_bridge_component (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingBridgePort *s_port;
-	GError *error = NULL;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_BRIDGE_COMPONENT,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bridge-component",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -10973,8 +7135,6 @@ test_write_bridge_component (void)
 	static const char *mac = "31:33:33:37:be:cd";
 	guint32 mtu = 1492;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -10991,8 +7151,8 @@ test_write_bridge_component (void)
 	              NM_SETTING_CONNECTION_UUID, uuid,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
 	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-				  NM_SETTING_CONNECTION_MASTER, "br0",
-				  NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
+	              NM_SETTING_CONNECTION_MASTER, "br0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
 	              NULL);
 	g_free (uuid);
 
@@ -11014,36 +7174,16 @@ test_write_bridge_component (void)
 	              NM_SETTING_BRIDGE_PORT_PATH_COST, 33,
 	              NULL);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	g_assert (reread);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -11055,16 +7195,9 @@ test_read_bridge_missing_stp (void)
 {
 	NMConnection *connection;
 	NMSettingBridge *s_bridge;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bridge-missing-stp",
-	                                        NULL,
-	                                        TYPE_BRIDGE,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
-	g_assert_no_error (error);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bridge-missing-stp",
+	                                    NULL, TYPE_BRIDGE, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "br0");
 
@@ -11083,18 +7216,11 @@ static void
 test_read_vlan_interface (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 	guint32 from = 0, to = 0;
 
-	connection = connection_from_file_test (TEST_IFCFG_VLAN_INTERFACE,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
-
+	connection = _connection_from_file (TEST_IFCFG_VLAN_INTERFACE,
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan43");
 
@@ -11104,7 +7230,7 @@ test_read_vlan_interface (void)
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth9");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 43);
 	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==,
-	                 NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING);
+	                 NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING | NM_VLAN_FLAG_REORDER_HEADERS);
 
 	/* Ingress map */
 	g_assert_cmpint (nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP), ==, 2);
@@ -11141,17 +7267,9 @@ static void
 test_read_vlan_only_vlan_id (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_VLAN_ONLY_VLANID,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
-
+	connection = _connection_from_file (TEST_IFCFG_VLAN_ONLY_VLANID, NULL, TYPE_ETHERNET, NULL);
 
 	g_assert (nm_connection_get_interface_name (connection) == NULL);
 
@@ -11160,29 +7278,19 @@ test_read_vlan_only_vlan_id (void)
 
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth9");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 43);
-	/* Ensure that flags are 0 if both REORDER_HDR and VLAN_FLAGS are missing */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_VLAN_ONLY_DEVICE TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-only-device"
-
 static void
 test_read_vlan_only_device (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_VLAN_ONLY_DEVICE,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
-
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-vlan-only-device",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "eth0.9");
 
@@ -11199,15 +7307,10 @@ static void
 test_read_vlan_physdev (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-physdev",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-physdev",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan0.3");
 
@@ -11224,15 +7327,13 @@ static void
 test_read_vlan_reorder_hdr_1 (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-reorder-hdr-1",
-	                                        NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	g_assert (nm_connection_verify (connection, &error));
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*REORDER_HDR key is deprecated, use VLAN_FLAGS*");
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-reorder-hdr-1",
+	                                        NULL, TYPE_ETHERNET, NULL);
+	g_test_assert_expected_messages ();
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan0.3");
 
@@ -11241,8 +7342,30 @@ test_read_vlan_reorder_hdr_1 (void)
 
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth0");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 3);
-	/* Check correct read of REORDER_HDR=1 */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 1);
+	/* Check that REORDER_HDR=0 is ignored */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS);
+
+	g_object_unref (connection);
+}
+
+static void
+test_read_vlan_reorder_hdr_2 (void)
+{
+	NMConnection *connection;
+	NMSettingVlan *s_vlan;
+
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-reorder-hdr-2",
+	                                    NULL, TYPE_ETHERNET, NULL);
+
+	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan0.3");
+
+	s_vlan = nm_connection_get_setting_vlan (connection);
+	g_assert (s_vlan);
+
+	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth0");
+	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 3);
+	/* Check that VLAN_FLAGS=NO_REORDER_HDR works */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_LOOSE_BINDING);
 
 	g_object_unref (connection);
 }
@@ -11251,16 +7374,10 @@ static void
 test_read_vlan_flags_1 (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-1",
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-1",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "super-vlan");
 
@@ -11269,8 +7386,9 @@ test_read_vlan_flags_1 (void)
 
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth9");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 44);
-	/* reorder_hdr and loose_binding */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 5);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==,
+	                                            NM_VLAN_FLAG_LOOSE_BINDING |
+	                                            NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
@@ -11279,16 +7397,10 @@ static void
 test_read_vlan_flags_2 (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingVlan *s_vlan;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-2",
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-2",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "super-vlan");
 
@@ -11297,8 +7409,10 @@ test_read_vlan_flags_2 (void)
 
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth9");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 44);
-	/* gvrp and loose_binding */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 6);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==,
+	                                            NM_VLAN_FLAG_GVRP |
+	                                            NM_VLAN_FLAG_LOOSE_BINDING |
+	                                            NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
@@ -11308,21 +7422,13 @@ test_write_vlan (void)
 {
 	NMConnection *connection;
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_VLAN_INTERFACE,
-	                                        NULL,
-	                                        TYPE_VLAN,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_VLAN_INTERFACE,
+	                                    NULL, TYPE_VLAN, NULL);
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
 	unlink (written);
 	g_free (written);
@@ -11335,44 +7441,20 @@ test_write_vlan_flags (void)
 {
 	NMConnection *connection, *reread;
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-2",
-	                                        NULL,
-	                                        TYPE_VLAN,
-	                                        NULL,
-	                                        &error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-flags-2",
+	                                    NULL, TYPE_VLAN, NULL);
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (written,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL);
 
 	unlink (written);
 	g_free (written);
 
-	g_assert_no_error (error);
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -11383,44 +7465,19 @@ test_write_vlan_only_vlanid (void)
 {
 	NMConnection *connection, *reread;
 	char *written = NULL;
-	GError *error = NULL;
-	gboolean success = FALSE;
 
-	connection = connection_from_file_test (TEST_IFCFG_VLAN_ONLY_VLANID,
-	                                        NULL,
-	                                        TYPE_VLAN,
-	                                        NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (TEST_IFCFG_VLAN_ONLY_VLANID,
+	                                    NULL, TYPE_VLAN, NULL);
 
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &written,
-	                                 &error);
-	g_assert (success);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &written);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (written,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL);
 	unlink (written);
 	g_free (written);
 
-	g_assert_no_error (error);
-	g_assert (reread != NULL);
-
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -11434,8 +7491,6 @@ test_write_vlan_reorder_hdr (void)
 	NMSettingVlan *s_vlan;
 	NMSettingWired *s_wired;
 	char *uuid;
-	GError *error = NULL;
-	gboolean success;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -11467,30 +7522,14 @@ test_write_vlan_reorder_hdr (void)
 	              NM_SETTING_VLAN_FLAGS, 1,
 	              NULL);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	g_assert_no_error (error);
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -11505,10 +7544,7 @@ test_write_ethernet_missing_ipv6 (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
-	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -11550,54 +7586,16 @@ test_write_ethernet_missing_ipv6 (void)
 	 * missing IPv6 as IPv6 with NM_SETTING_IP6_CONFIG_METHOD_AUTO method.
 	 */
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "ethernet-missing-ipv6", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "ethernet-missing-ipv6", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	ASSERT (testfile != NULL,
-	        "ethernet-missing-ipv6", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "ethernet-missing-ipv6-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "ethernet-missing-ipv6-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	/*
-	 * We need to add IPv6 setting to the original connection now so that
-	 * the comparison can succeed. Missing IPv6 setting should have been
-	 * written out (and re-read) as Automatic IPv6.
-	 */
-	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
-	g_assert (s_ip6);
-	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6,
-	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
-	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
-	              NULL);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "ethernet-missing-ipv6", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -11607,52 +7605,30 @@ test_write_ethernet_missing_ipv6 (void)
 static void
 test_read_ibft_ignored (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft",
-	                                        NULL, TYPE_ETHERNET,
-	                                        NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
-#define TEST_IFCFG_BOND_MAIN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bond-main"
-
 static void
 test_read_bond_main (void)
 {
 	NMConnection *connection;
 	NMSettingBond *s_bond;
-	GError *error = NULL;
-
-	connection = connection_from_file_test (TEST_IFCFG_BOND_MAIN,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "bond-main-read", "unexpected failure reading %s", TEST_IFCFG_BOND_MAIN);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "bond-main-read", "failed to verify %s: %s", TEST_IFCFG_BOND_MAIN, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-main",
+	                                    NULL, TYPE_ETHERNET,NULL);
 
-	ASSERT (g_strcmp0 (nm_connection_get_interface_name (connection), "bond0") == 0,
-	        "bond-main", "failed to verify %s: DEVICE=%s does not match bond0",
-	        TEST_IFCFG_BOND_MAIN, nm_connection_get_interface_name (connection));
+	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "bond0");
 
 	/* ===== Bonding SETTING ===== */
 
 	s_bond = nm_connection_get_setting_bond (connection);
-	ASSERT (s_bond != NULL,
-	        "bond-main", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_BOND_MAIN,
-	        NM_SETTING_BOND_SETTING_NAME);
+	g_assert (s_bond);
 
-	ASSERT (g_strcmp0 (nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON), "100") == 0,
-	        "bond-main", "failed to verify %s: miimon=%s does not match 100",
-	        TEST_IFCFG_BOND_MAIN, nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON));
+	g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON), ==, "100");
 
 	g_object_unref (connection);
 }
@@ -11669,7 +7645,6 @@ test_write_bond_main (void)
 	NMSettingWired *s_wired;
 	char *uuid;
 	NMIPAddress *addr;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 
@@ -11722,77 +7697,36 @@ test_write_bond_main (void)
 
 	nmtst_assert_connection_verifies_without_normalization (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "bond-main-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	ASSERT (testfile != NULL,
-	        "bond-main-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_BOND,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_BOND, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "bond-main-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "bond-main-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "bond-main-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_BOND_SLAVE TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bond-slave"
-
 static void
 test_read_bond_slave (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_BOND_SLAVE,
-	                                        NULL,
-	                                        TYPE_ETHERNET,
-	                                        NULL,
-	                                        &error);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-slave",
+	                                    NULL, TYPE_ETHERNET, NULL);
 	g_test_assert_expected_messages ();
 
-	ASSERT (connection != NULL,
-	        "bond-slave-read", "unexpected failure reading %s", TEST_IFCFG_BOND_SLAVE);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "bond-slave-read", "failed to verify %s: %s", TEST_IFCFG_BOND_SLAVE, error->message);
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "bond-slave-read", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_BOND_SLAVE, NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
-	ASSERT (g_strcmp0 (nm_setting_connection_get_master (s_con), "bond0") == 0,
-	        "bond-slave-read", "failed to verify %s: master is not bond0",
-	        TEST_IFCFG_BOND_SLAVE);
+	g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "bond0");
 
-	ASSERT (g_strcmp0 (nm_setting_connection_get_slave_type (s_con), NM_SETTING_BOND_SETTING_NAME) == 0,
-	        "bond-slave-read", "failed to verify %s: slave-type is not bond",
-	        TEST_IFCFG_BOND_SLAVE);
+	g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BOND_SETTING_NAME);
 
 	g_object_unref (connection);
 }
@@ -11807,8 +7741,6 @@ test_write_bond_slave (void)
 	static const char *mac = "31:33:33:37:be:cd";
 	guint32 mtu = 1492;
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -11823,8 +7755,8 @@ test_write_bond_slave (void)
 	              NM_SETTING_CONNECTION_UUID, uuid,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
 	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-				  NM_SETTING_CONNECTION_MASTER, "bond0",
-				  NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
+	              NM_SETTING_CONNECTION_MASTER, "bond0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
 	              NULL);
 	g_free (uuid);
 
@@ -11837,107 +7769,50 @@ test_write_bond_slave (void)
 	              NM_SETTING_WIRED_MTU, mtu,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "bond-slave-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "bond-slave-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "bond-slave-write", "didn't get ifcfg file path back after writing connection");
+	nmtst_assert_connection_verifies (connection);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "bond-slave-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "bond-slave-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "bond-slave-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_INFINIBAND TEST_IFCFG_DIR"/network-scripts/ifcfg-test-infiniband"
-
 static void
 test_read_infiniband (void)
 {
 	NMConnection *connection;
 	NMSettingInfiniband *s_infiniband;
 	char *unmanaged = NULL;
-	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[INFINIBAND_ALEN] = { 0x80, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22 };
 	const char *transport_mode;
 
-	connection = connection_from_file_test (TEST_IFCFG_INFINIBAND,
-	                                        NULL,
-	                                        TYPE_INFINIBAND,
-	                                        &unmanaged,
-	                                        &error);
-	ASSERT (connection != NULL,
-	        "infiniband-read", "failed to read %s: %s", TEST_IFCFG_INFINIBAND, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "infiniband-verify", "failed to verify %s: %s", TEST_IFCFG_INFINIBAND, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "infiniband-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_INFINIBAND);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-infiniband",
+	                                    NULL, TYPE_INFINIBAND, &unmanaged);
+	g_assert (!unmanaged);
 
 	/* ===== INFINIBAND SETTING ===== */
 
 	s_infiniband = nm_connection_get_setting_infiniband (connection);
-	ASSERT (s_infiniband != NULL,
-	        "infiniband-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_INFINIBAND,
-	        NM_SETTING_INFINIBAND_SETTING_NAME);
+	g_assert (s_infiniband);
 
 	/* MAC address */
 	mac = nm_setting_infiniband_get_mac_address (s_infiniband);
-	ASSERT (mac != NULL,
-	        "infiniband-verify-infiniband", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_INFINIBAND,
-	        NM_SETTING_INFINIBAND_SETTING_NAME,
-	        NM_SETTING_INFINIBAND_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "infiniband-verify-infiniband", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_INFINIBAND,
-	        NM_SETTING_INFINIBAND_SETTING_NAME,
-	        NM_SETTING_INFINIBAND_MAC_ADDRESS);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 
 	/* Transport mode */
 	transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);
-	ASSERT (transport_mode != NULL,
-	        "infiniband-verify-infiniband", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_INFINIBAND,
-	        NM_SETTING_INFINIBAND_SETTING_NAME,
-	        NM_SETTING_INFINIBAND_TRANSPORT_MODE);
-	ASSERT (strcmp (transport_mode, "connected") == 0,
-	        "infiniband-verify-infiniband", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_INFINIBAND,
-	        NM_SETTING_INFINIBAND_SETTING_NAME,
-	        NM_SETTING_INFINIBAND_TRANSPORT_MODE);
+	g_assert (transport_mode);
+	g_assert_cmpstr (transport_mode, ==, "connected");
 
 	g_object_unref (connection);
 }
@@ -11955,7 +7830,6 @@ test_write_infiniband (void)
 	guint32 mtu = 65520;
 	char *uuid;
 	NMIPAddress *addr;
-	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
 
@@ -12007,81 +7881,37 @@ test_write_infiniband (void)
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "infiniband-write", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "infiniband-write", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
-
-	ASSERT (testfile != NULL,
-	        "infiniband-write", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_INFINIBAND,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_INFINIBAND, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "infiniband-write-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "infiniband-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "infiniband-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
 	g_object_unref (reread);
 }
 
-#define TEST_IFCFG_BOND_SLAVE_IB TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bond-slave-ib"
-
 static void
 test_read_bond_slave_ib (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_BOND_SLAVE_IB,
-	                                        NULL,
-	                                        NULL,
-	                                        NULL,
-	                                        &error);
-	g_test_assert_expected_messages();
-
-	ASSERT (connection != NULL,
-	        "bond-slave-read-ib", "unexpected failure reading %s", TEST_IFCFG_BOND_SLAVE_IB);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "bond-slave-read-ib", "failed to verify %s: %s", TEST_IFCFG_BOND_SLAVE_IB, error->message);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-slave-ib",
+	                                    NULL, NULL, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "bond-slave-read-ib", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_BOND_SLAVE_IB, NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
 
-	ASSERT (g_strcmp0 (nm_setting_connection_get_master (s_con), "bond0") == 0,
-	        "bond-slave-read-ib", "failed to verify %s: master is not bond0",
-	        TEST_IFCFG_BOND_SLAVE_IB);
+	g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "bond0");
 
-	ASSERT (g_strcmp0 (nm_setting_connection_get_slave_type (s_con), NM_SETTING_BOND_SETTING_NAME) == 0,
-	        "bond-slave-read-ib", "failed to verify %s: slave-type is not bond",
-	        TEST_IFCFG_BOND_SLAVE_IB);
+	g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BOND_SETTING_NAME);
 
 	g_object_unref (connection);
 }
@@ -12095,8 +7925,6 @@ test_write_bond_slave_ib (void)
 	NMSettingInfiniband *s_infiniband;
 	static const char *mac = "80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22";
 	char *uuid;
-	gboolean success;
-	GError *error = NULL;
 	char *testfile = NULL;
 
 	connection = nm_simple_connection_new ();
@@ -12111,8 +7939,8 @@ test_write_bond_slave_ib (void)
 	              NM_SETTING_CONNECTION_UUID, uuid,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
 	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_INFINIBAND_SETTING_NAME,
-				  NM_SETTING_CONNECTION_MASTER, "bond0",
-				  NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
+	              NM_SETTING_CONNECTION_MASTER, "bond0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
 	              NULL);
 	g_free (uuid);
 
@@ -12126,41 +7954,16 @@ test_write_bond_slave_ib (void)
 	              NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
 	              NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "bond-slave-write-ib", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	ASSERT (success == TRUE,
-	        "bond-slave-write-ib", "failed to write connection to disk: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	ASSERT (testfile != NULL,
-	        "bond-slave-write-ib", "didn't get ifcfg file path back after writing connection");
-
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    NULL,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, NULL, NULL);
 	unlink (testfile);
 
-	ASSERT (reread != NULL,
-	        "bond-slave-write-ib-reread", "failed to read %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_verify (reread, &error),
-	        "bond-slave-write-ib-reread-verify", "failed to verify %s: %s", testfile, error->message);
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "bond-slave-write-ib", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -12173,17 +7976,9 @@ test_read_bond_opts_mode_numeric (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingBond *s_bond;
-	gboolean success;
-	GError *error = NULL;
-
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-mode-numeric",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-mode-numeric",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "bond0");
 
@@ -12206,9 +8001,7 @@ static void
 test_read_dcb_basic (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingDcb *s_dcb;
-	gboolean success;
 	guint i;
 	guint expected_group_ids[8] = { 0, 0, 0, 0, 1, 1, 1, 0xF };
 	guint expected_group_bandwidths[8] = { 25, 0, 0, 75, 0, 0, 0, 0 };
@@ -12217,13 +8010,8 @@ test_read_dcb_basic (void)
 	guint expected_traffic_classes[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
 	gboolean expected_pfcs[8] = { TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE };
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	s_dcb = nm_connection_get_setting_dcb (connection);
 	g_assert (s_dcb);
@@ -12270,13 +8058,11 @@ static void
 test_write_dcb_basic (void)
 {
 	NMConnection *connection, *reread;
-	GError *error = NULL;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingDcb *s_dcb;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	gboolean success;
 	guint i;
 	char *uuid, *testfile;
 	const guint group_ids[8] = { 4, 0xF, 6, 0xF, 1, 7, 3, 0xF };
@@ -12336,29 +8122,16 @@ test_write_dcb_basic (void)
 		nm_setting_dcb_set_priority_traffic_class (s_dcb, i, traffic_classes[i]);
 	}
 
-	g_assert (nm_connection_verify (connection, &error));
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	g_assert_no_error (error);
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -12369,17 +8142,10 @@ static void
 test_read_dcb_default_app_priorities (void)
 {
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingDcb *s_dcb;
-	gboolean success;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-default-app-priorities",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-default-app-priorities",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	s_dcb = nm_connection_get_setting_dcb (connection);
 	g_assert (s_dcb);
@@ -12399,127 +8165,106 @@ test_read_dcb_default_app_priorities (void)
 static void
 test_read_dcb_bad_booleans (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*invalid DCB_PG_STRICT value*not all 0s and 1s*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-booleans",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-booleans",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "invalid boolean digit"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_short_booleans (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*DCB_PG_STRICT value*8 characters*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-booleans",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-booleans",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "boolean array must be 8 characters"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_bad_uints (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*invalid DCB_PG_UP2TC value*not 0 - 7*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-uints",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-uints",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "invalid uint digit"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_short_uints (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*DCB_PG_UP2TC value*8 characters*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-uints",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-uints",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "uint array must be 8 characters"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_bad_percent (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*invalid DCB_PG_PCT percentage value*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-percent",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-percent",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "invalid percent element"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_short_percent (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*invalid DCB_PG_PCT percentage list value*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-percent",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-percent",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "percent array must be 8 elements"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
 test_read_dcb_pgpct_not_100 (void)
 {
-	NMConnection *connection;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*DCB_PG_PCT percentages do not equal 100*");
-	connection = connection_from_file_test (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-pgpct-not-100",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
+	_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-pgpct-not-100",
+	                            NULL, TYPE_ETHERNET, &error);
 	g_test_assert_expected_messages ();
 
 	g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
 	g_assert (strstr (error->message, "invalid percentage sum"));
-	g_assert (connection == NULL);
-	g_clear_error (&error);
 }
 
 static void
@@ -12527,19 +8272,12 @@ test_read_fcoe_mode (gconstpointer user_data)
 {
 	const char *expected_mode = user_data;
 	NMConnection *connection;
-	GError *error = NULL;
 	NMSettingDcb *s_dcb;
-	gboolean success;
 	char *file;
 
 	file = g_strdup_printf (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-fcoe-%s", expected_mode);
-	connection = connection_from_file_test (file, NULL, TYPE_ETHERNET, NULL, &error);
+	connection = _connection_from_file (file, NULL, TYPE_ETHERNET, NULL);
 	g_free (file);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
 	s_dcb = nm_connection_get_setting_dcb (connection);
 	g_assert (s_dcb);
@@ -12561,7 +8299,6 @@ test_write_fcoe_mode (gconstpointer user_data)
 	NMSettingDcb *s_dcb;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	gboolean success;
 	char *uuid, *testfile;
 
 	connection = nm_simple_connection_new ();
@@ -12599,16 +8336,11 @@ test_write_fcoe_mode (gconstpointer user_data)
 	              NM_SETTING_DCB_APP_FCOE_MODE, expected_mode,
 	              NULL);
 
-	g_assert (nm_connection_verify (connection, &error));
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
-	g_assert (testfile);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	{
 		shvarFile *ifcfg = svOpenFile (testfile, &error);
@@ -12622,18 +8354,10 @@ test_write_fcoe_mode (gconstpointer user_data)
 		g_free (written_mode);
 	}
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile,
-	                                    NULL,
-	                                    TYPE_ETHERNET,
-	                                    NULL,
-	                                    &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 	unlink (testfile);
 
-	g_assert_no_error (error);
-	g_assert (reread);
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_object_unref (connection);
 	g_object_unref (reread);
@@ -12646,18 +8370,10 @@ test_read_team_master (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingTeam *s_team;
-	gboolean success;
-	GError *error = NULL;
 	const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "team0");
 
@@ -12682,7 +8398,6 @@ test_write_team_master (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
 	const char *escaped_expected_config = "\"{ \\\"device\\\": \\\"team0\\\", \\\"link_watch\\\": { \\\"name\\\": \\\"ethtool\\\" } }\"";
@@ -12735,13 +8450,9 @@ test_write_team_master (void)
 
 	nmtst_assert_connection_verifies_without_normalization (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -12758,21 +8469,11 @@ test_write_team_master (void)
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_ETHERNET,
-	                                    NULL, &error);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -12785,18 +8486,10 @@ test_read_team_port (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingTeamPort *s_team_port;
-	gboolean success;
-	GError *error = NULL;
 	const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -12818,7 +8511,6 @@ test_write_team_port (void)
 	NMSettingTeamPort *s_team_port;
 	NMSettingWired *s_wired;
 	char *uuid, *testfile = NULL, *val;
-	gboolean success;
 	GError *error = NULL;
 	const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
 	const char *escaped_expected_config = "\"{ \\\"p4p1\\\": { \\\"prio\\\": -10, \\\"sticky\\\": true } }\"";
@@ -12849,17 +8541,11 @@ test_write_team_port (void)
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	nmtst_assert_connection_verifies (connection);
 
-	/* Save the ifcfg */
-	success = writer_new_connection (connection,
-	                                 TEST_SCRATCH_DIR "/network-scripts/",
-	                                 &testfile,
-	                                 &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	_writer_new_connection (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        &testfile);
 
 	f = svOpenFile (testfile, &error);
 	g_assert_no_error (error);
@@ -12882,21 +8568,11 @@ test_write_team_port (void)
 	g_free (val);
 	svCloseFile (f);
 
-	/* reread will be normalized, so we must normalize connection too. */
-	nm_connection_normalize (connection, NULL, NULL, NULL);
-
-	/* re-read the connection for comparison */
-	reread = connection_from_file_test (testfile, NULL, TYPE_ETHERNET,
-	                                    NULL, &error);
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET,
+	                                NULL);
 	unlink (testfile);
-	g_assert_no_error (error);
-	g_assert (reread);
 
-	success = nm_connection_verify (reread, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_free (testfile);
 	g_object_unref (connection);
@@ -12908,17 +8584,9 @@ test_read_team_port_empty_config (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	gboolean success;
-	GError *error = NULL;
 
-	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-empty-config",
-	                                        NULL, TYPE_ETHERNET, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-empty-config",
+	                                    NULL, TYPE_ETHERNET, NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -13057,10 +8725,7 @@ test_read_vlan_trailing_spaces (void)
 	g_assert (strstr (contents, "DEVICE=\"vlan201\"  \n"));
 	g_free (contents);
 
-	connection = connection_from_file_test (testfile, NULL, TYPE_ETHERNET, NULL,
-	                                        &error);
-	g_assert_no_error (error);
-	g_assert (connection != NULL);
+	connection = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
 
 	s_vlan = nm_connection_get_setting_vlan (connection);
 	g_assert (s_vlan);
@@ -13068,29 +8733,20 @@ test_read_vlan_trailing_spaces (void)
 	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan201");
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "enccw0.0.fb00");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 201);
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
 
 
+#define TPATH "/settings/plugins/ifcfg-rh/"
+
 #define TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex"
 #define TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted"
 #define TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-hex"
 
-
-#define TEST_IFCFG_WIRED_STATIC           TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static"
-#define TEST_IFCFG_WIRED_STATIC_BOOTPROTO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-bootproto"
-
-#define TEST_IFCFG_WIRED_IPV4_MANUAL_1 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv4-manual-1"
-#define TEST_IFCFG_WIRED_IPV4_MANUAL_2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv4-manual-2"
-#define TEST_IFCFG_WIRED_IPV4_MANUAL_3 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv4-manual-3"
-#define TEST_IFCFG_WIRED_IPV4_MANUAL_4 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv4-manual-4"
-
 #define DEFAULT_HEX_PSK "7d308b11df1b4243b0f78e5f3fc68cdbb9a264ed0edf4c188edf329ff5b467f0"
 
-#define TPATH "/settings/plugins/ifcfg-rh/"
-
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -13115,9 +8771,10 @@ int main (int argc, char **argv)
 	g_test_add_data_func (TPATH "static-ip6-only-gw/::ffff:255.255.255.255", "::ffff:255.255.255.255", test_write_wired_static_ip6_only_gw);
 	g_test_add_func (TPATH "read-dns-options", test_read_dns_options);
 
-	test_read_wired_static (TEST_IFCFG_WIRED_STATIC, "System test-wired-static", TRUE);
-	test_read_wired_static (TEST_IFCFG_WIRED_STATIC_BOOTPROTO, "System test-wired-static-bootproto", FALSE);
-	test_read_wired_dhcp ();
+	nmtst_add_test_func (TPATH "read-static",           test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static",           "System test-wired-static",           GINT_TO_POINTER (TRUE));
+	nmtst_add_test_func (TPATH "read-static-bootproto", test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-bootproto", "System test-wired-static-bootproto", GINT_TO_POINTER (FALSE));
+
+	g_test_add_func (TPATH "read-dhcp", test_read_wired_dhcp);
 	g_test_add_func (TPATH "read-dhcp-plus-ip", test_read_wired_dhcp_plus_ip);
 	g_test_add_func (TPATH "read-shared-plus-ip", test_read_wired_shared_plus_ip);
 	g_test_add_func (TPATH "read-dhcp-send-hostname", test_read_write_wired_dhcp_send_hostname);
@@ -13125,183 +8782,159 @@ int main (int argc, char **argv)
 	g_test_add_func (TPATH "read-global-gateway-ignore", test_read_wired_global_gateway_ignore);
 	g_test_add_func (TPATH "read-obsolete-gateway-n", test_read_wired_obsolete_gateway_n);
 	g_test_add_func (TPATH "read-never-default", test_read_wired_never_default);
-	test_read_wired_defroute_no ();
-	test_read_wired_defroute_no_gatewaydev_yes ();
+	g_test_add_func (TPATH "read-defroute-no", test_read_wired_defroute_no);
+	g_test_add_func (TPATH "read-defroute-no-gatewaydev-yes", test_read_wired_defroute_no_gatewaydev_yes);
 	g_test_add_func (TPATH "routes/read-static", test_read_wired_static_routes);
-	test_read_wired_static_routes_legacy ();
-	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_1, "System test-wired-ipv4-manual-1");
-	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_2, "System test-wired-ipv4-manual-2");
-	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_3, "System test-wired-ipv4-manual-3");
-	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_4, "System test-wired-ipv4-manual-4");
-	test_read_wired_ipv6_manual ();
-	test_read_wired_ipv6_only (TEST_IFCFG_WIRED_IPV6_ONLY, "System test-wired-ipv6-only");
-	test_read_wired_ipv6_only (TEST_IFCFG_WIRED_IPV6_ONLY_1, "System test-wired-ipv6-only-1");
-	test_read_wired_dhcp6_only ();
-	test_read_onboot_no ();
-	test_read_noip ();
-	test_read_wired_8021x_peap_mschapv2 ();
-	test_read_wired_8021x_tls_secret_flags (TEST_IFCFG_WIRED_8021X_TLS_AGENT, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
-	test_read_wired_8021x_tls_secret_flags (TEST_IFCFG_WIRED_8021X_TLS_ALWAYS,
-	                                        NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	g_test_add_func (TPATH "routes/read-static-legacy", test_read_wired_static_routes_legacy);
+
+	nmtst_add_test_func (TPATH "wired/read/manual/1", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-1", "System test-wired-ipv4-manual-1");
+	nmtst_add_test_func (TPATH "wired/read/manual/2", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-2", "System test-wired-ipv4-manual-2");
+	nmtst_add_test_func (TPATH "wired/read/manual/3", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-3", "System test-wired-ipv4-manual-3");
+	nmtst_add_test_func (TPATH "wired/read/manual/4", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-4", "System test-wired-ipv4-manual-4");
+
+	g_test_add_func (TPATH "wired/ipv6-manual", test_read_wired_ipv6_manual);
+
+	nmtst_add_test_func (TPATH "wired-ipv6-only/0", test_read_wired_ipv6_only, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only",   "System test-wired-ipv6-only");
+	nmtst_add_test_func (TPATH "wired-ipv6-only/1", test_read_wired_ipv6_only, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only-1", "System test-wired-ipv6-only-1");
+
+	g_test_add_func (TPATH "wired/dhcpv6-only", test_read_wired_dhcp6_only);
+	g_test_add_func (TPATH "wired/autoip", test_read_wired_autoip);
+	g_test_add_func (TPATH "wired/onboot/no", test_read_onboot_no);
+	g_test_add_func (TPATH "wired/no-ip", test_read_noip);
+	g_test_add_func (TPATH "802-1x/peap/mschapv2", test_read_wired_8021x_peap_mschapv2);
+
+	nmtst_add_test_func (TPATH "test-wired-8021x-tls/agent",  test_read_wired_8021x_tls_secret_flags, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-tls-agent", GINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
+	nmtst_add_test_func (TPATH "test-wired-8021x-tls/always", test_read_wired_8021x_tls_secret_flags, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-tls-always", GINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED));
+
 	g_test_add_func (TPATH "802-1x/subj-matches", test_read_write_802_1X_subj_matches);
 	g_test_add_func (TPATH "802-1x/ttls-eapgtc", test_read_802_1x_ttls_eapgtc);
-	test_read_wired_aliases_good ();
-	test_read_wired_aliases_bad_1 ();
-	test_read_wired_aliases_bad_2 ();
-	test_read_wifi_open ();
-	test_read_wifi_open_auto ();
-	test_read_wifi_open_ssid_hex ();
-	test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX, "wifi-open-ssid-bad-hex-read");
-	test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX, "wifi-open-ssid-long-hex-read");
-	test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED, "wifi-open-ssid-long-quoted-read");
-	test_read_wifi_open_ssid_quoted ();
-	test_read_wifi_wep ();
-	test_read_wifi_wep_adhoc ();
-	test_read_wifi_wep_passphrase ();
-	test_read_wifi_wep_40_ascii ();
-	test_read_wifi_wep_104_ascii ();
-	test_read_wifi_leap ();
-	test_read_wifi_leap_secret_flags (TEST_IFCFG_WIFI_LEAP_AGENT, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
-	test_read_wifi_leap_secret_flags (TEST_IFCFG_WIFI_LEAP_ALWAYS,
-	                                  NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
-	test_read_wifi_wpa_psk ();
-	test_read_wifi_wpa_psk_2 ();
-	test_read_wifi_wpa_psk_unquoted ();
-	test_read_wifi_wpa_psk_unquoted2 ();
-	test_read_wifi_wpa_psk_adhoc ();
-	test_read_wifi_wpa_psk_hex ();
-	test_read_wifi_dynamic_wep_leap ();
-	test_read_wifi_wpa_eap_tls ();
-	test_read_wifi_wpa_eap_ttls_tls ();
-	test_read_wifi_wep_eap_ttls_chap ();
+	g_test_add_func (TPATH "wired/read/aliases", test_read_wired_aliases_good);
+	g_test_add_func (TPATH "wired/read/aliases/bad1", test_read_wired_aliases_bad_1);
+	g_test_add_func (TPATH "wired/read/aliases/bad2", test_read_wired_aliases_bad_2);
+	g_test_add_func (TPATH "wifi/read/open", test_read_wifi_open);
+	g_test_add_func (TPATH "wifi/read/open/auto", test_read_wifi_open_auto);
+	g_test_add_func (TPATH "wifi/read/open/hex-ssid", test_read_wifi_open_ssid_hex);
+	g_test_add_data_func (TPATH "wifi/read/open-ssid/bad-hex", TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX, test_read_wifi_open_ssid_bad);
+	g_test_add_data_func (TPATH "wifi/read/open-ssid/long-hex", TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX, test_read_wifi_open_ssid_bad);
+	g_test_add_data_func (TPATH "wifi/read/open-ssid/long-quoted", TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED, test_read_wifi_open_ssid_bad);
+	g_test_add_func (TPATH "wifi/read/open/quoted-ssid", test_read_wifi_open_ssid_quoted);
+	g_test_add_func (TPATH "wifi/read/wep", test_read_wifi_wep);
+	g_test_add_func (TPATH "wifi/read/wep/adhoc", test_read_wifi_wep_adhoc);
+	g_test_add_func (TPATH "wifi/read/wep/passphrase", test_read_wifi_wep_passphrase);
+	g_test_add_func (TPATH "wifi/read/wep/40-ascii", test_read_wifi_wep_40_ascii);
+	g_test_add_func (TPATH "wifi/read/wep/104-ascii", test_read_wifi_wep_104_ascii);
+	g_test_add_func (TPATH "wifi/read/leap", test_read_wifi_leap);
+
+	nmtst_add_test_func (TPATH "wifi-leap-secret-flags/agent", test_read_wifi_leap_secret_flags, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-leap-agent",      GINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
+	nmtst_add_test_func (TPATH "wifi-leap-secret-flags/ask",   test_read_wifi_leap_secret_flags, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-leap-always-ask", GINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED));
+
+	g_test_add_func (TPATH "wifi/read/wpa-psk", test_read_wifi_wpa_psk);
+	g_test_add_func (TPATH "wifi/read/wpa-psk/2", test_read_wifi_wpa_psk_2);
+	g_test_add_func (TPATH "wifi/read/wpa-psk/unquoted", test_read_wifi_wpa_psk_unquoted);
+	g_test_add_func (TPATH "wifi/read/wpa-psk/unquoted2", test_read_wifi_wpa_psk_unquoted2);
+	g_test_add_func (TPATH "wifi/read/wpa-psk/adhoc", test_read_wifi_wpa_psk_adhoc);
+	g_test_add_func (TPATH "wifi/read/wpa-psk/hex", test_read_wifi_wpa_psk_hex);
+	g_test_add_func (TPATH "wifi/read/dynamic-wep/leap", test_read_wifi_dynamic_wep_leap);
+	g_test_add_func (TPATH "wifi/read/wpa/eap/tls", test_read_wifi_wpa_eap_tls);
+	g_test_add_func (TPATH "wifi/read/wpa/eap/ttls/tls", test_read_wifi_wpa_eap_ttls_tls);
+	g_test_add_func (TPATH "wifi/read/dynamic-wep/eap/ttls/chap", test_read_wifi_wep_eap_ttls_chap);
 	g_test_add_func (TPATH "wifi/read-band-a", test_read_wifi_band_a);
 	g_test_add_func (TPATH "wifi/read-band-a-channel-mismatch", test_read_wifi_band_a_channel_mismatch);
 	g_test_add_func (TPATH "wifi/read-band-bg-channel-mismatch", test_read_wifi_band_bg_channel_mismatch);
 	g_test_add_func (TPATH "wifi/read-hidden", test_read_wifi_hidden);
 
-	{
-		static const WifiMacRandomData test_wifi_mac_random[] = {
-			{ "always",  NM_SETTING_MAC_RANDOMIZATION_ALWAYS,  "always" },
-			{ "never",   NM_SETTING_MAC_RANDOMIZATION_NEVER,   "never" },
-			{ "default", NM_SETTING_MAC_RANDOMIZATION_DEFAULT, "default" },
-			{ "missing", NM_SETTING_MAC_RANDOMIZATION_NEVER,   "never" },
-		};
-		int i;
-
-		for (i = 0; i < G_N_ELEMENTS (test_wifi_mac_random); i++) {
-			char *tpath;
-
-			tpath = g_strdup_printf (TPATH "wifi/read-mac-random-%s", test_wifi_mac_random[i].name);
-			g_test_add_data_func_full (tpath,
-			                           g_memdup (&test_wifi_mac_random[i], sizeof (test_wifi_mac_random[i])),
-			                           test_read_wifi_mac_random,
-			                           g_free);
-			g_free (tpath);
-
-			tpath = g_strdup_printf (TPATH "wifi/write-mac-random-%s", test_wifi_mac_random[i].name);
-			g_test_add_data_func_full (tpath,
-			                           g_memdup (&test_wifi_mac_random[i], sizeof (test_wifi_mac_random[i])),
-			                           test_write_wifi_mac_random,
-			                           g_free);
-			g_free (tpath);
-		}
-	}
+	nmtst_add_test_func (TPATH "wifi/read-mac-random-always",   test_read_wifi_mac_random,  "always",  GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_ALWAYS));
+	nmtst_add_test_func (TPATH "wifi/read-mac-random-never",    test_read_wifi_mac_random,  "never",   GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_NEVER));
+	nmtst_add_test_func (TPATH "wifi/read-mac-random-default",  test_read_wifi_mac_random,  "default", GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_DEFAULT));
+	nmtst_add_test_func (TPATH "wifi/read-mac-random-missing",  test_read_wifi_mac_random,  "missing", GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_NEVER));
+
+	nmtst_add_test_func (TPATH "wifi/write-mac-random-always",  test_write_wifi_mac_random, "always",  GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_ALWAYS),  "always");
+	nmtst_add_test_func (TPATH "wifi/write-mac-random-never",   test_write_wifi_mac_random, "never",   GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_NEVER),   "never");
+	nmtst_add_test_func (TPATH "wifi/write-mac-random-default", test_write_wifi_mac_random, "default", GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_DEFAULT), "default");
+	nmtst_add_test_func (TPATH "wifi/write-mac-random-missing", test_write_wifi_mac_random, "missing", GINT_TO_POINTER (NM_SETTING_MAC_RANDOMIZATION_NEVER),   "never");
 
-	test_read_wired_qeth_static ();
-	test_read_wired_ctc_static ();
-	test_read_wifi_wep_no_keys ();
-	test_read_permissions ();
-	test_read_wifi_wep_agent_keys ();
-	test_read_infiniband ();
-	test_read_vlan_interface ();
+	g_test_add_func (TPATH "wifi/read/wep-no-keys", test_read_wifi_wep_no_keys);
+	g_test_add_func (TPATH "wifi/read/wep-agent-keys", test_read_wifi_wep_agent_keys);
+	g_test_add_func (TPATH "infiniband/read", test_read_infiniband);
+	g_test_add_func (TPATH "vlan/read", test_read_vlan_interface);
 	g_test_add_func (TPATH "vlan/read-flags-1", test_read_vlan_flags_1);
 	g_test_add_func (TPATH "vlan/read-flags-2", test_read_vlan_flags_2);
-	test_read_vlan_only_vlan_id ();
-	test_read_vlan_only_device ();
-	g_test_add_func (TPATH "vlan/physdev", test_read_vlan_physdev);
-	g_test_add_func (TPATH "vlan/reorder-hdr-1", test_read_vlan_reorder_hdr_1);
-	g_test_add_func (TPATH "wired/read-wake-on-lan", test_read_wired_wake_on_lan);
-
-	test_write_wired_static ();
-	test_write_wired_static_ip6_only ();
-	test_write_wired_static_routes ();
-	test_read_write_static_routes_legacy ();
-	test_write_wired_dhcp ();
+	g_test_add_func (TPATH "vlan/read/only-vlanid", test_read_vlan_only_vlan_id);
+	g_test_add_func (TPATH "vlan/read/only-device", test_read_vlan_only_device);
+	g_test_add_func (TPATH "vlan/read/physdev", test_read_vlan_physdev);
+	g_test_add_func (TPATH "vlan/read/reorder-hdr-1", test_read_vlan_reorder_hdr_1);
+	g_test_add_func (TPATH "vlan/read/reorder-hdr-2", test_read_vlan_reorder_hdr_2);
+	g_test_add_func (TPATH "wired/read/read-wake-on-lan", test_read_wired_wake_on_lan);
+
+	g_test_add_func (TPATH "wired/write/static", test_write_wired_static);
+	g_test_add_func (TPATH "wired/write/static-ip6-only", test_write_wired_static_ip6_only);
+	g_test_add_func (TPATH "wired/write-static-routes", test_write_wired_static_routes);
+	g_test_add_func (TPATH "wired/read-write-static-routes-legacy", test_read_write_static_routes_legacy);
+	g_test_add_func (TPATH "wired/write/dhcp", test_write_wired_dhcp);
 	g_test_add_func (TPATH "wired/write-dhcp-plus-ip", test_write_wired_dhcp_plus_ip);
-	test_write_wired_dhcp_8021x_peap_mschapv2 ();
-	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
-	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED);
-	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
-	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE);
-	test_write_wired_aliases ();
+	g_test_add_func (TPATH "wired/write/dhcp-8021x-peap-mschapv2", test_write_wired_dhcp_8021x_peap_mschapv2);
+
+#define _add_test_write_wired_8021x_tls(testpath, scheme, flags) \
+	nmtst_add_test_func (testpath, test_write_wired_8021x_tls, GINT_TO_POINTER (scheme), GINT_TO_POINTER (flags))
+	_add_test_write_wired_8021x_tls (TPATH "wired-8021x-tls/1", NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
+	_add_test_write_wired_8021x_tls (TPATH "wired-8021x-tls/2", NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	_add_test_write_wired_8021x_tls (TPATH "wired-8021x-tls/3", NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	_add_test_write_wired_8021x_tls (TPATH "wired-8021x-tls/4", NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE);
+
+	g_test_add_func (TPATH "wired/write-aliases", test_write_wired_aliases);
 	g_test_add_func (TPATH "ipv4/write-static-addresses-GATEWAY", test_write_gateway);
 	g_test_add_func (TPATH "wired/write-wake-on-lan", test_write_wired_wake_on_lan);
-	test_write_wifi_open ();
-	test_write_wifi_open_hex_ssid ();
-	test_write_wifi_wep ();
-	test_write_wifi_wep_adhoc ();
-	test_write_wifi_wep_passphrase ();
-	test_write_wifi_wep_40_ascii ();
-	test_write_wifi_wep_104_ascii ();
-	test_write_wifi_leap ();
-	test_write_wifi_leap_secret_flags (NM_SETTING_SECRET_FLAG_AGENT_OWNED);
-	test_write_wifi_leap_secret_flags (NM_SETTING_SECRET_FLAG_NOT_SAVED);
-	test_write_wifi_leap_secret_flags (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
-	test_write_wifi_wpa_psk ("Test Write Wifi WPA PSK",
-	                         "wifi-wpa-psk-write",
-	                         FALSE,
-	                         TRUE,
-	                         FALSE,
-	                         DEFAULT_HEX_PSK);
-	test_write_wifi_wpa_psk ("Test Write Wifi WPA2 PSK",
-	                         "wifi-wpa2-psk-write",
-	                         FALSE,
-	                         FALSE,
-	                         TRUE,
-	                         DEFAULT_HEX_PSK);
-	test_write_wifi_wpa_psk ("Test Write Wifi WPA WPA2 PSK",
-	                         "wifi-wpa-wpa2-psk-write",
-	                         FALSE,
-	                         TRUE,
-	                         TRUE,
-	                         DEFAULT_HEX_PSK);
-	test_write_wifi_wpa_psk ("Test Write Wifi WEP WPA WPA2 PSK",
-	                         "wifi-wep-wpa-wpa2-psk-write",
-	                         TRUE,
-	                         TRUE,
-	                         TRUE,
-	                         DEFAULT_HEX_PSK);
-	test_write_wifi_wpa_psk ("Test Write Wifi WPA WPA2 PSK Passphrase",
-	                         "wifi-wpa-wpa2-psk-passphrase-write",
-	                         FALSE,
-	                         TRUE,
-	                         TRUE,
-	                         "really insecure passphrase04!");
-	test_write_wifi_wpa_psk ("Test Write Wifi WPA WPA2 PSK Passphrase Special Chars",
-	                         "wifi-wpa-wpa2-psk-passphrase-write-spec-chars",
-	                         FALSE,
-	                         TRUE,
-	                         TRUE,
-	                         "blah`oops\"grr'$*@~!%\\");
-	test_write_wifi_wpa_psk_adhoc ();
-	test_write_wifi_wpa_eap_tls ();
-	test_write_wifi_wpa_eap_ttls_tls ();
-	test_write_wifi_wpa_eap_ttls_mschapv2 ();
-	test_write_wifi_dynamic_wep_leap ();
-	test_write_wifi_wpa_then_open ();
-	test_write_wifi_wpa_then_wep_with_perms ();
+	g_test_add_func (TPATH "wifi/write/open", test_write_wifi_open);
+	g_test_add_func (TPATH "wifi/write/open/hex-ssid", test_write_wifi_open_hex_ssid);
+	g_test_add_func (TPATH "wifi/write/wep", test_write_wifi_wep);
+	g_test_add_func (TPATH "wifi/write/wep/adhoc", test_write_wifi_wep_adhoc);
+	g_test_add_func (TPATH "wifi/write/wep/passphrase", test_write_wifi_wep_passphrase);
+	g_test_add_func (TPATH "wifi/write/wep/40-ascii", test_write_wifi_wep_40_ascii);
+	g_test_add_func (TPATH "wifi/write/wep/104-ascii", test_write_wifi_wep_104_ascii);
+	g_test_add_func (TPATH "wifi/write/leap", test_write_wifi_leap);
+	g_test_add_data_func (TPATH "wifi/write/leap/flags/agent",
+	                      GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED),
+	                      test_write_wifi_leap_secret_flags);
+	g_test_add_data_func (TPATH "wifi/write/leap/flags/not-saved",
+	                      GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_NOT_SAVED),
+	                      test_write_wifi_leap_secret_flags);
+	g_test_add_data_func (TPATH "wifi/write/leap/flags/agent-and-not-saved",
+	                      GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED),
+	                      test_write_wifi_leap_secret_flags);
+
+#define _add_test_write_wifi_wpa_psk(testpath, name, wep_group, wpa, wpa2, psk) \
+	nmtst_add_test_func (testpath, test_write_wifi_wpa_psk, name, GPOINTER_TO_INT (wep_group), GPOINTER_TO_INT (wpa), GPOINTER_TO_INT (wpa2), psk)
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wpa-psk-write",                            "Test Write Wifi WPA PSK",                               FALSE, TRUE,  FALSE, DEFAULT_HEX_PSK);
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wpa2-psk-write",                           "Test Write Wifi WPA2 PSK",                              FALSE, FALSE, TRUE,  DEFAULT_HEX_PSK);
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wpa-wpa2-psk-write",                       "Test Write Wifi WPA WPA2 PSK",                          FALSE, TRUE,  TRUE,  DEFAULT_HEX_PSK);
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wep-wpa-wpa2-psk-write",                   "Test Write Wifi WEP WPA WPA2 PSK",                      TRUE,  TRUE,  TRUE,  DEFAULT_HEX_PSK);
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wpa-wpa2-psk-passphrase-write",            "Test Write Wifi WPA WPA2 PSK Passphrase",               FALSE, TRUE,  TRUE,  "really insecure passphrase04!");
+	_add_test_write_wifi_wpa_psk (TPATH "wifi-wpa-psk/wpa-wpa2-psk-passphrase-write-spec-chars", "Test Write Wifi WPA WPA2 PSK Passphrase Special Chars", FALSE, TRUE,  TRUE,  "blah`oops\"grr'$*@~!%\\");
+
+	g_test_add_func (TPATH "wifi/write/wpa/psk/adhoc", test_write_wifi_wpa_psk_adhoc);
+	g_test_add_func (TPATH "wifi/write/wpa/eap/tls", test_write_wifi_wpa_eap_tls);
+	g_test_add_func (TPATH "wifi/write/wpa/eap/ttls/tls", test_write_wifi_wpa_eap_ttls_tls);
+	g_test_add_func (TPATH "wifi/write/wpa/eap/ttls/mschapv2", test_write_wifi_wpa_eap_ttls_mschapv2);
+	g_test_add_func (TPATH "wifi/write/dynamic-wep/leap", test_write_wifi_dynamic_wep_leap);
+	g_test_add_func (TPATH "wifi/write-wpa-then-open", test_write_wifi_wpa_then_open);
+	g_test_add_func (TPATH "wifi/write-wpa-then-wep-with-perms", test_write_wifi_wpa_then_wep_with_perms);
 	g_test_add_func (TPATH "wifi/write-hidden", test_write_wifi_hidden);
 	g_test_add_func (TPATH "wifi/write-band-a", test_write_wifi_band_a);
-	test_write_wired_qeth_dhcp ();
-	test_write_wired_ctc_dhcp ();
-	test_write_permissions ();
-	test_write_wifi_wep_agent_keys ();
-	test_write_infiniband ();
-	test_write_vlan ();
+
+	g_test_add_func (TPATH "s390/read-qeth-static", test_read_wired_qeth_static);
+	g_test_add_func (TPATH "s390/write-qeth-dhcp", test_write_wired_qeth_dhcp);
+	g_test_add_func (TPATH "s390/read-ctc-static", test_read_wired_ctc_static);
+	g_test_add_func (TPATH "s390/write-ctc-dhcp", test_write_wired_ctc_dhcp);
+
+	g_test_add_func (TPATH "permissions/read", test_read_permissions);
+	g_test_add_func (TPATH "permissions/write", test_write_permissions);
+	g_test_add_func (TPATH "wifi/write-wep-agent-keys", test_write_wifi_wep_agent_keys);
+	g_test_add_func (TPATH "infiniband/write", test_write_infiniband);
+	g_test_add_func (TPATH "vlan/write", test_write_vlan);
 	g_test_add_func (TPATH "vlan/write-flags", test_write_vlan_flags);
-	test_write_vlan_only_vlanid ();
+	g_test_add_func (TPATH "vlan/write-only-vlanid", test_write_vlan_only_vlanid);
 	g_test_add_func (TPATH "vlan/write-vlan-reorder-hdr", test_write_vlan_reorder_hdr);
-	test_write_ethernet_missing_ipv6 ();
+	g_test_add_func (TPATH "wired/write-missing-ipv6", test_write_ethernet_missing_ipv6);
 	g_test_add_func (TPATH "write-dns-options", test_write_dns_options);
 
 	/* iSCSI / ibft */
@@ -13324,20 +8957,20 @@ int main (int argc, char **argv)
 	g_test_add_data_func (TPATH "fcoe/write-vn2vn", (gpointer) NM_SETTING_DCB_FCOE_MODE_VN2VN, test_write_fcoe_mode);
 
 	/* bonding */
-	test_read_bond_main ();
-	test_read_bond_slave ();
-	test_read_bond_slave_ib ();
-	test_write_bond_main ();
-	test_write_bond_slave ();
-	test_write_bond_slave_ib ();
+	g_test_add_func (TPATH "bond/read-master", test_read_bond_main);
+	g_test_add_func (TPATH "bond/read-slave", test_read_bond_slave);
+	g_test_add_func (TPATH "bond/read-slave-ib", test_read_bond_slave_ib);
+	g_test_add_func (TPATH "bond/write-master", test_write_bond_main);
+	g_test_add_func (TPATH "bond/write-slave", test_write_bond_slave);
+	g_test_add_func (TPATH "bond/write-slave-ib", test_write_bond_slave_ib);
 	g_test_add_func (TPATH "bond/bonding-opts-numeric-mode", test_read_bond_opts_mode_numeric);
 
 	/* bridging */
-	test_read_bridge_main ();
-	test_write_bridge_main ();
-	test_read_bridge_component ();
-	test_write_bridge_component ();
-	test_read_bridge_missing_stp ();
+	g_test_add_func (TPATH "bridge/read-master", test_read_bridge_main);
+	g_test_add_func (TPATH "bridge/write-master", test_write_bridge_main);
+	g_test_add_func (TPATH "bridge/read-component", test_read_bridge_component);
+	g_test_add_func (TPATH "bridge/write-component", test_write_bridge_component);
+	g_test_add_func (TPATH "bridge/read-missing-stp", test_read_bridge_missing_stp);
 
 	/* Team */
 	g_test_add_func (TPATH "team/read-master", test_read_team_master);
@@ -13347,10 +8980,10 @@ int main (int argc, char **argv)
 	g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config);
 
 	/* Stuff we expect to fail for now */
-	test_write_wired_pppoe ();
-	test_write_vpn ();
-	test_write_mobile_broadband (TRUE);
-	test_write_mobile_broadband (FALSE);
+	g_test_add_func (TPATH "pppoe/write-wired", test_write_wired_pppoe);
+	g_test_add_func (TPATH "vpn/write", test_write_vpn);
+	g_test_add_data_func (TPATH "wwan/write-gsm", GUINT_TO_POINTER (TRUE), test_write_mobile_broadband);
+	g_test_add_data_func (TPATH "wwan/write-cdma", GUINT_TO_POINTER (FALSE), test_write_mobile_broadband);
 
 	return g_test_run ();
 }
diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c
index 599e3a49..fda900b2 100644
--- a/src/settings/plugins/ifcfg-rh/utils.c
+++ b/src/settings/plugins/ifcfg-rh/utils.c
@@ -18,17 +18,15 @@
  * (C) Copyright 2008 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "utils.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-core-internal.h"
-#include "nm-macros-internal.h"
 #include "NetworkManagerUtils.h"
-
-#include "utils.h"
 #include "shvar.h"
 
 /*
@@ -214,8 +212,8 @@ utils_get_ifcfg_name (const char *file, gboolean only_ifcfg)
 
 #define MATCH_TAG_AND_RETURN(name, TAG) \
 	G_STMT_START { \
-		if (strncmp (name, TAG, STRLEN (TAG)) == 0) { \
-			name += STRLEN (TAG); \
+		if (strncmp (name, TAG, NM_STRLEN (TAG)) == 0) { \
+			name += NM_STRLEN (TAG); \
 			if (name[0] == '\0') \
 				return NULL; \
 			else \
@@ -436,8 +434,8 @@ utils_detect_ifcfg_path (const char *path, gboolean only_ifcfg)
 
 	base = g_path_get_basename (path);
 
-	if (strncmp (base, IFCFG_TAG, STRLEN (IFCFG_TAG)) == 0) {
-		if (base[STRLEN (IFCFG_TAG)] == '\0')
+	if (strncmp (base, IFCFG_TAG, NM_STRLEN (IFCFG_TAG)) == 0) {
+		if (base[NM_STRLEN (IFCFG_TAG)] == '\0')
 			return NULL;
 		if (utils_is_ifcfg_alias_file (base, NULL)) {
 			ifcfg = g_strdup (path);
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 5770d668..e7d64379 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -18,7 +18,9 @@
  * Copyright 2009 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "writer.h"
 
 #include <string.h>
 #include <sys/types.h>
@@ -30,26 +32,24 @@
 #include <unistd.h>
 #include <stdio.h>
 
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-8021x.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-pppoe.h>
-#include <nm-setting-vlan.h>
-#include <nm-setting-team.h>
-#include <nm-setting-team-port.h>
+#include "nm-setting-connection.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-team.h"
+#include "nm-setting-team-port.h"
 #include "nm-core-internal.h"
-#include <nm-utils.h>
+#include "nm-utils.h"
 #include "nm-core-internal.h"
-#include "nm-macros-internal.h"
+#include "NetworkManagerUtils.h"
 
-#include "nm-default.h"
 #include "common.h"
 #include "shvar.h"
 #include "reader.h"
-#include "writer.h"
 #include "utils.h"
 #include "crypto.h"
 
@@ -144,11 +144,15 @@ write_secret_file (const char *path,
 	char *tmppath;
 	int fd = -1, written;
 	gboolean success = FALSE;
+	mode_t saved_umask;
 
 	tmppath = g_malloc0 (strlen (path) + 10);
 	memcpy (tmppath, path, strlen (path));
 	strcat (tmppath, ".XXXXXX");
 
+	/* Only readable by root */
+	saved_umask = umask (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
 	errno = 0;
 	fd = mkstemp (tmppath);
 	if (fd < 0) {
@@ -158,17 +162,6 @@ write_secret_file (const char *path,
 		goto out;
 	}
 
-	/* Only readable by root */
-	errno = 0;
-	if (fchmod (fd, S_IRUSR | S_IWUSR)) {
-		close (fd);
-		unlink (tmppath);
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
-		             "Could not set permissions for temporary file '%s': %d",
-		             path, errno);
-		goto out;
-	}
-
 	errno = 0;
 	written = write (fd, data, len);
 	if (written != len) {
@@ -193,6 +186,7 @@ write_secret_file (const char *path,
 	success = TRUE;
 
 out:
+	umask (saved_umask);
 	g_free (tmppath);
 	return success;
 }
@@ -987,7 +981,22 @@ write_wireless_setting (NMConnection *connection,
 	}
 
 	svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE);
-	svSetValue (ifcfg, "POWERSAVE", nm_setting_wireless_get_powersave (s_wireless) ? "yes" : NULL, TRUE);
+
+	switch (nm_setting_wireless_get_powersave (s_wireless)) {
+	case NM_SETTING_WIRELESS_POWERSAVE_IGNORE:
+		svSetValue (ifcfg, "POWERSAVE", "ignore", TRUE);
+		break;
+	case NM_SETTING_WIRELESS_POWERSAVE_DISABLE:
+		svSetValue (ifcfg, "POWERSAVE", "disable", TRUE);
+		break;
+	case NM_SETTING_WIRELESS_POWERSAVE_ENABLE:
+		svSetValue (ifcfg, "POWERSAVE", "enable", TRUE);
+		break;
+	default:
+	case NM_SETTING_WIRELESS_POWERSAVE_DEFAULT:
+		svSetValue (ifcfg, "POWERSAVE", NULL, TRUE);
+		break;
+	}
 
 	svSetValue (ifcfg, "MAC_ADDRESS_RANDOMIZATION", NULL, TRUE);
 	switch (nm_setting_wireless_get_mac_address_randomization (s_wireless)) {
@@ -1252,6 +1261,8 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired,
 	NMSettingConnection *s_con;
 	char *tmp;
 	guint32 vlan_flags = 0;
+	gsize s_buf_len;
+	char s_buf[50], *s_buf_ptr;
 
 	s_con = nm_connection_get_setting_connection (connection);
 	if (!s_con) {
@@ -1284,9 +1295,14 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired,
 
 	svSetValue (ifcfg, "GVRP", vlan_flags & NM_VLAN_FLAG_GVRP ? "yes" : "no", FALSE);
 
-	svSetValue (ifcfg, "VLAN_FLAGS", NULL, FALSE);
-	if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
-		svSetValue (ifcfg, "VLAN_FLAGS", "LOOSE_BINDING", FALSE);
+	nm_utils_strbuf_init (s_buf, &s_buf_ptr, &s_buf_len);
+
+	if (NM_FLAGS_HAS (vlan_flags, NM_VLAN_FLAG_LOOSE_BINDING))
+		nm_utils_strbuf_append_str (&s_buf_ptr, &s_buf_len, "LOOSE_BINDING");
+	if (!NM_FLAGS_HAS (vlan_flags, NM_VLAN_FLAG_REORDER_HEADERS))
+		nm_utils_strbuf_append (&s_buf_ptr, &s_buf_len, "%sNO_REORDER_HDR", s_buf[0] ? "," : "");
+
+	svSetValue (ifcfg, "VLAN_FLAGS", s_buf, FALSE);
 
 	svSetValue (ifcfg, "MVRP", vlan_flags & NM_VLAN_FLAG_MVRP ? "yes" : "no", FALSE);
 
@@ -1947,7 +1963,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	gint32 j;
 	guint32 i, n, num;
 	gint64 route_metric;
-	int dhcp_timeout;
+	int timeout;
 	GString *searches;
 	gboolean success = FALSE;
 	gboolean fake_ip4 = FALSE;
@@ -2156,8 +2172,8 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 		if (value)
 			svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
 
-		dhcp_timeout = nm_setting_ip4_config_get_dhcp_timeout (NM_SETTING_IP4_CONFIG (s_ip4));
-		tmp = dhcp_timeout ? g_strdup_printf ("%d", dhcp_timeout) : NULL;
+		timeout = nm_setting_ip_config_get_dhcp_timeout (s_ip4);
+		tmp = timeout ? g_strdup_printf ("%d", timeout) : NULL;
 		svSetValue (ifcfg, "IPV4_DHCP_TIMEOUT", tmp, FALSE);
 		g_free (tmp);
 	}
@@ -2248,6 +2264,16 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 			goto out;
 	}
 
+	timeout = nm_setting_ip_config_get_dad_timeout (s_ip4);
+	if (timeout < 0)
+		svSetValue (ifcfg, "ARPING_WAIT", NULL, FALSE);
+	else if (timeout == 0)
+		svSetValue (ifcfg, "ARPING_WAIT", "0", FALSE);
+	else {
+		/* Round the value up to next integer */
+		svSetValueInt64 (ifcfg, "ARPING_WAIT", (timeout - 1) / 1000 + 1);
+	}
+
 	success = TRUE;
 
 out:
diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
index 51ff9da6..bf8b9a42 100644
--- a/src/settings/plugins/ifnet/connection_parser.c
+++ b/src/settings/plugins/ifnet/connection_parser.c
@@ -19,7 +19,7 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
@@ -27,7 +27,6 @@
 #include <errno.h>
 
 #include "nm-settings-plugin.h"
-#include "nm-default.h"
 #include "nm-core-internal.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c
index ee66ff53..cad34f06 100644
--- a/src/settings/plugins/ifnet/net_parser.c
+++ b/src/settings/plugins/ifnet/net_parser.c
@@ -19,15 +19,14 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include <nm-settings-plugin.h>
-#include "nm-default.h"
+#include "nm-settings-plugin.h"
 
 #include "plugin.h"
 #include "nm-platform.h"
diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c
index 1c72e0b2..1944e478 100644
--- a/src/settings/plugins/ifnet/net_utils.c
+++ b/src/settings/plugins/ifnet/net_utils.c
@@ -19,17 +19,17 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <nm-utils.h>
+
+#include "nm-utils.h"
 #include "NetworkManagerUtils.h"
-#include <nm-settings-plugin.h>
+#include "nm-settings-plugin.h"
 #include "nm-config.h"
-#include "nm-default.h"
 #include "net_utils.h"
 #include "wpa_parser.h"
 #include "net_parser.h"
@@ -712,7 +712,7 @@ _has_prefix_impl (char *str, const char *prefix, gsize prefix_len)
 	} while (g_ascii_isspace (str[0]));
 	return str;
 }
-#define _has_prefix(STR, PREFIX) _has_prefix_impl (STR, PREFIX, STRLEN (PREFIX))
+#define _has_prefix(STR, PREFIX) _has_prefix_impl (STR, PREFIX, NM_STRLEN (PREFIX))
 
 void
 get_dhcp_hostname_and_client_id (char **hostname, char **client_id)
diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.c b/src/settings/plugins/ifnet/nm-ifnet-connection.c
index 450fe931..84515519 100644
--- a/src/settings/plugins/ifnet/nm-ifnet-connection.c
+++ b/src/settings/plugins/ifnet/nm-ifnet-connection.c
@@ -19,16 +19,16 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <glib/gstdio.h>
-#include <nm-dbus-interface.h>
-#include <nm-utils.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-settings-connection.h>
-#include <nm-settings-plugin.h>
-#include "nm-default.h"
+
+#include "nm-dbus-interface.h"
+#include "nm-utils.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-settings-connection.h"
+#include "nm-settings-plugin.h"
 #include "nm-ifnet-connection.h"
 #include "connection_parser.h"
 #include "net_parser.h"
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
index b670cdac..a0676cf8 100644
--- a/src/settings/plugins/ifnet/plugin.c
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -20,14 +20,14 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
 #include <gmodule.h>
 
-#include <nm-utils.h>
-#include <nm-setting-connection.h>
+#include "nm-utils.h"
+#include "nm-setting-connection.h"
 
 #include "nm-default.h"
 #include "nm-dbus-interface.h"
diff --git a/src/settings/plugins/ifnet/tests/test-ifnet.c b/src/settings/plugins/ifnet/tests/test-ifnet.c
index 96fb5dd3..c870152b 100644
--- a/src/settings/plugins/ifnet/tests/test-ifnet.c
+++ b/src/settings/plugins/ifnet/tests/test-ifnet.c
@@ -20,16 +20,16 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <nm-utils.h>
 
-#include "nm-default.h"
+#include "nm-utils.h"
+
 #include "nm-linux-platform.h"
 
 #include "net_parser.h"
diff --git a/src/settings/plugins/ifnet/wpa_parser.c b/src/settings/plugins/ifnet/wpa_parser.c
index 9f228d0b..501bca7a 100644
--- a/src/settings/plugins/ifnet/wpa_parser.c
+++ b/src/settings/plugins/ifnet/wpa_parser.c
@@ -19,12 +19,12 @@
  * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
-#include <nm-settings-plugin.h>
-#include "nm-default.h"
+
+#include "nm-settings-plugin.h"
 #include "wpa_parser.h"
 #include "net_parser.h"
 #include "net_utils.h"
diff --git a/src/settings/plugins/ifupdown/interface_parser.c b/src/settings/plugins/ifupdown/interface_parser.c
index 4606f5ab..be7d387d 100644
--- a/src/settings/plugins/ifupdown/interface_parser.c
+++ b/src/settings/plugins/ifupdown/interface_parser.c
@@ -20,16 +20,17 @@
  * (C) Copyright 2004 Tom Parker
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include "interface_parser.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wordexp.h>
 #include <libgen.h>
+
 #include "nm-utils.h"
-#include "nm-default.h"
 
 if_block* first;
 if_block* last;
diff --git a/src/settings/plugins/ifupdown/nm-ifupdown-connection.c b/src/settings/plugins/ifupdown/nm-ifupdown-connection.c
index 2c8504b0..19de1db6 100644
--- a/src/settings/plugins/ifupdown/nm-ifupdown-connection.c
+++ b/src/settings/plugins/ifupdown/nm-ifupdown-connection.c
@@ -21,16 +21,16 @@
  * (C) Copyright 2007,2008 Canonical Ltd.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <glib/gstdio.h>
-#include <nm-dbus-interface.h>
-#include <nm-utils.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-settings-connection.h>
-#include <nm-settings-plugin.h>
-#include "nm-default.h"
+
+#include "nm-dbus-interface.h"
+#include "nm-utils.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-settings-connection.h"
+#include "nm-settings-plugin.h"
 #include "nm-ifupdown-connection.h"
 #include "parser.h"
 
diff --git a/src/settings/plugins/ifupdown/parser.c b/src/settings/plugins/ifupdown/parser.c
index 8a3d4551..bd200cd5 100644
--- a/src/settings/plugins/ifupdown/parser.c
+++ b/src/settings/plugins/ifupdown/parser.c
@@ -21,7 +21,7 @@
  * (C) Copyright 2008 Canonical Ltd.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
@@ -31,7 +31,6 @@
 
 #include "nm-core-internal.h"
 #include "nm-settings-plugin.h"
-#include "nm-default.h"
 
 #include "parser.h"
 #include "plugin.h"
diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c
index fc361de5..dbc96eac 100644
--- a/src/settings/plugins/ifupdown/plugin.c
+++ b/src/settings/plugins/ifupdown/plugin.c
@@ -22,14 +22,15 @@
  * (C) Copyright 2009 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
-
+#include <arpa/inet.h>
+#include <gudev/gudev.h>
 #include <gmodule.h>
-#include <nm-setting-connection.h>
 
-#include "nm-default.h"
+#include "nm-setting-connection.h"
+
 #include "interface_parser.h"
 
 #include "nm-dbus-interface.h"
@@ -48,10 +49,6 @@
 
 #include "nm-config.h"
 
-#include <arpa/inet.h>
-
-#include <gudev/gudev.h>
-
 #define ENI_INTERFACES_FILE "/etc/network/interfaces"
 
 #define IFUPDOWN_PLUGIN_NAME "ifupdown"
diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c
index 24e8afdc..f383821c 100644
--- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c
+++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c
@@ -18,11 +18,10 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-core-internal.h"
 #include "interface_parser.h"
 #include "parser.h"
@@ -462,145 +461,50 @@ test17_read_static_ipv4 (const char *path)
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
 	NMSettingWired *s_wired;
-	char *unmanaged = NULL;
 	GError *error = NULL;
-	const char* tmp;
-	const char *expected_id = "Ifupdown (eth0)";
-	const char *expected_search1 = "example.com";
-	const char *expected_search2 = "foo.example.com";
+	gboolean success;
 	NMIPAddress *ip4_addr;
-#define TEST17_NAME "wired-static-verify-ip4"
 	if_block *block = NULL;
 
-	const char* file = "test17-" TEST17_NAME;
-
-	init_ifparser_with_file (path, file);
+	init_ifparser_with_file (path, "test17-wired-static-verify-ip4");
 	block = ifparser_getfirst ();
 	connection = nm_simple_connection_new();
-	ifupdown_update_connection_from_if_block(connection, block, &error);
-
-	ASSERT (connection != NULL,
-			TEST17_NAME, "failed to read %s: %s", file, error->message);
+	g_assert (connection);
 
-	ASSERT (nm_connection_verify (connection, &error),
-			TEST17_NAME, "failed to verify %s: %s", file, error->message);
+	ifupdown_update_connection_from_if_block(connection, block, &error);
+	g_assert_no_error (error);
 
-	ASSERT (unmanaged == NULL,
-			TEST17_NAME, "failed to verify %s: unexpected unmanaged value", file);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s / %s key",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME,
-			NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value: %s",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME,
-			NM_SETTING_CONNECTION_ID, tmp);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Ifupdown (eth0)");
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_METHOD);
-
-	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 1,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
 
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
 	ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
 	g_assert (ip4_addr != NULL);
 	g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "10.0.0.3");
 	g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 8);
 
-	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns (s_ip4, 0), "10.0.0.1"),
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value #1",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns (s_ip4, 1), "10.0.0.2"),
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value #2",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 1,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	/* DNS search domains */
-	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip4) == 2,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip4, 0);
-	ASSERT (tmp != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s / %s key",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (strcmp (tmp, expected_search1) == 0,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip4, 1);
-	ASSERT (tmp != NULL,
-			TEST17_NAME, "failed to verify %s: missing %s / %s key",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	ASSERT (strcmp (tmp, expected_search2) == 0,
-			TEST17_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "10.0.0.1");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "10.0.0.2");
+
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip4), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 0), ==, "example.com");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 1), ==, "foo.example.com");
 
 	g_object_unref (connection);
 }
@@ -612,157 +516,50 @@ test18_read_static_ipv6 (const char *path)
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip6;
 	NMSettingWired *s_wired;
-	char *unmanaged = NULL;
 	GError *error = NULL;
-	const char* tmp;
-	const char *expected_id = "Ifupdown (myip6tunnel)";
-	const char *expected_search1 = "example.com";
-	const char *expected_search2 = "foo.example.com";
+	gboolean success;
 	NMIPAddress *ip6_addr;
 	if_block *block = NULL;
-#define TEST18_NAME "wired-static-verify-ip6"
-	const char* file = "test18-" TEST18_NAME;
 
-	init_ifparser_with_file (path, file);
+	init_ifparser_with_file (path, "test18-wired-static-verify-ip6");
 	block = ifparser_getfirst ();
 	connection = nm_simple_connection_new();
+	g_assert (connection);
 	ifupdown_update_connection_from_if_block(connection, block, &error);
+	g_assert_no_error (error);
 
-	ASSERT (connection != NULL,
-			TEST18_NAME
-			"failed to read %s: %s", file, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-			TEST18_NAME,
-			"failed to verify %s: %s", file, error->message);
-
-	ASSERT (unmanaged == NULL,
-			TEST18_NAME,
-			"failed to verify %s: unexpected unmanaged value", file);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-			TEST18_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-			TEST18_NAME,
-			"failed to verify %s: missing %s / %s key",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME,
-			NM_SETTING_CONNECTION_ID);
-
-	ASSERT (strcmp (tmp, expected_id) == 0,
-			TEST18_NAME,
-			"failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_CONNECTION_SETTING_NAME,
-			NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Ifupdown (myip6tunnel)");
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-			TEST18_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv6 SETTING ===== */
-
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-			TEST18_NAME,
-			"failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-			TEST18_NAME,
-			"failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_METHOD);
-
-	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip6) == 1,
-			TEST18_NAME,
-			"failed to verify %s: unexpected number of %s / %s",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
 
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 1);
 	ip6_addr = nm_setting_ip_config_get_address (s_ip6, 0);
 	g_assert (ip6_addr != NULL);
 	g_assert_cmpstr (nm_ip_address_get_address (ip6_addr), ==, "fc00::1");
 	g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 64);
 
-	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip6) == 2,
-			TEST18_NAME,
-			"failed to verify %s: unexpected number of %s / %s values",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns (s_ip6, 0), "fc00::2"),
-			TEST18_NAME,
-			"failed to verify %s: unexpected %s / %s #1",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns (s_ip6, 1), "fc00::3"),
-			TEST18_NAME, "failed to verify %s: unexpected %s / %s #2",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS);
-
-	/* DNS search domains */
-	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip6) == 2,
-			TEST18_NAME,
-			"failed to verify %s: unexpected number of %s / %s values",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip6, 0);
-	ASSERT (tmp != NULL,
-			"wired-ipv6-manual-verify-ip6",
-			"failed to verify %s: missing %s / %s #1",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	ASSERT (strcmp (tmp, expected_search1) == 0,
-			"wired-ipv6-manual-verify-ip6",
-			"failed to verify %s: unexpected %s / %s #1",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	tmp = nm_setting_ip_config_get_dns_search (s_ip6, 1);
-	ASSERT (tmp != NULL,
-			TEST18_NAME,
-			"failed to verify %s: missing %s / %s #2",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	ASSERT (strcmp (tmp, expected_search2) == 0,
-			TEST18_NAME,
-			"failed to verify %s: unexpected %s / %s #2",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	g_free (unmanaged);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "fc00::2");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 1), ==, "fc00::3");
+
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 0), ==, "example.com");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 1), ==, "foo.example.com");
+
 	g_object_unref (connection);
 }
 
@@ -771,43 +568,27 @@ test19_read_static_ipv4_plen (const char *path)
 {
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
-	char *unmanaged = NULL;
 	GError *error = NULL;
 	NMIPAddress *ip4_addr;
-#define TEST19_NAME "wired-static-verify-ip4-plen"
 	if_block *block = NULL;
+	gboolean success;
 
-	const char* file = "test19-" TEST19_NAME;
-
-	init_ifparser_with_file (path, file);
+	init_ifparser_with_file (path, "test19-wired-static-verify-ip4-plen");
 	block = ifparser_getfirst ();
 	connection = nm_simple_connection_new();
+	g_assert (connection);
 	ifupdown_update_connection_from_if_block(connection, block, &error);
+	g_assert_no_error (error);
 
-	ASSERT (connection != NULL,
-			TEST19_NAME, "failed to read %s: %s", file, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-			TEST19_NAME, "failed to verify %s: %s", file, error->message);
-
-	ASSERT (unmanaged == NULL,
-			TEST19_NAME, "failed to verify %s: unexpected unmanaged value", file);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-			TEST19_NAME, "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* IP addresses */
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 1,
-			TEST19_NAME, "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP4_CONFIG_SETTING_NAME,
-			NM_SETTING_IP_CONFIG_ADDRESSES);
+	g_assert (s_ip4);
 
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
 	ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
 	g_assert (ip4_addr != NULL);
 	g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "10.0.0.3");
diff --git a/src/settings/plugins/keyfile/nm-keyfile-connection.c b/src/settings/plugins/keyfile/nm-keyfile-connection.c
index c217de68..97a5ee4c 100644
--- a/src/settings/plugins/keyfile/nm-keyfile-connection.c
+++ b/src/settings/plugins/keyfile/nm-keyfile-connection.c
@@ -19,21 +19,20 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <glib/gstdio.h>
-#include <nm-dbus-interface.h>
-#include <nm-setting-connection.h>
-#include <nm-utils.h>
 
-#include "nm-default.h"
+#include "nm-dbus-interface.h"
+#include "nm-setting-connection.h"
+#include "nm-utils.h"
+
 #include "nm-settings-plugin.h"
 #include "nm-keyfile-connection.h"
 #include "reader.h"
 #include "writer.h"
 #include "utils.h"
-#include "nm-logging.h"
 
 G_DEFINE_TYPE (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SETTINGS_CONNECTION)
 
diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c
index e352e523..29a1141b 100644
--- a/src/settings/plugins/keyfile/plugin.c
+++ b/src/settings/plugins/keyfile/plugin.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2008 - 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/stat.h>
 #include <unistd.h>
@@ -29,12 +29,11 @@
 #include <gmodule.h>
 #include <glib/gstdio.h>
 
-#include <nm-connection.h>
-#include <nm-setting.h>
-#include <nm-setting-connection.h>
-#include <nm-utils.h>
+#include "nm-connection.h"
+#include "nm-setting.h"
+#include "nm-setting-connection.h"
+#include "nm-utils.h"
 #include "nm-config.h"
-#include "nm-default.h"
 #include "nm-core-internal.h"
 
 #include "plugin.h"
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index 1c984a16..264b26a4 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -18,14 +18,13 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/stat.h>
 #include <string.h>
 
 #include "reader.h"
 
-#include "nm-default.h"
 #include "nm-keyfile-internal.h"
 #include "NetworkManagerUtils.h"
 
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index 250bad36..c1b79ef7 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2008 - 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -29,7 +29,6 @@
 #include <sys/socket.h>
 
 #include "nm-core-internal.h"
-#include "nm-default.h"
 
 #include "reader.h"
 #include "writer.h"
@@ -37,9 +36,6 @@
 
 #include "nm-test-utils.h"
 
-#define TEST_WIRED_FILE    TEST_KEYFILES_DIR"/Test_Wired_Connection"
-#define TEST_WIRELESS_FILE TEST_KEYFILES_DIR"/Test_Wireless_Connection"
-
 static void
 check_ip_address (NMSettingIPConfig *config, int idx, const char *address, int plen)
 {
@@ -90,14 +86,7 @@ test_read_valid_wired_connection (void)
 	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
-	const char *tmp;
-	const char *expected_id = "Test Wired Connection";
-	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
-	const guint64 expected_timestamp = 6654332;
-	guint64 timestamp;
-	const char *expected6_dnssearch1 = "super-domain.com";
-	const char *expected6_dnssearch2 = "redhat.com";
-	const char *expected6_dnssearch3 = "gnu.org";
+	gboolean success;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*ipv4.addresses:*semicolon at the end*addresses1*");
@@ -127,127 +116,41 @@ test_read_valid_wired_connection (void)
 	                       "*ipv6.routes*semicolon at the end*routes1*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*ipv6.route*semicolon at the end*route6*");
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_FILE, NULL);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection", NULL);
 	g_test_assert_expected_messages ();
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_WIRED_FILE);
+	g_assert (connection);
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_WIRED_FILE, error->message);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* UUID */
-	tmp = nm_setting_connection_get_uuid (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-	ASSERT (strcmp (tmp, expected_uuid) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-
-	/* Timestamp */
-	timestamp = nm_setting_connection_get_timestamp (s_con);
-	ASSERT (timestamp == expected_timestamp,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection");
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57");
+	g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 6654332);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "connection-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
-	/* MAC address */
 	mac = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (mac != NULL,
-	        "connection-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-
-	ASSERT (nm_setting_wired_get_mtu (s_wired) == 1400,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MTU);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
+	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "connection-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 0), "4.2.2.1") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 1), "4.2.2.2") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "4.2.2.1");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "4.2.2.2");
 
 	/* IPv4 addresses */
-	g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == 6);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 6);
 	check_ip_address (s_ip4, 0, "2.3.4.5", 24);
 	check_ip_address (s_ip4, 1, "192.168.0.5", 24);
 	check_ip_address (s_ip4, 2, "1.2.3.4", 16);
@@ -256,14 +159,10 @@ test_read_valid_wired_connection (void)
 	check_ip_address (s_ip4, 5, "5.6.7.8", 24);
 
 	/* IPv4 gateway */
-	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip4), "2.3.4.6") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_GATEWAY);
+	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "2.3.4.6");
 
 	/* IPv4 routes */
-	g_assert (nm_setting_ip_config_get_num_routes (s_ip4) == 12);
+	g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 12);
 	check_ip_route (s_ip4, 0, "5.6.7.8", 32, NULL, -1);
 	check_ip_route (s_ip4, 1, "1.2.3.0", 24, "2.3.4.8", 99);
 	check_ip_route (s_ip4, 2, "1.1.1.2", 12, NULL, -1);
@@ -278,65 +177,21 @@ test_read_valid_wired_connection (void)
 	check_ip_route (s_ip4, 11, "1.1.1.11", 21, NULL, 21);
 
 	/* ===== IPv6 SETTING ===== */
-
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "connection-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	/* DNS Addresses */
-	ASSERT (nm_setting_ip_config_get_num_dns (s_ip6) == 2,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 0), "1111:dddd::aaaa") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 1), "1::cafe") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
-
-	/* DNS Searches */
-	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip6) == 3,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 0), expected6_dnssearch1),
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 1), expected6_dnssearch2),
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 2), expected6_dnssearch3),
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #3",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	g_assert (s_ip6);
+
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
+
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 2);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "1111:dddd::aaaa");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 1), ==, "1::cafe");
+	g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 3);
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 0), ==, "super-domain.com");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 1), ==, "redhat.com");
+	g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 2), ==, "gnu.org");
 
 	/* IPv6 addresses */
-	g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 10);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 10);
 	check_ip_address (s_ip6, 0, "2:3:4:5:6:7:8:9", 64);
 	check_ip_address (s_ip6, 1, "abcd:1234:ffff::cdde", 64);
 	check_ip_address (s_ip6, 2, "1:2:3:4:5:6:7:8", 96);
@@ -349,14 +204,10 @@ test_read_valid_wired_connection (void)
 	check_ip_address (s_ip6, 9, "3:4:5:6:7:8:9:19", 69);
 
 	/* IPv6 gateway */
-	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "2:3:4:5:1:2:3:4") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_GATEWAY);
-
-	/* Route #1 */
-	g_assert (nm_setting_ip_config_get_num_routes (s_ip6) == 7);
+	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "2:3:4:5:1:2:3:4");
+
+	/* Routes */
+	g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 7);
 	check_ip_route (s_ip6, 0, "d:e:f:0:1:2:3:4", 64, "f:e:d:c:1:2:3:4", -1);
 	check_ip_route (s_ip6, 1, "a:b:c:d::", 64, "f:e:d:c:1:2:3:4", 99);
 	check_ip_route (s_ip6, 2, "8:7:6:5:4:3:2:1", 128, NULL, -1);
@@ -525,19 +376,14 @@ test_write_wired_connection (void)
 	owner_uid = geteuid ();
 	owner_grp = getegid ();
 	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
-	ASSERT (success == TRUE,
-			"connection-write", "failed to write keyfile: %s",
-			error ? error->message : "(none)");
-
-	ASSERT (testfile != NULL,
-			"connection-write", "didn't get keyfile name back after writing connection");
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
-	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	g_assert (reread);
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -547,8 +393,6 @@ test_write_wired_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_IP6_FILE    TEST_KEYFILES_DIR"/Test_Wired_Connection_IP6"
-
 static void
 test_read_ip6_wired_connection (void)
 {
@@ -558,107 +402,37 @@ test_read_ip6_wired_connection (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	GError *error = NULL;
-	const char *tmp;
-	const char *expected_id = "Test Wired Connection IP6";
-	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
-
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_IP6_FILE, NULL);
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_WIRED_IP6_FILE);
+	gboolean success;
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_WIRED_IP6_FILE, error->message);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_IP6", NULL);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* UUID */
-	tmp = nm_setting_connection_get_uuid (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-	ASSERT (strcmp (tmp, expected_uuid) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection IP6");
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57");
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "connection-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "connection-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_DNS);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
 
 	/* ===== IPv6 SETTING ===== */
-
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
-	ASSERT (s_ip6 != NULL,
-	        "connection-verify-ip6", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip6);
-	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
-
-	/* IPv6 address */
-	g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 1);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 1);
 	check_ip_address (s_ip6, 0, "abcd:1234:ffff::cdde", 64);
-
-	/* IPv6 gateway */
-	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "abcd:1234:ffff::cdd1") == 0,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_IP6_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_GATEWAY);
+	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd:1234:ffff::cdd1");
 
 	g_object_unref (connection);
 }
@@ -735,19 +509,14 @@ test_write_ip6_wired_connection (void)
 	owner_uid = geteuid ();
 	owner_grp = getegid ();
 	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
-	ASSERT (success == TRUE,
-			"connection-write", "failed to write keyfile: %s",
-			error ? error->message : "(none)");
-
-	ASSERT (testfile != NULL,
-			"connection-write", "didn't get keyfile name back after writing connection");
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
-	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	g_assert (reread);
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -757,8 +526,6 @@ test_write_ip6_wired_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_MAC_CASE_FILE TEST_KEYFILES_DIR"/Test_Wired_Connection_MAC_Case"
-
 static void
 test_read_wired_mac_case (void)
 {
@@ -768,9 +535,7 @@ test_read_wired_mac_case (void)
 	GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
-	const char *tmp;
-	const char *expected_id = "Test Wired Connection MAC Case";
-	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
+	gboolean success;
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*ipv4.addresses*semicolon at the end*addresses1*");
@@ -778,74 +543,29 @@ test_read_wired_mac_case (void)
 	                       "*ipv4.addresses*semicolon at the end*addresses2*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*ipv6.routes*semicolon at the end*routes1*");
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_MAC_CASE_FILE, NULL);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case", NULL);
 	g_test_assert_expected_messages ();
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_WIRED_MAC_CASE_FILE);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_WIRED_MAC_CASE_FILE, error->message);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* UUID */
-	tmp = nm_setting_connection_get_uuid (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-	ASSERT (strcmp (tmp, expected_uuid) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection MAC Case");
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57");
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "connection-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME);
-
-	/* MAC address */
+	g_assert (s_wired);
 	mac = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (mac != NULL,
-	        "connection-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 
 	g_object_unref (connection);
 }
 
-#define TEST_MAC_OLD_FORMAT_FILE TEST_KEYFILES_DIR"/Test_MAC_Old_Format"
-
 static void
 test_read_mac_old_format (void)
 {
@@ -857,7 +577,7 @@ test_read_mac_old_format (void)
 	char expected_mac[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
 	char expected_cloned_mac[ETH_ALEN] = { 0x00, 0x16, 0xaa, 0xbb, 0xcc, 0xfe };
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_MAC_OLD_FORMAT_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_Old_Format", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -881,8 +601,6 @@ test_read_mac_old_format (void)
 	g_object_unref (connection);
 }
 
-#define TEST_MAC_IB_OLD_FORMAT_FILE TEST_KEYFILES_DIR"/Test_MAC_IB_Old_Format"
-
 static void
 test_read_mac_ib_old_format (void)
 {
@@ -895,7 +613,7 @@ test_read_mac_ib_old_format (void)
 		0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
 		0x90 };
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_MAC_IB_OLD_FORMAT_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_IB_Old_Format", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -924,104 +642,33 @@ test_read_valid_wireless_connection (void)
 	GError *error = NULL;
 	const char *bssid;
 	const guint8 expected_bssid[ETH_ALEN] = { 0x00, 0x1a, 0x33, 0x44, 0x99, 0x82 };
-	const char *tmp;
-	const char *expected_id = "Test Wireless Connection";
-	const char *expected_uuid = "2f962388-e5f3-45af-a62c-ac220b8f7baa";
-	const guint64 expected_timestamp = 1226604314;
-	guint64 timestamp;
-
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRELESS_FILE, NULL);
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_WIRELESS_FILE);
+	gboolean success;
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_WIRELESS_FILE, error->message);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wireless_Connection", NULL);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* UUID */
-	tmp = nm_setting_connection_get_uuid (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-	ASSERT (strcmp (tmp, expected_uuid) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-
-	/* Timestamp */
-	timestamp = nm_setting_connection_get_timestamp (s_con);
-	ASSERT (timestamp == expected_timestamp,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == FALSE,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
-
-	/* ===== WIRED SETTING ===== */
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wireless Connection");
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "2f962388-e5f3-45af-a62c-ac220b8f7baa");
+	g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 1226604314);
+	g_assert (nm_setting_connection_get_autoconnect (s_con) == FALSE);
 
+	/* ===== WIRELESS SETTING ===== */
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "connection-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME);
-
-	/* BSSID */
+	g_assert (s_wireless);
 	bssid = nm_setting_wireless_get_bssid (s_wireless);
-	ASSERT (bssid != NULL,
-	        "connection-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-	ASSERT (nm_utils_hwaddr_matches (bssid, -1, expected_bssid, sizeof (expected_bssid)),
-	        "connection-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
+	g_assert (bssid);
+	g_assert (nm_utils_hwaddr_matches (bssid, -1, expected_bssid, sizeof (expected_bssid)));
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "connection-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "connection-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	g_object_unref (connection);
 }
@@ -1100,19 +747,14 @@ test_write_wireless_connection (void)
 	owner_uid = geteuid ();
 	owner_grp = getegid ();
 	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
-	ASSERT (success == TRUE,
-			"connection-write", "failed to write keyfile: %s",
-			error ? error->message : "(none)");
-
-	ASSERT (testfile != NULL,
-			"connection-write", "didn't get keyfile name back after writing connection");
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
-	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
-
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	g_assert (reread);
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -1122,8 +764,6 @@ test_write_wireless_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_STRING_SSID_FILE TEST_KEYFILES_DIR"/Test_String_SSID"
-
 static void
 test_read_string_ssid (void)
 {
@@ -1134,32 +774,21 @@ test_read_string_ssid (void)
 	const guint8 *ssid_data;
 	gsize ssid_len;
 	const char *expected_ssid = "blah blah ssid 1234";
+	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_STRING_SSID_FILE, NULL);
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_STRING_SSID_FILE);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_STRING_SSID_FILE, error->message);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_String_SSID", NULL);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== WIRELESS SETTING ===== */
-
 	s_wireless = nm_connection_get_setting_wireless (connection);
-	ASSERT (s_wireless != NULL,
-	        "connection-verify-wireless", "failed to verify %s: missing %s setting",
-	        TEST_STRING_SSID_FILE,
-	        NM_SETTING_WIRELESS_SETTING_NAME);
-
-	/* SSID */
+	g_assert (s_wireless);
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (ssid != NULL,
-	        "connection-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_STRING_SSID_FILE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SSID);
+	g_assert (ssid);
 	ssid_data = g_bytes_get_data (ssid, &ssid_len);
-	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
-	g_assert (memcmp (ssid_data, expected_ssid, ssid_len) == 0);
+	g_assert_cmpmem (ssid_data, ssid_len, expected_ssid, strlen (expected_ssid));
 
 	g_object_unref (connection);
 }
@@ -1218,29 +847,22 @@ test_write_string_ssid (void)
 	owner_uid = geteuid ();
 	owner_grp = getegid ();
 	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
-	ASSERT (success == TRUE,
-			"connection-write", "failed to write keyfile: %s",
-			error ? error->message : "(none)");
-
-	ASSERT (testfile != NULL,
-			"connection-write", "didn't get keyfile name back after writing connection");
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
 
 	/* Ensure the SSID was written out as a string */
 	keyfile = g_key_file_new ();
-	ASSERT (g_key_file_load_from_file (keyfile, testfile, 0, NULL) == TRUE,
-	        "string-ssid-verify", "failed to load keyfile to verify");
+	g_assert (g_key_file_load_from_file (keyfile, testfile, 0, NULL));
 	tmp = g_key_file_get_string (keyfile, "wifi", NM_SETTING_WIRELESS_SSID, NULL);
-	ASSERT (tmp, "string-ssid-verify", "failed to load 'ssid' key from file");
-	ASSERT (strlen (tmp) == sizeof (tmpssid),
-	        "string-ssid-verify", "reread SSID and expected were different sizes");
-	ASSERT (memcmp (tmp, tmpssid, sizeof (tmpssid)) == 0,
-	        "string-ssid-verify", "reread SSID and expected were different");
+	g_assert (tmp);
+	g_assert_cmpmem (tmp, strlen (tmp), tmpssid, sizeof (tmpssid));
 	g_free (tmp);
 	g_key_file_free (keyfile);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
-	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
+	g_assert (reread);
 
 	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
@@ -1252,8 +874,6 @@ test_write_string_ssid (void)
 	g_object_unref (connection);
 }
 
-#define TEST_INTLIST_SSID_FILE TEST_KEYFILES_DIR"/Test_Intlist_SSID"
-
 static void
 test_read_intlist_ssid (void)
 {
@@ -1266,7 +886,7 @@ test_read_intlist_ssid (void)
 	gsize ssid_len;
 	const char *expected_ssid = "blah1234";
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIST_SSID_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlist_SSID", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -1281,8 +901,7 @@ test_read_intlist_ssid (void)
 	ssid = nm_setting_wireless_get_ssid (s_wifi);
 	g_assert (ssid != NULL);
 	ssid_data = g_bytes_get_data (ssid, &ssid_len);
-	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
-	g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0);
+	g_assert_cmpmem (ssid_data, ssid_len, expected_ssid, strlen (expected_ssid));
 
 	g_object_unref (connection);
 }
@@ -1378,8 +997,6 @@ test_write_intlist_ssid (void)
 	g_object_unref (connection);
 }
 
-#define TEST_INTLIKE_SSID_FILE TEST_KEYFILES_DIR"/Test_Intlike_SSID"
-
 static void
 test_read_intlike_ssid (void)
 {
@@ -1392,7 +1009,7 @@ test_read_intlike_ssid (void)
 	gsize ssid_len;
 	const char *expected_ssid = "101";
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIKE_SSID_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -1413,8 +1030,6 @@ test_read_intlike_ssid (void)
 	g_object_unref (connection);
 }
 
-#define TEST_INTLIKE_SSID_2_FILE TEST_KEYFILES_DIR"/Test_Intlike_SSID_2"
-
 static void
 test_read_intlike_ssid_2 (void)
 {
@@ -1427,7 +1042,7 @@ test_read_intlike_ssid_2 (void)
 	gsize ssid_len;
 	const char *expected_ssid = "11;12;13;";
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIKE_SSID_2_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID_2", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -1622,8 +1237,6 @@ test_write_intlike_ssid_2 (void)
 	g_object_unref (connection);
 }
 
-#define TEST_BT_DUN_FILE TEST_KEYFILES_DIR"/ATT_Data_Connect_BT"
-
 static void
 test_read_bt_dun_connection (void)
 {
@@ -1635,150 +1248,39 @@ test_read_bt_dun_connection (void)
 	GError *error = NULL;
 	const char *bdaddr;
 	const guint8 expected_bdaddr[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
-	const char *tmp;
-	NMSettingSerialParity parity;
-	const char *expected_id = "AT&T Data Connect BT";
-	const char *expected_uuid = "089130ab-ce28-46e4-ad77-d44869b03d19";
-	const char *expected_apn = "ISP.CINGULAR";
-	const char *expected_username = "ISP@CINGULARGPRS.COM";
-	const char *expected_password = "CINGULAR1";
-
-	connection = nm_keyfile_plugin_connection_from_file (TEST_BT_DUN_FILE, NULL);
-	ASSERT (connection != NULL,
-			"connection-read", "failed to read %s", TEST_BT_DUN_FILE);
+	gboolean success;
 
-	ASSERT (nm_connection_verify (connection, &error),
-	        "connection-verify", "failed to verify %s: %s", TEST_BT_DUN_FILE, error->message);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_BT", NULL);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* UUID */
-	tmp = nm_setting_connection_get_uuid (s_con);
-	ASSERT (tmp != NULL,
-	        "connection-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
-	ASSERT (strcmp (tmp, expected_uuid) == 0,
-	        "connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_UUID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "AT&T Data Connect BT");
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "089130ab-ce28-46e4-ad77-d44869b03d19");
 
 	/* ===== BLUETOOTH SETTING ===== */
-
 	s_bluetooth = nm_connection_get_setting_bluetooth (connection);
-	ASSERT (s_bluetooth != NULL,
-	        "connection-verify-bt", "failed to verify %s: missing %s setting",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME);
-
-	/* BDADDR */
+	g_assert (s_bluetooth);
 	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bluetooth);
-	ASSERT (bdaddr != NULL,
-	        "connection-verify-bt", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_BLUETOOTH_SETTING_NAME,
-	        NM_SETTING_BLUETOOTH_BDADDR);
-	ASSERT (nm_utils_hwaddr_matches (bdaddr, -1, expected_bdaddr, sizeof (expected_bdaddr)),
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_BLUETOOTH_SETTING_NAME,
-	        NM_SETTING_BLUETOOTH_BDADDR);
-
-	/* Type */
-	tmp = nm_setting_bluetooth_get_connection_type (s_bluetooth);
-	ASSERT (tmp != NULL,
-	        "connection-verify-bt", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_BLUETOOTH_SETTING_NAME,
-	        NM_SETTING_BLUETOOTH_TYPE);
-	ASSERT (strcmp (tmp, NM_SETTING_BLUETOOTH_TYPE_DUN) == 0,
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_BLUETOOTH_SETTING_NAME,
-	        NM_SETTING_BLUETOOTH_TYPE);
+	g_assert (bdaddr);
+	g_assert (nm_utils_hwaddr_matches (bdaddr, -1, expected_bdaddr, sizeof (expected_bdaddr)));
+	g_assert_cmpstr (nm_setting_bluetooth_get_connection_type (s_bluetooth), ==, NM_SETTING_BLUETOOTH_TYPE_DUN);
 
 	/* ===== GSM SETTING ===== */
-
 	s_gsm = nm_connection_get_setting_gsm (connection);
-	ASSERT (s_gsm != NULL,
-	        "connection-verify-gsm", "failed to verify %s: missing %s setting",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME);
-
-	/* APN */
-	tmp = nm_setting_gsm_get_apn (s_gsm);
-	ASSERT (tmp != NULL,
-	        "connection-verify-gsm", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_APN);
-	ASSERT (strcmp (tmp, expected_apn) == 0,
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_APN);
-
-	/* Username */
-	tmp = nm_setting_gsm_get_username (s_gsm);
-	ASSERT (tmp != NULL,
-	        "connection-verify-gsm", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_USERNAME);
-	ASSERT (strcmp (tmp, expected_username) == 0,
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_USERNAME);
-
-	/* Password */
-	tmp = nm_setting_gsm_get_password (s_gsm);
-	ASSERT (tmp != NULL,
-	        "connection-verify-gsm", "failed to verify %s: missing %s / %s key",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_PASSWORD);
-	ASSERT (strcmp (tmp, expected_password) == 0,
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_GSM_SETTING_NAME,
-	        NM_SETTING_GSM_PASSWORD);
+	g_assert (s_gsm);
+	g_assert_cmpstr (nm_setting_gsm_get_apn (s_gsm), ==, "ISP.CINGULAR");
+	g_assert_cmpstr (nm_setting_gsm_get_username (s_gsm), ==, "ISP@CINGULARGPRS.COM");
+	g_assert_cmpstr (nm_setting_gsm_get_password (s_gsm), ==, "CINGULAR1");
 
 	/* ===== SERIAL SETTING ===== */
-
 	s_serial = nm_connection_get_setting_serial (connection);
-	ASSERT (s_serial != NULL,
-	        "connection-verify-serial", "failed to verify %s: missing %s setting",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_SERIAL_SETTING_NAME);
-
-	parity = nm_setting_serial_get_parity (s_serial);
-	ASSERT (parity == NM_SETTING_SERIAL_PARITY_ODD,
-	        "connection-verify-serial", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_SERIAL_SETTING_NAME,
-	        NM_SETTING_SERIAL_PARITY);
+	g_assert (s_serial);
+	g_assert (nm_setting_serial_get_parity (s_serial) == NM_SETTING_SERIAL_PARITY_ODD);
 
 	g_object_unref (connection);
 }
@@ -1852,16 +1354,13 @@ test_write_bt_dun_connection (void)
 	owner_uid = geteuid ();
 	owner_grp = getegid ();
 	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
-	ASSERT (success == TRUE,
-			"connection-write", "failed to write keyfile: %s",
-			error ? error->message : "(none)");
-
-	ASSERT (testfile != NULL,
-			"connection-write", "didn't get keyfile name back after writing connection");
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
-	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
+	g_assert (reread);
 
 	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
@@ -1873,8 +1372,6 @@ test_write_bt_dun_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_GSM_FILE TEST_KEYFILES_DIR"/ATT_Data_Connect_Plain"
-
 static void
 test_read_gsm_connection (void)
 {
@@ -1885,7 +1382,7 @@ test_read_gsm_connection (void)
 	GError *error = NULL;
 	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_GSM_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_Plain", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 
@@ -2005,8 +1502,6 @@ test_write_gsm_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_TLS_BLOB_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Blob"
-
 static void
 test_read_wired_8021x_tls_blob_connection (void)
 {
@@ -2022,19 +1517,12 @@ test_read_wired_8021x_tls_blob_connection (void)
 	                       "*<warn>  keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*<warn>  keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_BLOB_FILE, &error);
-	if (connection == NULL) {
-		g_assert (error);
-		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
-		g_assert (connection);
-	}
-
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -2077,8 +1565,6 @@ test_read_wired_8021x_tls_blob_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_TLS_PATH_MISSING_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Path_Missing"
-
 static void
 test_read_wired_8021x_tls_bad_path_connection (void)
 {
@@ -2092,20 +1578,13 @@ test_read_wired_8021x_tls_bad_path_connection (void)
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*does not exist*");
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_PATH_MISSING_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing", &error);
 	g_test_assert_expected_messages ();
-	if (connection == NULL) {
-		g_assert (error);
-		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_PATH_MISSING_FILE, error->message);
-		g_assert (connection);
-	}
-
+	g_assert_no_error (error);
+	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -2142,8 +1621,6 @@ test_read_wired_8021x_tls_bad_path_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_TLS_OLD_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Old"
-
 static void
 test_read_wired_8021x_tls_old_connection (void)
 {
@@ -2160,19 +1637,12 @@ test_read_wired_8021x_tls_old_connection (void)
 	                       "*<warn>  keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
 	                       "*<warn>  keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_OLD_FILE, &error);
-	if (connection == NULL) {
-		g_assert (error);
-		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_OLD_FILE, error->message);
-		g_assert (connection);
-	}
-
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_OLD_FILE, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -2204,8 +1674,6 @@ test_read_wired_8021x_tls_old_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_WIRED_TLS_NEW_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_New"
-
 static void
 test_read_wired_8021x_tls_new_connection (void)
 {
@@ -2217,19 +1685,12 @@ test_read_wired_8021x_tls_new_connection (void)
 	char *tmp2;
 	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_NEW_FILE, &error);
-	if (connection == NULL) {
-		g_assert (error);
-		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_NEW_FILE, error->message);
-		g_assert (connection);
-	}
-
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_New", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_NEW_FILE, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
@@ -2322,22 +1783,16 @@ create_wired_tls_connection (NMSetting8021xCKScheme scheme)
 	                                         scheme,
 	                                         NULL,
 	                                         &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to set CA cert %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	success = nm_setting_802_1x_set_client_cert (s_8021x,
 	                                             TEST_WIRED_TLS_CLIENT_CERT,
 	                                             scheme,
 	                                             NULL,
 	                                             &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to set client cert %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	success = nm_setting_802_1x_set_private_key (s_8021x,
 	                                             TEST_WIRED_TLS_PRIVKEY,
@@ -2345,11 +1800,8 @@ create_wired_tls_connection (NMSetting8021xCKScheme scheme)
 	                                             scheme,
 	                                             NULL,
 	                                             &error);
-	if (!success) {
-		g_assert (error);
-		g_warning ("Failed to set private key %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
-		g_assert (success);
-	}
+	g_assert_no_error (error);
+	g_assert (success);
 
 	return connection;
 }
@@ -2478,7 +1930,7 @@ test_write_wired_8021x_tls_connection_blob (void)
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	g_assert (s_8021x);
 
-	password_raw = g_bytes_new (PASSWORD_RAW, STRLEN (PASSWORD_RAW));
+	password_raw = g_bytes_new (PASSWORD_RAW, NM_STRLEN (PASSWORD_RAW));
 	g_object_set (s_8021x,
 	              NM_SETTING_802_1X_PASSWORD_RAW,
 	              password_raw,
@@ -2529,8 +1981,8 @@ test_write_wired_8021x_tls_connection_blob (void)
 
 	password_raw = nm_setting_802_1x_get_password_raw (s_8021x);
 	g_assert (password_raw);
-	g_assert (g_bytes_get_size (password_raw) == STRLEN (PASSWORD_RAW));
-	g_assert (!memcmp (g_bytes_get_data (password_raw, NULL), PASSWORD_RAW, STRLEN (PASSWORD_RAW)));
+	g_assert (g_bytes_get_size (password_raw) == NM_STRLEN (PASSWORD_RAW));
+	g_assert (!memcmp (g_bytes_get_data (password_raw, NULL), PASSWORD_RAW, NM_STRLEN (PASSWORD_RAW)));
 
 	unlink (testfile);
 	g_free (testfile);
@@ -2549,8 +2001,6 @@ test_write_wired_8021x_tls_connection_blob (void)
 	g_object_unref (connection);
 }
 
-#define TEST_INFINIBAND_FILE    TEST_KEYFILES_DIR"/Test_InfiniBand_Connection"
-
 static void
 test_read_infiniband_connection (void)
 {
@@ -2566,7 +2016,7 @@ test_read_infiniband_connection (void)
 	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
 	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_INFINIBAND_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_InfiniBand_Connection", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
@@ -2670,8 +2120,6 @@ test_write_infiniband_connection (void)
 	g_object_unref (connection);
 }
 
-#define TEST_BRIDGE_MAIN_FILE TEST_KEYFILES_DIR"/Test_Bridge_Main"
-
 static void
 test_read_bridge_main (void)
 {
@@ -2684,7 +2132,7 @@ test_read_bridge_main (void)
 	const char *expected_uuid = "8f061643-fe41-4d4c-a8d9-097d26e2ad3a";
 	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_BRIDGE_MAIN_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Main", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
@@ -2796,8 +2244,6 @@ test_write_bridge_main (void)
 	g_object_unref (connection);
 }
 
-#define TEST_BRIDGE_COMPONENT_FILE TEST_KEYFILES_DIR"/Test_Bridge_Component"
-
 static void
 test_read_bridge_component (void)
 {
@@ -2812,7 +2258,7 @@ test_read_bridge_component (void)
 	const char *expected_uuid = "d7b4f96c-c45e-4298-bef8-f48574f8c1c0";
 	gboolean success;
 
-	connection = nm_keyfile_plugin_connection_from_file (TEST_BRIDGE_COMPONENT_FILE, &error);
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Component", &error);
 	g_assert_no_error (error);
 	g_assert (connection);
 	success = nm_connection_verify (connection, &error);
@@ -3184,8 +2630,7 @@ test_read_missing_vlan_setting (void)
 	s_vlan = nm_connection_get_setting_vlan (connection);
 	g_assert (s_vlan);
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 0);
-	/* Ensure the VLAN flags are not set (0) */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
@@ -3211,8 +2656,7 @@ test_read_missing_vlan_flags (void)
 
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 444);
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "em1");
-	/* Ensure the VLAN flags are not set (0) */
-	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS);
 
 	g_object_unref (connection);
 }
diff --git a/src/settings/plugins/keyfile/utils.c b/src/settings/plugins/keyfile/utils.c
index 48795ffb..b5c306e4 100644
--- a/src/settings/plugins/keyfile/utils.c
+++ b/src/settings/plugins/keyfile/utils.c
@@ -18,15 +18,15 @@
  * (C) Copyright 2010 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <string.h>
-#include "nm-default.h"
+
 #include "utils.h"
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-wireless-security.h>
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
 #include "nm-config.h"
 
 #define NM_CONFIG_KEYFILE_PATH_DEFAULT NMCONFDIR "/system-connections"
diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c
index db00b061..c8eb8800 100644
--- a/src/settings/plugins/keyfile/writer.c
+++ b/src/settings/plugins/keyfile/writer.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2008 - 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -27,7 +27,6 @@
 #include <errno.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "writer.h"
 #include "utils.h"
 #include "nm-keyfile-internal.h"
@@ -46,12 +45,16 @@ write_cert_key_file (const char *path,
 	char *tmppath;
 	int fd = -1, written;
 	gboolean success = FALSE;
+	mode_t saved_umask;
 
 	tmppath = g_malloc0 (strlen (path) + 10);
 	g_assert (tmppath);
 	memcpy (tmppath, path, strlen (path));
 	strcat (tmppath, ".XXXXXX");
 
+	/* Only readable by root */
+	saved_umask = umask (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
 	errno = 0;
 	fd = mkstemp (tmppath);
 	if (fd < 0) {
@@ -61,17 +64,6 @@ write_cert_key_file (const char *path,
 		goto out;
 	}
 
-	/* Only readable by root */
-	errno = 0;
-	if (fchmod (fd, S_IRUSR | S_IWUSR) != 0) {
-		close (fd);
-		unlink (tmppath);
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
-		             "Could not set permissions for temporary file '%s': %d",
-		             path, errno);
-		goto out;
-	}
-
 	errno = 0;
 	written = write (fd, data, data_len);
 	if (written != data_len) {
@@ -96,6 +88,7 @@ write_cert_key_file (const char *path,
 	}
 
 out:
+	umask (saved_umask);
 	g_free (tmppath);
 	return success;
 }
@@ -241,6 +234,8 @@ _internal_write_connection (NMConnection *connection,
 	WriteInfo info = { 0 };
 	GError *local_err = NULL;
 	int errsv;
+	gboolean success = FALSE;
+	mode_t saved_umask;
 
 	g_return_val_if_fail (!out_path || !*out_path, FALSE);
 	g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
@@ -324,13 +319,15 @@ _internal_write_connection (NMConnection *connection,
 	if (existing_path != NULL && strcmp (path, existing_path) != 0)
 		unlink (existing_path);
 
+	saved_umask = umask (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
 	g_file_set_contents (path, data, len, &local_err);
 	if (local_err) {
 		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "error writing to file '%s': %s",
 		             path, local_err->message);
 		g_error_free (local_err);
-		return FALSE;
+		goto out;
 	}
 
 	if (chown (path, owner_uid, owner_grp) < 0) {
@@ -339,23 +336,18 @@ _internal_write_connection (NMConnection *connection,
 		             "error chowning '%s': %s (%d)",
 		             path, g_strerror (errsv), errsv);
 		unlink (path);
-		return FALSE;
-	}
-
-	if (chmod (path, S_IRUSR | S_IWUSR) < 0) {
-		errsv = errno;
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
-		             "error setting permissions on '%s': %s (%d)",
-		             path, g_strerror (errsv), errsv);
-		unlink (path);
-		return FALSE;
+		goto out;
 	}
 
 	if (out_path && g_strcmp0 (existing_path, path)) {
 		*out_path = path;  /* pass path out to caller */
 		path = NULL;
 	}
-	return TRUE;
+
+	success = TRUE;
+out:
+	umask (saved_umask);
+	return success;
 }
 
 gboolean
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index 190ee0a7..091742e5 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -19,12 +19,11 @@
  * Copyright (C) 2007 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-supplicant-config.h"
 #include "nm-supplicant-settings-verify.h"
 #include "nm-setting.h"
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 9251af1f..ce7a2a2c 100644
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -19,12 +19,11 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-supplicant-interface.h"
 #include "nm-supplicant-config.h"
@@ -59,21 +58,22 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 
 /* Properties */
-enum {
-	PROP_0 = 0,
+NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface,
+	PROP_IFACE,
 	PROP_SCANNING,
 	PROP_CURRENT_BSS,
-	LAST_PROP
-};
-
+	PROP_IS_WIRELESS,
+	PROP_FAST_SUPPORTED,
+	PROP_AP_SUPPORT,
+);
 
 typedef struct {
 	char *         dev;
-	gboolean       is_wireless;
+	bool           is_wireless;
+	bool           fast_supported;
 	gboolean       has_credreq;  /* Whether querying 802.1x credentials is supported */
 	NMSupplicantFeature ap_support;   /* Lightweight AP mode support */
 	NMSupplicantFeature mac_randomization_support;
-	gboolean       fast_supported;
 	guint32        max_scan_ssids;
 	guint32        ready_count;
 
@@ -98,7 +98,27 @@ typedef struct {
 	NMSupplicantConfig *cfg;
 } NMSupplicantInterfacePrivate;
 
-/***************************************************************/
+/*********************************************************************************************/
+
+#define _NMLOG_DOMAIN           LOGD_SUPPLICANT
+#define _NMLOG_PREFIX_NAME      "sup-iface"
+#define _NMLOG(level, ...) \
+    G_STMT_START { \
+         char _sbuf[64]; \
+         \
+         nm_log ((level), _NMLOG_DOMAIN, \
+                 "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+                 _NMLOG_PREFIX_NAME, \
+                 ((self) \
+                      ? nm_sprintf_buf (_sbuf, \
+                                        "[%p,%s]", \
+                                        (self), \
+                                        NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev) \
+                      : "") \
+                 _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+    } G_STMT_END
+
+/*********************************************************************************************/
 
 static void
 emit_error_helper (NMSupplicantInterface *self, GError *error)
@@ -162,8 +182,9 @@ on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da
 
 	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			nm_log_dbg (LOGD_SUPPLICANT, "Failed to acquire BSS proxy: (%s)", error->message);
-			g_hash_table_remove (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data)->bss_proxies,
+			self = NM_SUPPLICANT_INTERFACE (user_data);
+			_LOGD ("failed to acquire BSS proxy: (%s)", error->message);
+			g_hash_table_remove (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->bss_proxies,
 			                     g_dbus_proxy_get_object_path (proxy));
 		}
 		return;
@@ -288,7 +309,6 @@ wpas_state_string_to_enum (const char *str_state)
 	else if (!strcmp (str_state, "completed"))
 		return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED;
 
-	nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant state '%s'", str_state);
 	return -1;
 }
 
@@ -298,9 +318,11 @@ set_state_from_string (NMSupplicantInterface *self, const char *new_state)
 	int state;
 
 	state = wpas_state_string_to_enum (new_state);
-	g_warn_if_fail (state > 0);
-	if (state > 0)
-		set_state (self, (guint32) state);
+	if (state == -1) {
+		_LOGW ("unknown supplicant state '%s'", new_state);
+		return;
+	}
+	set_state (self, (guint32) state);
 }
 
 static void
@@ -315,7 +337,7 @@ set_scanning (NMSupplicantInterface *self, gboolean new_scanning)
 		if (priv->scanning == FALSE)
 			priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 
-		g_object_notify (G_OBJECT (self), "scanning");
+		_notify (self, PROP_SCANNING);
 	}
 }
 
@@ -379,8 +401,7 @@ parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
 			 * list, we'll limit to 5.
 			 */
 			priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, 5);
-			nm_log_info (LOGD_SUPPLICANT, "(%s) supports %d scan SSIDs",
-				         priv->dev, priv->max_scan_ssids);
+			_LOGI ("supports %d scan SSIDs", priv->max_scan_ssids);
 		}
 	}
 }
@@ -456,8 +477,8 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
 	if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
 		priv->has_credreq = TRUE;
 
-	nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests",
-	            priv->has_credreq ? "supports" : "does not support");
+	_LOGD ("supplicant %s network credentials requests",
+	       priv->has_credreq ? "supports" : "does not support");
 
 	iface_check_ready (self);
 }
@@ -490,6 +511,7 @@ nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *se
 static void
 set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
+	NMSupplicantInterface *self;
 	gs_unref_variant GVariant *variant = NULL;
 	gs_free_error GError *error = NULL;
 
@@ -498,10 +520,11 @@ set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user
 	                                      &error);
 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 		return;
-	if (error)
-		nm_log_warn (LOGD_SUPPLICANT, "Failed to enable scan MAC address randomization");
 
-	iface_check_ready (NM_SUPPLICANT_INTERFACE (user_data));
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	if (error)
+		_LOGW ("failed to enable scan MAC address randomization (%s)", error->message);
+	iface_check_ready (self);
 }
 
 static void
@@ -665,7 +688,7 @@ props_changed_cb (GDBusProxy *proxy,
 		if (g_strcmp0 (s, priv->current_bss) != 0) {
 			g_free (priv->current_bss);
 			priv->current_bss = g_strdup (s);
-			g_object_notify (G_OBJECT (self), NM_SUPPLICANT_INTERFACE_CURRENT_BSS);
+			_notify (self, PROP_CURRENT_BSS);
 		}
 	}
 
@@ -683,10 +706,8 @@ props_changed_cb (GDBusProxy *proxy,
 		 * AP will be positive.
 		 */
 		priv->disconnect_reason = i32;
-		if (priv->disconnect_reason != 0) {
-			nm_log_warn (LOGD_SUPPLICANT, "Connection disconnected (reason %d)",
-				         priv->disconnect_reason);
-		}
+		if (priv->disconnect_reason != 0)
+			_LOGW ("connection disconnected (reason %d)", priv->disconnect_reason);
 	}
 
 	g_object_thaw_notify (G_OBJECT (self));
@@ -701,8 +722,9 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
 
 	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			nm_log_warn (LOGD_SUPPLICANT, "Failed to acquire wpa_supplicant interface proxy: (%s)", error->message);
-			set_state (NM_SUPPLICANT_INTERFACE (user_data), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+			self = NM_SUPPLICANT_INTERFACE (user_data);
+			_LOGW ("failed to acquire wpa_supplicant interface proxy: (%s)", error->message);
+			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
 		}
 		return;
 	}
@@ -781,7 +803,7 @@ interface_add_done (NMSupplicantInterface *self, const char *path)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev);
+	_LOGD ("interface added to supplicant");
 
 	priv->object_path = g_strdup (path);
 	priv->iface_proxy = g_object_new (G_TYPE_DBUS_PROXY,
@@ -822,7 +844,7 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 		interface_add_done (self, path);
 	} else {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message);
+		_LOGE ("error getting interface: %s", error->message);
 		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
 	}
 }
@@ -871,12 +893,11 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 		 * state.
 		 */
 		g_dbus_error_strip_remote_error (error);
-		nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s",
-		            priv->dev, error->message);
+		_LOGD ("failed to activate supplicant: %s", error->message);
 		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT);
 	} else {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", priv->dev, error->message);
+		_LOGE ("error adding interface: %s", error->message);
 		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
 	}
 }
@@ -899,9 +920,9 @@ on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d
 	wpas_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
 	if (!wpas_proxy) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			nm_log_warn (LOGD_SUPPLICANT, "Failed to acquire wpa_supplicant proxy: (%s)",
-			             error ? error->message : "unknown");
-			set_state (NM_SUPPLICANT_INTERFACE (user_data), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+			self = NM_SUPPLICANT_INTERFACE (user_data);
+			_LOGW ("failed to acquire wpa_supplicant proxy: (%s)", error->message);
+			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
 		}
 		return;
 	}
@@ -935,16 +956,14 @@ on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d
 }
 
 static void
-interface_add (NMSupplicantInterface *self, gboolean is_wireless)
+interface_add (NMSupplicantInterface *self)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
 	/* Can only start the interface from INIT state */
 	g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
 
-	nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev);
-
-	priv->is_wireless = is_wireless;
+	_LOGD ("adding interface to supplicant");
 
 	/* Move to starting to prevent double-calls of interface_add() */
 	set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
@@ -969,14 +988,18 @@ void
 nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
                                                   gboolean available)
 {
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInterfacePrivate *priv;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
+
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
 	if (available) {
 		/* This can happen if the supplicant couldn't be activated but
 		 * for some reason was started after the activation failure.
 		 */
 		if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT)
-			interface_add (self, priv->is_wireless);
+			interface_add (self);
 	} else {
 		/* The supplicant stopped; so we must tear down the interface */
 		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
@@ -994,7 +1017,8 @@ log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 	    && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
 	    && !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_warn (LOGD_SUPPLICANT, "Failed to %s: %s.", (char *) user_data, error->message);
+		nm_log_warn (_NMLOG_DOMAIN, "%s: failed to %s: %s",
+		             _NMLOG_PREFIX_NAME, (const char *) user_data, error->message);
 	}
 }
 
@@ -1048,14 +1072,17 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
 static void
 select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
+	NMSupplicantInterface *self;
 	gs_unref_variant GVariant *reply = NULL;
-	gs_free_error GError *err = NULL;
+	gs_free_error GError *error = NULL;
 
-	reply = g_dbus_proxy_call_finish (proxy, result, &err);
-	if (!reply && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-		g_dbus_error_strip_remote_error (err);
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message);
-		emit_error_helper (NM_SUPPLICANT_INTERFACE (user_data), err);
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (   !reply
+	    && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		self = NM_SUPPLICANT_INTERFACE (user_data);
+		g_dbus_error_strip_remote_error (error);
+		_LOGW ("couldn't select network config: %s", error->message);
+		emit_error_helper (self, error);
 	}
 }
 
@@ -1083,10 +1110,10 @@ add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 	NMSupplicantInterface *self;
 	NMSupplicantInterfacePrivate *priv;
 	gs_unref_variant GVariant *reply = NULL;
-	gs_free_error GError *err = NULL;
+	gs_free_error GError *error = NULL;
 
-	reply = g_dbus_proxy_call_finish (proxy, result, &err);
-	if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 		return;
 
 	self = NM_SUPPLICANT_INTERFACE (user_data);
@@ -1096,9 +1123,9 @@ add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 	if (reply)
 		call_select_network (self);
 	else {
-		g_dbus_error_strip_remote_error (err);
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message);
-		emit_error_helper (self, err);
+		g_dbus_error_strip_remote_error (error);
+		_LOGW ("couldn't set network certificates: %s", error->message);
+		emit_error_helper (self, error);
 	}
 }
 
@@ -1128,7 +1155,7 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 
 	if (error) {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_warn (LOGD_SUPPLICANT, "Adding network to supplicant failed: %s.", error->message);
+		_LOGW ("adding network to supplicant failed: %s", error->message);
 		emit_error_helper (self, error);
 		return;
 	}
@@ -1189,15 +1216,14 @@ set_mac_randomization_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user
 
 	if (!reply) {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't send MAC randomization mode to "
-		             "the supplicant interface: %s.",
-		             error->message);
+		_LOGW ("couldn't send MAC randomization mode to the supplicant interface: %s",
+		       error->message);
 		emit_error_helper (self, error);
 		return;
 	}
 
-	nm_log_info (LOGD_SUPPLICANT, "Config: set MAC randomization to %s",
-	             nm_supplicant_config_get_mac_randomization (priv->cfg));
+	_LOGI ("config: set MAC randomization to %s",
+	       nm_supplicant_config_get_mac_randomization (priv->cfg));
 
 	add_network (self);
 }
@@ -1219,14 +1245,14 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 
 	if (!reply) {
 		g_dbus_error_strip_remote_error (error);
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.",
-		             error->message);
+		_LOGW ("couldn't send AP scan mode to the supplicant interface: %s",
+		       error->message);
 		emit_error_helper (self, error);
 		return;
 	}
 
-	nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d",
-	             nm_supplicant_config_get_ap_scan (priv->cfg));
+	_LOGI ("config: set interface ap_scan to %d",
+	       nm_supplicant_config_get_ap_scan (priv->cfg));
 
 	if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) {
 		const char *mac_randomization = nm_supplicant_config_get_mac_randomization (priv->cfg);
@@ -1291,6 +1317,7 @@ nm_supplicant_interface_set_config (NMSupplicantInterface *self,
 static void
 scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
+	NMSupplicantInterface *self;
 	gs_unref_variant GVariant *reply = NULL;
 	gs_free_error GError *error = NULL;
 
@@ -1298,15 +1325,17 @@ scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 		return;
 
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+
 	if (error) {
 		if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
-			nm_log_dbg (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message);
+			_LOGD ("could not get scan request result: %s", error->message);
 		else {
 			g_dbus_error_strip_remote_error (error);
-			nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message);
+			_LOGW ("could not get scan request result: %s", error->message);
 		}
 	}
-	g_signal_emit (NM_SUPPLICANT_INTERFACE (user_data), signals[SCAN_DONE], 0, error ? FALSE : TRUE);
+	g_signal_emit (self, signals[SCAN_DONE], 0, error ? FALSE : TRUE);
 }
 
 gboolean
@@ -1394,14 +1423,6 @@ nm_supplicant_interface_state_to_string (guint32 state)
 }
 
 const char *
-nm_supplicant_interface_get_device (NMSupplicantInterface * self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
-
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev;
-}
-
-const char *
 nm_supplicant_interface_get_object_path (NMSupplicantInterface *self)
 {
 	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
@@ -1431,26 +1452,16 @@ NMSupplicantInterface *
 nm_supplicant_interface_new (const char *ifname,
                              gboolean is_wireless,
                              gboolean fast_supported,
-                             NMSupplicantFeature ap_support,
-                             gboolean start_now)
+                             NMSupplicantFeature ap_support)
 {
-	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
-
 	g_return_val_if_fail (ifname != NULL, NULL);
 
-	self = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, NULL);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	priv->dev = g_strdup (ifname);
-	priv->is_wireless = is_wireless;
-	priv->fast_supported = fast_supported;
-	priv->ap_support = ap_support;
-
-	if (start_now)
-		interface_add (self, priv->is_wireless);
-
-	return self;
+	return g_object_new (NM_TYPE_SUPPLICANT_INTERFACE,
+	                     NM_SUPPLICANT_INTERFACE_IFACE, ifname,
+	                     NM_SUPPLICANT_INTERFACE_IS_WIRELESS, is_wireless,
+	                     NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, fast_supported,
+	                     NM_SUPPLICANT_INTERFACE_AP_SUPPORT, (int) ap_support,
+	                     NULL);
 }
 
 static void
@@ -1468,7 +1479,30 @@ set_property (GObject *object,
               const GValue *value,
               GParamSpec *pspec)
 {
-	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_IFACE:
+		/* construct-only */
+		priv->dev = g_value_dup_string (value);
+		g_return_if_fail (priv->dev);
+		break;
+	case PROP_IS_WIRELESS:
+		/* construct-only */
+		priv->is_wireless = g_value_get_boolean (value);
+		break;
+	case PROP_FAST_SUPPORTED:
+		/* construct-only */
+		priv->fast_supported = g_value_get_boolean (value);
+		break;
+	case PROP_AP_SUPPORT:
+		/* construct-only */
+		priv->ap_support = g_value_get_int (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
 }
 
 static void
@@ -1535,19 +1569,44 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 	object_class->get_property = get_property;
 
 	/* Properties */
-	g_object_class_install_property
-		(object_class, PROP_SCANNING,
-		 g_param_spec_boolean ("scanning", "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_CURRENT_BSS,
-		 g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_SCANNING] =
+	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_SCANNING, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_CURRENT_BSS] =
+	    g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IFACE] =
+	    g_param_spec_string (NM_SUPPLICANT_INTERFACE_IFACE, "", "",
+	                         NULL,
+	                         G_PARAM_WRITABLE |
+	                         G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_IS_WIRELESS] =
+	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_IS_WIRELESS, "", "",
+	                          TRUE,
+	                          G_PARAM_WRITABLE |
+	                          G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_FAST_SUPPORTED] =
+	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, "", "",
+	                          TRUE,
+	                          G_PARAM_WRITABLE |
+	                          G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_AP_SUPPORT] =
+	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_AP_SUPPORT, "", "",
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      NM_SUPPLICANT_FEATURE_YES,
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      G_PARAM_WRITABLE |
+	                      G_PARAM_CONSTRUCT_ONLY |
+	                      G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	/* Signals */
 	signals[STATE] =
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
index 2f866076..dbe77b1c 100644
--- a/src/supplicant-manager/nm-supplicant-interface.h
+++ b/src/supplicant-manager/nm-supplicant-interface.h
@@ -55,7 +55,12 @@ enum {
 #define NM_SUPPLICANT_INTERFACE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass))
 
 /* Properties */
+#define NM_SUPPLICANT_INTERFACE_IFACE            "iface"
+#define NM_SUPPLICANT_INTERFACE_SCANNING         "scanning"
 #define NM_SUPPLICANT_INTERFACE_CURRENT_BSS      "current-bss"
+#define NM_SUPPLICANT_INTERFACE_IS_WIRELESS      "is-wireless"
+#define NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED   "fast-supported"
+#define NM_SUPPLICANT_INTERFACE_AP_SUPPORT       "ap-support"
 
 /* Signals */
 #define NM_SUPPLICANT_INTERFACE_STATE            "state"
@@ -119,8 +124,7 @@ GType nm_supplicant_interface_get_type (void);
 NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname,
                                                      gboolean is_wireless,
                                                      gboolean fast_supported,
-                                                     NMSupplicantFeature ap_support,
-                                                     gboolean start_now);
+                                                     NMSupplicantFeature ap_support);
 
 void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
                                                        gboolean available);
@@ -131,8 +135,6 @@ gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
 
 void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
 
-const char * nm_supplicant_interface_get_device (NMSupplicantInterface * iface);
-
 const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface);
 
 gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self, const GPtrArray *ssids);
diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c
index 29c0cd42..1b352527 100644
--- a/src/supplicant-manager/nm-supplicant-manager.c
+++ b/src/supplicant-manager/nm-supplicant-manager.c
@@ -19,11 +19,10 @@
  * Copyright (C) 2007 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-supplicant-manager.h"
 #include "nm-supplicant-interface.h"
 #include "nm-supplicant-types.h"
@@ -40,7 +39,7 @@ typedef struct {
 	GCancellable *   cancellable;
 	gboolean         running;
 
-	GHashTable *      ifaces;
+	GSList          *ifaces;
 	gboolean          fast_supported;
 	NMSupplicantFeature ap_support;
 	guint             die_count_reset_id;
@@ -59,67 +58,40 @@ die_count_exceeded (guint32 count)
 	return count > 2;
 }
 
-NMSupplicantInterface *
-nm_supplicant_manager_iface_get (NMSupplicantManager * self,
-                                 const char *ifname,
-                                 gboolean is_wireless)
+static gboolean
+is_available (NMSupplicantManager *self)
 {
-	NMSupplicantManagerPrivate *priv;
-	NMSupplicantInterface *iface = NULL;
-	gboolean start_now;
-
-	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL);
-	g_return_val_if_fail (ifname != NULL, NULL);
-
-	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-
-	iface = g_hash_table_lookup (priv->ifaces, ifname);
-	if (!iface) {
-		/* If we're making the supplicant take a time out for a bit, don't
-		 * let the supplicant interface start immediately, just let it hang
-		 * around in INIT state until we're ready to talk to the supplicant
-		 * again.
-		 */
-		start_now = !die_count_exceeded (priv->die_count);
-
-		nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname);
-		iface = nm_supplicant_interface_new (ifname,
-		                                     is_wireless,
-		                                     priv->fast_supported,
-		                                     priv->ap_support,
-		                                     start_now);
-		if (iface) {
-			g_hash_table_insert (priv->ifaces,
-			                     (char *) nm_supplicant_interface_get_ifname (iface),
-			                     iface);
-		}
-	} else {
-		nm_log_dbg (LOGD_SUPPLICANT, "(%s): returning existing supplicant interface", ifname);
-	}
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
 
-	return iface;
+	return    priv->running
+	       && !die_count_exceeded (priv->die_count);
 }
 
-void
-nm_supplicant_manager_iface_release (NMSupplicantManager *self,
-                                     NMSupplicantInterface *iface)
+/********************************************************************/
+
+static void
+_sup_iface_last_ref (gpointer data,
+                     GObject *object,
+                     gboolean is_last_ref)
 {
+	NMSupplicantManager *self = data;
 	NMSupplicantManagerPrivate *priv;
-	const char *ifname, *op;
+	NMSupplicantInterface *sup_iface = (NMSupplicantInterface *) object;
+	const char *op;
 
 	g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self));
-	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface));
-
-	ifname = nm_supplicant_interface_get_ifname (iface);
-	g_assert (ifname);
+	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (sup_iface));
+	g_return_if_fail (is_last_ref);
 
 	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
 
-	g_return_if_fail (g_hash_table_lookup (priv->ifaces, ifname) == iface);
+	if (!g_slist_find (priv->ifaces, sup_iface))
+		g_return_if_reached ();
 
 	/* Ask wpa_supplicant to remove this interface */
-	op = nm_supplicant_interface_get_object_path (iface);
-	if (priv->running && priv->proxy && op) {
+	if (   priv->running
+	    && priv->proxy
+	    && (op = nm_supplicant_interface_get_object_path (sup_iface))) {
 		g_dbus_proxy_call (priv->proxy,
 		                   "RemoveInterface",
 		                   g_variant_new ("(o)", op),
@@ -130,15 +102,69 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self,
 		                   NULL);
 	}
 
-	g_hash_table_remove (priv->ifaces, ifname);
+	priv->ifaces = g_slist_remove (priv->ifaces, sup_iface);
+	g_object_remove_toggle_ref ((GObject *) sup_iface, _sup_iface_last_ref, self);
+}
+
+/**
+ * nm_supplicant_manager_create_interface:
+ * @self: the #NMSupplicantManager
+ * @ifname: the interface for which to obtain the supplicant interface
+ * @is_wireless: whether the interface is supposed to be wireless.
+ *
+ * Note: the manager owns a reference to the instance and the only way to
+ *   get the manager to release it, is by dropping all other references
+ *   to the supplicant-interface (or destroying the manager).
+ *
+ * Returns: (transfer full): returns a #NMSupplicantInterface or %NULL.
+ *   Must be unrefed at the end.
+ * */
+NMSupplicantInterface *
+nm_supplicant_manager_create_interface (NMSupplicantManager *self,
+                                        const char *ifname,
+                                        gboolean is_wireless)
+{
+	NMSupplicantManagerPrivate *priv;
+	NMSupplicantInterface *iface;
+	GSList *ifaces;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL);
+	g_return_val_if_fail (ifname != NULL, NULL);
+
+	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+
+	nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname);
+
+	/* assert against not requesting duplicate interfaces. */
+	for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next) {
+		if (g_strcmp0 (nm_supplicant_interface_get_ifname (ifaces->data), ifname) == 0)
+			g_return_val_if_reached (NULL);
+	}
+
+	iface = nm_supplicant_interface_new (ifname,
+	                                     is_wireless,
+	                                     priv->fast_supported,
+	                                     priv->ap_support);
+
+	priv->ifaces = g_slist_prepend (priv->ifaces, iface);
+	g_object_add_toggle_ref ((GObject *) iface, _sup_iface_last_ref, self);
+
+	/* If we're making the supplicant take a time out for a bit, don't
+	 * let the supplicant interface start immediately, just let it hang
+	 * around in INIT state until we're ready to talk to the supplicant
+	 * again.
+	 */
+	if (is_available (self))
+		nm_supplicant_interface_set_supplicant_available (iface, TRUE);
+
+	return iface;
 }
 
 static void
 update_capabilities (NMSupplicantManager *self)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	NMSupplicantInterface *iface;
-	GHashTableIter hash_iter;
+	GSList *ifaces;
 	const char **array;
 	GVariant *value;
 
@@ -166,9 +192,8 @@ update_capabilities (NMSupplicantManager *self)
 	}
 
 	/* Tell all interfaces about results of the AP check */
-	g_hash_table_iter_init (&hash_iter, priv->ifaces);
-	while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &iface))
-		nm_supplicant_interface_set_ap_support (iface, priv->ap_support);
+	for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next)
+		nm_supplicant_interface_set_ap_support (ifaces->data, priv->ap_support);
 
 	nm_log_dbg (LOGD_SUPPLICANT, "AP mode is %ssupported",
 	            (priv->ap_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
@@ -194,23 +219,20 @@ static void
 availability_changed (NMSupplicantManager *self, gboolean available)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	GList *ifaces, *iter;
-
-	/* priv->ifaces may be modified if availability changes; can't use GHashTableIter */
-	ifaces = g_hash_table_get_values (priv->ifaces);
-	for (iter = ifaces; iter; iter = iter->next)
-		nm_supplicant_interface_set_supplicant_available (NM_SUPPLICANT_INTERFACE (iter->data), available);
-	g_list_free (ifaces);
-}
+	GSList *ifaces, *iter;
 
-static gboolean
-is_available (NMSupplicantManager *self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE);
+	if (!priv->ifaces)
+		return;
 
-	if (die_count_exceeded (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->die_count))
-		return FALSE;
-	return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->running;
+	/* setting the supplicant as unavailable might cause the caller to unref
+	 * the supplicant (and thus remove the instance from the list of interfaces.
+	 * Delay that by taking an additional reference first. */
+	ifaces = g_slist_copy (priv->ifaces);
+	for (iter = ifaces; iter; iter = iter->next)
+		g_object_ref (iter->data);
+	for (iter = ifaces; iter; iter = iter->next)
+		nm_supplicant_interface_set_supplicant_available (iter->data, available);
+	g_slist_free_full (ifaces, g_object_unref);
 }
 
 static void
@@ -326,8 +348,6 @@ nm_supplicant_manager_init (NMSupplicantManager *self)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
 
-	priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
-
 	priv->cancellable = g_cancellable_new ();
 	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
 	                          G_DBUS_PROXY_FLAGS_NONE,
@@ -343,7 +363,9 @@ nm_supplicant_manager_init (NMSupplicantManager *self)
 static void
 dispose (GObject *object)
 {
-	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object);
+	NMSupplicantManager *self = (NMSupplicantManager *) object;
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	GSList *ifaces;
 
 	nm_clear_g_source (&priv->die_count_reset_id);
 
@@ -352,7 +374,13 @@ dispose (GObject *object)
 		g_clear_object (&priv->cancellable);
 	}
 
-	g_clear_pointer (&priv->ifaces, g_hash_table_unref);
+	if (priv->ifaces) {
+		for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next)
+			g_object_remove_toggle_ref (ifaces->data, _sup_iface_last_ref, self);
+		g_slist_free (priv->ifaces);
+		priv->ifaces = NULL;
+	}
+
 	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h
index d7456467..b0ce6a52 100644
--- a/src/supplicant-manager/nm-supplicant-manager.h
+++ b/src/supplicant-manager/nm-supplicant-manager.h
@@ -49,11 +49,8 @@ GType nm_supplicant_manager_get_type (void);
 
 NMSupplicantManager *nm_supplicant_manager_get (void);
 
-NMSupplicantInterface *nm_supplicant_manager_iface_get (NMSupplicantManager *mgr,
-                                                        const char *ifname,
-                                                        gboolean is_wireless);
-
-void nm_supplicant_manager_iface_release (NMSupplicantManager *mgr,
-                                          NMSupplicantInterface *iface);
+NMSupplicantInterface *nm_supplicant_manager_create_interface (NMSupplicantManager *mgr,
+                                                               const char *ifname,
+                                                               gboolean is_wireless);
 
 #endif /* __NETWORKMANAGER_SUPPLICANT_MANAGER_H__ */
diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.c b/src/supplicant-manager/nm-supplicant-settings-verify.c
index f2d56540..ec660d18 100644
--- a/src/supplicant-manager/nm-supplicant-settings-verify.c
+++ b/src/supplicant-manager/nm-supplicant-settings-verify.c
@@ -18,14 +18,13 @@
  * Copyright (C) 2006 - 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "nm-supplicant-settings-verify.h"
 
 struct Opt {
diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c
index bd532b24..0c3e9a47 100644
--- a/src/supplicant-manager/tests/test-supplicant-config.c
+++ b/src/supplicant-manager/tests/test-supplicant-config.c
@@ -18,7 +18,7 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -34,7 +34,6 @@
 
 #include "nm-supplicant-config.h"
 #include "nm-supplicant-settings-verify.h"
-#include "nm-default.h"
 
 #include "nm-test-utils.h"
 
diff --git a/src/systemd/nm-sd-adapt.c b/src/systemd/nm-sd-adapt.c
index 8b29aed5..fa7cd938 100644
--- a/src/systemd/nm-sd-adapt.c
+++ b/src/systemd/nm-sd-adapt.c
@@ -16,9 +16,10 @@
  * Copyright (C) 2014 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-sd-adapt.h"
 
-#include <glib.h>
 #include <unistd.h>
 #include <errno.h>
 
diff --git a/src/systemd/nm-sd-adapt.h b/src/systemd/nm-sd-adapt.h
index 967cb48f..f48c86f1 100644
--- a/src/systemd/nm-sd-adapt.h
+++ b/src/systemd/nm-sd-adapt.h
@@ -19,15 +19,13 @@
 #ifndef NM_SD_ADAPT_H
 #define NM_SD_ADAPT_H
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <stdbool.h>
 #include <syslog.h>
 #include <sys/resource.h>
 #include <time.h>
 
-#include "nm-default.h"
-
 #define noreturn G_GNUC_NORETURN
 
 #ifndef CLOCK_BOOTTIME
@@ -114,6 +112,12 @@ G_STMT_START { \
 
 /*****************************************************************************/
 
+/* work around missing uchar.h */
+typedef guint16 char16_t;
+typedef guint32 char32_t;
+
+/*****************************************************************************/
+
 /* Can't include both net/if.h and linux/if.h; so have to define this here */
 #ifndef IFNAMSIZ
 #define IFNAMSIZ 16
diff --git a/src/systemd/src/basic/alloc-util.c b/src/systemd/src/basic/alloc-util.c
index a849e139..5fae60c9 100644
--- a/src/systemd/src/basic/alloc-util.c
+++ b/src/systemd/src/basic/alloc-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index f9be5e85..679ba7f3 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <alloca.h>
 #include <stddef.h>
 #include <stdlib.h>
diff --git a/src/systemd/src/basic/async.h b/src/systemd/src/basic/async.h
index 44b886a6..9bd13ff6 100644
--- a/src/systemd/src/basic/async.h
+++ b/src/systemd/src/basic/async.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 int asynchronous_job(void* (*func)(void *p), void *arg);
 
 int asynchronous_sync(void);
diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c
index fe1737e5..34fb0ced 100644
--- a/src/systemd/src/basic/escape.c
+++ b/src/systemd/src/basic/escape.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -121,16 +119,18 @@ char *cescape(const char *s) {
         return cescape_length(s, strlen(s));
 }
 
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
         int r = 1;
 
         assert(p);
         assert(*p);
         assert(ret);
 
-        /* Unescapes C style. Returns the unescaped character in ret,
-         * unless we encountered a \u sequence in which case the full
-         * unicode character is returned in ret_unicode, instead. */
+        /* Unescapes C style. Returns the unescaped character in ret.
+         * Sets *eight_bit to true if the escaped sequence either fits in
+         * one byte in UTF-8 or is a non-unicode literal byte and should
+         * instead be copied directly.
+         */
 
         if (length != (size_t) -1 && length < 1)
                 return -EINVAL;
@@ -192,7 +192,8 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (a == 0 && b == 0)
                         return -EINVAL;
 
-                *ret = (char) ((a << 4U) | b);
+                *ret = (a << 4U) | b;
+                *eight_bit = true;
                 r = 3;
                 break;
         }
@@ -219,16 +220,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (c == 0)
                         return -EINVAL;
 
-                if (c < 128)
-                        *ret = c;
-                else {
-                        if (!ret_unicode)
-                                return -EINVAL;
-
-                        *ret = 0;
-                        *ret_unicode = c;
-                }
-
+                *ret = c;
                 r = 5;
                 break;
         }
@@ -238,7 +230,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
 
                 int a[8];
                 unsigned i;
-                uint32_t c;
+                char32_t c;
 
                 if (length != (size_t) -1 && length < 9)
                         return -EINVAL;
@@ -260,16 +252,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (!unichar_is_valid(c))
                         return -EINVAL;
 
-                if (c < 128)
-                        *ret = c;
-                else {
-                        if (!ret_unicode)
-                                return -EINVAL;
-
-                        *ret = 0;
-                        *ret_unicode = c;
-                }
-
+                *ret = c;
                 r = 9;
                 break;
         }
@@ -284,7 +267,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
         case '7': {
                 /* octal encoding */
                 int a, b, c;
-                uint32_t m;
+                char32_t m;
 
                 if (length != (size_t) -1 && length < 3)
                         return -EINVAL;
@@ -311,6 +294,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                         return -EINVAL;
 
                 *ret = m;
+                *eight_bit = true;
                 r = 3;
                 break;
         }
@@ -343,8 +327,8 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
 
         for (f = s, t = r + pl; f < s + length; f++) {
                 size_t remaining;
-                uint32_t u;
-                char c;
+                bool eight_bit = false;
+                char32_t u;
                 int k;
 
                 remaining = s + length - f;
@@ -367,7 +351,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
                         return -EINVAL;
                 }
 
-                k = cunescape_one(f + 1, remaining - 1, &c, &u);
+                k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
                 if (k < 0) {
                         if (flags & UNESCAPE_RELAX) {
                                 /* Invalid escape code, let's take it literal then */
@@ -379,14 +363,13 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
                         return k;
                 }
 
-                if (c != 0)
-                        /* Non-Unicode? Let's encode this directly */
-                        *(t++) = c;
+                f += k;
+                if (eight_bit)
+                        /* One byte? Set directly as specified */
+                        *(t++) = u;
                 else
-                        /* Unicode? Then let's encode this in UTF-8 */
+                        /* Otherwise encode as multi-byte UTF-8 */
                         t += utf8_encode_unichar(t, u);
-
-                f += k;
         }
 
         *t = 0;
diff --git a/src/systemd/src/basic/escape.h b/src/systemd/src/basic/escape.h
index da8f7143..ce518111 100644
--- a/src/systemd/src/basic/escape.h
+++ b/src/systemd/src/basic/escape.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,14 +19,18 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <sys/types.h>
+#if 0 /* NM_IGNORED */
+#include <uchar.h>
+#endif /* NM_IGNORED */
 
 #include "string-util.h"
+#if 0 /* NM_IGNORED */
+#include "missing.h"
+#endif /* NM_IGNORED */
 
 /* What characters are special in the shell? */
 /* must be escaped outside and inside double-quotes */
@@ -47,7 +49,7 @@ size_t cescape_char(char c, char *buf);
 int cunescape(const char *s, UnescapeFlags flags, char **ret);
 int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode);
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
 char *xescape(const char *s, const char *bad);
 
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 3828148c..e92b3740 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index 3614dc78..44528c6e 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <dirent.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -75,3 +71,7 @@ int same_fd(int a, int b);
 void cmsg_close_all(struct msghdr *mh);
 
 bool fdname_is_valid(const char *s);
+
+/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
+#define ERRNO_IS_DISCONNECT(r) \
+        IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 913c6293..9b091213 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -169,7 +167,7 @@ int read_one_line_file(const char *fn, char **line) {
         if (!fgets(t, sizeof(t), f)) {
 
                 if (ferror(f))
-                        return errno ? -errno : -EIO;
+                        return errno > 0 ? -errno : -EIO;
 
                 t[0] = 0;
         }
@@ -1070,7 +1068,7 @@ int fflush_and_check(FILE *f) {
         fflush(f);
 
         if (ferror(f))
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
@@ -1259,3 +1257,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
         *ret = (usec_t) t;
         return 0;
 }
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
+        int r;
+
+        assert(s);
+
+        /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
+         * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
+         * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
+         * element, but not before the first one. */
+
+        if (!f)
+                f = stdout;
+
+        if (space) {
+                if (!separator)
+                        separator = " ";
+
+                if (*space) {
+                        r = fputs(separator, f);
+                        if (r < 0)
+                                return r;
+                }
+
+                *space = true;
+        }
+
+        return fputs(s, f);
+}
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index daaa7802..8084895f 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <dirent.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -84,3 +80,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret);
 
 int write_timestamp_file_atomic(const char *fn, usec_t n);
 int read_timestamp_file(const char *fn, usec_t *ret);
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 741bd31f..a3306e3d 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -352,7 +350,8 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
         if (parents)
                 mkdir_parents(path, 0755);
 
-        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
+                        (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
         if (fd < 0)
                 return -errno;
 
@@ -492,7 +491,7 @@ int get_files_in_directory(const char *path, char ***list) {
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
                 if (!de)
                         break;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index d13c0194..0e2fcb21 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <fcntl.h>
 #include <limits.h>
 #include <stdbool.h>
diff --git a/src/systemd/src/basic/hash-funcs.c b/src/systemd/src/basic/hash-funcs.c
new file mode 100644
index 00000000..4a29f43c
--- /dev/null
+++ b/src/systemd/src/basic/hash-funcs.c
@@ -0,0 +1,83 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2014 Michal Schmidt
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "nm-sd-adapt.h"
+
+#include "hash-funcs.h"
+
+void string_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, strlen(p) + 1, state);
+}
+
+int string_compare_func(const void *a, const void *b) {
+        return strcmp(a, b);
+}
+
+const struct hash_ops string_hash_ops = {
+        .hash = string_hash_func,
+        .compare = string_compare_func
+};
+
+void trivial_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(&p, sizeof(p), state);
+}
+
+int trivial_compare_func(const void *a, const void *b) {
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops trivial_hash_ops = {
+        .hash = trivial_hash_func,
+        .compare = trivial_compare_func
+};
+
+void uint64_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, sizeof(uint64_t), state);
+}
+
+int uint64_compare_func(const void *_a, const void *_b) {
+        uint64_t a, b;
+        a = *(const uint64_t*) _a;
+        b = *(const uint64_t*) _b;
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops uint64_hash_ops = {
+        .hash = uint64_hash_func,
+        .compare = uint64_compare_func
+};
+
+#if SIZEOF_DEV_T != 8
+void devt_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, sizeof(dev_t), state);
+}
+
+int devt_compare_func(const void *_a, const void *_b) {
+        dev_t a, b;
+        a = *(const dev_t*) _a;
+        b = *(const dev_t*) _b;
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops devt_hash_ops = {
+        .hash = devt_hash_func,
+        .compare = devt_compare_func
+};
+#endif
diff --git a/src/systemd/src/basic/hash-funcs.h b/src/systemd/src/basic/hash-funcs.h
new file mode 100644
index 00000000..299189d1
--- /dev/null
+++ b/src/systemd/src/basic/hash-funcs.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2014 Michal Schmidt
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+#include "siphash24.h"
+
+typedef void (*hash_func_t)(const void *p, struct siphash *state);
+typedef int (*compare_func_t)(const void *a, const void *b);
+
+struct hash_ops {
+        hash_func_t hash;
+        compare_func_t compare;
+};
+
+void string_hash_func(const void *p, struct siphash *state);
+int string_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops string_hash_ops;
+
+/* This will compare the passed pointers directly, and will not
+ * dereference them. This is hence not useful for strings or
+ * suchlike. */
+void trivial_hash_func(const void *p, struct siphash *state);
+int trivial_compare_func(const void *a, const void *b) _const_;
+extern const struct hash_ops trivial_hash_ops;
+
+/* 32bit values we can always just embed in the pointer itself, but
+ * in order to support 32bit archs we need store 64bit values
+ * indirectly, since they don't fit in a pointer. */
+void uint64_hash_func(const void *p, struct siphash *state);
+int uint64_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops uint64_hash_ops;
+
+/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
+ * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
+#if SIZEOF_DEV_T != 8
+void devt_hash_func(const void *p, struct siphash *state) _pure_;
+int devt_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops devt_hash_ops = {
+        .hash = devt_hash_func,
+        .compare = devt_compare_func
+};
+#else
+#define devt_hash_func uint64_hash_func
+#define devt_compare_func uint64_compare_func
+#define devt_hash_ops uint64_hash_ops
+#endif
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index 4ebb73b5..85071d3e 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -284,66 +282,6 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
         },
 };
 
-void string_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, strlen(p) + 1, state);
-}
-
-int string_compare_func(const void *a, const void *b) {
-        return strcmp(a, b);
-}
-
-const struct hash_ops string_hash_ops = {
-        .hash = string_hash_func,
-        .compare = string_compare_func
-};
-
-void trivial_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(&p, sizeof(p), state);
-}
-
-int trivial_compare_func(const void *a, const void *b) {
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops trivial_hash_ops = {
-        .hash = trivial_hash_func,
-        .compare = trivial_compare_func
-};
-
-void uint64_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, sizeof(uint64_t), state);
-}
-
-int uint64_compare_func(const void *_a, const void *_b) {
-        uint64_t a, b;
-        a = *(const uint64_t*) _a;
-        b = *(const uint64_t*) _b;
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops uint64_hash_ops = {
-        .hash = uint64_hash_func,
-        .compare = uint64_compare_func
-};
-
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, sizeof(dev_t), state);
-}
-
-int devt_compare_func(const void *_a, const void *_b) {
-        dev_t a, b;
-        a = *(const dev_t*) _a;
-        b = *(const dev_t*) _b;
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops devt_hash_ops = {
-        .hash = devt_hash_func,
-        .compare = devt_compare_func
-};
-#endif
-
 static unsigned n_buckets(HashmapBase *h) {
         return h->has_indirect ? h->indirect.n_buckets
                                : hashmap_type_info[h->type].n_direct_buckets;
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index 0485e1d4..6d1ae48b 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,14 +20,12 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <limits.h>
 #include <stdbool.h>
 #include <stddef.h>
 
+#include "hash-funcs.h"
 #include "macro.h"
-#include "siphash24.h"
 #include "util.h"
 
 /*
@@ -72,47 +68,6 @@ typedef struct {
 #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
 #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
 
-typedef void (*hash_func_t)(const void *p, struct siphash *state);
-typedef int (*compare_func_t)(const void *a, const void *b);
-
-struct hash_ops {
-        hash_func_t hash;
-        compare_func_t compare;
-};
-
-void string_hash_func(const void *p, struct siphash *state);
-int string_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops string_hash_ops;
-
-/* This will compare the passed pointers directly, and will not
- * dereference them. This is hence not useful for strings or
- * suchlike. */
-void trivial_hash_func(const void *p, struct siphash *state);
-int trivial_compare_func(const void *a, const void *b) _const_;
-extern const struct hash_ops trivial_hash_ops;
-
-/* 32bit values we can always just embedd in the pointer itself, but
- * in order to support 32bit archs we need store 64bit values
- * indirectly, since they don't fit in a pointer. */
-void uint64_hash_func(const void *p, struct siphash *state);
-int uint64_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops uint64_hash_ops;
-
-/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
- * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) _pure_;
-int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
-        .hash = devt_hash_func,
-        .compare = devt_compare_func
-};
-#else
-#define devt_hash_func uint64_hash_func
-#define devt_compare_func uint64_compare_func
-#define devt_hash_ops uint64_hash_ops
-#endif
-
 /* Macros for type checking */
 #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
         (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c
index 1f257bd5..99eaa7a2 100644
--- a/src/systemd/src/basic/hexdecoct.c
+++ b/src/systemd/src/basic/hexdecoct.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -516,14 +514,14 @@ int unbase64char(char c) {
         return -EINVAL;
 }
 
-char *base64mem(const void *p, size_t l) {
+ssize_t base64mem(const void *p, size_t l, char **out) {
         char *r, *z;
         const uint8_t *x;
 
         /* three input bytes makes four output bytes, padding is added so we must round up */
         z = r = malloc(4 * (l + 2) / 3 + 1);
         if (!r)
-                return NULL;
+                return -ENOMEM;
 
         for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
@@ -551,9 +549,64 @@ char *base64mem(const void *p, size_t l) {
         }
 
         *z = 0;
-        return r;
+        *out = r;
+        return z - r;
 }
 
+static int base64_append_width(char **prefix, int plen,
+                               const char *sep, int indent,
+                               const void *p, size_t l,
+                               int width) {
+
+        _cleanup_free_ char *x = NULL;
+        char *t, *s;
+        ssize_t slen, len, avail;
+        int line, lines;
+
+        len = base64mem(p, l, &x);
+        if (len <= 0)
+                return len;
+
+        lines = (len + width - 1) / width;
+
+        slen = sep ? strlen(sep) : 0;
+        t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
+        if (!t)
+                return -ENOMEM;
+
+        memcpy(t + plen, sep, slen);
+
+        for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
+                int act = MIN(width, avail);
+
+                if (line > 0 || sep) {
+                        memset(s, ' ', indent);
+                        s += indent;
+                }
+
+                memcpy(s, x + width * line, act);
+                s += act;
+                *(s++) = line < lines - 1 ? '\n' : '\0';
+                avail -= act;
+        }
+        assert(avail == 0);
+
+        *prefix = t;
+        return 0;
+}
+
+int base64_append(char **prefix, int plen,
+                  const void *p, size_t l,
+                  int indent, int width) {
+        if (plen > width / 2 || plen + indent > width)
+                /* leave indent on the left, keep last column free */
+                return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
+        else
+                /* leave plen on the left, keep last column free */
+                return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
+};
+
+
 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
         _cleanup_free_ uint8_t *r = NULL;
         int a, b, c, d;
diff --git a/src/systemd/src/basic/hexdecoct.h b/src/systemd/src/basic/hexdecoct.h
index ec4115f2..1ba2f69e 100644
--- a/src/systemd/src/basic/hexdecoct.h
+++ b/src/systemd/src/basic/hexdecoct.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -51,7 +47,10 @@ int unbase64char(char c) _const_;
 char *base32hexmem(const void *p, size_t l, bool padding);
 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
 
-char *base64mem(const void *p, size_t l);
+ssize_t base64mem(const void *p, size_t l, char **out);
+int base64_append(char **prefix, int plen,
+                  const void *p, size_t l,
+                  int margin, int width);
 int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
 
 void hexdump(FILE *f, const void *p, size_t s);
diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c
index 50f81925..5875f4b4 100644
--- a/src/systemd/src/basic/hostname-util.c
+++ b/src/systemd/src/basic/hostname-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/hostname-util.h b/src/systemd/src/basic/hostname-util.h
index a2e69200..d062edde 100644
--- a/src/systemd/src/basic/hostname-util.h
+++ b/src/systemd/src/basic/hostname-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 
 #include "macro.h"
diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c
index 5027f401..10898dae 100644
--- a/src/systemd/src/basic/in-addr-util.c
+++ b/src/systemd/src/basic/in-addr-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -221,7 +219,7 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
         errno = 0;
         if (!inet_ntop(family, u, x, l)) {
                 free(x);
-                return errno ? -errno : -EINVAL;
+                return errno > 0 ? -errno : -EINVAL;
         }
 
         *ret = x;
@@ -238,7 +236,7 @@ int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
 
         errno = 0;
         if (inet_pton(family, s, ret) <= 0)
-                return errno ? -errno : -EINVAL;
+                return errno > 0 ? -errno : -EINVAL;
 
         return 0;
 }
diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h
index f94aba83..17798ce8 100644
--- a/src/systemd/src/basic/in-addr-util.h
+++ b/src/systemd/src/basic/in-addr-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <netinet/in.h>
 #include <stddef.h>
 #include <sys/socket.h>
@@ -35,6 +31,11 @@ union in_addr_union {
         struct in6_addr in6;
 };
 
+struct in_addr_data {
+        int family;
+        union in_addr_union address;
+};
+
 int in_addr_is_null(int family, const union in_addr_union *u);
 int in_addr_is_link_local(int family, const union in_addr_union *u);
 int in_addr_is_localhost(int family, const union in_addr_union *u);
diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c
index c7bb1e78..1b2fc99f 100644
--- a/src/systemd/src/basic/io-util.c
+++ b/src/systemd/src/basic/io-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/io-util.h b/src/systemd/src/basic/io-util.h
index a6260965..142c940d 100644
--- a/src/systemd/src/basic/io-util.h
+++ b/src/systemd/src/basic/io-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -79,3 +75,21 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
 
         return k;
 }
+
+static inline bool FILE_SIZE_VALID(uint64_t l) {
+        /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than
+         * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */
+
+        return (l >> 63) == 0;
+}
+
+static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
+
+        /* Same as above, but allows one extra value: -1 as indication for infinity. */
+
+        if (l == (uint64_t) -1)
+                return true;
+
+        return FILE_SIZE_VALID(l);
+
+}
diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h
index 3ac38418..c68185f5 100644
--- a/src/systemd/src/basic/list.h
+++ b/src/systemd/src/basic/list.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 /* The head of the linked list. Use this in the structure that shall
  * contain the head of the linked list */
 #define LIST_HEAD(t,name)                                               \
diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h
index bc316189..d0ec4dfa 100644
--- a/src/systemd/src/basic/log.h
+++ b/src/systemd/src/basic/log.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,13 +19,12 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <errno.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <sys/signalfd.h>
+#include <sys/socket.h>
 #include <syslog.h>
 
 #include "sd-id128.h"
@@ -130,6 +127,15 @@ int log_oom_internal(
                 int line,
                 const char *func);
 
+int log_format_iovec(
+                struct iovec *iovec,
+                unsigned iovec_len,
+                unsigned *n,
+                bool newline_separator,
+                int error,
+                const char *format,
+                va_list ap);
+
 /* This modifies the buffer passed! */
 int log_dump_internal(
                 int level,
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 222f3c42..d12e09a7 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <assert.h>
 #include <inttypes.h>
 #include <stdbool.h>
@@ -331,18 +327,47 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
 #define SET_FLAG(v, flag, b) \
         (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
 
-#define IN_SET(x, y, ...)                                               \
-        ({                                                              \
-                static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \
-                const typeof(y) _x = (x);                               \
-                unsigned _i;                                            \
-                bool _found = false;                                    \
-                for (_i = 0; _i < ELEMENTSOF(_array); _i++)             \
-                        if (_array[_i] == _x) {                         \
-                                _found = true;                          \
-                                break;                                  \
-                        }                                               \
-                _found;                                                 \
+#define CASE_F(X) case X:
+#define CASE_F_1(CASE, X) CASE_F(X)
+#define CASE_F_2(CASE, X, ...)  CASE(X) CASE_F_1(CASE, __VA_ARGS__)
+#define CASE_F_3(CASE, X, ...)  CASE(X) CASE_F_2(CASE, __VA_ARGS__)
+#define CASE_F_4(CASE, X, ...)  CASE(X) CASE_F_3(CASE, __VA_ARGS__)
+#define CASE_F_5(CASE, X, ...)  CASE(X) CASE_F_4(CASE, __VA_ARGS__)
+#define CASE_F_6(CASE, X, ...)  CASE(X) CASE_F_5(CASE, __VA_ARGS__)
+#define CASE_F_7(CASE, X, ...)  CASE(X) CASE_F_6(CASE, __VA_ARGS__)
+#define CASE_F_8(CASE, X, ...)  CASE(X) CASE_F_7(CASE, __VA_ARGS__)
+#define CASE_F_9(CASE, X, ...)  CASE(X) CASE_F_8(CASE, __VA_ARGS__)
+#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
+#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
+#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
+#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
+#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
+#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
+#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
+#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
+#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
+#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
+#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
+
+#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
+#define FOR_EACH_MAKE_CASE(...) \
+        GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
+                               CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
+                   (CASE_F,__VA_ARGS__)
+
+#define IN_SET(x, ...)                          \
+        ({                                      \
+                bool _found = false;            \
+                /* If the build breaks in the line below, you need to extend the case macros */ \
+                static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
+                switch(x) {                     \
+                FOR_EACH_MAKE_CASE(__VA_ARGS__) \
+                        _found = true;          \
+                        break;                  \
+                default:                        \
+                        break;                  \
+                }                               \
+                _found;                         \
         })
 
 /* Define C11 thread_local attribute even on older gcc compiler
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index 511b962f..c1635964 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index e9753adb..fea7841b 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stddef.h>
 
 struct pool;
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index 86aec95c..beb90fa6 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -85,7 +83,7 @@ int parse_mode(const char *s, mode_t *ret) {
 
         errno = 0;
         l = strtol(s, &x, 8);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -180,7 +178,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
 
                 errno = 0;
                 l = strtoull(p, &e, 10);
-                if (errno != 0)
+                if (errno > 0)
                         return -errno;
                 if (e == p)
                         return -EINVAL;
@@ -196,7 +194,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
                                 char *e2;
 
                                 l2 = strtoull(e, &e2, 10);
-                                if (errno != 0)
+                                if (errno > 0)
                                         return -errno;
 
                                 /* Ignore failure. E.g. 10.M is valid */
@@ -336,7 +334,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -358,7 +356,7 @@ int safe_atoi(const char *s, int *ret_i) {
 
         errno = 0;
         l = strtol(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -380,7 +378,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
 
         errno = 0;
         l = strtoull(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -400,7 +398,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
 
         errno = 0;
         l = strtoll(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -420,7 +418,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -444,7 +442,7 @@ int safe_atou16(const char *s, uint16_t *ret) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -466,7 +464,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
 
         errno = 0;
         l = strtol(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -491,7 +489,7 @@ int safe_atod(const char *s, double *ret_d) {
 
         errno = 0;
         d = strtod_l(s, &x, loc);
-        if (errno != 0) {
+        if (errno > 0) {
                 freelocale(loc);
                 return -errno;
         }
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index fbdf1e43..d8dc26a3 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <limits.h>
 #include <stddef.h>
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index 14dc35db..c3b7d187 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -111,7 +109,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
 
                 cwd = get_current_dir_name();
                 if (!cwd)
-                        return -errno;
+                        return negative_errno();
 
                 c = strjoin(cwd, "/", p, NULL);
         }
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 2bc23fec..2c2f87a9 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <alloca.h>
 #include <stdbool.h>
 #include <stddef.h>
diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c
index 4be4ad6e..809e2122 100644
--- a/src/systemd/src/basic/prioq.c
+++ b/src/systemd/src/basic/prioq.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/prioq.h b/src/systemd/src/basic/prioq.h
index f6a88f0a..113c73d0 100644
--- a/src/systemd/src/basic/prioq.h
+++ b/src/systemd/src/basic/prioq.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 
 #include "hashmap.h"
diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c
index 21d9bde7..5500fd28 100644
--- a/src/systemd/src/basic/random-util.c
+++ b/src/systemd/src/basic/random-util.c
@@ -103,17 +103,18 @@ void initialize_srand(void) {
         if (srand_called)
                 return;
 
-        x = 0;
-
 #ifdef HAVE_SYS_AUXV_H
-        /* The kernel provides us with a bit of entropy in auxv, so
-         * let's try to make use of that to seed the pseudo-random
-         * generator. It's better than nothing... */
+        /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the
+         * pseudo-random generator. It's better than nothing... */
 
         auxv = (void*) getauxval(AT_RANDOM);
-        if (auxv)
-                x ^= *(unsigned*) auxv;
+        if (auxv) {
+                assert_cc(sizeof(x) < 16);
+                memcpy(&x, auxv, sizeof(x));
+        } else
 #endif
+                x = 0;
+
 
         x ^= (unsigned) now(CLOCK_REALTIME);
         x ^= (unsigned) gettid();
diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h
index 1ae76ef0..3cee4c50 100644
--- a/src/systemd/src/basic/random-util.h
+++ b/src/systemd/src/basic/random-util.h
@@ -19,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stddef.h>
 #include <stdint.h>
 
diff --git a/src/systemd/src/basic/refcnt.h b/src/systemd/src/basic/refcnt.h
index f7a26192..1d77a644 100644
--- a/src/systemd/src/basic/refcnt.h
+++ b/src/systemd/src/basic/refcnt.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 /* A type-safe atomic refcounter.
  *
  * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index 84c53888..2bff5062 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include "hashmap.h"
 #include "macro.h"
 
diff --git a/src/systemd/src/basic/siphash24.h b/src/systemd/src/basic/siphash24.h
index 0cc0163d..54e2420c 100644
--- a/src/systemd/src/basic/siphash24.h
+++ b/src/systemd/src/basic/siphash24.h
@@ -1,7 +1,5 @@
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -18,6 +16,8 @@ struct siphash {
 
 void siphash24_init(struct siphash *state, const uint8_t k[16]);
 void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
+#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
+
 uint64_t siphash24_finalize(struct siphash *state);
 
 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index d06a7645..92edc1dc 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <netinet/ether.h>
 #include <netinet/in.h>
 #include <stdbool.h>
@@ -91,7 +87,7 @@ int socket_address_listen(
                 mode_t directory_mode,
                 mode_t socket_mode,
                 const char *label);
-int make_socket_fd(int log_level, const char* address, int flags);
+int make_socket_fd(int log_level, const char* address, int type, int flags);
 
 bool socket_address_is(const SocketAddress *a, const char *s, int type);
 bool socket_address_is_netlink(const SocketAddress *a, const char *s);
@@ -107,7 +103,7 @@ bool socket_ipv6_is_supported(void);
 int sockaddr_port(const struct sockaddr *_sa) _pure_;
 
 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
-int getpeername_pretty(int fd, char **ret);
+int getpeername_pretty(int fd, bool include_port, char **ret);
 int getsockname_pretty(int fd, char **ret);
 
 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
diff --git a/src/systemd/src/basic/sparse-endian.h b/src/systemd/src/basic/sparse-endian.h
index 02de0fec..c913fda8 100644
--- a/src/systemd/src/basic/sparse-endian.h
+++ b/src/systemd/src/basic/sparse-endian.h
@@ -21,8 +21,6 @@
 #ifndef SPARSE_ENDIAN_H
 #define SPARSE_ENDIAN_H
 
-#include "nm-sd-adapt.h"
-
 #include <byteswap.h>
 #include <endian.h>
 #include <stdint.h>
diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h
new file mode 100644
index 00000000..0a675571
--- /dev/null
+++ b/src/systemd/src/basic/stdio-util.h
@@ -0,0 +1,76 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <printf.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+#define xsprintf(buf, fmt, ...) \
+        assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
+
+
+#define VA_FORMAT_ADVANCE(format, ap)                                   \
+do {                                                                    \
+        int _argtypes[128];                                             \
+        size_t _i, _k;                                                  \
+        _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
+        assert(_k < ELEMENTSOF(_argtypes));                             \
+        for (_i = 0; _i < _k; _i++) {                                   \
+                if (_argtypes[_i] & PA_FLAG_PTR)  {                     \
+                        (void) va_arg(ap, void*);                       \
+                        continue;                                       \
+                }                                                       \
+                                                                        \
+                switch (_argtypes[_i]) {                                \
+                case PA_INT:                                            \
+                case PA_INT|PA_FLAG_SHORT:                              \
+                case PA_CHAR:                                           \
+                        (void) va_arg(ap, int);                         \
+                        break;                                          \
+                case PA_INT|PA_FLAG_LONG:                               \
+                        (void) va_arg(ap, long int);                    \
+                        break;                                          \
+                case PA_INT|PA_FLAG_LONG_LONG:                          \
+                        (void) va_arg(ap, long long int);               \
+                        break;                                          \
+                case PA_WCHAR:                                          \
+                        (void) va_arg(ap, wchar_t);                     \
+                        break;                                          \
+                case PA_WSTRING:                                        \
+                case PA_STRING:                                         \
+                case PA_POINTER:                                        \
+                        (void) va_arg(ap, void*);                       \
+                        break;                                          \
+                case PA_FLOAT:                                          \
+                case PA_DOUBLE:                                         \
+                        (void) va_arg(ap, double);                      \
+                        break;                                          \
+                case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:                     \
+                        (void) va_arg(ap, long double);                 \
+                        break;                                          \
+                default:                                                \
+                        assert_not_reached("Unknown format string argument."); \
+                }                                                       \
+        }                                                               \
+} while(false)
diff --git a/src/systemd/src/basic/string-table.c b/src/systemd/src/basic/string-table.c
index be02c2f9..df26d5fb 100644
--- a/src/systemd/src/basic/string-table.c
+++ b/src/systemd/src/basic/string-table.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h
index ee64d34f..b180488f 100644
--- a/src/systemd/src/basic/string-table.h
+++ b/src/systemd/src/basic/string-table.h
@@ -1,6 +1,4 @@
 
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <errno.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -49,16 +45,34 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
         }
 
+#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        scope type name##_from_string(const char *s) {                  \
+                int b;                                                  \
+                b = parse_boolean(s);                                   \
+                if (b == 0)                                             \
+                        return (type) 0;                                \
+                else if (b > 0)                                         \
+                        return yes;                                     \
+                return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
+        }
+
 #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
         _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
         _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
         struct __useless_struct_to_allow_trailing_semicolon__
 
+#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
 #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
 
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
+
 /* For string conversions where numbers are also acceptable */
 #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
         int name##_to_string_alloc(type i, char **str) {                \
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index 35e00af9..75df2121 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -321,18 +319,67 @@ char *truncate_nl(char *s) {
         return s;
 }
 
+char ascii_tolower(char x) {
+
+        if (x >= 'A' && x <= 'Z')
+                return x - 'A' + 'a';
+
+        return x;
+}
+
 char *ascii_strlower(char *t) {
         char *p;
 
         assert(t);
 
         for (p = t; *p; p++)
-                if (*p >= 'A' && *p <= 'Z')
-                        *p = *p - 'A' + 'a';
+                *p = ascii_tolower(*p);
+
+        return t;
+}
+
+char *ascii_strlower_n(char *t, size_t n) {
+        size_t i;
+
+        if (n <= 0)
+                return t;
+
+        for (i = 0; i < n; i++)
+                t[i] = ascii_tolower(t[i]);
 
         return t;
 }
 
+int ascii_strcasecmp_n(const char *a, const char *b, size_t n) {
+
+        for (; n > 0; a++, b++, n--) {
+                int x, y;
+
+                x = (int) (uint8_t) ascii_tolower(*a);
+                y = (int) (uint8_t) ascii_tolower(*b);
+
+                if (x != y)
+                        return x - y;
+        }
+
+        return 0;
+}
+
+int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
+        int r;
+
+        r = ascii_strcasecmp_n(a, b, MIN(n, m));
+        if (r != 0)
+                return r;
+
+        if (n < m)
+                return -1;
+        else if (n > m)
+                return 1;
+        else
+                return 0;
+}
+
 bool chars_intersect(const char *a, const char *b) {
         const char *p;
 
@@ -406,6 +453,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
         char *e;
         const char *i, *j;
         unsigned k, len, len2;
+        int r;
 
         assert(s);
         assert(percent <= 100);
@@ -425,10 +473,10 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
 
         k = 0;
         for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
-                int c;
+                char32_t c;
 
-                c = utf8_encoded_to_unichar(i);
-                if (c < 0)
+                r = utf8_encoded_to_unichar(i, &c);
+                if (r < 0)
                         return NULL;
                 k += unichar_iswide(c) ? 2 : 1;
         }
@@ -437,11 +485,11 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
                 x ++;
 
         for (j = s + old_length; k < new_length && j > i; ) {
-                int c;
+                char32_t c;
 
                 j = utf8_prev_char(j);
-                c = utf8_encoded_to_unichar(j);
-                if (c < 0)
+                r = utf8_encoded_to_unichar(j, &c);
+                if (r < 0)
                         return NULL;
                 k += unichar_iswide(c) ? 2 : 1;
         }
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index f6aa4584..ad0c8137 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <alloca.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -132,7 +128,12 @@ char *strstrip(char *s);
 char *delete_chars(char *s, const char *bad);
 char *truncate_nl(char *s);
 
-char *ascii_strlower(char *path);
+char ascii_tolower(char x);
+char *ascii_strlower(char *s);
+char *ascii_strlower_n(char *s, size_t n);
+
+int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
+int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
 
 bool chars_intersect(const char *a, const char *b) _pure_;
 
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 38624902..c003091b 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -33,6 +31,7 @@
 #if 0 /* NM_IGNORED */
 #include "extract-word.h"
 #endif /* NM_IGNORED */
+#include "fileio.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
@@ -877,3 +876,22 @@ rollback:
         nl[k] = NULL;
         return -ENOMEM;
 }
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
+        bool b = false;
+        char **s;
+        int r;
+
+        /* Like fputs(), but for strv, and with a less stupid argument order */
+
+        if (!space)
+                space = &b;
+
+        STRV_FOREACH(s, l) {
+                r = fputs_with_space(f, *s, separator, space);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index d3608af3..4a93818a 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <fnmatch.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -175,3 +171,5 @@ char ***strv_free_free(char ***l);
 char **strv_skip(char **l, size_t n);
 
 int strv_extend_n(char ***l, const char *value, size_t n);
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 8ca41f0c..ed239be1 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -44,6 +42,8 @@
 #include "strv.h"
 #include "time-util.h"
 
+static nsec_t timespec_load_nsec(const struct timespec *ts);
+
 usec_t now(clockid_t clock_id) {
         struct timespec ts;
 
@@ -81,12 +81,7 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         ts->realtime = u;
 
         delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
-        ts->monotonic = now(CLOCK_MONOTONIC);
-
-        if ((int64_t) ts->monotonic > delta)
-                ts->monotonic -= delta;
-        else
-                ts->monotonic = 0;
+        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
 
         return ts;
 }
@@ -102,12 +97,7 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
 
         ts->monotonic = u;
         delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u;
-
-        ts->realtime = now(CLOCK_REALTIME);
-        if ((int64_t) ts->realtime > delta)
-                ts->realtime -= delta;
-        else
-                ts->realtime = 0;
+        ts->realtime = usec_sub(now(CLOCK_REALTIME), delta);
 
         return ts;
 }
@@ -119,25 +109,15 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
                 ts->realtime = ts->monotonic = USEC_INFINITY;
                 return ts;
         }
-        ts->realtime = now(CLOCK_REALTIME);
-        ts->monotonic = now(CLOCK_MONOTONIC);
 
+        dual_timestamp_get(ts);
         delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
-
-        if ((int64_t) ts->realtime > delta)
-                ts->realtime -= delta;
-        else
-                ts->realtime = 0;
-
-        if ((int64_t) ts->monotonic > delta)
-                ts->monotonic -= delta;
-        else
-                ts->monotonic = 0;
+        ts->realtime = usec_sub(ts->realtime, delta);
+        ts->monotonic = usec_sub(ts->monotonic, delta);
 
         return ts;
 }
 
-
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
@@ -153,7 +133,7 @@ usec_t timespec_load(const struct timespec *ts) {
                 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
 }
 
-nsec_t timespec_load_nsec(const struct timespec *ts) {
+static nsec_t timespec_load_nsec(const struct timespec *ts) {
         assert(ts);
 
         if (ts->tv_sec == (time_t) -1 &&
@@ -210,9 +190,11 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
         return tv;
 }
 
-static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc) {
+static char *format_timestamp_internal(char *buf, size_t l, usec_t t,
+                                       bool utc, bool us) {
         struct tm tm;
         time_t sec;
+        int k;
 
         assert(buf);
         assert(l > 0);
@@ -223,48 +205,36 @@ static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc)
         sec = (time_t) (t / USEC_PER_SEC);
         localtime_or_gmtime_r(&sec, &tm, utc);
 
-        if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm) <= 0)
+        if (us)
+                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm);
+        else
+                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm);
+
+        if (k <= 0)
                 return NULL;
+        if (us) {
+                snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
+                if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
+                        return NULL;
+        }
 
         return buf;
 }
 
 char *format_timestamp(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal(buf, l, t, false);
+        return format_timestamp_internal(buf, l, t, false, false);
 }
 
 char *format_timestamp_utc(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal(buf, l, t, true);
-}
-
-static char *format_timestamp_internal_us(char *buf, size_t l, usec_t t, bool utc) {
-        struct tm tm;
-        time_t sec;
-
-        assert(buf);
-        assert(l > 0);
-
-        if (t <= 0 || t == USEC_INFINITY)
-                return NULL;
-
-        sec = (time_t) (t / USEC_PER_SEC);
-        localtime_or_gmtime_r(&sec, &tm, utc);
-
-        if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0)
-                return NULL;
-        snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
-        if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
-                return NULL;
-
-        return buf;
+        return format_timestamp_internal(buf, l, t, true, false);
 }
 
 char *format_timestamp_us(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal_us(buf, l, t, false);
+        return format_timestamp_internal(buf, l, t, false, true);
 }
 
 char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal_us(buf, l, t, true);
+        return format_timestamp_internal(buf, l, t, true, true);
 }
 
 char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 760ac2a0..9894e626 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -71,7 +67,7 @@ typedef struct dual_timestamp {
 #define FORMAT_TIMESTAMP_RELATIVE_MAX 256
 #define FORMAT_TIMESPAN_MAX 64
 
-#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
+#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
 
 #define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
 
@@ -94,8 +90,6 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u);
 usec_t timeval_load(const struct timeval *tv) _pure_;
 struct timeval *timeval_store(struct timeval *tv, usec_t u);
 
-nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
-
 char *format_timestamp(char *buf, size_t l, usec_t t);
 char *format_timestamp_utc(char *buf, size_t l, usec_t t);
 char *format_timestamp_us(char *buf, size_t l, usec_t t);
@@ -129,3 +123,29 @@ time_t mktime_or_timegm(struct tm *tm, bool utc);
 struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
 
 unsigned long usec_to_jiffies(usec_t usec);
+
+static inline usec_t usec_add(usec_t a, usec_t b) {
+        usec_t c;
+
+        /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't
+         * overflow. */
+
+        c = a + b;
+        if (c < a || c < b) /* overflow check */
+                return USEC_INFINITY;
+
+        return c;
+}
+
+static inline usec_t usec_sub(usec_t timestamp, int64_t delta) {
+        if (delta < 0)
+                return usec_add(timestamp, (usec_t) (-delta));
+
+        if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */
+                return USEC_INFINITY;
+
+        if (timestamp < (usec_t) delta)
+                return 0;
+
+        return timestamp - delta;
+}
diff --git a/src/systemd/src/basic/umask-util.h b/src/systemd/src/basic/umask-util.h
index aada0540..359d87d2 100644
--- a/src/systemd/src/basic/umask-util.h
+++ b/src/systemd/src/basic/umask-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/types.h>
diff --git a/src/systemd/src/basic/unaligned.h b/src/systemd/src/basic/unaligned.h
index 597c890d..79be645b 100644
--- a/src/systemd/src/basic/unaligned.h
+++ b/src/systemd/src/basic/unaligned.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <endian.h>
 #include <stdint.h>
 
diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c
index 20beb6ea..5a1d3678 100644
--- a/src/systemd/src/basic/utf8.c
+++ b/src/systemd/src/basic/utf8.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -55,7 +53,7 @@
 #include "macro.h"
 #include "utf8.h"
 
-bool unichar_is_valid(uint32_t ch) {
+bool unichar_is_valid(char32_t ch) {
 
         if (ch >= 0x110000) /* End of unicode space */
                 return false;
@@ -69,7 +67,7 @@ bool unichar_is_valid(uint32_t ch) {
         return true;
 }
 
-static bool unichar_is_control(uint32_t ch) {
+static bool unichar_is_control(char32_t ch) {
 
         /*
           0 to ' '-1 is the C0 range.
@@ -105,8 +103,9 @@ static int utf8_encoded_expected_len(const char *str) {
 }
 
 /* decode one unicode char */
-int utf8_encoded_to_unichar(const char *str) {
-        int unichar, len, i;
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
+        char32_t unichar;
+        int len, i;
 
         assert(str);
 
@@ -114,34 +113,37 @@ int utf8_encoded_to_unichar(const char *str) {
 
         switch (len) {
         case 1:
-                return (int)str[0];
+                *ret_unichar = (char32_t)str[0];
+                return 0;
         case 2:
                 unichar = str[0] & 0x1f;
                 break;
         case 3:
-                unichar = (int)str[0] & 0x0f;
+                unichar = (char32_t)str[0] & 0x0f;
                 break;
         case 4:
-                unichar = (int)str[0] & 0x07;
+                unichar = (char32_t)str[0] & 0x07;
                 break;
         case 5:
-                unichar = (int)str[0] & 0x03;
+                unichar = (char32_t)str[0] & 0x03;
                 break;
         case 6:
-                unichar = (int)str[0] & 0x01;
+                unichar = (char32_t)str[0] & 0x01;
                 break;
         default:
                 return -EINVAL;
         }
 
         for (i = 1; i < len; i++) {
-                if (((int)str[i] & 0xc0) != 0x80)
+                if (((char32_t)str[i] & 0xc0) != 0x80)
                         return -EINVAL;
                 unichar <<= 6;
-                unichar |= (int)str[i] & 0x3f;
+                unichar |= (char32_t)str[i] & 0x3f;
         }
 
-        return unichar;
+        *ret_unichar = unichar;
+
+        return 0;
 }
 
 bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
@@ -150,15 +152,16 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
         assert(str);
 
         for (p = str; length;) {
-                int encoded_len, val;
+                int encoded_len, r;
+                char32_t val;
 
                 encoded_len = utf8_encoded_valid_unichar(p);
                 if (encoded_len < 0 ||
                     (size_t) encoded_len > length)
                         return false;
 
-                val = utf8_encoded_to_unichar(p);
-                if (val < 0 ||
+                r = utf8_encoded_to_unichar(p, &val);
+                if (r < 0 ||
                     unichar_is_control(val) ||
                     (!newline && val == '\n'))
                         return false;
@@ -278,7 +281,7 @@ char *ascii_is_valid(const char *str) {
  * Returns: The length in bytes that the UTF-8 representation does or would
  *          occupy.
  */
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
+size_t utf8_encode_unichar(char *out_utf8, char32_t g) {
 
         if (g < (1 << 7)) {
                 if (out_utf8)
@@ -322,7 +325,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
         t = r;
 
         while (f < (const uint8_t*) s + length) {
-                uint16_t w1, w2;
+                char16_t w1, w2;
 
                 /* see RFC 2781 section 2.2 */
 
@@ -356,7 +359,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
 }
 
 /* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(int unichar) {
+static int utf8_unichar_to_encoded_len(char32_t unichar) {
 
         if (unichar < 0x80)
                 return 1;
@@ -374,7 +377,8 @@ static int utf8_unichar_to_encoded_len(int unichar) {
 
 /* validate one encoded unicode char and return its length */
 int utf8_encoded_valid_unichar(const char *str) {
-        int len, unichar, i;
+        int len, i, r;
+        char32_t unichar;
 
         assert(str);
 
@@ -391,7 +395,9 @@ int utf8_encoded_valid_unichar(const char *str) {
                 if ((str[i] & 0x80) != 0x80)
                         return -EINVAL;
 
-        unichar = utf8_encoded_to_unichar(str);
+        r = utf8_encoded_to_unichar(str, &unichar);
+        if (r < 0)
+                return r;
 
         /* check if encoded length matches encoded value */
         if (utf8_unichar_to_encoded_len(unichar) != len)
diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h
index 32172c31..a3c8558e 100644
--- a/src/systemd/src/basic/utf8.h
+++ b/src/systemd/src/basic/utf8.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,17 +19,21 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#if 0 /* NM_IGNORED */
+#include <uchar.h>
+#endif /* NM_IGNORED */
 
 #include "macro.h"
+#if 0 /* NM_IGNORED */
+#include "missing.h"
+#endif /* NM_IGNORED */
 
 #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
 
-bool unichar_is_valid(uint32_t c);
+bool unichar_is_valid(char32_t c);
 
 const char *utf8_is_valid(const char *s) _pure_;
 char *ascii_is_valid(const char *s) _pure_;
@@ -42,20 +44,20 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pu
 char *utf8_escape_invalid(const char *s);
 char *utf8_escape_non_printable(const char *str);
 
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g);
+size_t utf8_encode_unichar(char *out_utf8, char32_t g);
 char *utf16_to_utf8(const void *s, size_t length);
 
 int utf8_encoded_valid_unichar(const char *str);
-int utf8_encoded_to_unichar(const char *str);
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
 
-static inline bool utf16_is_surrogate(uint16_t c) {
+static inline bool utf16_is_surrogate(char16_t c) {
         return (0xd800 <= c && c <= 0xdfff);
 }
 
-static inline bool utf16_is_trailing_surrogate(uint16_t c) {
+static inline bool utf16_is_trailing_surrogate(char16_t c) {
         return (0xdc00 <= c && c <= 0xdfff);
 }
 
-static inline uint32_t utf16_surrogate_pair_to_unichar(uint16_t lead, uint16_t trail) {
+static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
                 return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
 }
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 43e453ee..6d641a4a 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -530,7 +528,7 @@ int on_ac_power(void) {
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
 
                 if (!de)
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 9393919d..5033b029 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <alloca.h>
 #include <errno.h>
 #include <fcntl.h>
diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/systemd/src/libsystemd-network/arp-util.h
index 16af8962..3ef56b00 100644
--- a/src/systemd/src/libsystemd-network/arp-util.h
+++ b/src/systemd/src/libsystemd-network/arp-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <netinet/if_ether.h>
 
 #include "socket-util.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 732199de..0cbce155 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index 106dba39..93f06f59 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include "sd-id128.h"
 
 #include "macro.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index 09dcf7e9..a3b842cd 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <linux/if_packet.h>
 #include <net/ethernet.h>
 #include <net/if_arp.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index 8ce52a7d..82cae230 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdint.h>
 #include <linux/if_packet.h>
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index 8c359a48..4f025b68 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -36,14 +34,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
         assert(options);
         assert(offset);
 
-        if (code != DHCP_OPTION_END)
+        if (code != SD_DHCP_OPTION_END)
                 /* always make sure there is space for an END option */
                 size --;
 
         switch (code) {
 
-        case DHCP_OPTION_PAD:
-        case DHCP_OPTION_END:
+        case SD_DHCP_OPTION_PAD:
+        case SD_DHCP_OPTION_END:
                 if (size < *offset + 1)
                         return -ENOBUFS;
 
@@ -93,7 +91,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
                 else if (r == -ENOBUFS && (file || sname)) {
                         /* did not fit, but we have more buffers to try
                            close the options array and move the offset to its end */
-                        r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL);
+                        r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
                         if (r < 0)
                                 return r;
 
@@ -114,7 +112,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
                         } else if (r == -ENOBUFS && sname) {
                                 /* did not fit, but we have more buffers to try
                                    close the file array and move the offset to its end */
-                                r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL);
+                                r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
                                 if (r < 0)
                                         return r;
 
@@ -154,10 +152,10 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
                 code = options[offset ++];
 
                 switch (code) {
-                case DHCP_OPTION_PAD:
+                case SD_DHCP_OPTION_PAD:
                         continue;
 
-                case DHCP_OPTION_END:
+                case SD_DHCP_OPTION_END:
                         return 0;
                 }
 
@@ -172,7 +170,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
                 option = &options[offset];
 
                 switch (code) {
-                case DHCP_OPTION_MESSAGE_TYPE:
+                case SD_DHCP_OPTION_MESSAGE_TYPE:
                         if (len != 1)
                                 return -EINVAL;
 
@@ -181,7 +179,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
 
                         break;
 
-                case DHCP_OPTION_ERROR_MESSAGE:
+                case SD_DHCP_OPTION_ERROR_MESSAGE:
                         if (len == 0)
                                 return -EINVAL;
 
@@ -205,7 +203,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
                         }
 
                         break;
-                case DHCP_OPTION_OVERLOAD:
+                case SD_DHCP_OPTION_OVERLOAD:
                         if (len != 1)
                                 return -EINVAL;
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c
index 88a2161d..26dc2fa2 100644
--- a/src/systemd/src/libsystemd-network/dhcp-packet.c
+++ b/src/systemd/src/libsystemd-network/dhcp-packet.c
@@ -46,7 +46,7 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
         message->magic = htobe32(DHCP_MAGIC_COOKIE);
 
         r = dhcp_option_append(message, optlen, &offset, 0,
-                               DHCP_OPTION_MESSAGE_TYPE, 1, &type);
+                               SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
         if (r < 0)
                 return r;
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h
index 0d80a916..3e32484c 100644
--- a/src/systemd/src/libsystemd-network/dhcp-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <netinet/ip.h>
 #include <netinet/udp.h>
 #include <stdint.h>
@@ -107,48 +103,6 @@ enum {
         DHCP_OVERLOAD_SNAME                     = 2,
 };
 
-enum {
-        DHCP_OPTION_PAD                         = 0,
-        DHCP_OPTION_SUBNET_MASK                 = 1,
-        DHCP_OPTION_TIME_OFFSET                 = 2,
-        DHCP_OPTION_ROUTER                      = 3,
-        DHCP_OPTION_DOMAIN_NAME_SERVER          = 6,
-        DHCP_OPTION_HOST_NAME                   = 12,
-        DHCP_OPTION_BOOT_FILE_SIZE              = 13,
-        DHCP_OPTION_DOMAIN_NAME                 = 15,
-        DHCP_OPTION_ROOT_PATH                   = 17,
-        DHCP_OPTION_ENABLE_IP_FORWARDING        = 19,
-        DHCP_OPTION_ENABLE_IP_FORWARDING_NL     = 20,
-        DHCP_OPTION_POLICY_FILTER               = 21,
-        DHCP_OPTION_INTERFACE_MDR               = 22,
-        DHCP_OPTION_INTERFACE_TTL               = 23,
-        DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
-        DHCP_OPTION_INTERFACE_MTU               = 26,
-        DHCP_OPTION_BROADCAST                   = 28,
-        DHCP_OPTION_STATIC_ROUTE                = 33,
-        DHCP_OPTION_NTP_SERVER                  = 42,
-        DHCP_OPTION_VENDOR_SPECIFIC             = 43,
-        DHCP_OPTION_REQUESTED_IP_ADDRESS        = 50,
-        DHCP_OPTION_IP_ADDRESS_LEASE_TIME       = 51,
-        DHCP_OPTION_OVERLOAD                    = 52,
-        DHCP_OPTION_MESSAGE_TYPE                = 53,
-        DHCP_OPTION_SERVER_IDENTIFIER           = 54,
-        DHCP_OPTION_PARAMETER_REQUEST_LIST      = 55,
-        DHCP_OPTION_ERROR_MESSAGE               = 56,
-        DHCP_OPTION_MAXIMUM_MESSAGE_SIZE        = 57,
-        DHCP_OPTION_RENEWAL_T1_TIME             = 58,
-        DHCP_OPTION_REBINDING_T2_TIME           = 59,
-        DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,
-        DHCP_OPTION_CLIENT_IDENTIFIER           = 61,
-        DHCP_OPTION_FQDN                        = 81,
-        DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
-        DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
-        DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
-        DHCP_OPTION_PRIVATE_BASE                = 224,
-        DHCP_OPTION_PRIVATE_LAST                = 254,
-        DHCP_OPTION_END                         = 255,
-};
-
 #define DHCP_MAX_FQDN_LENGTH 255
 
 enum {
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index 09cff3c4..749086d3 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <net/ethernet.h>
 #include <netinet/in.h>
 
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index 6b51658c..14e708ef 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdint.h>
 
 #include "sd-dhcp6-lease.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index 0d61eddb..d4f726b5 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -25,6 +23,8 @@
 #include <netinet/in.h>
 #include <string.h>
 
+#include "sd-dhcp6-client.h"
+
 #include "alloc-util.h"
 #include "dhcp6-internal.h"
 #include "dhcp6-protocol.h"
@@ -92,11 +92,11 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
         assert_return(buf && *buf && buflen && ia, -EINVAL);
 
         switch (ia->type) {
-        case DHCP6_OPTION_IA_NA:
+        case SD_DHCP6_OPTION_IA_NA:
                 len = DHCP6_OPTION_IA_NA_LEN;
                 break;
 
-        case DHCP6_OPTION_IA_TA:
+        case SD_DHCP6_OPTION_IA_TA:
                 len = DHCP6_OPTION_IA_TA_LEN;
                 break;
 
@@ -119,7 +119,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
         *buflen -= len;
 
         LIST_FOREACH(addresses, addr, ia->addresses) {
-                r = option_append_hdr(buf, buflen, DHCP6_OPTION_IAADDR,
+                r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR,
                                       sizeof(addr->iaaddr));
                 if (r < 0)
                         return r;
@@ -198,7 +198,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
         assert_return(!ia->addresses, -EINVAL);
 
         switch (iatype) {
-        case DHCP6_OPTION_IA_NA:
+        case SD_DHCP6_OPTION_IA_NA:
 
                 if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
                     sizeof(addr->iaaddr)) {
@@ -221,7 +221,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
 
                 break;
 
-        case DHCP6_OPTION_IA_TA:
+        case SD_DHCP6_OPTION_IA_TA:
                 if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
                     sizeof(addr->iaaddr)) {
                         r = -ENOBUFS;
@@ -249,7 +249,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
         while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) {
 
                 switch (opt) {
-                case DHCP6_OPTION_IAADDR:
+                case SD_DHCP6_OPTION_IAADDR:
 
                         addr = new0(DHCP6Address, 1);
                         if (!addr) {
@@ -276,7 +276,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
 
                         break;
 
-                case DHCP6_OPTION_STATUS_CODE:
+                case SD_DHCP6_OPTION_STATUS_CODE:
                         if (optlen < sizeof(status))
                                 break;
 
diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
index 1318c816..ee4bdfb0 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <netinet/ip6.h>
 #include <netinet/udp.h>
 
@@ -101,41 +97,6 @@ enum {
 };
 
 enum {
-        DHCP6_OPTION_CLIENTID                   = 1,
-        DHCP6_OPTION_SERVERID                   = 2,
-        DHCP6_OPTION_IA_NA                      = 3,
-        DHCP6_OPTION_IA_TA                      = 4,
-        DHCP6_OPTION_IAADDR                     = 5,
-        DHCP6_OPTION_ORO                        = 6,
-        DHCP6_OPTION_PREFERENCE                 = 7,
-        DHCP6_OPTION_ELAPSED_TIME               = 8,
-        DHCP6_OPTION_RELAY_MSG                  = 9,
-        /* option code 10 is unassigned */
-        DHCP6_OPTION_AUTH                       = 11,
-        DHCP6_OPTION_UNICAST                    = 12,
-        DHCP6_OPTION_STATUS_CODE                = 13,
-        DHCP6_OPTION_RAPID_COMMIT               = 14,
-        DHCP6_OPTION_USER_CLASS                 = 15,
-        DHCP6_OPTION_VENDOR_CLASS               = 16,
-        DHCP6_OPTION_VENDOR_OPTS                = 17,
-        DHCP6_OPTION_INTERFACE_ID               = 18,
-        DHCP6_OPTION_RECONF_MSG                 = 19,
-        DHCP6_OPTION_RECONF_ACCEPT              = 20,
-
-        DHCP6_OPTION_DNS_SERVERS                = 23,  /* RFC 3646 */
-        DHCP6_OPTION_DOMAIN_LIST                = 24,  /* RFC 3646 */
-
-        DHCP6_OPTION_SNTP_SERVERS               = 31,  /* RFC 4075, deprecated */
-
-        /* option code 35 is unassigned */
-
-        DHCP6_OPTION_NTP_SERVER                 = 56,  /* RFC 5908 */
-
-        /* option codes 89-142 are unassigned */
-        /* option codes 144-65535 are unassigned */
-};
-
-enum {
         DHCP6_NTP_SUBOPTION_SRV_ADDR            = 1,
         DHCP6_NTP_SUBOPTION_MC_ADDR             = 2,
         DHCP6_NTP_SUBOPTION_SRV_FQDN            = 3,
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.c b/src/systemd/src/libsystemd-network/lldp-internal.c
index 87fecd0a..8194a601 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.c
+++ b/src/systemd/src/libsystemd-network/lldp-internal.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h
index 5496fae7..15b4a11b 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.h
+++ b/src/systemd/src/libsystemd-network/lldp-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,8 +20,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #include "sd-event.h"
 
 #include "list.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c
index e7f575a0..b96e9741 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.c
+++ b/src/systemd/src/libsystemd-network/lldp-network.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h
index b1e428e7..dcf31faa 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.h
+++ b/src/systemd/src/libsystemd-network/lldp-network.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,8 +20,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #include "sd-event.h"
 
 int lldp_network_bind_raw_socket(int ifindex);
diff --git a/src/systemd/src/libsystemd-network/lldp-port.c b/src/systemd/src/libsystemd-network/lldp-port.c
index 7374f18d..e96ef8a7 100644
--- a/src/systemd/src/libsystemd-network/lldp-port.c
+++ b/src/systemd/src/libsystemd-network/lldp-port.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd-network/lldp-port.h b/src/systemd/src/libsystemd-network/lldp-port.h
index 063eaa27..96092f8d 100644
--- a/src/systemd/src/libsystemd-network/lldp-port.h
+++ b/src/systemd/src/libsystemd-network/lldp-port.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,8 +20,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #include <net/ethernet.h>
 
 #include "sd-event.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-tlv.c b/src/systemd/src/libsystemd-network/lldp-tlv.c
index b589402f..28161bc1 100644
--- a/src/systemd/src/libsystemd-network/lldp-tlv.c
+++ b/src/systemd/src/libsystemd-network/lldp-tlv.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd-network/lldp-tlv.h b/src/systemd/src/libsystemd-network/lldp-tlv.h
index 7d7459e9..8e7706c6 100644
--- a/src/systemd/src/libsystemd-network/lldp-tlv.h
+++ b/src/systemd/src/libsystemd-network/lldp-tlv.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,8 +20,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #include <net/ethernet.h>
 
 #include "sd-lldp.h"
diff --git a/src/systemd/src/libsystemd-network/lldp.h b/src/systemd/src/libsystemd-network/lldp.h
index 974fd8b0..d2c71646 100644
--- a/src/systemd/src/libsystemd-network/lldp.h
+++ b/src/systemd/src/libsystemd-network/lldp.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,8 +20,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
-
 #define LLDP_MULTICAST_ADDR     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
 
 #define ETHERTYPE_LLDP          0x88cc
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index 579329c7..383660f8 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
@@ -443,7 +441,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
         return size;
 }
 
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
+void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
         unsigned i;
 
         assert(f);
@@ -454,10 +452,15 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
         fprintf(f, "%s=", key);
 
         for (i = 0; i < size; i++) {
-                fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
-                        routes[i].dst_prefixlen);
-                fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
-                        (i < (size - 1)) ? " ": "");
+                struct in_addr dest, gw;
+                uint8_t length;
+
+                assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0);
+                assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
+                assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
+
+                fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length);
+                fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": "");
         }
 
         fputs("\n", f);
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index 17c2f4fb..fd161056 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,10 +19,10 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <stdbool.h>
 
+#include "sd-dhcp-lease.h"
+
 #if 0 /* NM_IGNORED */
 #include "condition.h"
 #include "udev.h"
@@ -78,7 +76,7 @@ int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
 /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
 struct sd_dhcp_route;
 
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size);
+void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
 
 int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 23d2c4b0..d00e1d34 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -45,6 +45,9 @@
 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
 
+#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
+#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
+
 struct sd_dhcp_client {
         unsigned n_ref;
 
@@ -103,14 +106,15 @@ struct sd_dhcp_client {
         sd_dhcp_client_cb_t cb;
         void *userdata;
         sd_dhcp_lease *lease;
+        usec_t start_delay;
 };
 
 static const uint8_t default_req_opts[] = {
-        DHCP_OPTION_SUBNET_MASK,
-        DHCP_OPTION_ROUTER,
-        DHCP_OPTION_HOST_NAME,
-        DHCP_OPTION_DOMAIN_NAME,
-        DHCP_OPTION_DOMAIN_NAME_SERVER,
+        SD_DHCP_OPTION_SUBNET_MASK,
+        SD_DHCP_OPTION_ROUTER,
+        SD_DHCP_OPTION_HOST_NAME,
+        SD_DHCP_OPTION_DOMAIN_NAME,
+        SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
 };
 
 static int client_receive_message_raw(sd_event_source *s, int fd,
@@ -145,11 +149,11 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
                               DHCP_STATE_STOPPED), -EBUSY);
 
         switch(option) {
-        case DHCP_OPTION_PAD:
-        case DHCP_OPTION_OVERLOAD:
-        case DHCP_OPTION_MESSAGE_TYPE:
-        case DHCP_OPTION_PARAMETER_REQUEST_LIST:
-        case DHCP_OPTION_END:
+        case SD_DHCP_OPTION_PAD:
+        case SD_DHCP_OPTION_OVERLOAD:
+        case SD_DHCP_OPTION_MESSAGE_TYPE:
+        case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
+        case SD_DHCP_OPTION_END:
                 return -EINVAL;
 
         default:
@@ -488,7 +492,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            Identifier option is not set */
         if (client->client_id_len) {
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_CLIENT_IDENTIFIER,
+                                       SD_DHCP_OPTION_CLIENT_IDENTIFIER,
                                        client->client_id_len,
                                        &client->client_id);
                 if (r < 0)
@@ -504,7 +508,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            messages.
          */
         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_PARAMETER_REQUEST_LIST,
+                               SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
                                client->req_opts_size, client->req_opts);
         if (r < 0)
                 return r;
@@ -533,7 +537,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
          */
         max_size = htobe16(size);
         r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
-                               DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
+                               SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
                                2, &max_size);
         if (r < 0)
                 return r;
@@ -559,7 +563,7 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
         r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
         if (r > 0)
                 r = dhcp_option_append(message, optlen, optoffset, 0,
-                                       DHCP_OPTION_FQDN, 3 + r, buffer);
+                                       SD_DHCP_OPTION_FQDN, 3 + r, buffer);
 
         return r;
 }
@@ -595,7 +599,7 @@ static int client_send_discover(sd_dhcp_client *client) {
          */
         if (client->last_addr != INADDR_ANY) {
                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->last_addr);
                 if (r < 0)
                         return r;
@@ -611,7 +615,7 @@ static int client_send_discover(sd_dhcp_client *client) {
                            DHCPDISCOVER but dhclient does and so we do as well
                         */
                         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                               DHCP_OPTION_HOST_NAME,
+                                               SD_DHCP_OPTION_HOST_NAME,
                                                strlen(client->hostname), client->hostname);
                 } else
                         r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
@@ -622,7 +626,7 @@ static int client_send_discover(sd_dhcp_client *client) {
 
         if (client->vendor_class_identifier) {
                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
+                                       SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
                                        strlen(client->vendor_class_identifier),
                                        client->vendor_class_identifier);
                 if (r < 0)
@@ -630,7 +634,7 @@ static int client_send_discover(sd_dhcp_client *client) {
         }
 
         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_END, 0, NULL);
+                               SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -669,13 +673,13 @@ static int client_send_request(sd_dhcp_client *client) {
                  */
 
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_SERVER_IDENTIFIER,
+                                       SD_DHCP_OPTION_SERVER_IDENTIFIER,
                                        4, &client->lease->server_address);
                 if (r < 0)
                         return r;
 
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->lease->address);
                 if (r < 0)
                         return r;
@@ -688,7 +692,7 @@ static int client_send_request(sd_dhcp_client *client) {
                    assigned address. ’ciaddr’ MUST be zero.
                  */
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->last_addr);
                 if (r < 0)
                         return r;
@@ -723,7 +727,7 @@ static int client_send_request(sd_dhcp_client *client) {
         if (client->hostname) {
                 if (dns_name_is_single_label(client->hostname))
                         r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                               DHCP_OPTION_HOST_NAME,
+                                               SD_DHCP_OPTION_HOST_NAME,
                                                strlen(client->hostname), client->hostname);
                 else
                         r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
@@ -733,7 +737,7 @@ static int client_send_request(sd_dhcp_client *client) {
         }
 
         r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_END, 0, NULL);
+                               SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -947,6 +951,7 @@ error:
 }
 
 static int client_initialize_time_events(sd_dhcp_client *client) {
+        uint64_t usec = 0;
         int r;
 
         assert(client);
@@ -954,10 +959,15 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
 
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
+        if (client->start_delay) {
+                sd_event_now(client->event, clock_boottime_or_monotonic(), &usec);
+                usec += client->start_delay;
+        }
+
         r = sd_event_add_time(client->event,
                               &client->timeout_resend,
                               clock_boottime_or_monotonic(),
-                              0, 0,
+                              usec, 0,
                               client_timeout_resend, client);
         if (r < 0)
                 goto error;
@@ -987,7 +997,7 @@ static int client_initialize_events(sd_dhcp_client *client,
         return 0;
 }
 
-static int client_start(sd_dhcp_client *client) {
+static int client_start_delayed(sd_dhcp_client *client) {
         int r;
 
         assert_return(client, -EINVAL);
@@ -1015,6 +1025,11 @@ static int client_start(sd_dhcp_client *client) {
         return client_initialize_events(client, client_receive_message_raw);
 }
 
+static int client_start(sd_dhcp_client *client) {
+        client->start_delay = 0;
+        return client_start_delayed(client);
+}
+
 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
                                  void *userdata) {
         sd_dhcp_client *client = userdata;
@@ -1364,6 +1379,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                                  int len) {
         DHCP_CLIENT_DONT_DESTROY(client);
+        char time_string[FORMAT_TIMESPAN_MAX];
         int r = 0, notify_event = 0;
 
         assert(client);
@@ -1411,6 +1427,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                 r = client_handle_ack(client, message, len);
                 if (r >= 0) {
+                        client->start_delay = 0;
                         client->timeout_resend =
                                 sd_event_source_unref(client->timeout_resend);
                         client->receive_message =
@@ -1460,11 +1477,15 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                         if (r < 0)
                                 goto error;
 
-                        r = client_start(client);
+                        r = client_start_delayed(client);
                         if (r < 0)
                                 goto error;
 
-                        log_dhcp_client(client, "REBOOTED");
+                        log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX,
+                                                                                client->start_delay, USEC_PER_SEC));
+
+                        client->start_delay = CLAMP(client->start_delay * 2,
+                                                    RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC);
 
                         return 0;
                 } else if (r == -ENOMSG)
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index e6caab54..b0f0a844 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -39,6 +39,7 @@
 #include "in-addr-util.h"
 #include "network-internal.h"
 #include "parse-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "unaligned.h"
 
@@ -207,14 +208,28 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
         return 0;
 }
 
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
+/*
+ * The returned routes array must be freed by the caller.
+ * Route objects have the same lifetime of the lease and must not be freed.
+ */
+int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
+        sd_dhcp_route **ret;
+        unsigned i;
+
         assert_return(lease, -EINVAL);
         assert_return(routes, -EINVAL);
 
         if (lease->static_route_size <= 0)
                 return -ENODATA;
 
-        *routes = lease->static_route;
+        ret = new(sd_dhcp_route *, lease->static_route_size);
+        if (!ret)
+                return -ENOMEM;
+
+        for (i = 0; i < lease->static_route_size; i++)
+                ret[i] = &lease->static_route[i];
+
+        *routes = ret;
         return (int) lease->static_route_size;
 }
 
@@ -340,6 +355,38 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
         return 0;
 }
 
+static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
+        _cleanup_free_ char *name = NULL, *normalized = NULL;
+        int r;
+
+        assert(option);
+        assert(ret);
+
+        r = lease_parse_string(option, len, &name);
+        if (r < 0)
+                return r;
+        if (!name) {
+                *ret = mfree(*ret);
+                return 0;
+        }
+
+        r = dns_name_normalize(name, &normalized);
+        if (r < 0)
+                return r;
+
+        if (is_localhost(normalized))
+                return -EINVAL;
+
+        if (dns_name_is_root(normalized))
+                return -EINVAL;
+
+        free(*ret);
+        *ret = normalized;
+        normalized = NULL;
+
+        return 0;
+}
+
 static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
         assert(option);
         assert(ret);
@@ -454,7 +501,7 @@ static int lease_parse_classless_routes(
                 if (len < 4)
                         return -EINVAL;
 
-                lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+                assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
                 option += 4;
                 len -= 4;
 
@@ -472,21 +519,21 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
 
         switch(code) {
 
-        case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
+        case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
                 r = lease_parse_u32(option, len, &lease->lifetime, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
 
                 break;
 
-        case DHCP_OPTION_SERVER_IDENTIFIER:
+        case SD_DHCP_OPTION_SERVER_IDENTIFIER:
                 r = lease_parse_be32(option, len, &lease->server_address);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
 
                 break;
 
-        case DHCP_OPTION_SUBNET_MASK:
+        case SD_DHCP_OPTION_SUBNET_MASK:
                 r = lease_parse_be32(option, len, &lease->subnet_mask);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
@@ -494,7 +541,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         lease->have_subnet_mask = true;
                 break;
 
-        case DHCP_OPTION_BROADCAST:
+        case SD_DHCP_OPTION_BROADCAST:
                 r = lease_parse_be32(option, len, &lease->broadcast);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
@@ -502,7 +549,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         lease->have_broadcast = true;
                 break;
 
-        case DHCP_OPTION_ROUTER:
+        case SD_DHCP_OPTION_ROUTER:
                 if (len >= 4) {
                         r = lease_parse_be32(option, 4, &lease->router);
                         if (r < 0)
@@ -510,103 +557,67 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 }
                 break;
 
-        case DHCP_OPTION_DOMAIN_NAME_SERVER:
+        case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
                 r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_NTP_SERVER:
+        case SD_DHCP_OPTION_NTP_SERVER:
                 r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_STATIC_ROUTE:
+        case SD_DHCP_OPTION_STATIC_ROUTE:
                 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_INTERFACE_MTU:
+        case SD_DHCP_OPTION_INTERFACE_MTU:
                 r = lease_parse_u16(option, len, &lease->mtu, 68);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_DOMAIN_NAME: {
-                _cleanup_free_ char *domainname = NULL, *normalized = NULL;
-
-                r = lease_parse_string(option, len, &domainname);
+        case SD_DHCP_OPTION_DOMAIN_NAME:
+                r = lease_parse_domain(option, len, &lease->domainname);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
                         return 0;
                 }
 
-                r = dns_name_normalize(domainname, &normalized);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
-                        return 0;
-                }
-
-                if (is_localhost(normalized)) {
-                        log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
-                        break;
-                }
-
-                free(lease->domainname);
-                lease->domainname = normalized;
-                normalized = NULL;
-
                 break;
-        }
-
-        case DHCP_OPTION_HOST_NAME: {
-                _cleanup_free_ char *hostname = NULL, *normalized = NULL;
 
-                r = lease_parse_string(option, len, &hostname);
+        case SD_DHCP_OPTION_HOST_NAME:
+                r = lease_parse_domain(option, len, &lease->hostname);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to parse host name, ignoring: %m");
                         return 0;
                 }
 
-                r = dns_name_normalize(hostname, &normalized);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
-                        return 0;
-                }
-
-                if (is_localhost(normalized)) {
-                        log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
-                        return 0;
-                }
-
-                free(lease->hostname);
-                lease->hostname = normalized;
-                normalized = NULL;
-
                 break;
-        }
 
-        case DHCP_OPTION_ROOT_PATH:
+        case SD_DHCP_OPTION_ROOT_PATH:
                 r = lease_parse_string(option, len, &lease->root_path);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse root path, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_RENEWAL_T1_TIME:
+        case SD_DHCP_OPTION_RENEWAL_T1_TIME:
                 r = lease_parse_u32(option, len, &lease->t1, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_REBINDING_T2_TIME:
+        case SD_DHCP_OPTION_REBINDING_T2_TIME:
                 r = lease_parse_u32(option, len, &lease->t2, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+        case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
                 r = lease_parse_classless_routes(
                                 option, len,
                                 &lease->static_route,
@@ -616,7 +627,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_NEW_TZDB_TIMEZONE: {
+        case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: {
                 _cleanup_free_ char *tz = NULL;
 
                 r = lease_parse_string(option, len, &tz);
@@ -637,7 +648,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 break;
         }
 
-        case DHCP_OPTION_VENDOR_SPECIFIC:
+        case SD_DHCP_OPTION_VENDOR_SPECIFIC:
 
                 if (len <= 0)
                         lease->vendor_specific = mfree(lease->vendor_specific);
@@ -655,7 +666,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 lease->vendor_specific_len = len;
                 break;
 
-        case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST:
+        case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
                 r = dhcp_lease_insert_private_option(lease, code, option, len);
                 if (r < 0)
                         return r;
@@ -724,7 +735,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         size_t client_id_len, data_len;
         const char *string;
         uint16_t mtu;
-        struct sd_dhcp_route *routes;
+        _cleanup_free_ sd_dhcp_route **routes = NULL;
         uint32_t t1, t2, lifetime;
         int r;
 
@@ -841,7 +852,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         LIST_FOREACH(options, option, lease->private_options) {
                 char key[strlen("OPTION_000")+1];
 
-                snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag);
+                xsprintf(key, "OPTION_%" PRIu8, option->tag);
                 r = serialize_dhcp_option(f, key, option->data, option->length);
                 if (r < 0)
                         goto fail;
@@ -884,7 +895,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                 *lifetime = NULL,
                 *t1 = NULL,
                 *t2 = NULL,
-                *options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {};
+                *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {};
 
         int r, i;
 
@@ -1052,7 +1063,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
         }
 
-        for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) {
+        for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
                 _cleanup_free_ void *data = NULL;
                 size_t len;
 
@@ -1065,7 +1076,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         continue;
                 }
 
-                r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len);
+                r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
                 if (r < 0)
                         return r;
         }
@@ -1143,3 +1154,27 @@ int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
         *tz = lease->timezone;
         return 0;
 }
+
+int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
+        assert_return(route, -EINVAL);
+        assert_return(destination, -EINVAL);
+
+        *destination = route->dst_addr;
+        return 0;
+}
+
+int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
+        assert_return(route, -EINVAL);
+        assert_return(length, -EINVAL);
+
+        *length = route->dst_prefixlen;
+        return 0;
+}
+
+int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
+        assert_return(route, -EINVAL);
+        assert_return(gateway, -EINVAL);
+
+        *gateway = route->gw_addr;
+        return 0;
+}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index 64793fc6..9665d327 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -74,10 +72,10 @@ struct sd_dhcp6_client {
 };
 
 static const uint16_t default_req_opts[] = {
-        DHCP6_OPTION_DNS_SERVERS,
-        DHCP6_OPTION_DOMAIN_LIST,
-        DHCP6_OPTION_NTP_SERVER,
-        DHCP6_OPTION_SNTP_SERVERS,
+        SD_DHCP6_OPTION_DNS_SERVERS,
+        SD_DHCP6_OPTION_DOMAIN_LIST,
+        SD_DHCP6_OPTION_NTP_SERVER,
+        SD_DHCP6_OPTION_SNTP_SERVERS,
 };
 
 const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
@@ -247,10 +245,10 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
         assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         switch(option) {
-        case DHCP6_OPTION_DNS_SERVERS:
-        case DHCP6_OPTION_DOMAIN_LIST:
-        case DHCP6_OPTION_SNTP_SERVERS:
-        case DHCP6_OPTION_NTP_SERVER:
+        case SD_DHCP6_OPTION_DNS_SERVERS:
+        case SD_DHCP6_OPTION_DOMAIN_LIST:
+        case SD_DHCP6_OPTION_SNTP_SERVERS:
+        case SD_DHCP6_OPTION_NTP_SERVER:
                 break;
 
         default:
@@ -364,7 +362,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 message->type = DHCP6_SOLICIT;
 
                 r = dhcp6_option_append(&opt, &optlen,
-                                        DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+                                        SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
                 if (r < 0)
                         return r;
 
@@ -382,7 +380,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 else
                         message->type = DHCP6_RENEW;
 
-                r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
+                r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
                                         client->lease->serverid_len,
                                         client->lease->serverid);
                 if (r < 0)
@@ -408,14 +406,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 return -EINVAL;
         }
 
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
                                 client->req_opts_len * sizeof(be16_t),
                                 client->req_opts);
         if (r < 0)
                 return r;
 
         assert (client->duid_len);
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
                                 client->duid_len, &client->duid);
         if (r < 0)
                 return r;
@@ -426,7 +424,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
         else
                 elapsed_time = 0xffff;
 
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME,
                                 sizeof(elapsed_time), &elapsed_time);
         if (r < 0)
                 return r;
@@ -689,7 +687,7 @@ static int client_parse_message(sd_dhcp6_client *client,
         while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
                                        &optval)) >= 0) {
                 switch (optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         if (clientid) {
                                 log_dhcp6_client(client, "%s contains multiple clientids",
                                                  dhcp6_message_type_to_string(message->type));
@@ -707,7 +705,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_SERVERID:
+                case SD_DHCP6_OPTION_SERVERID:
                         r = dhcp6_lease_get_serverid(lease, &id, &id_len);
                         if (r >= 0 && id) {
                                 log_dhcp6_client(client, "%s contains multiple serverids",
@@ -721,7 +719,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_PREFERENCE:
+                case SD_DHCP6_OPTION_PREFERENCE:
                         if (optlen != 1)
                                 return -EINVAL;
 
@@ -731,7 +729,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_STATUS_CODE:
+                case SD_DHCP6_OPTION_STATUS_CODE:
                         if (optlen < 2)
                                 return -EINVAL;
 
@@ -745,7 +743,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
                                 log_dhcp6_client(client, "Information request ignoring IA NA option");
 
@@ -769,35 +767,35 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_RAPID_COMMIT:
+                case SD_DHCP6_OPTION_RAPID_COMMIT:
                         r = dhcp6_lease_set_rapid_commit(lease);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_DNS_SERVERS:
+                case SD_DHCP6_OPTION_DNS_SERVERS:
                         r = dhcp6_lease_set_dns(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_DOMAIN_LIST:
+                case SD_DHCP6_OPTION_DOMAIN_LIST:
                         r = dhcp6_lease_set_domains(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_NTP_SERVER:
+                case SD_DHCP6_OPTION_NTP_SERVER:
                         r = dhcp6_lease_set_ntp(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_SNTP_SERVERS:
+                case SD_DHCP6_OPTION_SNTP_SERVERS:
                         r = dhcp6_lease_set_sntp(lease, optval, optlen);
                         if (r < 0)
                                 return r;
@@ -1287,7 +1285,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
 
         client->n_ref = 1;
 
-        client->ia_na.type = DHCP6_OPTION_IA_NA;
+        client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
 
         client->index = -1;
 
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 6a575aac..0070a78f 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -258,7 +256,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
         assert_return(lease, -EINVAL);
         assert_return(optval, -EINVAL);
 
-        free(lease->ntp);
+        lease->ntp = mfree(lease->ntp);
         lease->ntp_count = 0;
         lease->ntp_allocated = 0;
 
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index 882f130a..852d5358 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index bda3b735..ea09d19e 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 3a0d9e86..525ce7fb 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -265,7 +263,6 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
                         *(q++) = '0' + (char) ((uint8_t) *p % 10);
 
                         sz -= 4;
-
                 }
 
                 p++;
@@ -408,15 +405,20 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
 int dns_name_concat(const char *a, const char *b, char **_ret) {
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
-        const char *p = a;
+        const char *p;
         bool first = true;
         int r;
 
-        assert(a);
+        if (a)
+                p = a;
+        else if (b) {
+                p = b;
+                b = NULL;
+        } else
+                goto finish;
 
         for (;;) {
                 char label[DNS_LABEL_MAX];
-                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
@@ -435,12 +437,6 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
                         break;
                 }
 
-                k = dns_label_undo_idna(label, r, label, sizeof(label));
-                if (k < 0)
-                        return k;
-                if (k > 0)
-                        r = k;
-
                 if (_ret) {
                         if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
                                 return -ENOMEM;
@@ -467,12 +463,21 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
                 n += r;
         }
 
+finish:
         if (n > DNS_HOSTNAME_MAX)
                 return -EINVAL;
 
         if (_ret) {
-                if (!GREEDY_REALLOC(ret, allocated, n + 1))
-                        return -ENOMEM;
+                if (n == 0) {
+                        /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
+                        if (!GREEDY_REALLOC(ret, allocated, 2))
+                                return -ENOMEM;
+
+                        ret[n++] = '.';
+                } else {
+                        if (!GREEDY_REALLOC(ret, allocated, n + 1))
+                                return -ENOMEM;
+                }
 
                 ret[n] = 0;
                 *_ret = ret;
@@ -489,27 +494,18 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
 
         assert(p);
 
-        while (*p) {
+        for (;;) {
                 char label[DNS_LABEL_MAX+1];
-                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
                         break;
-
-                k = dns_label_undo_idna(label, r, label, sizeof(label));
-                if (k < 0)
-                        break;
-                if (k > 0)
-                        r = k;
-
                 if (r == 0)
                         break;
 
-                label[r] = 0;
-                ascii_strlower(label);
-
-                string_hash_func(label, state);
+                ascii_strlower_n(label, r);
+                siphash24_compress(label, r, state);
+                siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */
         }
 
         /* enforce that all names are terminated by the empty label */
@@ -518,7 +514,7 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
 
 int dns_name_compare_func(const void *a, const void *b) {
         const char *x, *y;
-        int r, q, k, w;
+        int r, q;
 
         assert(a);
         assert(b);
@@ -527,7 +523,7 @@ int dns_name_compare_func(const void *a, const void *b) {
         y = (const char *) b + strlen(b);
 
         for (;;) {
-                char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
 
                 if (x == NULL && y == NULL)
                         return 0;
@@ -537,17 +533,7 @@ int dns_name_compare_func(const void *a, const void *b) {
                 if (r < 0 || q < 0)
                         return r - q;
 
-                k = dns_label_undo_idna(la, r, la, sizeof(la));
-                w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
-                if (k < 0 || w < 0)
-                        return k - w;
-                if (k > 0)
-                        r = k;
-                if (w > 0)
-                        q = w;
-
-                la[r] = lb[q] = 0;
-                r = strcasecmp(la, lb);
+                r = ascii_strcasecmp_nn(la, r, lb, q);
                 if (r != 0)
                         return r;
         }
@@ -559,53 +545,35 @@ const struct hash_ops dns_name_hash_ops = {
 };
 
 int dns_name_equal(const char *x, const char *y) {
-        int r, q, k, w;
+        int r, q;
 
         assert(x);
         assert(y);
 
         for (;;) {
-                char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
-
-                if (*x == 0 && *y == 0)
-                        return true;
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
 
                 r = dns_label_unescape(&x, la, sizeof(la));
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        k = dns_label_undo_idna(la, r, la, sizeof(la));
-                        if (k < 0)
-                                return k;
-                        if (k > 0)
-                                r = k;
-                }
 
                 q = dns_label_unescape(&y, lb, sizeof(lb));
                 if (q < 0)
                         return q;
-                if (q > 0) {
-                        w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
-                        if (w < 0)
-                                return w;
-                        if (w > 0)
-                                q = w;
-                }
 
-                /* If one name had fewer labels than the other, this
-                 * will show up as empty label here, which the
-                 * strcasecmp() below will properly consider different
-                 * from a non-empty label. */
+                if (r != q)
+                        return false;
+                if (r == 0)
+                        return true;
 
-                la[r] = lb[q] = 0;
-                if (strcasecmp(la, lb) != 0)
+                if (ascii_strcasecmp_n(la, lb, r) != 0)
                         return false;
         }
 }
 
 int dns_name_endswith(const char *name, const char *suffix) {
         const char *n, *s, *saved_n = NULL;
-        int r, q, k, w;
+        int r, q;
 
         assert(name);
         assert(suffix);
@@ -614,18 +582,11 @@ int dns_name_endswith(const char *name, const char *suffix) {
         s = suffix;
 
         for (;;) {
-                char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
 
                 r = dns_label_unescape(&n, ln, sizeof(ln));
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
-                        if (k < 0)
-                                return k;
-                        if (k > 0)
-                                r = k;
-                }
 
                 if (!saved_n)
                         saved_n = n;
@@ -633,22 +594,13 @@ int dns_name_endswith(const char *name, const char *suffix) {
                 q = dns_label_unescape(&s, ls, sizeof(ls));
                 if (q < 0)
                         return q;
-                if (q > 0) {
-                        w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
-                        if (w < 0)
-                                return w;
-                        if (w > 0)
-                                q = w;
-                }
 
                 if (r == 0 && q == 0)
                         return true;
                 if (r == 0 && saved_n == n)
                         return false;
 
-                ln[r] = ls[q] = 0;
-
-                if (r != q || strcasecmp(ln, ls)) {
+                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
 
                         /* Not the same, let's jump back, and try with the next label again */
                         s = suffix;
@@ -658,9 +610,39 @@ int dns_name_endswith(const char *name, const char *suffix) {
         }
 }
 
+int dns_name_startswith(const char *name, const char *prefix) {
+        const char *n, *p;
+        int r, q;
+
+        assert(name);
+        assert(prefix);
+
+        n = name;
+        p = prefix;
+
+        for (;;) {
+                char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX];
+
+                r = dns_label_unescape(&p, lp, sizeof(lp));
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return true;
+
+                q = dns_label_unescape(&n, ln, sizeof(ln));
+                if (q < 0)
+                        return q;
+
+                if (r != q)
+                        return false;
+                if (ascii_strcasecmp_n(ln, lp, r) != 0)
+                        return false;
+        }
+}
+
 int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) {
         const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix;
-        int r, q, k, w;
+        int r, q;
 
         assert(name);
         assert(old_suffix);
@@ -671,7 +653,7 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
         s = old_suffix;
 
         for (;;) {
-                char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
 
                 if (!saved_before)
                         saved_before = n;
@@ -679,13 +661,6 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
                 r = dns_label_unescape(&n, ln, sizeof(ln));
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
-                        if (k < 0)
-                                return k;
-                        if (k > 0)
-                                r = k;
-                }
 
                 if (!saved_after)
                         saved_after = n;
@@ -693,13 +668,6 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
                 q = dns_label_unescape(&s, ls, sizeof(ls));
                 if (q < 0)
                         return q;
-                if (q > 0) {
-                        w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
-                        if (w < 0)
-                                return w;
-                        if (w > 0)
-                                q = w;
-                }
 
                 if (r == 0 && q == 0)
                         break;
@@ -708,9 +676,7 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
                         return 0;
                 }
 
-                ln[r] = ls[q] = 0;
-
-                if (r != q || strcasecmp(ln, ls)) {
+                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
 
                         /* Not the same, let's jump back, and try with the next label again */
                         s = old_suffix;
@@ -879,12 +845,11 @@ bool dns_name_is_root(const char *name) {
 }
 
 bool dns_name_is_single_label(const char *name) {
-        char label[DNS_LABEL_MAX+1];
         int r;
 
         assert(name);
 
-        r = dns_label_unescape(&name, label, sizeof(label));
+        r = dns_name_parent(&name);
         if (r <= 0)
                 return false;
 
@@ -917,19 +882,11 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, boo
                 if (r < 0)
                         return r;
 
-                if (canonical) {
-                        size_t i;
-
-                        /* Optionally, output the name in DNSSEC
-                         * canonical format, as described in RFC 4034,
-                         * section 6.2. Or in other words: in
-                         * lower-case. */
-
-                        for (i = 0; i < (size_t) r; i++) {
-                                if (out[i] >= 'A' && out[i] <= 'Z')
-                                        out[i] = out[i] - 'A' + 'a';
-                        }
-                }
+                /* Optionally, output the name in DNSSEC canonical
+                 * format, as described in RFC 4034, section 6.2. Or
+                 * in other words: in lower-case. */
+                if (canonical)
+                        ascii_strlower_n((char*) out, (size_t) r);
 
                 /* Fill label length, move forward */
                 *label_length = r;
@@ -1114,17 +1071,15 @@ int dns_service_split(const char *joined, char **_name, char **_type, char **_do
                 if (x >= 3 && srv_type_label_is_valid(c, cn)) {
 
                         if (dns_service_name_label_is_valid(a, an)) {
-
                                 /* OK, got <name> . <type> . <type2> . <domain> */
 
                                 name = strndup(a, an);
                                 if (!name)
                                         return -ENOMEM;
 
-                                type = new(char, bn+1+cn+1);
+                                type = strjoin(b, ".", c, NULL);
                                 if (!type)
                                         return -ENOMEM;
-                                strcpy(stpcpy(stpcpy(type, b), "."), c);
 
                                 d = p;
                                 goto finish;
@@ -1136,10 +1091,9 @@ int dns_service_split(const char *joined, char **_name, char **_type, char **_do
 
                         name = NULL;
 
-                        type = new(char, an+1+bn+1);
+                        type = strjoin(a, ".", b, NULL);
                         if (!type)
                                 return -ENOMEM;
-                        strcpy(stpcpy(stpcpy(type, a), "."), b);
 
                         d = q;
                         goto finish;
@@ -1173,22 +1127,20 @@ finish:
         return 0;
 }
 
-int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
-        const char* labels[DNS_N_LABELS_MAX+1];
-        unsigned n = 0;
+static int dns_name_build_suffix_table(const char *name, const char*table[]) {
         const char *p;
+        unsigned n = 0;
         int r;
 
         assert(name);
-        assert(ret);
+        assert(table);
 
         p = name;
         for (;;) {
                 if (n > DNS_N_LABELS_MAX)
                         return -EINVAL;
 
-                labels[n] = p;
-
+                table[n] = p;
                 r = dns_name_parent(&p);
                 if (r < 0)
                         return r;
@@ -1198,13 +1150,47 @@ int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
                 n++;
         }
 
-        if (n < n_labels)
+        return (int) n;
+}
+
+int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
+        const char* labels[DNS_N_LABELS_MAX+1];
+        int n;
+
+        assert(name);
+        assert(ret);
+
+        n = dns_name_build_suffix_table(name, labels);
+        if (n < 0)
+                return n;
+
+        if ((unsigned) n < n_labels)
                 return -EINVAL;
 
         *ret = labels[n - n_labels];
         return (int) (n - n_labels);
 }
 
+int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
+        int r;
+
+        assert(a);
+        assert(ret);
+
+        for (; n_labels > 0; n_labels --) {
+                r = dns_name_parent(&a);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        *ret = "";
+                        return 0;
+                }
+        }
+
+        *ret = a;
+        return 1;
+}
+
 int dns_name_count_labels(const char *name) {
         unsigned n = 0;
         const char *p;
@@ -1235,15 +1221,108 @@ int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {
         assert(a);
         assert(b);
 
-        while (n_labels > 0) {
+        r = dns_name_skip(a, n_labels, &a);
+        if (r <= 0)
+                return r;
 
-                r = dns_name_parent(&a);
-                if (r <= 0)
+        return dns_name_equal(a, b);
+}
+
+int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
+        const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1];
+        int n = 0, m = 0, k = 0, r, q;
+
+        assert(a);
+        assert(b);
+        assert(ret);
+
+        /* Determines the common suffix of domain names a and b */
+
+        n = dns_name_build_suffix_table(a, a_labels);
+        if (n < 0)
+                return n;
+
+        m = dns_name_build_suffix_table(b, b_labels);
+        if (m < 0)
+                return m;
+
+        for (;;) {
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
+                const char *x, *y;
+
+                if (k >= n || k >= m) {
+                        *ret = a_labels[n - k];
+                        return 0;
+                }
+
+                x = a_labels[n - 1 - k];
+                r = dns_label_unescape(&x, la, sizeof(la));
+                if (r < 0)
                         return r;
 
-                n_labels --;
+                y = b_labels[m - 1 - k];
+                q = dns_label_unescape(&y, lb, sizeof(lb));
+                if (q < 0)
+                        return q;
+
+                if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) {
+                        *ret = a_labels[n - k];
+                        return 0;
+                }
+
+                k++;
         }
+}
 
-        return dns_name_equal(a, b);
+int dns_name_apply_idna(const char *name, char **ret) {
+        _cleanup_free_ char *buf = NULL;
+        size_t n = 0, allocated = 0;
+        bool first = true;
+        int r, q;
+
+        assert(name);
+        assert(ret);
+
+        for (;;) {
+                char label[DNS_LABEL_MAX];
+
+                r = dns_label_unescape(&name, label, sizeof(label));
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                q = dns_label_apply_idna(label, r, label, sizeof(label));
+                if (q < 0)
+                        return q;
+                if (q > 0)
+                        r = q;
+
+                if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+                        return -ENOMEM;
+
+                r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
+                if (r < 0)
+                        return r;
+
+                if (first)
+                        first = false;
+                else
+                        buf[n++] = '.';
+
+                n +=r;
+        }
+
+        if (n > DNS_HOSTNAME_MAX)
+                return -EINVAL;
+
+        if (!GREEDY_REALLOC(buf, allocated, n + 1))
+                return -ENOMEM;
+
+        buf[n] = 0;
+        *ret = buf;
+        buf = NULL;
+
+        return (int) n;
 }
 #endif /* NM_IGNORED */
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
index 54860fb8..2de3642c 100644
--- a/src/systemd/src/shared/dns-domain.h
+++ b/src/systemd/src/shared/dns-domain.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,7 +19,6 @@
 
 #pragma once
 
-#include "nm-sd-adapt.h"
 
 #include <errno.h>
 #include <stdbool.h>
@@ -84,6 +81,7 @@ extern const struct hash_ops dns_name_hash_ops;
 int dns_name_between(const char *a, const char *b, const char *c);
 int dns_name_equal(const char *x, const char *y);
 int dns_name_endswith(const char *name, const char *suffix);
+int dns_name_startswith(const char *name, const char *prefix);
 
 int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);
 
@@ -104,4 +102,9 @@ int dns_service_split(const char *joined, char **name, char **type, char **domai
 int dns_name_suffix(const char *name, unsigned n_labels, const char **ret);
 int dns_name_count_labels(const char *name);
 
+int dns_name_skip(const char *a, unsigned n_labels, const char **ret);
 int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
+
+int dns_name_common_suffix(const char *a, const char *b, const char **ret);
+
+int dns_name_apply_idna(const char *name, char **ret);
diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h
index 5960a1c3..2d4e1f26 100644
--- a/src/systemd/src/systemd/_sd-common.h
+++ b/src/systemd/src/systemd/_sd-common.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdcommonhfoo
 #define foosdcommonhfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 /* This is a private header; never even think of including this directly! */
 
 #if __INCLUDE_LEVEL__ <= 1
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index 0fad8f36..2b865a80 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcpclienthfoo
 #define foosddhcpclienthfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <net/ethernet.h>
 #include <netinet/in.h>
@@ -44,6 +40,48 @@ enum {
         SD_DHCP_CLIENT_EVENT_RENEW              = 4,
 };
 
+enum {
+        SD_DHCP_OPTION_PAD                         = 0,
+        SD_DHCP_OPTION_SUBNET_MASK                 = 1,
+        SD_DHCP_OPTION_TIME_OFFSET                 = 2,
+        SD_DHCP_OPTION_ROUTER                      = 3,
+        SD_DHCP_OPTION_DOMAIN_NAME_SERVER          = 6,
+        SD_DHCP_OPTION_HOST_NAME                   = 12,
+        SD_DHCP_OPTION_BOOT_FILE_SIZE              = 13,
+        SD_DHCP_OPTION_DOMAIN_NAME                 = 15,
+        SD_DHCP_OPTION_ROOT_PATH                   = 17,
+        SD_DHCP_OPTION_ENABLE_IP_FORWARDING        = 19,
+        SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL     = 20,
+        SD_DHCP_OPTION_POLICY_FILTER               = 21,
+        SD_DHCP_OPTION_INTERFACE_MDR               = 22,
+        SD_DHCP_OPTION_INTERFACE_TTL               = 23,
+        SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
+        SD_DHCP_OPTION_INTERFACE_MTU               = 26,
+        SD_DHCP_OPTION_BROADCAST                   = 28,
+        SD_DHCP_OPTION_STATIC_ROUTE                = 33,
+        SD_DHCP_OPTION_NTP_SERVER                  = 42,
+        SD_DHCP_OPTION_VENDOR_SPECIFIC             = 43,
+        SD_DHCP_OPTION_REQUESTED_IP_ADDRESS        = 50,
+        SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME       = 51,
+        SD_DHCP_OPTION_OVERLOAD                    = 52,
+        SD_DHCP_OPTION_MESSAGE_TYPE                = 53,
+        SD_DHCP_OPTION_SERVER_IDENTIFIER           = 54,
+        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST      = 55,
+        SD_DHCP_OPTION_ERROR_MESSAGE               = 56,
+        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE        = 57,
+        SD_DHCP_OPTION_RENEWAL_T1_TIME             = 58,
+        SD_DHCP_OPTION_REBINDING_T2_TIME           = 59,
+        SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,
+        SD_DHCP_OPTION_CLIENT_IDENTIFIER           = 61,
+        SD_DHCP_OPTION_FQDN                        = 81,
+        SD_DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
+        SD_DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
+        SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
+        SD_DHCP_OPTION_PRIVATE_BASE                = 224,
+        SD_DHCP_OPTION_PRIVATE_LAST                = 254,
+        SD_DHCP_OPTION_END                         = 255,
+};
+
 typedef struct sd_dhcp_client sd_dhcp_client;
 
 typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index eed38eeb..2f565ca8 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcpleasehfoo
 #define foosddhcpleasehfoo
 
@@ -23,8 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <net/ethernet.h>
 #include <netinet/in.h>
@@ -35,7 +31,7 @@
 _SD_BEGIN_DECLARATIONS;
 
 typedef struct sd_dhcp_lease sd_dhcp_lease;
-struct sd_dhcp_route;
+typedef struct sd_dhcp_route sd_dhcp_route;
 
 sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease);
 sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
@@ -55,11 +51,15 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
 int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
 int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes);
+int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes);
 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
 int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
 int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
 
+int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
+int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
+int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway);
+
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);
 
 _SD_END_DECLARATIONS;
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index c18d91bf..96080608 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcp6clienthfoo
 #define foosddhcp6clienthfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <net/ethernet.h>
 #include <sys/types.h>
@@ -43,6 +39,41 @@ enum {
         SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST       = 13,
 };
 
+enum {
+        SD_DHCP6_OPTION_CLIENTID                   = 1,
+        SD_DHCP6_OPTION_SERVERID                   = 2,
+        SD_DHCP6_OPTION_IA_NA                      = 3,
+        SD_DHCP6_OPTION_IA_TA                      = 4,
+        SD_DHCP6_OPTION_IAADDR                     = 5,
+        SD_DHCP6_OPTION_ORO                        = 6,
+        SD_DHCP6_OPTION_PREFERENCE                 = 7,
+        SD_DHCP6_OPTION_ELAPSED_TIME               = 8,
+        SD_DHCP6_OPTION_RELAY_MSG                  = 9,
+        /* option code 10 is unassigned */
+        SD_DHCP6_OPTION_AUTH                       = 11,
+        SD_DHCP6_OPTION_UNICAST                    = 12,
+        SD_DHCP6_OPTION_STATUS_CODE                = 13,
+        SD_DHCP6_OPTION_RAPID_COMMIT               = 14,
+        SD_DHCP6_OPTION_USER_CLASS                 = 15,
+        SD_DHCP6_OPTION_VENDOR_CLASS               = 16,
+        SD_DHCP6_OPTION_VENDOR_OPTS                = 17,
+        SD_DHCP6_OPTION_INTERFACE_ID               = 18,
+        SD_DHCP6_OPTION_RECONF_MSG                 = 19,
+        SD_DHCP6_OPTION_RECONF_ACCEPT              = 20,
+
+        SD_DHCP6_OPTION_DNS_SERVERS                = 23,  /* RFC 3646 */
+        SD_DHCP6_OPTION_DOMAIN_LIST                = 24,  /* RFC 3646 */
+
+        SD_DHCP6_OPTION_SNTP_SERVERS               = 31,  /* RFC 4075, deprecated */
+
+        /* option code 35 is unassigned */
+
+        SD_DHCP6_OPTION_NTP_SERVER                 = 56,  /* RFC 5908 */
+
+        /* option codes 89-142 are unassigned */
+        /* option codes 144-65535 are unassigned */
+};
+
 typedef struct sd_dhcp6_client sd_dhcp6_client;
 
 typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event,
diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h
index 149cb239..184fbb8e 100644
--- a/src/systemd/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp6-lease.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcp6leasehfoo
 #define foosddhcp6leasehfoo
 
@@ -23,8 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <netinet/in.h>
 
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 17b95244..1ea97e47 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdeventhfoo
 #define foosdeventhfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <signal.h>
 #include <sys/epoll.h>
diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h
index da1bb2fa..a3bf5897 100644
--- a/src/systemd/src/systemd/sd-id128.h
+++ b/src/systemd/src/systemd/sd-id128.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdid128hfoo
 #define foosdid128hfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <string.h>
 
diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h
index 14d0e5a9..3a2219c8 100644
--- a/src/systemd/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/src/systemd/sd-ipv4acd.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdipv4acdfoo
 #define foosdipv4acdfoo
 
@@ -23,8 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <net/ethernet.h>
 #include <netinet/in.h>
 
diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h
index 307aa6f7..67c566fe 100644
--- a/src/systemd/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/src/systemd/sd-ipv4ll.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdipv4llfoo
 #define foosdipv4llfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <net/ethernet.h>
 #include <netinet/in.h>
 
diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h
index d4e7a4fa..ea952ef1 100644
--- a/src/systemd/src/systemd/sd-lldp.h
+++ b/src/systemd/src/systemd/sd-lldp.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdlldphfoo
 #define foosdlldphfoo
 
@@ -23,8 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <net/ethernet.h>
 
diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h
index cc674336..76294753 100644
--- a/src/systemd/src/systemd/sd-ndisc.h
+++ b/src/systemd/src/systemd/sd-ndisc.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdndiscfoo
 #define foosdndiscfoo
 
@@ -22,8 +20,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "nm-sd-adapt.h"
-
 #include <inttypes.h>
 #include <net/ethernet.h>
 
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 26c2ed7f..a3447fbf 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -23,6 +23,7 @@ noinst_PROGRAMS = \
 	test-route-manager-linux \
 	test-route-manager-fake \
 	test-dcb \
+	test-systemd \
 	test-resolvconf-capture \
 	test-wired-defname \
 	test-utils
@@ -111,6 +112,20 @@ test_wired_defname_SOURCES = \
 test_wired_defname_LDADD = \
 	$(top_builddir)/src/libNetworkManager.la
 
+####### systemd test #######
+
+test_systemd_CFLAGS = \
+	"-I$(srcdir)/../" \
+	"-I$(srcdir)/../platform" \
+	"-I$(srcdir)/../systemd/src/systemd"
+
+test_systemd_SOURCES = \
+	test-systemd.c
+
+test_systemd_LDADD = \
+	$(top_builddir)/src/libNetworkManager-base.la \
+	$(top_builddir)/src/libsystemd-nm.la
+
 ####### utils test #######
 
 test_utils_SOURCES = \
@@ -143,6 +158,7 @@ TESTS = \
 	test-resolvconf-capture \
 	test-general \
 	test-general-with-expect \
+	test-systemd \
 	test-wired-defname \
 	test-utils
 
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index e0967f7b..9d67063e 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -92,14 +92,14 @@ noinst_PROGRAMS = test-general$(EXEEXT) \
 	test-general-with-expect$(EXEEXT) test-ip4-config$(EXEEXT) \
 	test-ip6-config$(EXEEXT) test-route-manager-linux$(EXEEXT) \
 	test-route-manager-fake$(EXEEXT) test-dcb$(EXEEXT) \
-	test-resolvconf-capture$(EXEEXT) test-wired-defname$(EXEEXT) \
-	test-utils$(EXEEXT)
+	test-systemd$(EXEEXT) test-resolvconf-capture$(EXEEXT) \
+	test-wired-defname$(EXEEXT) test-utils$(EXEEXT)
 TESTS = test-ip4-config$(EXEEXT) test-ip6-config$(EXEEXT) \
 	test-route-manager-fake$(EXEEXT) \
 	test-route-manager-linux$(EXEEXT) test-dcb$(EXEEXT) \
 	test-resolvconf-capture$(EXEEXT) test-general$(EXEEXT) \
-	test-general-with-expect$(EXEEXT) test-wired-defname$(EXEEXT) \
-	test-utils$(EXEEXT)
+	test-general-with-expect$(EXEEXT) test-systemd$(EXEEXT) \
+	test-wired-defname$(EXEEXT) test-utils$(EXEEXT)
 subdir = src/tests
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
@@ -167,6 +167,14 @@ test_route_manager_linux_OBJECTS =  \
 	$(am_test_route_manager_linux_OBJECTS)
 test_route_manager_linux_DEPENDENCIES =  \
 	$(top_builddir)/src/libNetworkManager.la
+am_test_systemd_OBJECTS = test_systemd-test-systemd.$(OBJEXT)
+test_systemd_OBJECTS = $(am_test_systemd_OBJECTS)
+test_systemd_DEPENDENCIES =  \
+	$(top_builddir)/src/libNetworkManager-base.la \
+	$(top_builddir)/src/libsystemd-nm.la
+test_systemd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_systemd_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
 am_test_utils_OBJECTS = test_utils-test-utils.$(OBJEXT)
 test_utils_OBJECTS = $(am_test_utils_OBJECTS)
 am_test_wired_defname_OBJECTS = test-wired-defname.$(OBJEXT)
@@ -211,14 +219,14 @@ SOURCES = $(test_dcb_SOURCES) $(test_general_SOURCES) \
 	$(test_general_with_expect_SOURCES) $(test_ip4_config_SOURCES) \
 	$(test_ip6_config_SOURCES) $(test_resolvconf_capture_SOURCES) \
 	$(test_route_manager_fake_SOURCES) \
-	$(test_route_manager_linux_SOURCES) $(test_utils_SOURCES) \
-	$(test_wired_defname_SOURCES)
+	$(test_route_manager_linux_SOURCES) $(test_systemd_SOURCES) \
+	$(test_utils_SOURCES) $(test_wired_defname_SOURCES)
 DIST_SOURCES = $(test_dcb_SOURCES) $(test_general_SOURCES) \
 	$(test_general_with_expect_SOURCES) $(test_ip4_config_SOURCES) \
 	$(test_ip6_config_SOURCES) $(test_resolvconf_capture_SOURCES) \
 	$(test_route_manager_fake_SOURCES) \
-	$(test_route_manager_linux_SOURCES) $(test_utils_SOURCES) \
-	$(test_wired_defname_SOURCES)
+	$(test_route_manager_linux_SOURCES) $(test_systemd_SOURCES) \
+	$(test_utils_SOURCES) $(test_wired_defname_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
 	ctags-recursive dvi-recursive html-recursive info-recursive \
 	install-data-recursive install-dvi-recursive \
@@ -855,6 +863,20 @@ test_wired_defname_LDADD = \
 	$(top_builddir)/src/libNetworkManager.la
 
 
+####### systemd test #######
+test_systemd_CFLAGS = \
+	"-I$(srcdir)/../" \
+	"-I$(srcdir)/../platform" \
+	"-I$(srcdir)/../systemd/src/systemd"
+
+test_systemd_SOURCES = \
+	test-systemd.c
+
+test_systemd_LDADD = \
+	$(top_builddir)/src/libNetworkManager-base.la \
+	$(top_builddir)/src/libsystemd-nm.la
+
+
 ####### utils test #######
 test_utils_SOURCES = \
 	test-utils.c
@@ -948,6 +970,10 @@ test-route-manager-linux$(EXEEXT): $(test_route_manager_linux_OBJECTS) $(test_ro
 	@rm -f test-route-manager-linux$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(test_route_manager_linux_OBJECTS) $(test_route_manager_linux_LDADD) $(LIBS)
 
+test-systemd$(EXEEXT): $(test_systemd_OBJECTS) $(test_systemd_DEPENDENCIES) $(EXTRA_test_systemd_DEPENDENCIES) 
+	@rm -f test-systemd$(EXEEXT)
+	$(AM_V_CCLD)$(test_systemd_LINK) $(test_systemd_OBJECTS) $(test_systemd_LDADD) $(LIBS)
+
 test-utils$(EXEEXT): $(test_utils_OBJECTS) $(test_utils_DEPENDENCIES) $(EXTRA_test_utils_DEPENDENCIES) 
 	@rm -f test-utils$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(test_utils_OBJECTS) $(test_utils_LDADD) $(LIBS)
@@ -973,6 +999,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_manager_fake-test-route-manager.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_manager_linux-test-common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_manager_linux-test-route-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_systemd-test-systemd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_utils-test-utils.Po@am__quote@
 
 .c.o:
@@ -1052,6 +1079,20 @@ test_route_manager_linux-test-route-manager.obj: test-route-manager.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_manager_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_manager_linux-test-route-manager.obj `if test -f 'test-route-manager.c'; then $(CYGPATH_W) 'test-route-manager.c'; else $(CYGPATH_W) '$(srcdir)/test-route-manager.c'; fi`
 
+test_systemd-test-systemd.o: test-systemd.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_systemd_CFLAGS) $(CFLAGS) -MT test_systemd-test-systemd.o -MD -MP -MF $(DEPDIR)/test_systemd-test-systemd.Tpo -c -o test_systemd-test-systemd.o `test -f 'test-systemd.c' || echo '$(srcdir)/'`test-systemd.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_systemd-test-systemd.Tpo $(DEPDIR)/test_systemd-test-systemd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-systemd.c' object='test_systemd-test-systemd.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_systemd_CFLAGS) $(CFLAGS) -c -o test_systemd-test-systemd.o `test -f 'test-systemd.c' || echo '$(srcdir)/'`test-systemd.c
+
+test_systemd-test-systemd.obj: test-systemd.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_systemd_CFLAGS) $(CFLAGS) -MT test_systemd-test-systemd.obj -MD -MP -MF $(DEPDIR)/test_systemd-test-systemd.Tpo -c -o test_systemd-test-systemd.obj `if test -f 'test-systemd.c'; then $(CYGPATH_W) 'test-systemd.c'; else $(CYGPATH_W) '$(srcdir)/test-systemd.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_systemd-test-systemd.Tpo $(DEPDIR)/test_systemd-test-systemd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-systemd.c' object='test_systemd-test-systemd.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_systemd_CFLAGS) $(CFLAGS) -c -o test_systemd-test-systemd.obj `if test -f 'test-systemd.c'; then $(CYGPATH_W) 'test-systemd.c'; else $(CYGPATH_W) '$(srcdir)/test-systemd.c'; fi`
+
 test_utils-test-utils.o: test-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_utils_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils-test-utils.o -MD -MP -MF $(DEPDIR)/test_utils-test-utils.Tpo -c -o test_utils-test-utils.o `test -f 'test-utils.c' || echo '$(srcdir)/'`test-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_utils-test-utils.Tpo $(DEPDIR)/test_utils-test-utils.Po
@@ -1368,6 +1409,13 @@ test-general-with-expect.log: test-general-with-expect$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+test-systemd.log: test-systemd$(EXEEXT)
+	@p='test-systemd$(EXEEXT)'; \
+	b='test-systemd'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 test-wired-defname.log: test-wired-defname$(EXEEXT)
 	@p='test-wired-defname$(EXEEXT)'; \
 	b='test-wired-defname'; \
diff --git a/src/tests/config/nm-test-device.c b/src/tests/config/nm-test-device.c
index 681f4966..04ccaec2 100644
--- a/src/tests/config/nm-test-device.c
+++ b/src/tests/config/nm-test-device.c
@@ -18,7 +18,7 @@
  * Copyright 2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c
index e8de86c8..19306df7 100644
--- a/src/tests/config/test-config.c
+++ b/src/tests/config/test-config.c
@@ -18,13 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <unistd.h>
 
-
 #include "nm-config.h"
-#include "nm-default.h"
 #include "nm-test-device.h"
 #include "nm-fake-platform.h"
 #include "nm-bus-manager.h"
diff --git a/src/tests/test-dcb.c b/src/tests/test-dcb.c
index 35f1ed0f..e8e1ec86 100644
--- a/src/tests/test-dcb.c
+++ b/src/tests/test-dcb.c
@@ -18,11 +18,10 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-dcb.h"
 
 #include "nm-test-utils.h"
diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c
index c6abdccf..43595c8d 100644
--- a/src/tests/test-general-with-expect.c
+++ b/src/tests/test-general-with-expect.c
@@ -18,7 +18,7 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <errno.h>
@@ -27,7 +27,6 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-multi-index.h"
 
@@ -225,33 +224,33 @@ test_nm_utils_kill_child (void)
 	int err;
 	GLogLevelFlags fatal_mask;
 	char *argv_watchdog[] = {
-			"sh",
+			"bash",
 			"-c",
 			"sleep 4; "
 			"kill -KILL 0; #watchdog for #" TEST_TOKEN,
 			NULL,
 		};
 	char *argv1[] = {
-			"sh",
+			"bash",
 			"-c",
 			"trap \"sleep 0.3; exit 10\" EXIT; "
 			"sleep 100000; exit $? #" TEST_TOKEN,
 			NULL,
 		};
 	char *argv2[] = {
-			"sh",
+			"bash",
 			"-c",
 			"exit 47; #" TEST_TOKEN,
 			NULL,
 		};
 	char *argv3[] = {
-			"sh",
+			"bash",
 			"-c",
 			"trap \"exit 47\" TERM; while true; do :; done; #" TEST_TOKEN,
 			NULL,
 		};
 	char *argv4[] = {
-			"sh",
+			"bash",
 			"-c",
 			"trap \"while true; do :; done\" TERM; while true; do :; done; #" TEST_TOKEN,
 			NULL,
@@ -855,6 +854,49 @@ test_nm_multi_index (void)
 
 /*******************************************/
 
+static void
+test_nm_utils_new_vlan_name (void)
+{
+	guint i, j;
+	const char *parent_names[] = {
+		"a",
+		"a2",
+		"a23",
+		"a23456789",
+		"a2345678901",
+		"a23456789012",
+		"a234567890123",
+		"a2345678901234",
+		"a23456789012345",
+		"a234567890123456",
+		"a2345678901234567",
+	};
+
+	for (i = 0; i < G_N_ELEMENTS (parent_names); i++) {
+		for (j = 0; j < 10; j++) {
+			gs_free char *ifname = NULL;
+			gs_free char *vlan_id_s = NULL;
+			guint vlan_id;
+
+			/* Create a random VLAN id between 0 and 4094 */
+			vlan_id = nmtst_get_rand_int () % 4095;
+
+			vlan_id_s = g_strdup_printf (".%d", vlan_id);
+
+			ifname = nm_utils_new_vlan_name (parent_names[i], vlan_id);
+			g_assert (ifname && ifname[0]);
+			g_assert_cmpint (strlen (ifname), ==, MIN (15, strlen (parent_names[i]) + strlen (vlan_id_s)));
+			g_assert (g_str_has_suffix (ifname, vlan_id_s));
+			g_assert (ifname[strlen (ifname) - strlen (vlan_id_s)] == '.');
+			g_assert (strncmp (ifname, parent_names[i], strlen (ifname) - strlen (vlan_id_s)) == 0);
+			if (!g_str_has_prefix (ifname, parent_names[i]))
+				g_assert_cmpint (strlen (ifname), ==, 15);
+		}
+	}
+}
+
+/*******************************************/
+
 NMTST_DEFINE ();
 
 int
@@ -867,6 +909,7 @@ main (int argc, char **argv)
 	g_test_add_func ("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes);
 	g_test_add_func ("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid);
 	g_test_add_func ("/general/nm_multi_index", test_nm_multi_index);
+	g_test_add_func ("/general/nm_utils_new_vlan_name", test_nm_utils_new_vlan_name);
 
 	return g_test_run ();
 }
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index da68c9a9..b8a51f2a 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <errno.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-core-internal.h"
 
@@ -205,7 +204,7 @@ test_connection_match_basic (void)
 	copy = nm_simple_connection_new_clone (orig);
 	connections = g_slist_append (connections, copy);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	/* Now change a material property like IPv4 method and ensure matching fails */
@@ -214,7 +213,7 @@ test_connection_match_basic (void)
 	g_object_set (G_OBJECT (s_ip4),
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
 	              NULL);
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == NULL);
 
 	g_slist_free (connections);
@@ -250,7 +249,7 @@ test_connection_match_ip6_method (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -284,7 +283,7 @@ test_connection_match_ip6_method_ignore (void)
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -318,7 +317,7 @@ test_connection_match_ip6_method_ignore_auto (void)
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -326,7 +325,6 @@ test_connection_match_ip6_method_ignore_auto (void)
 	g_object_unref (copy);
 }
 
-
 static void
 test_connection_match_ip4_method (void)
 {
@@ -355,11 +353,11 @@ test_connection_match_ip4_method (void)
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, FALSE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, FALSE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	/* Ensure when carrier=true matching fails */
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == NULL);
 
 	g_slist_free (connections);
@@ -393,7 +391,7 @@ test_connection_match_interface_name (void)
 	              NM_SETTING_CONNECTION_INTERFACE_NAME, NULL,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -430,7 +428,7 @@ test_connection_match_wired (void)
 	              NM_SETTING_WIRED_S390_NETTYPE, "qeth",
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -462,7 +460,7 @@ test_connection_match_wired2 (void)
 	 * the connections match. It can happen if assuming VLAN devices. */
 	nm_connection_remove_setting (orig, NM_TYPE_SETTING_WIRED);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == copy);
 
 	g_slist_free (connections);
@@ -487,7 +485,7 @@ test_connection_match_cloned_mac (void)
 	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23",
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == fuzzy);
 
 	exact = nm_simple_connection_new_clone (orig);
@@ -498,14 +496,14 @@ test_connection_match_cloned_mac (void)
 	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23",
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == exact);
 
 	g_object_set (G_OBJECT (s_wired),
 	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:24",
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched == fuzzy);
 
 	g_slist_free (connections);
@@ -565,7 +563,7 @@ test_connection_no_match_ip4_addr (void)
 	nm_setting_ip_config_add_address (s_ip4, nm_addr);
 	nm_ip_address_unref (nm_addr);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched != copy);
 
 	g_slist_free (connections);
@@ -611,7 +609,7 @@ test_connection_no_match_vlan (void)
 	              NM_SETTING_VLAN_FLAGS, 0,
 	              NULL);
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched != copy);
 
 	/* Check that the connections do not match if VLAN priorities differ */
@@ -621,7 +619,7 @@ test_connection_no_match_vlan (void)
 	g_object_set (G_OBJECT (s_vlan_copy), NM_SETTING_VLAN_FLAGS, 0, NULL);
 	nm_setting_vlan_add_priority_str (s_vlan_copy, NM_VLAN_INGRESS_MAP, "4:2");
 
-	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL);
 	g_assert (matched != copy);
 
 	g_slist_free (connections);
@@ -629,6 +627,118 @@ test_connection_no_match_vlan (void)
 	g_object_unref (copy);
 }
 
+static void
+test_connection_match_ip4_routes1 (void)
+{
+	gs_unref_object NMConnection *orig = NULL, *copy = NULL;
+	NMConnection *matched;
+	gs_free_slist GSList *connections = NULL;
+	NMSettingIPConfig *s_ip4;
+
+	orig = _match_connection_new ();
+
+	s_ip4 = nm_connection_get_setting_ip4_config (orig);
+	g_assert (s_ip4);
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NULL);
+
+	nmtst_setting_ip_config_add_address (s_ip4, "10.0.0.1", 8);
+
+	/* Clone connection */
+	copy = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, copy);
+
+	/* Set routes on original connection */
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.16.0", 24, "10.0.0.2", -1);
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.17.0", 24, "10.0.0.3", 20);
+
+	/* Set single route on cloned connection */
+	s_ip4 = nm_connection_get_setting_ip4_config (copy);
+	g_assert (s_ip4);
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.17.0", 24, "10.0.0.3", 20);
+
+	/* Try to match the connections */
+	matched = nm_utils_match_connection (connections, orig, FALSE, 100, 0, NULL, NULL);
+	g_assert (matched == NULL);
+}
+
+static void
+test_connection_match_ip4_routes2 (void)
+{
+	gs_unref_object NMConnection *orig = NULL, *copy = NULL;
+	NMConnection *matched;
+	gs_free_slist GSList *connections = NULL;
+	NMSettingIPConfig *s_ip4;
+
+	orig = _match_connection_new ();
+
+	s_ip4 = nm_connection_get_setting_ip4_config (orig);
+	g_assert (s_ip4);
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NULL);
+
+	nmtst_setting_ip_config_add_address (s_ip4, "10.0.0.1", 8);
+
+	/* Clone connection */
+	copy = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, copy);
+
+	/* Set routes on original connection */
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.16.0", 24, "10.0.0.2", -1);
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.17.0", 24, "10.0.0.3", 20);
+
+	/* Set routes on cloned connection, changing order and using explicit metrics */
+	s_ip4 = nm_connection_get_setting_ip4_config (copy);
+	g_assert (s_ip4);
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.17.0", 24, "10.0.0.3", 20);
+	nmtst_setting_ip_config_add_route (s_ip4, "172.25.16.0", 24, "10.0.0.2", 100);
+
+	/* Try to match the connections using different default metrics */
+	matched = nm_utils_match_connection (connections, orig, FALSE, 100, 0, NULL, NULL);
+	g_assert (matched == copy);
+	matched = nm_utils_match_connection (connections, orig, FALSE, 500, 0, NULL, NULL);
+	g_assert (matched == NULL);
+}
+
+static void
+test_connection_match_ip6_routes (void)
+{
+	gs_unref_object NMConnection *orig = NULL, *copy = NULL;
+	NMConnection *matched;
+	gs_free_slist GSList *connections = NULL;
+	NMSettingIPConfig *s_ip6;
+
+	orig = _match_connection_new ();
+
+	s_ip6 = nm_connection_get_setting_ip6_config (orig);
+	g_assert (s_ip6);
+	g_object_set (G_OBJECT (s_ip6),
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
+	              NULL);
+
+	nmtst_setting_ip_config_add_address (s_ip6, "fd01::15", 64);
+
+	/* Clone connection */
+	copy = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, copy);
+
+	/* Set routes on original connection */
+	nmtst_setting_ip_config_add_route (s_ip6, "2001:db8:a:b:0:0:0:0", 64, "fd01::16", -1);
+
+	/* Set routes on cloned connection */
+	s_ip6 = nm_connection_get_setting_ip6_config (copy);
+	g_assert (s_ip6);
+	nmtst_setting_ip_config_add_route (s_ip6, "2001:db8:a:b:0:0:0:0", 64, "fd01::16", 50);
+
+	/* Try to match the connections */
+	matched = nm_utils_match_connection (connections, orig, FALSE, 0, 100, NULL, NULL);
+	g_assert (matched == NULL);
+	matched = nm_utils_match_connection (connections, orig, FALSE, 0, 50, NULL, NULL);
+	g_assert (matched == copy);
+}
+
 static NMConnection *
 _create_connection_autoconnect (const char *id, gboolean autoconnect, int autoconnect_priority)
 {
@@ -1010,8 +1120,8 @@ test_nm_utils_strbuf_append (void)
 #define STR_ORIG "abcdefghijklmnopqrstuvwxyz"
 	int buf_len;
 	int rep;
-	char buf[STRLEN (BUF_ORIG) + 1];
-	char str[STRLEN (BUF_ORIG) + 1];
+	char buf[NM_STRLEN (BUF_ORIG) + 1];
+	char str[NM_STRLEN (BUF_ORIG) + 1];
 
 	for (buf_len = 0; buf_len < 10; buf_len++) {
 		for (rep = 0; rep < 50; rep++) {
@@ -1136,6 +1246,9 @@ main (int argc, char **argv)
 	g_test_add_func ("/general/connection-match/cloned_mac", test_connection_match_cloned_mac);
 	g_test_add_func ("/general/connection-match/no-match-ip4-addr", test_connection_no_match_ip4_addr);
 	g_test_add_func ("/general/connection-match/no-match-vlan", test_connection_no_match_vlan);
+	g_test_add_func ("/general/connection-match/routes/ip4/1", test_connection_match_ip4_routes1);
+	g_test_add_func ("/general/connection-match/routes/ip4/2", test_connection_match_ip4_routes2);
+	g_test_add_func ("/general/connection-match/routes/ip6", test_connection_match_ip6_routes);
 
 	g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
 
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
index 16cd3d1e..2b743c8c 100644
--- a/src/tests/test-ip4-config.c
+++ b/src/tests/test-ip4-config.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-ip4-config.h"
 #include "nm-platform.h"
 
diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c
index 2639a1f0..5a2bb589 100644
--- a/src/tests/test-ip6-config.c
+++ b/src/tests/test-ip6-config.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-ip6-config.h"
 
 #include "nm-platform.h"
diff --git a/src/tests/test-resolvconf-capture.c b/src/tests/test-resolvconf-capture.c
index db7006ba..31b6e177 100644
--- a/src/tests/test-resolvconf-capture.c
+++ b/src/tests/test-resolvconf-capture.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c
index 347c122c..742f4ee5 100644
--- a/src/tests/test-route-manager.c
+++ b/src/tests/test-route-manager.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <arpa/inet.h>
 #include <linux/rtnetlink.h>
 
-#include "nm-default.h"
 #include "test-common.h"
 
 #include "nm-platform.h"
diff --git a/src/tests/test-systemd.c b/src/tests/test-systemd.c
new file mode 100644
index 00000000..84ad95ba
--- /dev/null
+++ b/src/tests/test-systemd.c
@@ -0,0 +1,53 @@
+/* -*- 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) 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "sd-dhcp-client.h"
+
+#include "nm-test-utils.h"
+
+/*****************************************************************************/
+
+static void
+test_dhcp_create (void)
+{
+	sd_dhcp_client *client4 = NULL;
+	int r;
+
+	r = sd_dhcp_client_new (&client4);
+	g_assert (r == 0);
+	g_assert (client4);
+
+	sd_dhcp_client_unref (client4);
+}
+
+/*****************************************************************************/
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+	nmtst_init_assert_logging (&argc, &argv, "INFO", "ALL");
+
+	g_test_add_func ("/systemd/dhcp/create", test_dhcp_create);
+
+	return g_test_run ();
+}
diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c
index 79a7e680..c8c82aef 100644
--- a/src/tests/test-utils.c
+++ b/src/tests/test-utils.c
@@ -18,13 +18,13 @@
  *
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <errno.h>
 #include <arpa/inet.h>
 
-#include "NetworkManagerUtils.c"
+#include "nm-core-utils.c"
 
 #include "nm-test-utils.h"
 
diff --git a/src/tests/test-wired-defname.c b/src/tests/test-wired-defname.c
index 989345d8..6edd5ff2 100644
--- a/src/tests/test-wired-defname.c
+++ b/src/tests/test-wired-defname.c
@@ -18,12 +18,10 @@
  *
  */
 
-#include "config.h"
-
-
-#include <nm-simple-connection.h>
-#include <nm-setting-connection.h>
 #include "nm-default.h"
+
+#include "nm-simple-connection.h"
+#include "nm-setting-connection.h"
 #include "nm-device-ethernet-utils.h"
 
 #include "nm-test-utils.h"
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index c548c9fa..653b9972 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 #include <sys/socket.h>
@@ -28,7 +28,6 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "nm-default.h"
 #include "nm-vpn-connection.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
@@ -767,21 +766,13 @@ nm_vpn_connection_get_service (NMVpnConnection *self)
 	return nm_setting_vpn_get_service_type (s_vpn);
 }
 
-static const char *
-vpn_plugin_failure_to_string (NMVpnPluginFailure failure)
-{
-	switch (failure) {
-	case NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED:
-		return "login-failed";
-	case NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED:
-		return "connect-failed";
-	case NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG:
-		return "bad-ip-config";
-	default:
-		break;
-	}
-	return "unknown";
-}
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_vpn_plugin_failure_to_string, NMVpnPluginFailure,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED,   "login-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED, "connect-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG,  "bad-ip-config"),
+);
+#define vpn_plugin_failure_to_string(failure) NM_UTILS_LOOKUP_STR (_vpn_plugin_failure_to_string, failure)
 
 static void
 plugin_failed (NMVpnConnection *self, guint reason)
@@ -803,81 +794,50 @@ plugin_failed (NMVpnConnection *self, guint reason)
 	}
 }
 
-static const char *
-vpn_service_state_to_string (NMVpnServiceState state)
-{
-	switch (state) {
-	case NM_VPN_SERVICE_STATE_INIT:
-		return "init";
-	case NM_VPN_SERVICE_STATE_SHUTDOWN:
-		return "shutdown";
-	case NM_VPN_SERVICE_STATE_STARTING:
-		return "starting";
-	case NM_VPN_SERVICE_STATE_STARTED:
-		return "started";
-	case NM_VPN_SERVICE_STATE_STOPPING:
-		return "stopping";
-	case NM_VPN_SERVICE_STATE_STOPPED:
-		return "stopped";
-	default:
-		break;
-	}
-	return "unknown";
-}
-
-static const char *state_table[] = {
-	[STATE_UNKNOWN]       = "unknown",
-	[STATE_WAITING]       = "waiting",
-	[STATE_PREPARE]       = "prepare",
-	[STATE_NEED_AUTH]     = "need-auth",
-	[STATE_CONNECT]       = "connect",
-	[STATE_IP_CONFIG_GET] = "ip-config-get",
-	[STATE_PRE_UP]        = "pre-up",
-	[STATE_ACTIVATED]     = "activated",
-	[STATE_DEACTIVATING]  = "deactivating",
-	[STATE_DISCONNECTED]  = "disconnected",
-	[STATE_FAILED]        = "failed",
-};
-
-static const char *
-vpn_state_to_string (VpnState state)
-{
-	if ((gsize) state < G_N_ELEMENTS (state_table))
-		return state_table[state];
-	return "unknown";
-}
-
-static const char *
-vpn_reason_to_string (NMVpnConnectionStateReason reason)
-{
-	switch (reason) {
-	case NM_VPN_CONNECTION_STATE_REASON_NONE:
-		return "none";
-	case NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED:
-		return "user-disconnected";
-	case NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
-		return "device-disconnected";
-	case NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED:
-		return "service-stopped";
-	case NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
-		return "ip-config-invalid";
-	case NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
-		return "connect-timeout";
-	case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
-		return "service-start-timeout";
-	case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
-		return "service-start-failed";
-	case NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS:
-		return "no-secrets";
-	case NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED:
-		return "login-failed";
-	case NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED:
-		return "connection-removed";
-	default:
-		break;
-	}
-	return "unknown";
-}
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_vpn_service_state_to_string, NMVpnServiceState,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_UNKNOWN,  "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_INIT,     "init"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_SHUTDOWN, "shutdown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_STARTING, "starting"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_STARTED,  "started"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_STOPPING, "stopping"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_SERVICE_STATE_STOPPED,  "stopped"),
+);
+#define vpn_service_state_to_string(state) NM_UTILS_LOOKUP_STR (_vpn_service_state_to_string, state)
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_vpn_state_to_string, VpnState,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_UNKNOWN,       "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_WAITING,       "waiting"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_PREPARE,       "prepare"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_NEED_AUTH,     "need-auth"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_CONNECT,       "connect"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_IP_CONFIG_GET, "ip-config-get"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_PRE_UP,        "pre-up"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_ACTIVATED,     "activated"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_DEACTIVATING,  "deactivating"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_DISCONNECTED,  "disconnected"),
+	NM_UTILS_LOOKUP_STR_ITEM (STATE_FAILED,        "failed"),
+);
+#define vpn_state_to_string(state) NM_UTILS_LOOKUP_STR (_vpn_state_to_string, state)
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_vpn_reason_to_string, NMVpnConnectionStateReason,
+	NM_UTILS_LOOKUP_DEFAULT (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_UNKNOWN,               "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_NONE,                  "none"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED,     "user-disconnected"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,   "device-disconnected"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED,       "service-stopped"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID,     "ip-config-invalid"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT,       "connect-timeout"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, "service-start-timeout"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED,  "service-start-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS,            "no-secrets"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED,          "login-failed"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED,    "connection-removed"),
+);
+#define vpn_reason_to_string(reason) NM_UTILS_LOOKUP_STR (_vpn_reason_to_string, reason)
 
 static void
 plugin_state_changed (NMVpnConnection *self, NMVpnServiceState new_service_state)
@@ -1321,6 +1281,8 @@ nm_vpn_connection_config_get (NMVpnConnection *self, GVariant *dict)
 	if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &b))
 		priv->has_ip6 = b;
 	nm_exported_object_clear_and_unexport (&priv->ip6_config);
+
+	nm_vpn_connection_config_maybe_complete (self, TRUE);
 }
 
 guint32
diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c
index 45d22998..6dcd5463 100644
--- a/src/vpn-manager/nm-vpn-manager.c
+++ b/src/vpn-manager/nm-vpn-manager.c
@@ -19,11 +19,10 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <string.h>
 
-#include "nm-default.h"
 #include "nm-vpn-manager.h"
 #include "nm-vpn-plugin-info.h"
 #include "nm-vpn-connection.h"