summary refs log tree commit diff
path: root/src/devices/wwan
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wwan')
-rw-r--r--src/devices/wwan/Makefile.am24
-rw-r--r--src/devices/wwan/Makefile.in55
-rw-r--r--src/devices/wwan/nm-device-modem-glue.h73
-rw-r--r--src/devices/wwan/nm-device-modem.c33
-rw-r--r--src/devices/wwan/nm-device-modem.h3
-rw-r--r--src/devices/wwan/nm-modem-broadband.c368
-rw-r--r--src/devices/wwan/nm-modem-broadband.h1
-rw-r--r--src/devices/wwan/nm-modem-enum-types.c2
-rw-r--r--src/devices/wwan/nm-modem-manager.c15
-rw-r--r--src/devices/wwan/nm-modem-manager.h1
-rw-r--r--src/devices/wwan/nm-modem.c171
-rw-r--r--src/devices/wwan/nm-modem.h50
-rw-r--r--src/devices/wwan/nm-wwan-factory.c17
-rw-r--r--src/devices/wwan/nm-wwan-factory.h2
14 files changed, 483 insertions, 332 deletions
diff --git a/src/devices/wwan/Makefile.am b/src/devices/wwan/Makefile.am
index 055b07b9..107f630b 100644
--- a/src/devices/wwan/Makefile.am
+++ b/src/devices/wwan/Makefile.am
@@ -8,14 +8,14 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
-	-I${top_srcdir}/include \
-	-I$(top_builddir)/include \
+	-I${top_builddir}/introspection \
+	-I${top_srcdir}/shared \
+	-I$(top_builddir)/shared \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(DBUS_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(MM_GLIB_CFLAGS)
 
@@ -47,31 +47,29 @@ WWAN_SYMBOL_VIS_FILE=$(srcdir)/wwan-exports.ver
 libnm_wwan_la_LDFLAGS = \
 	-avoid-version \
 	-Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE)
-libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS)
+libnm_wwan_la_LIBADD = \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(GLIB_LIBS) \
+	$(MM_GLIB_LIBS)
 
 ###########################################################
 
-nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml
-	dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $<
-
-BUILT_SOURCES += nm-device-modem-glue.h
-
 SYMBOL_VIS_FILE=$(srcdir)/exports.ver
 
 libnm_device_plugin_wwan_la_SOURCES = \
 	nm-wwan-factory.c \
 	nm-wwan-factory.h \
 	nm-device-modem.c \
-	nm-device-modem.h \
-	nm-device-modem-glue.h
+	nm-device-modem.h
 
 libnm_device_plugin_wwan_la_LDFLAGS = \
 	-module -avoid-version \
 	-Wl,--version-script=$(SYMBOL_VIS_FILE)
 
 libnm_device_plugin_wwan_la_LIBADD = \
+	$(top_builddir)/introspection/libnmdbus.la \
 	libnm-wwan.la \
-	$(DBUS_LIBS)
+	$(GLIB_LIBS)
 
 ###########################################################
 
diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in
index 571b1b7d..ac13135e 100644
--- a/src/devices/wwan/Makefile.in
+++ b/src/devices/wwan/Makefile.in
@@ -140,7 +140,8 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(pkglibdir)"
 LTLIBRARIES = $(pkglib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
-libnm_device_plugin_wwan_la_DEPENDENCIES = libnm-wwan.la \
+libnm_device_plugin_wwan_la_DEPENDENCIES =  \
+	$(top_builddir)/introspection/libnmdbus.la libnm-wwan.la \
 	$(am__DEPENDENCIES_1)
 am_libnm_device_plugin_wwan_la_OBJECTS = nm-wwan-factory.lo \
 	nm-device-modem.lo
@@ -154,8 +155,9 @@ libnm_device_plugin_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wwan_la_LDFLAGS) \
 	$(LDFLAGS) -o $@
-libnm_wwan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+libnm_wwan_la_DEPENDENCIES =  \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_1 = nm-modem-enum-types.lo
 am_libnm_wwan_la_OBJECTS = nm-modem-broadband.lo nm-modem-manager.lo \
 	nm-modem.lo $(am__objects_1)
@@ -243,7 +245,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -255,8 +256,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
-DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
@@ -266,6 +265,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -320,16 +320,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -366,6 +363,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -394,7 +393,6 @@ POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
 PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
-PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
@@ -409,6 +407,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -469,6 +469,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -476,6 +477,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -497,18 +499,18 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
-	-I${top_srcdir}/include \
-	-I$(top_builddir)/include \
+	-I${top_builddir}/introspection \
+	-I${top_srcdir}/shared \
+	-I$(top_builddir)/shared \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(DBUS_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(MM_GLIB_CFLAGS)
 
-BUILT_SOURCES = $(null) $(GLIB_GENERATED) nm-device-modem-glue.h
+BUILT_SOURCES = $(null) $(GLIB_GENERATED)
 pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la
 
 ###########################################################
@@ -531,22 +533,28 @@ libnm_wwan_la_LDFLAGS = \
 	-avoid-version \
 	-Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE)
 
-libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS)
+libnm_wwan_la_LIBADD = \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(GLIB_LIBS) \
+	$(MM_GLIB_LIBS)
+
+
+###########################################################
 SYMBOL_VIS_FILE = $(srcdir)/exports.ver
 libnm_device_plugin_wwan_la_SOURCES = \
 	nm-wwan-factory.c \
 	nm-wwan-factory.h \
 	nm-device-modem.c \
-	nm-device-modem.h \
-	nm-device-modem-glue.h
+	nm-device-modem.h
 
 libnm_device_plugin_wwan_la_LDFLAGS = \
 	-module -avoid-version \
 	-Wl,--version-script=$(SYMBOL_VIS_FILE)
 
 libnm_device_plugin_wwan_la_LIBADD = \
+	$(top_builddir)/introspection/libnmdbus.la \
 	libnm-wwan.la \
-	$(DBUS_LIBS)
+	$(GLIB_LIBS)
 
 
 ###########################################################
@@ -887,11 +895,6 @@ include $(GLIB_MAKEFILE)
 
 @GNOME_CODE_COVERAGE_RULES@
 
-###########################################################
-
-nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml
-	dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $<
-
 @ENABLE_TESTS_TRUE@check-local:
 @ENABLE_TESTS_TRUE@	$(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE)
 @ENABLE_TESTS_TRUE@	$(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE)
diff --git a/src/devices/wwan/nm-device-modem-glue.h b/src/devices/wwan/nm-device-modem-glue.h
deleted file mode 100644
index 21271491..00000000
--- a/src/devices/wwan/nm-device-modem-glue.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Generated by dbus-binding-tool; do not edit! */
-
-
-#ifndef __dbus_glib_marshal_nm_device_modem_MARSHAL_H__
-#define __dbus_glib_marshal_nm_device_modem_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-G_END_DECLS
-
-#endif /* __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ */
-
-#include <dbus/dbus-glib.h>
-static const DBusGMethodInfo dbus_glib_nm_device_modem_methods[] = {
-};
-
-const DBusGObjectInfo dbus_glib_nm_device_modem_object_info = {  1,
-  dbus_glib_nm_device_modem_methods,
-  0,
-"\0",
-"org.freedesktop.NetworkManager.Device.Modem\0PropertiesChanged\0\0",
-"org.freedesktop.NetworkManager.Device.Modem\0ModemCapabilities\0modem_capabilities\0read\0org.freedesktop.NetworkManager.Device.Modem\0CurrentCapabilities\0current_capabilities\0read\0\0"
-};
-
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index ca724c04..edecd24d 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -21,14 +21,12 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib.h>
 
+#include "nm-default.h"
 #include "nm-device-modem.h"
 #include "nm-modem.h"
 #include "nm-device-private.h"
 #include "nm-rfkill-manager.h"
-#include "nm-logging.h"
-#include "nm-dbus-manager.h"
 #include "nm-settings-connection.h"
 #include "nm-modem-broadband.h"
 #include "NetworkManagerUtils.h"
@@ -37,12 +35,12 @@
 #include "nm-device-logging.h"
 _LOG_DECLARE_SELF(NMDeviceModem);
 
+#include "nmdbus-device-modem.h"
+
 G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate))
 
-#include "nm-device-modem-glue.h"
-
 typedef struct {
 	NMModem *modem;
 	NMDeviceModemCapabilities caps;
@@ -108,7 +106,7 @@ modem_prepare_result (NMModem *modem,
 			 * the device to be auto-activated anymore, which would risk locking
 			 * the SIM if the incorrect PIN continues to be used.
 			 */
-			g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, FALSE, NULL);
+			nm_device_set_autoconnect (device, FALSE);
 			_LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN");
 		}
 
@@ -256,6 +254,12 @@ data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
 }
 
 static void
+ids_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+	nm_device_recheck_available_connections (NM_DEVICE (user_data));
+}
+
+static void
 modem_state_cb (NMModem *modem,
                 NMModemState new_state,
                 NMModemState old_state,
@@ -332,7 +336,7 @@ device_state_changed (NMDevice *device,
 {
 	NMDeviceModem *self = NM_DEVICE_MODEM (device);
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
-	NMConnection *connection = nm_device_get_connection (device);
+	NMConnection *connection = nm_device_get_applied_connection (device);
 
 	g_assert (priv->modem);
 
@@ -411,10 +415,7 @@ check_connection_available (NMDevice *device,
 		return FALSE;
 
 	if (state == NM_MODEM_STATE_LOCKED) {
-		NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (connection);
-
-		/* Can't use a connection without a PIN if the modem is locked */
-		if (!s_gsm || !nm_setting_gsm_get_pin (s_gsm))
+		if (!nm_connection_get_setting_gsm (connection))
 			return FALSE;
 	}
 
@@ -679,6 +680,10 @@ set_modem (NMDeviceModem *self, NMModem *modem)
 	 * while in the new ModemManager the data port is set afterwards when the bearer gets
 	 * created */
 	g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self);
+
+	g_signal_connect (modem, "notify::" NM_MODEM_DEVICE_ID, G_CALLBACK (ids_changed_cb), self);
+	g_signal_connect (modem, "notify::" NM_MODEM_SIM_ID, G_CALLBACK (ids_changed_cb), self);
+	g_signal_connect (modem, "notify::" NM_MODEM_SIM_OPERATOR_ID, G_CALLBACK (ids_changed_cb), self);
 }
 
 static void
@@ -795,7 +800,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
 		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
 		                    G_PARAM_STATIC_STRINGS));
 
-	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
-	                                        G_TYPE_FROM_CLASS (mclass),
-	                                        &dbus_glib_nm_device_modem_object_info);
+	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (mclass),
+	                                        NMDBUS_TYPE_DEVICE_MODEM_SKELETON,
+	                                        NULL);
 }
diff --git a/src/devices/wwan/nm-device-modem.h b/src/devices/wwan/nm-device-modem.h
index 996195c4..1cf399e1 100644
--- a/src/devices/wwan/nm-device-modem.h
+++ b/src/devices/wwan/nm-device-modem.h
@@ -21,9 +21,6 @@
 #ifndef __NETWORKMANAGER_DEVICE_MODEM_H__
 #define __NETWORKMANAGER_DEVICE_MODEM_H__
 
-#include <glib.h>
-#include <glib-object.h>
-
 #include "nm-device.h"
 #include "nm-modem.h"
 
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index ec4f4a2f..427f3ed6 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -20,28 +20,51 @@
 
 #include "config.h"
 
-#include <glib/gi18n.h>
 #include <string.h>
 #include <arpa/inet.h>
 #include <libmm-glib.h>
 
 #include "nm-modem-broadband.h"
 #include "nm-core-internal.h"
-#include "nm-logging.h"
+#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
 #include "nm-platform.h"
 
 G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM)
 
+typedef enum {
+    CONNECT_STEP_FIRST,
+    CONNECT_STEP_WAIT_FOR_SIM,
+    CONNECT_STEP_UNLOCK,
+    CONNECT_STEP_WAIT_FOR_READY,
+    CONNECT_STEP_CONNECT,
+    CONNECT_STEP_LAST
+} ConnectStep;
+
+typedef struct {
+	NMModemBroadband *self;
+	ConnectStep step;
+
+	MMModemCapability caps;
+	NMConnection *connection;
+	GCancellable *cancellable;
+	MMSimpleConnectProperties *connect_properties;
+	GArray *ip_types;
+	guint ip_types_i;
+	GError *first_error;
+} ConnectContext;
+
 struct _NMModemBroadbandPrivate {
 	/* The modem object from dbus */
 	MMObject *modem_object;
 	/* Per-interface objects */
 	MMModem *modem_iface;
 	MMModemSimple *simple_iface;
+	MMSim *sim_iface;
 
 	/* Connection setup */
+	ConnectContext *ctx;
 
 	MMBearer *bearer;
 	MMBearerIpConfig *ipv4_config;
@@ -257,45 +280,45 @@ create_gsm_connect_properties (NMConnection *connection)
 	return properties;
 }
 
-typedef struct {
-	NMModemBroadband *self;
-	MMModemCapability caps;
-	MMSimpleConnectProperties *connect_properties;
-	GArray *ip_types;
-	guint ip_types_i;
-	GError *first_error;
-} ActStageContext;
-
 static void
-act_stage_context_free (ActStageContext *ctx)
+connect_context_clear (NMModemBroadband *self)
 {
-	g_clear_error (&ctx->first_error);
-	g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref);
-	g_clear_object (&ctx->connect_properties);
-	g_object_unref (ctx->self);
-	g_slice_free (ActStageContext, ctx);
+	if (self->priv->ctx) {
+		ConnectContext *ctx = self->priv->ctx;
+
+		g_clear_error (&ctx->first_error);
+		g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref);
+		g_clear_object (&ctx->cancellable);
+		g_clear_object (&ctx->connection);
+		g_clear_object (&ctx->connect_properties);
+		g_clear_object (&ctx->self);
+		g_slice_free (ConnectContext, ctx);
+		self->priv->ctx = NULL;
+	}
 }
 
-static void act_stage_context_step (ActStageContext *ctx);
+static void connect_context_step (NMModemBroadband *self);
 
 static void
 connect_ready (MMModemSimple *simple_iface,
                GAsyncResult *res,
-               ActStageContext *ctx)
+               NMModemBroadband *self)
 {
+	ConnectContext *ctx = self->priv->ctx;
 	GError *error = NULL;
 	NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN;
 	NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN;
 
-	ctx->self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error);
-	if (!ctx->self->priv->bearer) {
+	self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error);
+	if (!self->priv->bearer) {
 		if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) ||
 		    (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) &&
-		     mm_modem_get_unlock_required (ctx->self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) {
-			/* Request PIN */
-			ask_for_pin (ctx->self);
+		     mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) {
 			g_error_free (error);
-			act_stage_context_free (ctx);
+
+			/* Request PIN */
+			ask_for_pin (self);
+			connect_context_clear (self);
 			return;
 		}
 
@@ -312,79 +335,190 @@ connect_ready (MMModemSimple *simple_iface,
 		 * retry with the next one, if any.
 		 */
 		ctx->ip_types_i++;
-		act_stage_context_step (ctx);
+		connect_context_clear (self);
 		return;
 	}
 
 	/* Grab IP configurations */
-	ctx->self->priv->ipv4_config = mm_bearer_get_ipv4_config (ctx->self->priv->bearer);
-	if (ctx->self->priv->ipv4_config)
-		ip4_method = get_bearer_ip_method (ctx->self->priv->ipv4_config);
+	self->priv->ipv4_config = mm_bearer_get_ipv4_config (self->priv->bearer);
+	if (self->priv->ipv4_config)
+		ip4_method = get_bearer_ip_method (self->priv->ipv4_config);
 
-	ctx->self->priv->ipv6_config = mm_bearer_get_ipv6_config (ctx->self->priv->bearer);
-	if (ctx->self->priv->ipv6_config)
-		ip6_method = get_bearer_ip_method (ctx->self->priv->ipv6_config);
+	self->priv->ipv6_config = mm_bearer_get_ipv6_config (self->priv->bearer);
+	if (self->priv->ipv6_config)
+		ip6_method = get_bearer_ip_method (self->priv->ipv6_config);
 
 	if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN &&
 	    ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) {
 		nm_log_warn (LOGD_MB, "(%s): failed to connect modem: invalid bearer IP configuration",
-		             nm_modem_get_uid (NM_MODEM (ctx->self)));
-		g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
-		act_stage_context_free (ctx);
+		             nm_modem_get_uid (NM_MODEM (self)));
+		g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+		connect_context_clear (self);
 		return;
 	}
 
-	g_object_set (ctx->self,
-	              NM_MODEM_DATA_PORT,  mm_bearer_get_interface (ctx->self->priv->bearer),
+	g_object_set (self,
+	              NM_MODEM_DATA_PORT,  mm_bearer_get_interface (self->priv->bearer),
 	              NM_MODEM_IP4_METHOD, ip4_method,
 	              NM_MODEM_IP6_METHOD, ip6_method,
-	              NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (ctx->self->priv->bearer),
+	              NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->priv->bearer),
 	              NULL);
 
-	g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
-	act_stage_context_free (ctx);
+	ctx->step++;
+	connect_context_step (self);
 }
 
 static void
-act_stage_context_step (ActStageContext *ctx)
+send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self)
 {
-	if (ctx->ip_types_i < ctx->ip_types->len) {
-		NMModemIPType current;
-
-		current = g_array_index (ctx->ip_types, NMModemIPType, ctx->ip_types_i);
-
-		if (current == NM_MODEM_IP_TYPE_IPV4)
-			mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4);
-		else if (current == NM_MODEM_IP_TYPE_IPV6)
-			mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV6);
-		else if (current == NM_MODEM_IP_TYPE_IPV4V6)
-			mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6);
-		else
-			g_assert_not_reached ();
-
-		nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'",
-		            nm_modem_get_uid (NM_MODEM (ctx->self)),
-		            nm_modem_ip_type_to_string (current));
-
-		mm_modem_simple_connect (ctx->self->priv->simple_iface,
-		                         ctx->connect_properties,
-		                         NULL,
-		                         (GAsyncReadyCallback)connect_ready,
-		                         ctx);
+    GError *error = NULL;
+
+    if (!mm_sim_send_pin_finish (sim, result, &error)) {
+		if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) ||
+		    (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) &&
+		     mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) {
+			ask_for_pin (self);
+		} else {
+			g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error));
+		}
+		g_error_free (error);
 		return;
+    }
+
+	self->priv->ctx->step++;
+	connect_context_step (self);
+}
+
+static void
+connect_context_step (NMModemBroadband *self)
+{
+	ConnectContext *ctx = self->priv->ctx;
+
+	switch (ctx->step) {
+	case CONNECT_STEP_FIRST:
+		ctx->step++;
+		/* fall through */
+
+	case CONNECT_STEP_WAIT_FOR_SIM:
+		if (MODEM_CAPS_3GPP (ctx->caps) && !self->priv->sim_iface) {
+			/* Have to wait for the SIM to show up */
+			break;
+		}
+		ctx->step++;
+		/* fall through */
+
+	case CONNECT_STEP_UNLOCK:
+		if (   MODEM_CAPS_3GPP (ctx->caps)
+		    && mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN) {
+			NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (ctx->connection);
+			const char *pin = nm_setting_gsm_get_pin (s_gsm);
+
+			/* If we have a PIN already, send it.  If we don't, get it. */
+			if (pin) {
+				mm_sim_send_pin (self->priv->sim_iface,
+				                 pin,
+				                 ctx->cancellable,
+				                 (GAsyncReadyCallback) send_pin_ready,
+				                 self);
+			} else {
+				ask_for_pin (self);
+			}
+			break;
+		}
+		ctx->step++;
+		/* fall through */
+
+	case CONNECT_STEP_WAIT_FOR_READY: {
+		GError *error = NULL;
+
+		if (mm_modem_get_state (self->priv->modem_iface) <= MM_MODEM_STATE_LOCKED)
+			break;
+
+		/* Create core connect properties based on the modem capabilities */
+		g_assert (!ctx->connect_properties);
+
+		if (MODEM_CAPS_3GPP (ctx->caps))
+			ctx->connect_properties = create_gsm_connect_properties (ctx->connection);
+		else if (MODEM_CAPS_3GPP2 (ctx->caps))
+			ctx->connect_properties = create_cdma_connect_properties (ctx->connection);
+		else {
+			nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem",
+			             nm_modem_get_uid (NM_MODEM (self)),
+			             nm_connection_get_id (ctx->connection));
+
+			g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
+			connect_context_clear (self);
+			break;
+		}
+		g_assert (ctx->connect_properties);
+
+		/* Build up list of IP types that we need to use in the retries */
+		ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error);
+		if (!ctx->ip_types) {
+			nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s",
+			             nm_modem_get_uid (NM_MODEM (self)),
+			             nm_connection_get_id (ctx->connection),
+			             error ? error->message : "unknown error");
+			g_clear_error (&error);
+
+			g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
+			connect_context_clear (self);
+			break;
+		}
+
+		ctx->step++;
+		/* fall through */
 	}
 
-	/* If we have a saved error from a previous attempt, use it */
-	if (!ctx->first_error)
-		ctx->first_error = g_error_new_literal (NM_DEVICE_ERROR,
-		                                        NM_DEVICE_ERROR_INVALID_CONNECTION,
-		                                        "invalid bearer IP configuration");
-
-	nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s",
-	             nm_modem_get_uid (NM_MODEM (ctx->self)),
-	             ctx->first_error->message);
-	g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error));
-	act_stage_context_free (ctx);
+	case CONNECT_STEP_CONNECT:
+		if (ctx->ip_types_i < ctx->ip_types->len) {
+			NMModemIPType current;
+
+			current = g_array_index (ctx->ip_types, NMModemIPType, ctx->ip_types_i);
+
+			if (current == NM_MODEM_IP_TYPE_IPV4)
+				mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4);
+			else if (current == NM_MODEM_IP_TYPE_IPV6)
+				mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV6);
+			else if (current == NM_MODEM_IP_TYPE_IPV4V6)
+				mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6);
+			else
+				g_assert_not_reached ();
+
+			nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'",
+			            nm_modem_get_uid (NM_MODEM (self)),
+			            nm_modem_ip_type_to_string (current));
+
+			mm_modem_simple_connect (self->priv->simple_iface,
+			                         ctx->connect_properties,
+			                         NULL,
+			                         (GAsyncReadyCallback) connect_ready,
+			                         self);
+			break;
+		}
+
+		ctx->step++;
+		/* fall through */
+
+	case CONNECT_STEP_LAST:
+		if (self->priv->ipv4_config || self->priv->ipv6_config) {
+			g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
+		} else {
+			/* If we have a saved error from a previous attempt, use it */
+			if (!ctx->first_error)
+				ctx->first_error = g_error_new_literal (NM_DEVICE_ERROR,
+				                                        NM_DEVICE_ERROR_INVALID_CONNECTION,
+				                                        "invalid bearer IP configuration");
+
+			nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s",
+					     nm_modem_get_uid (NM_MODEM (self)),
+					     ctx->first_error->message);
+			g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error));
+		}
+
+		connect_context_clear (self);
+		break;
+	}
 }
 
 static NMActStageReturn
@@ -393,8 +527,6 @@ act_stage1_prepare (NMModem *_self,
                     NMDeviceStateReason *reason)
 {
 	NMModemBroadband *self = NM_MODEM_BROADBAND (_self);
-	ActStageContext *ctx;
-	GError *error = NULL;
 
 	/* Make sure we can get the Simple interface from the modem */
 	if (!self->priv->simple_iface) {
@@ -407,41 +539,16 @@ act_stage1_prepare (NMModem *_self,
 		}
 	}
 
-	/* Allocate new context for this activation stage attempt */
-	ctx = g_slice_new0 (ActStageContext);
-	ctx->self = NM_MODEM_BROADBAND (g_object_ref (self));
-	ctx->caps = mm_modem_get_current_capabilities (self->priv->modem_iface);
+	connect_context_clear (self);
 
-	/* Create core connect properties based on the modem capabilities */
-	if (MODEM_CAPS_3GPP (ctx->caps))
-		ctx->connect_properties = create_gsm_connect_properties (connection);
-	else if (MODEM_CAPS_3GPP2 (ctx->caps))
-		ctx->connect_properties = create_cdma_connect_properties (connection);
-	else {
-		nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem",
-		             nm_modem_get_uid (NM_MODEM (self)),
-		             nm_connection_get_id (connection));
-		act_stage_context_free (ctx);
-		*reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-	g_assert (ctx->connect_properties);
-
-	/* Checkout list of IP types that we need to use in the retries */
-	ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), connection, &error);
-	if (!ctx->ip_types) {
-		nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s",
-		             nm_modem_get_uid (NM_MODEM (self)),
-		             nm_connection_get_id (connection),
-		             error ? error->message : "unknown error");
-		g_clear_error (&error);
-		act_stage_context_free (ctx);
-		*reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
+	/* Allocate new context for this connect stage attempt */
+	self->priv->ctx = g_slice_new0 (ConnectContext);
+	self->priv->ctx->caps = mm_modem_get_current_capabilities (self->priv->modem_iface);
+	self->priv->ctx->cancellable = g_cancellable_new ();
+	self->priv->ctx->connection = g_object_ref (connection);
 
 	g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (self->priv->simple_iface), MODEM_CONNECT_TIMEOUT_SECS * 1000);
-	act_stage_context_step (ctx);
+	connect_context_step (self);
 
 	return NM_ACT_STAGE_RETURN_POSTPONE;
 }
@@ -715,6 +822,7 @@ static_stage3_ip4_done (NMModemBroadband *self)
 {
 	GError *error = NULL;
 	NMIP4Config *config = NULL;
+	const char *data_port;
 	const gchar *address_string;
 	const gchar *gw_string;
 	guint32 address_network;
@@ -724,6 +832,7 @@ static_stage3_ip4_done (NMModemBroadband *self)
 	guint i;
 
 	g_assert (self->priv->ipv4_config);
+	g_assert (self->priv->bearer);
 
 	nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:",
 	             nm_modem_get_uid (NM_MODEM (self)));
@@ -743,10 +852,13 @@ static_stage3_ip4_done (NMModemBroadband *self)
 	gw_string = mm_bearer_ip_config_get_gateway (self->priv->ipv4_config);
 	ip4_string_to_num (gw_string, &gw);
 
-	config = nm_ip4_config_new ();
+	data_port = mm_bearer_get_interface (self->priv->bearer);
+	g_assert (data_port);
+	config = nm_ip4_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port));
 
 	memset (&address, 0, sizeof (address));
 	address.address = address_network;
+	address.peer_address = address_network;
 	address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config);
 	address.source = NM_IP_CONFIG_SOURCE_WWAN;
 	nm_ip4_config_add_address (config, &address);
@@ -796,6 +908,7 @@ stage3_ip6_done (NMModemBroadband *self)
 {
 	GError *error = NULL;
 	NMIP6Config *config = NULL;
+	const char *data_port;
 	const gchar *address_string;
 	NMPlatformIP6Address address;
 	NMModemIPMethod ip_method;
@@ -833,7 +946,9 @@ stage3_ip6_done (NMModemBroadband *self)
 	nm_log_info (LOGD_MB, "(%s): IPv6 base configuration:",
 	             nm_modem_get_uid (NM_MODEM (self)));
 
-	config = nm_ip6_config_new ();
+	data_port = mm_bearer_get_interface (self->priv->bearer);
+	g_assert (data_port);
+	config = nm_ip6_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port));
 
 	address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv6_config);
 	nm_ip6_config_add_address (config, &address);
@@ -941,10 +1056,11 @@ simple_disconnect_ready (MMModemSimple *modem_iface,
 	GError *error = NULL;
 
 	if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) {
-		if (ctx->warn)
+		if (ctx->warn && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
 			nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s",
 			             nm_modem_get_uid (NM_MODEM (ctx->self)),
 			             error->message);
+		}
 		g_simple_async_result_take_error (ctx->result, error);
 	}
 
@@ -1042,7 +1158,6 @@ modem_state_changed (MMModem *modem,
                      MMModemStateChangeReason reason,
                      NMModemBroadband *self)
 {
-
 	/* After the SIM is unlocked MM1 will move the device to INITIALIZING which
 	 * is an unavailable state.  That makes state handling confusing here, so
 	 * suppress this state change and let the modem move from LOCKED to DISABLED.
@@ -1053,6 +1168,9 @@ modem_state_changed (MMModem *modem,
 	nm_modem_set_state (NM_MODEM (self),
 	                    mm_state_to_nm (new_state),
 	                    mm_modem_state_change_reason_get_string (reason));
+
+	if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_READY)
+		connect_context_step (self);
 }
 
 /*****************************************************************************/
@@ -1114,12 +1232,23 @@ get_sim_ready (MMModem *modem,
 	GError *error = NULL;
 	MMSim *new_sim;
 
+
 	new_sim = mm_modem_get_sim_finish (modem, res, &error);
-	if (new_sim) {
+	if (new_sim != self->priv->sim_iface) {
+		g_clear_object (&self->priv->sim_iface);
+		self->priv->sim_iface = new_sim;
+	} else
+		g_clear_object (&new_sim);
+
+	if (self->priv->sim_iface) {
 		g_object_set (G_OBJECT (self),
-		              NM_MODEM_SIM_ID, mm_sim_get_identifier (new_sim),
+		              NM_MODEM_SIM_ID, mm_sim_get_identifier (self->priv->sim_iface),
+		              NM_MODEM_SIM_OPERATOR_ID, mm_sim_get_operator_identifier (self->priv->sim_iface),
 		              NULL);
-		g_object_unref (new_sim);
+
+		/* If we're waiting for the SIM during a connect, proceed with the connect */
+		if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_SIM)
+			connect_context_step (self);
 	} else {
 		nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s",
 		             nm_modem_get_uid (NM_MODEM (self)),
@@ -1142,7 +1271,10 @@ sim_changed (MMModem *modem, GParamSpec *pspec, gpointer user_data)
 		                  (GAsyncReadyCallback) get_sim_ready,
 		                  g_object_ref (self));
 	} else
-		g_object_set (G_OBJECT (self), NM_MODEM_SIM_ID, NULL, NULL);
+		g_object_set (G_OBJECT (self),
+		              NM_MODEM_SIM_ID, NULL,
+		              NM_MODEM_SIM_OPERATOR_ID, NULL,
+		              NULL);
 }
 
 static void
@@ -1226,11 +1358,13 @@ dispose (GObject *object)
 {
 	NMModemBroadband *self = NM_MODEM_BROADBAND (object);
 
+	connect_context_clear (self);
 	g_clear_object (&self->priv->ipv4_config);
 	g_clear_object (&self->priv->ipv6_config);
 	g_clear_object (&self->priv->bearer);
 	g_clear_object (&self->priv->modem_iface);
 	g_clear_object (&self->priv->simple_iface);
+	g_clear_object (&self->priv->sim_iface);
 	g_clear_object (&self->priv->modem_object);
 
 	G_OBJECT_CLASS (nm_modem_broadband_parent_class)->dispose (object);
diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/devices/wwan/nm-modem-broadband.h
index 2268bac4..a54e63a6 100644
--- a/src/devices/wwan/nm-modem-broadband.h
+++ b/src/devices/wwan/nm-modem-broadband.h
@@ -21,7 +21,6 @@
 #ifndef __NETWORKMANAGER_MODEM_BROADBAND_H__
 #define __NETWORKMANAGER_MODEM_BROADBAND_H__
 
-#include <glib-object.h>
 #include "nm-modem.h"
 
 G_BEGIN_DECLS
diff --git a/src/devices/wwan/nm-modem-enum-types.c b/src/devices/wwan/nm-modem-enum-types.c
index 6fbb3b6d..2d02ede9 100644
--- a/src/devices/wwan/nm-modem-enum-types.c
+++ b/src/devices/wwan/nm-modem-enum-types.c
@@ -3,6 +3,8 @@
 
 /* Generated by glib-mkenums. Do not edit */
 
+#include "config.h"
+
 #include "nm-modem-enum-types.h"
 
 #include "nm-modem.h"
diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c
index f0e56926..c28d86ad 100644
--- a/src/devices/wwan/nm-modem-manager.c
+++ b/src/devices/wwan/nm-modem-manager.c
@@ -27,7 +27,8 @@
 #include <libmm-glib.h>
 
 #include "nm-modem-manager.h"
-#include "nm-logging.h"
+#include "nm-default.h"
+#include "nm-dbus-compat.h"
 #include "nm-modem.h"
 #include "nm-modem-broadband.h"
 
@@ -193,10 +194,7 @@ modem_manager_name_owner_changed (MMManager *modem_manager,
 	gchar *name_owner;
 
 	/* Quit poking, if any */
-	if (self->priv->mm_launch_id) {
-		g_source_remove (self->priv->mm_launch_id);
-		self->priv->mm_launch_id = 0;
-	}
+	nm_clear_g_source (&self->priv->mm_launch_id);
 
 	name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (modem_manager));
 	if (!name_owner) {
@@ -265,7 +263,7 @@ modem_manager_poke (NMModemManager *self)
 	g_dbus_connection_call (self->priv->dbus_connection,
 	                        "org.freedesktop.ModemManager1",
 	                        "/org/freedesktop/ModemManager1",
-	                        "org.freedesktop.DBus.Peer",
+	                        DBUS_INTERFACE_PEER,
 	                        "Ping",
 	                        NULL, /* inputs */
 	                        NULL, /* outputs */
@@ -434,10 +432,7 @@ dispose (GObject *object)
 {
 	NMModemManager *self = NM_MODEM_MANAGER (object);
 
-	if (self->priv->mm_launch_id) {
-		g_source_remove (self->priv->mm_launch_id);
-		self->priv->mm_launch_id = 0;
-	}
+	nm_clear_g_source (&self->priv->mm_launch_id);
 
 	modem_manager_clear_signals (self);
 	g_clear_object (&self->priv->modem_manager);
diff --git a/src/devices/wwan/nm-modem-manager.h b/src/devices/wwan/nm-modem-manager.h
index 9e0db41e..b0014c6a 100644
--- a/src/devices/wwan/nm-modem-manager.h
+++ b/src/devices/wwan/nm-modem-manager.h
@@ -23,7 +23,6 @@
 #ifndef __NETWORKMANAGER_MODEM_MANAGER_H__
 #define __NETWORKMANAGER_MODEM_MANAGER_H__
 
-#include <glib-object.h>
 #include "nm-modem.h"
 
 #define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ())
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index 3385a6fd..15104307 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -22,17 +22,17 @@
 #include "config.h"
 
 #include <string.h>
+
 #include "nm-modem.h"
+#include "nm-core-internal.h"
 #include "nm-platform.h"
-#include "nm-dbus-manager.h"
 #include "nm-setting-connection.h"
-#include "nm-properties-changed-signal.h"
-#include "nm-logging.h"
+#include "nm-default.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
-#include "nm-dbus-glib-types.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)
 
@@ -52,6 +52,7 @@ enum {
 	PROP_DEVICE_ID,
 	PROP_SIM_ID,
 	PROP_IP_TYPES,
+	PROP_SIM_OPERATOR_ID,
 
 	LAST_PROP
 };
@@ -71,12 +72,13 @@ typedef struct {
 	char *device_id;
 	char *sim_id;
 	NMModemIPType ip_types;
+	char *sim_operator_id;
 
 	NMPPPManager *ppp_manager;
 
 	NMActRequest *act_request;
 	guint32 secrets_tries;
-	guint32 secrets_id;
+	NMActRequestGetSecretsCallId secrets_id;
 
 	guint32 mm_ip_timeout;
 
@@ -287,7 +289,7 @@ nm_modem_get_connection_ip_type (NMModem *self,
 			                     NM_DEVICE_ERROR,
 			                     NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
 			                     "Connection requested IPv4 but IPv4 is "
-			                     "unsuported by the modem.");
+			                     "unsupported by the modem.");
 			return NULL;
 		}
 		return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV4);
@@ -299,7 +301,7 @@ nm_modem_get_connection_ip_type (NMModem *self,
 			                     NM_DEVICE_ERROR,
 			                     NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
 			                     "Connection requested IPv6 but IPv6 is "
-			                     "unsuported by the modem.");
+			                     "unsupported by the modem.");
 			return NULL;
 		}
 		return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV6);
@@ -350,6 +352,24 @@ nm_modem_get_connection_ip_type (NMModem *self,
 	return NULL;
 }
 
+const char *
+nm_modem_get_device_id (NMModem *self)
+{
+	return NM_MODEM_GET_PRIVATE (self)->device_id;
+}
+
+const char *
+nm_modem_get_sim_id (NMModem *self)
+{
+	return NM_MODEM_GET_PRIVATE (self)->sim_id;
+}
+
+const char *
+nm_modem_get_sim_operator_id (NMModem *self)
+{
+	return NM_MODEM_GET_PRIVATE (self)->sim_operator_id;
+}
+
 /*****************************************************************************/
 /* IP method PPP */
 
@@ -493,7 +513,7 @@ ppp_stage3_ip_config_start (NMModem *self,
 		return NM_ACT_STAGE_RETURN_POSTPONE;
 
 	if (NM_MODEM_GET_CLASS (self)->get_user_pass) {
-		NMConnection *connection = nm_act_request_get_connection (req);
+		NMConnection *connection = nm_act_request_get_applied_connection (req);
 
 		g_assert (connection);
 		if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL))
@@ -511,7 +531,7 @@ ppp_stage3_ip_config_start (NMModem *self,
 
 	priv->ppp_manager = nm_ppp_manager_new (priv->data_port);
 	if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) {
-		g_signal_connect (priv->ppp_manager, "state-changed",
+		g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
 		                  G_CALLBACK (ppp_state_changed),
 		                  self);
 		g_signal_connect (priv->ppp_manager, "ip4-config",
@@ -532,8 +552,7 @@ ppp_stage3_ip_config_start (NMModem *self,
 		            error && error->message ? error->message : "(unknown)");
 		g_error_free (error);
 
-		g_object_unref (priv->ppp_manager);
-		priv->ppp_manager = NULL;
+		nm_exported_object_clear_and_unexport (&priv->ppp_manager);
 
 		*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
 		ret = NM_ACT_STAGE_RETURN_FAILURE;
@@ -563,7 +582,7 @@ nm_modem_stage3_ip4_config_start (NMModem *self,
 
 	req = nm_device_get_act_request (device);
 	g_assert (req);
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
 
@@ -680,7 +699,7 @@ nm_modem_stage3_ip6_config_start (NMModem *self,
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
 
@@ -725,16 +744,13 @@ cancel_get_secrets (NMModem *self)
 {
 	NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
 
-	if (priv->secrets_id) {
-		nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id);
-		priv->secrets_id = 0;
-	}
+	nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id);
 }
 
 static void
 modem_secrets_cb (NMActRequest *req,
-                  guint32 call_id,
-                  NMConnection *connection,
+                  NMActRequestGetSecretsCallId call_id,
+                  NMSettingsConnection *connection,
                   GError *error,
                   gpointer user_data)
 {
@@ -743,7 +759,10 @@ modem_secrets_cb (NMActRequest *req,
 
 	g_return_if_fail (call_id == priv->secrets_id);
 
-	priv->secrets_id = 0;
+	priv->secrets_id = NULL;
+
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
 	if (error)
 		nm_log_warn (LOGD_MB, "(%s): %s", nm_modem_get_uid (self), error->message);
@@ -751,7 +770,7 @@ modem_secrets_cb (NMActRequest *req,
 	g_signal_emit (self, signals[AUTH_RESULT], 0, error);
 }
 
-gboolean
+void
 nm_modem_get_secrets (NMModem *self,
                       const char *setting_name,
                       gboolean request_new,
@@ -770,10 +789,8 @@ nm_modem_get_secrets (NMModem *self,
 	                                               hint,
 	                                               modem_secrets_cb,
 	                                               self);
-	if (priv->secrets_id)
-		g_signal_emit (self, signals[AUTH_REQUESTED], 0);
-
-	return !!(priv->secrets_id);
+	g_return_if_fail (priv->secrets_id);
+	g_signal_emit (self, signals[AUTH_REQUESTED], 0);
 }
 
 /*****************************************************************************/
@@ -793,8 +810,7 @@ nm_modem_act_stage1_prepare (NMModem *self,
                              NMDeviceStateReason *reason)
 {
 	NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	GPtrArray *hints = NULL;
+	gs_unref_ptrarray GPtrArray *hints = NULL;
 	const char *setting_name = NULL;
 	NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION;
 	NMConnection *connection;
@@ -803,7 +819,7 @@ nm_modem_act_stage1_prepare (NMModem *self,
 		g_object_unref (priv->act_request);
 	priv->act_request = g_object_ref (req);
 
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 
 	setting_name = nm_connection_need_secrets (connection, &hints);
@@ -823,18 +839,9 @@ nm_modem_act_stage1_prepare (NMModem *self,
 	                                               hints ? g_ptr_array_index (hints, 0) : NULL,
 	                                               modem_secrets_cb,
 	                                               self);
-	if (priv->secrets_id) {
-		g_signal_emit (self, signals[AUTH_REQUESTED], 0);
-		ret = NM_ACT_STAGE_RETURN_POSTPONE;
-	} else {
-		*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
-		ret = NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	if (hints)
-		g_ptr_array_free (hints, TRUE);
-
-	return ret;
+	g_return_val_if_fail (priv->secrets_id, NM_ACT_STAGE_RETURN_FAILURE);
+	g_signal_emit (self, signals[AUTH_REQUESTED], 0);
+	return NM_ACT_STAGE_RETURN_POSTPONE;
 }
 
 /*****************************************************************************/
@@ -859,6 +866,67 @@ nm_modem_act_stage2_config (NMModem *self,
 gboolean
 nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection)
 {
+	NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
+	NMSettingConnection *s_con;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+
+	if (g_str_equal (nm_setting_connection_get_connection_type (s_con),
+	                 NM_SETTING_GSM_SETTING_NAME)) {
+		NMSettingGsm *s_gsm;
+		const char *str;
+
+		s_gsm = nm_connection_get_setting_gsm (connection);
+		if (!s_gsm)
+			return FALSE;
+
+		str = nm_setting_gsm_get_device_id (s_gsm);
+		if (str) {
+			if (!priv->device_id) {
+				nm_log_dbg (LOGD_MB, "(%s): %s/%s has device-id, device does not",
+				            priv->uid,
+				            nm_connection_get_uuid (connection),
+				            nm_connection_get_id (connection));
+				return FALSE;
+			}
+			if (strcmp (str, priv->device_id)) {
+				nm_log_dbg (LOGD_MB, "(%s): %s/%s device-id mismatch",
+				            priv->uid,
+				            nm_connection_get_uuid (connection),
+				            nm_connection_get_id (connection));
+				return FALSE;
+			}
+		}
+
+		/* SIM properties may not be available before the SIM is unlocked, so
+		 * to ensure that autoconnect works, the connection's SIM properties
+		 * are only compared if present on the device.
+		 */
+
+		str = nm_setting_gsm_get_sim_id (s_gsm);
+		if (str && priv->sim_id) {
+			if (strcmp (str, priv->sim_id)) {
+				nm_log_dbg (LOGD_MB, "(%s): %s/%s sim-id mismatch",
+				            priv->uid,
+				            nm_connection_get_uuid (connection),
+				            nm_connection_get_id (connection));
+				return FALSE;
+			}
+		}
+
+		str = nm_setting_gsm_get_sim_operator_id (s_gsm);
+		if (str && priv->sim_operator_id) {
+			if (strcmp (str, priv->sim_operator_id)) {
+				nm_log_dbg (LOGD_MB, "(%s): %s/%s sim-operator-id mismatch",
+				            priv->uid,
+				            nm_connection_get_uuid (connection),
+				            nm_connection_get_id (connection));
+				return FALSE;
+			}
+		}
+	}
+
 	if (NM_MODEM_GET_CLASS (self)->check_connection_compatible)
 		return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection);
 	return FALSE;
@@ -899,10 +967,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
 
 	priv->in_bytes = priv->out_bytes = 0;
 
-	if (priv->ppp_manager) {
-		g_object_unref (priv->ppp_manager);
-		priv->ppp_manager = NULL;
-	}
+	nm_exported_object_clear_and_unexport (&priv->ppp_manager);
 
 	if (device) {
 		g_return_if_fail (NM_IS_DEVICE (device));
@@ -1315,6 +1380,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_IP_TYPES:
 		g_value_set_uint (value, priv->ip_types);
 		break;
+	case PROP_SIM_OPERATOR_ID:
+		g_value_set_string (value, priv->sim_operator_id);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1326,6 +1394,7 @@ set_property (GObject *object, guint prop_id,
               const GValue *value, GParamSpec *pspec)
 {
 	NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object);
+	const char *s;
 
 	switch (prop_id) {
 	case PROP_PATH:
@@ -1369,6 +1438,12 @@ set_property (GObject *object, guint prop_id,
 	case PROP_IP_TYPES:
 		priv->ip_types = g_value_get_uint (value);
 		break;
+	case PROP_SIM_OPERATOR_ID:
+		g_clear_pointer (&priv->sim_operator_id, g_free);
+		s = g_value_get_string (value);
+		if (s && s[0])
+			priv->sim_operator_id = g_strdup (s);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1400,6 +1475,7 @@ finalize (GObject *object)
 	g_free (priv->data_port);
 	g_free (priv->device_id);
 	g_free (priv->sim_id);
+	g_free (priv->sim_operator_id);
 
 	G_OBJECT_CLASS (nm_modem_parent_class)->finalize (object);
 }
@@ -1514,6 +1590,13 @@ nm_modem_class_init (NMModemClass *klass)
 		                    0, G_MAXUINT32, NM_MODEM_IP_TYPE_IPV4,
 		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+	g_object_class_install_property
+		(object_class, PROP_SIM_OPERATOR_ID,
+		 g_param_spec_string (NM_MODEM_SIM_OPERATOR_ID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+		                      G_PARAM_STATIC_STRINGS));
+
 	/* Signals */
 
 	signals[PPP_STATS] =
diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h
index 2cace890..60e5589b 100644
--- a/src/devices/wwan/nm-modem.h
+++ b/src/devices/wwan/nm-modem.h
@@ -22,7 +22,7 @@
 #ifndef __NETWORKMANAGER_MODEM_H__
 #define __NETWORKMANAGER_MODEM_H__
 
-#include <glib-object.h>
+#include "nm-default.h"
 #include "ppp-manager/nm-ppp-manager.h"
 #include "nm-device.h"
 
@@ -36,18 +36,19 @@ G_BEGIN_DECLS
 #define NM_MODEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_MODEM, NMModemClass))
 
 /* Properties */
-#define NM_MODEM_UID          "uid"
-#define NM_MODEM_PATH         "path"
-#define NM_MODEM_DRIVER       "driver"
-#define NM_MODEM_CONTROL_PORT "control-port"
-#define NM_MODEM_DATA_PORT    "data-port"
-#define NM_MODEM_IP4_METHOD   "ip4-method"
-#define NM_MODEM_IP6_METHOD   "ip6-method"
-#define NM_MODEM_IP_TIMEOUT   "ip-timeout"
-#define NM_MODEM_STATE        "state"
-#define NM_MODEM_DEVICE_ID    "device-id"
-#define NM_MODEM_SIM_ID       "sim-id"
-#define NM_MODEM_IP_TYPES     "ip-types"   /* Supported IP types */
+#define NM_MODEM_UID             "uid"
+#define NM_MODEM_PATH            "path"
+#define NM_MODEM_DRIVER          "driver"
+#define NM_MODEM_CONTROL_PORT    "control-port"
+#define NM_MODEM_DATA_PORT       "data-port"
+#define NM_MODEM_IP4_METHOD      "ip4-method"
+#define NM_MODEM_IP6_METHOD      "ip6-method"
+#define NM_MODEM_IP_TIMEOUT      "ip-timeout"
+#define NM_MODEM_STATE           "state"
+#define NM_MODEM_DEVICE_ID       "device-id"
+#define NM_MODEM_SIM_ID          "sim-id"
+#define NM_MODEM_IP_TYPES        "ip-types"   /* Supported IP types */
+#define NM_MODEM_SIM_OPERATOR_ID "sim-operator-id"
 
 /* Signals */
 #define NM_MODEM_PPP_STATS         "ppp-stats"
@@ -179,12 +180,15 @@ typedef struct {
 
 GType nm_modem_get_type (void);
 
-const char *nm_modem_get_path         (NMModem *modem);
-const char *nm_modem_get_uid          (NMModem *modem);
-const char *nm_modem_get_control_port (NMModem *modem);
-const char *nm_modem_get_data_port    (NMModem *modem);
-const char *nm_modem_get_driver       (NMModem *modem);
-gboolean    nm_modem_get_iid          (NMModem *modem, NMUtilsIPv6IfaceId *out_iid);
+const char *nm_modem_get_path            (NMModem *modem);
+const char *nm_modem_get_uid             (NMModem *modem);
+const char *nm_modem_get_control_port    (NMModem *modem);
+const char *nm_modem_get_data_port       (NMModem *modem);
+const char *nm_modem_get_driver          (NMModem *modem);
+const char *nm_modem_get_device_id       (NMModem *modem);
+const char *nm_modem_get_sim_id          (NMModem *modem);
+const char *nm_modem_get_sim_operator_id (NMModem *modem);
+gboolean    nm_modem_get_iid             (NMModem *modem, NMUtilsIPv6IfaceId *out_iid);
 
 gboolean    nm_modem_owns_port        (NMModem *modem, const char *iface);
 
@@ -218,10 +222,10 @@ NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem,
 
 void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config);
 
-gboolean nm_modem_get_secrets (NMModem *modem,
-                               const char *setting_name,
-                               gboolean request_new,
-                               const char *hint);
+void nm_modem_get_secrets (NMModem *modem,
+                           const char *setting_name,
+                           gboolean request_new,
+                           const char *hint);
 
 void nm_modem_deactivate (NMModem *modem, NMDevice *device);
 
diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c
index 49b0b0af..2fd9e0bd 100644
--- a/src/devices/wwan/nm-wwan-factory.c
+++ b/src/devices/wwan/nm-wwan-factory.c
@@ -29,12 +29,12 @@
 #include "nm-setting-cdma.h"
 #include "nm-modem-manager.h"
 #include "nm-device-modem.h"
-#include "nm-logging.h"
+#include "nm-default.h"
 #include "nm-platform.h"
 
 static GType nm_wwan_factory_get_type (void);
 
-static void device_factory_interface_init (NMDeviceFactory *factory_iface);
+static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface);
 
 G_DEFINE_TYPE_EXTENDED (NMWwanFactory, nm_wwan_factory, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init))
@@ -96,9 +96,14 @@ NM_DEVICE_FACTORY_DECLARE_TYPES (
 )
 
 static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+               const char *iface,
+               const NMPlatformLink *plink,
+               NMConnection *connection,
+               gboolean *out_ignore)
 {
-	g_warn_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET);
+	g_return_val_if_fail (plink, NULL);
+	g_return_val_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET, NULL);
 	*out_ignore = TRUE;
 	return NULL;
 }
@@ -123,10 +128,10 @@ nm_wwan_factory_init (NMWwanFactory *self)
 }
 
 static void
-device_factory_interface_init (NMDeviceFactory *factory_iface)
+device_factory_interface_init (NMDeviceFactoryInterface *factory_iface)
 {
 	factory_iface->get_supported_types = get_supported_types;
-	factory_iface->new_link = new_link;
+	factory_iface->create_device = create_device;
 	factory_iface->start = start;
 }
 
diff --git a/src/devices/wwan/nm-wwan-factory.h b/src/devices/wwan/nm-wwan-factory.h
index c6c03f1f..78031e60 100644
--- a/src/devices/wwan/nm-wwan-factory.h
+++ b/src/devices/wwan/nm-wwan-factory.h
@@ -21,7 +21,7 @@
 #ifndef __NETWORKMANAGER_WWAN_FACTORY_H__
 #define __NETWORKMANAGER_WWAN_FACTORY_H__
 
-#include <glib-object.h>
+#include "nm-default.h"
 
 #define NM_TYPE_WWAN_FACTORY (nm_wwan_factory_get_type ())
 #define NM_WWAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WWAN_FACTORY, NMWwanFactory))