summary refs log tree commit diff
path: root/src/ppp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ppp')
-rw-r--r--src/ppp/meson.build41
-rw-r--r--src/ppp/nm-ppp-manager-call.c36
-rw-r--r--src/ppp/nm-ppp-manager-call.h14
-rw-r--r--src/ppp/nm-ppp-manager.c564
-rw-r--r--src/ppp/nm-ppp-manager.h8
-rw-r--r--src/ppp/nm-ppp-plugin-api.h14
-rw-r--r--src/ppp/nm-pppd-plugin.c32
7 files changed, 450 insertions, 259 deletions
diff --git a/src/ppp/meson.build b/src/ppp/meson.build
new file mode 100644
index 00000000..38f9a0f1
--- /dev/null
+++ b/src/ppp/meson.build
@@ -0,0 +1,41 @@
+name = 'nm-pppd-plugin'
+
+deps = [
+  dl_dep,
+  nm_core_dep
+]
+
+nm_pppd_plugin = shared_module(
+  name,
+  name_prefix: '',
+  sources: name + '.c',
+  include_directories: src_inc,
+  dependencies: deps,
+  c_args: [
+    '-DG_LOG_DOMAIN="@0@"'.format(name),
+    '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB',
+  ],
+  install: true,
+  install_dir: pppd_plugin_dir
+)
+
+name = 'nm-ppp-plugin'
+
+deps = [
+  nm_dep
+]
+
+linker_script = join_paths(meson.current_source_dir(), 'nm-ppp-plugin.ver')
+
+core_plugins += shared_module(
+  name,
+  sources: 'nm-ppp-manager.c',
+  dependencies: deps,
+  c_args: '-DPPPD_PLUGIN_DIR="@0@"'.format(pppd_plugin_dir),
+  link_args: [
+    '-Wl,--version-script,@0@'.format(linker_script),
+  ],
+  link_depends: linker_script,
+  install: true,
+  install_dir: nm_plugindir
+)
diff --git a/src/ppp/nm-ppp-manager-call.c b/src/ppp/nm-ppp-manager-call.c
index ad3307a9..3d6fee49 100644
--- a/src/ppp/nm-ppp-manager-call.c
+++ b/src/ppp/nm-ppp-manager-call.c
@@ -44,11 +44,9 @@ nm_ppp_manager_create (const char *iface, GError **error)
 	GError *error_local = NULL;
 	NMPPPOps *ops;
 	struct stat st;
-	int errsv;
 
 	if (G_UNLIKELY (!ppp_ops)) {
 		if (stat (PPP_PLUGIN_PATH, &st) != 0) {
-			errsv = errno;
 			g_set_error_literal (error,
 			                     NM_MANAGER_ERROR, NM_MANAGER_ERROR_MISSING_PLUGIN,
 			                     "the PPP plugin " PPP_PLUGIN_PATH " is not installed");
@@ -84,9 +82,8 @@ nm_ppp_manager_create (const char *iface, GError **error)
 		nm_assert (ops);
 		nm_assert (ops->create);
 		nm_assert (ops->start);
-		nm_assert (ops->stop_async);
-		nm_assert (ops->stop_finish);
-		nm_assert (ops->stop_sync);
+		nm_assert (ops->stop);
+		nm_assert (ops->stop_cancel);
 
 		ppp_ops = ops;
 
@@ -127,32 +124,21 @@ nm_ppp_manager_start (NMPPPManager *self,
 	return ppp_ops->start (self, req, ppp_name, timeout_secs, baud_override, err);
 }
 
-void
-nm_ppp_manager_stop_async (NMPPPManager *self,
-                           GCancellable *cancellable,
-                           GAsyncReadyCallback callback,
-                           gpointer user_data)
+NMPPPManagerStopHandle *
+nm_ppp_manager_stop (NMPPPManager *self,
+                     NMPPPManagerStopCallback callback,
+                     gpointer user_data)
 {
-	g_return_if_fail (ppp_ops);
+	g_return_val_if_fail (ppp_ops, NULL);
 
-	ppp_ops->stop_async (self, cancellable, callback, user_data);
-}
-
-gboolean
-nm_ppp_manager_stop_finish (NMPPPManager *self,
-                            GAsyncResult *res,
-                            GError **error)
-{
-	g_return_val_if_fail (ppp_ops, FALSE);
-
-	return ppp_ops->stop_finish (self, res, error);
+	return ppp_ops->stop (self, callback, user_data);
 }
 
 void
-nm_ppp_manager_stop_sync (NMPPPManager *self)
+nm_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle)
 {
 	g_return_if_fail (ppp_ops);
+	g_return_if_fail (handle);
 
-	ppp_ops->stop_sync (self);
+	ppp_ops->stop_cancel (handle);
 }
-
diff --git a/src/ppp/nm-ppp-manager-call.h b/src/ppp/nm-ppp-manager-call.h
index 2258ae08..daf8a82e 100644
--- a/src/ppp/nm-ppp-manager-call.h
+++ b/src/ppp/nm-ppp-manager-call.h
@@ -38,13 +38,11 @@ gboolean            nm_ppp_manager_start       (NMPPPManager *self,
                                                 guint32 timeout_secs,
                                                 guint baud_override,
                                                 GError **error);
-void                nm_ppp_manager_stop_async  (NMPPPManager *self,
-                                                GCancellable *cancellable,
-                                                GAsyncReadyCallback callback,
-                                                gpointer user_data);
-gboolean            nm_ppp_manager_stop_finish (NMPPPManager *self,
-                                                GAsyncResult *res,
-                                                GError **error);
-void                nm_ppp_manager_stop_sync   (NMPPPManager *self);
+
+NMPPPManagerStopHandle *nm_ppp_manager_stop (NMPPPManager *self,
+                                             NMPPPManagerStopCallback callback,
+                                             gpointer user_data);
+
+void nm_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle);
 
 #endif /* __NM_PPP_MANAGER_CALL_H__ */
diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c
index 743f80a2..fc658bec 100644
--- a/src/ppp/nm-ppp-manager.c
+++ b/src/ppp/nm-ppp-manager.c
@@ -50,13 +50,12 @@
 #include "nm-act-request.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
+#include "nm-dbus-object.h"
 
 #include "nm-pppd-plugin.h"
 #include "nm-ppp-plugin-api.h"
 #include "nm-ppp-status.h"
 
-#include "introspection/org.freedesktop.NetworkManager.PPP.h"
-
 #define NM_PPPD_PLUGIN PPPD_PLUGIN_DIR "/nm-pppd-plugin.so"
 
 static NM_CACHED_QUARK_FCN ("ppp-manager-secret-tries", ppp_manager_secret_tries_quark)
@@ -76,6 +75,7 @@ GType nm_ppp_manager_get_type (void);
 
 enum {
 	STATE_CHANGED,
+	IFINDEX_SET,
 	IP4_CONFIG,
 	IP6_CONFIG,
 	STATS,
@@ -93,6 +93,8 @@ typedef struct {
 	GPid pid;
 
 	char *parent_iface;
+	char *ip_iface;
+	int ifindex;
 
 	NMActRequest *act_req;
 	GDBusMethodInvocation *pending_secrets_context;
@@ -103,7 +105,6 @@ typedef struct {
 	guint ppp_timeout_handler;
 
 	/* Monitoring */
-	char *ip_iface;
 	int monitor_fd;
 	guint monitor_id;
 
@@ -114,17 +115,17 @@ typedef struct {
 } NMPPPManagerPrivate;
 
 struct _NMPPPManager {
-	NMExportedObject parent;
+	NMDBusObject parent;
 	NMPPPManagerPrivate _priv;
 };
 
 typedef struct {
-	NMExportedObjectClass parent;
+	NMDBusObjectClass parent;
 } NMPPPManagerClass;
 
-G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_EXPORTED_OBJECT)
+G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_DBUS_OBJECT)
 
-#define NM_PPP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPPPManager, NM_IS_PPP_MANAGER)
+#define NM_PPP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPPPManager, NM_IS_PPP_MANAGER, NMDBusObject)
 
 /*****************************************************************************/
 
@@ -133,8 +134,11 @@ G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_EXPORTED_OBJECT)
 
 /*****************************************************************************/
 
-static void _ppp_cleanup  (NMPPPManager *manager);
-static void _ppp_kill (NMPPPManager *manager);
+static void _ppp_cleanup  (NMPPPManager *self);
+
+static NMPPPManagerStopHandle *_ppp_manager_stop (NMPPPManager *self,
+                                                  NMPPPManagerStopCallback callback,
+                                                  gpointer user_data);
 
 /*****************************************************************************/
 
@@ -172,32 +176,36 @@ _ppp_manager_set_route_parameters (NMPPPManager *self,
 static gboolean
 monitor_cb (gpointer user_data)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (user_data);
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
-	struct ifreq req;
-	struct ppp_stats stats;
-
-	memset (&req, 0, sizeof (req));
-	memset (&stats, 0, sizeof (stats));
-	req.ifr_data = (caddr_t) &stats;
-
-	strncpy (req.ifr_name, priv->ip_iface, sizeof (req.ifr_name));
-	if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) {
-		if (errno != ENODEV)
-			_LOGW ("could not read ppp stats: %s", strerror (errno));
-	} else {
-		g_signal_emit (manager, signals[STATS], 0,
-		               (guint) stats.p.ppp_ibytes,
-		               (guint) stats.p.ppp_obytes);
+	NMPPPManager *self = NM_PPP_MANAGER (user_data);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+	const char *ifname;
+
+	ifname = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex);
+
+	if (ifname) {
+		struct ppp_stats stats = { };
+		struct ifreq req = {
+			.ifr_data = (caddr_t) &stats,
+		};
+
+		nm_utils_ifname_cpy (req.ifr_name, ifname);
+		if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) {
+			if (errno != ENODEV)
+				_LOGW ("could not read ppp stats: %s", strerror (errno));
+		} else {
+			g_signal_emit (self, signals[STATS], 0,
+			               (guint) stats.p.ppp_ibytes,
+			               (guint) stats.p.ppp_obytes);
+		}
 	}
 
-	return TRUE;
+	return G_SOURCE_CONTINUE;
 }
 
 static void
-monitor_stats (NMPPPManager *manager)
+monitor_stats (NMPPPManager *self)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
 	/* already monitoring */
 	if (priv->monitor_fd >= 0)
@@ -208,7 +216,7 @@ monitor_stats (NMPPPManager *manager)
 		g_warn_if_fail (priv->monitor_id == 0);
 		if (priv->monitor_id)
 			g_source_remove (priv->monitor_id);
-		priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, manager);
+		priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, self);
 	} else
 		_LOGW ("could not monitor PPP stats: %s", strerror (errno));
 }
@@ -326,21 +334,28 @@ ppp_secrets_cb (NMActRequest *req,
 	 * against libnm just to parse this. So instead, let's just send what
 	 * it needs.
 	 */
-	g_dbus_method_invocation_return_value (
-		priv->pending_secrets_context,
-		g_variant_new ("(ss)", username ? username : "", password ? password : ""));
+	g_dbus_method_invocation_return_value (priv->pending_secrets_context,
+	                                       g_variant_new ("(ss)",
+	                                                      username ?: "",
+	                                                      password ?: ""));
 
- out:
+out:
 	priv->pending_secrets_context = NULL;
 	priv->secrets_id = NULL;
 	priv->secrets_setting_name = NULL;
 }
 
 static void
-impl_ppp_manager_need_secrets (NMPPPManager *manager,
-                               GDBusMethodInvocation *context)
+impl_ppp_manager_need_secrets (NMDBusObject *obj,
+                               const NMDBusInterfaceInfoExtended *interface_info,
+                               const NMDBusMethodInfoExtended *method_info,
+                               GDBusConnection *connection,
+                               const char *sender,
+                               GDBusMethodInvocation *invocation,
+                               GVariant *parameters)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 	NMConnection *applied_connection;
 	const char *username = NULL;
 	const char *password = NULL;
@@ -358,8 +373,8 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager,
 		/* Use existing secrets from the connection */
 		if (extract_details_from_connection (applied_connection, NULL, &username, &password, &error)) {
 			/* Send existing secrets to the PPP plugin */
-			priv->pending_secrets_context = context;
-			ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, manager);
+			priv->pending_secrets_context = invocation;
+			ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, self);
 		} else {
 			_LOGW ("%s", error->message);
 			g_dbus_method_invocation_take_error (priv->pending_secrets_context, error);
@@ -381,41 +396,87 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager,
 	                                               flags,
 	                                               hints ? g_ptr_array_index (hints, 0) : NULL,
 	                                               ppp_secrets_cb,
-	                                               manager);
+	                                               self);
 	g_object_set_qdata (G_OBJECT (applied_connection), ppp_manager_secret_tries_quark (), GUINT_TO_POINTER (++tries));
-	priv->pending_secrets_context = context;
+	priv->pending_secrets_context = invocation;
 
 	if (hints)
 		g_ptr_array_free (hints, TRUE);
 }
 
 static void
-impl_ppp_manager_set_state (NMPPPManager *manager,
-                            GDBusMethodInvocation *context,
-                            guint32 state)
+impl_ppp_manager_set_state (NMDBusObject *obj,
+                            const NMDBusInterfaceInfoExtended *interface_info,
+                            const NMDBusMethodInfoExtended *method_info,
+                            GDBusConnection *connection,
+                            const char *sender,
+                            GDBusMethodInvocation *invocation,
+                            GVariant *parameters)
 {
-	g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) state);
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
+	guint32 state;
 
-	g_dbus_method_invocation_return_value (context, NULL);
+	g_variant_get (parameters, "(u)", &state);
+	g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state);
+	g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static void
+impl_ppp_manager_set_ifindex (NMDBusObject *obj,
+                              const NMDBusInterfaceInfoExtended *interface_info,
+                              const NMDBusMethodInfoExtended *method_info,
+                              GDBusConnection *connection,
+                              const char *sender,
+                              GDBusMethodInvocation *invocation,
+                              GVariant *parameters)
+{
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+	const NMPlatformLink *plink = NULL;
+	nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL;
+	gint32 ifindex;
+
+	g_variant_get (parameters, "(i)", &ifindex);
+
+	_LOGD ("set-ifindex %d", (int) ifindex);
+
+	if (priv->ifindex >= 0) {
+		_LOGW ("can't change the ifindex from %d to %d", priv->ifindex, (int) ifindex);
+		return;
+	}
+
+	if (ifindex > 0) {
+		plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
+		if (!plink) {
+			nm_platform_process_events (NM_PLATFORM_GET);
+			plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
+		}
+	}
+
+	if (!plink) {
+		_LOGW ("unknown interface with ifindex %d", ifindex);
+		ifindex = 0;
+	}
+
+	priv->ifindex = ifindex;
+
+	obj_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink));
+
+	g_signal_emit (self, signals[IFINDEX_SET], 0, ifindex, plink->name);
+	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
 static gboolean
 set_ip_config_common (NMPPPManager *self,
                       GVariant *config_dict,
-                      const char *iface_prop,
                       guint32 *out_mtu)
 {
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 	NMConnection *applied_connection;
 	NMSettingPpp *s_ppp;
-	const char *iface;
 
-	if (!g_variant_lookup (config_dict, iface_prop, "&s", &iface)) {
-		_LOGE ("no interface received!");
+	if (priv->ifindex <= 0)
 		return FALSE;
-	}
-	if (priv->ip_iface == NULL)
-		priv->ip_iface = g_strdup (iface);
 
 	/* Got successful IP config; obviously the secrets worked */
 	applied_connection = nm_act_request_get_applied_connection (priv->act_req);
@@ -432,29 +493,32 @@ set_ip_config_common (NMPPPManager *self,
 }
 
 static void
-impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
-                                 GDBusMethodInvocation *context,
-                                 GVariant *config_dict)
+impl_ppp_manager_set_ip4_config (NMDBusObject *obj,
+                                 const NMDBusInterfaceInfoExtended *interface_info,
+                                 const NMDBusMethodInfoExtended *method_info,
+                                 GDBusConnection *connection,
+                                 const char *sender,
+                                 GDBusMethodInvocation *invocation,
+                                 GVariant *parameters)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 	gs_unref_object NMIP4Config *config = NULL;
 	NMPlatformIP4Address address;
 	guint32 u32, mtu;
 	GVariantIter *iter;
-	int ifindex;
+	gs_unref_variant GVariant *config_dict = NULL;
 
 	_LOGI ("(IPv4 Config Get) reply received.");
 
-	nm_clear_g_source (&priv->ppp_timeout_handler);
+	g_variant_get (parameters, "(@a{sv})", &config_dict);
 
-	if (!set_ip_config_common (manager, config_dict, NM_PPP_IP4_CONFIG_INTERFACE, &mtu))
-		goto out;
+	nm_clear_g_source (&priv->ppp_timeout_handler);
 
-	ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface);
-	if (ifindex <= 0)
+	if (!set_ip_config_common (self, config_dict, &mtu))
 		goto out;
 
-	config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex);
+	config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex);
 
 	if (mtu)
 		nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_PPP);
@@ -467,7 +531,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
 
 	if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) {
 		const NMPlatformIP4Route r = {
-			.ifindex   = ifindex,
+			.ifindex   = priv->ifindex,
 			.rt_source = NM_IP_CONFIG_SOURCE_PPP,
 			.gateway   = u32,
 			.table_coerced = nm_platform_route_table_coerce (priv->ip4_route_table),
@@ -503,10 +567,10 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
 	}
 
 	/* Push the IP4 config up to the device */
-	g_signal_emit (manager, signals[IP4_CONFIG], 0, priv->ip_iface, config);
+	g_signal_emit (self, signals[IP4_CONFIG], 0, config);
 
 out:
-	g_dbus_method_invocation_return_value (context, NULL);
+	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
 /* Converts the named Interface Identifier item to an IPv6 LL address and
@@ -539,37 +603,40 @@ iid_value_to_ll6_addr (GVariant *dict,
 }
 
 static void
-impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
-                                 GDBusMethodInvocation *context,
-                                 GVariant *config_dict)
+impl_ppp_manager_set_ip6_config (NMDBusObject *obj,
+                                 const NMDBusInterfaceInfoExtended *interface_info,
+                                 const NMDBusMethodInfoExtended *method_info,
+                                 GDBusConnection *connection,
+                                 const char *sender,
+                                 GDBusMethodInvocation *invocation,
+                                 GVariant *parameters)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 	gs_unref_object NMIP6Config *config = NULL;
 	NMPlatformIP6Address addr;
 	struct in6_addr a;
 	NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
 	gboolean has_peer = FALSE;
-	int ifindex;
+	gs_unref_variant GVariant *config_dict = NULL;
 
 	_LOGI ("(IPv6 Config Get) reply received.");
 
-	nm_clear_g_source (&priv->ppp_timeout_handler);
+	g_variant_get (parameters, "(@a{sv})", &config_dict);
 
-	if (!set_ip_config_common (manager, config_dict, NM_PPP_IP6_CONFIG_INTERFACE, NULL))
-		goto out;
+	nm_clear_g_source (&priv->ppp_timeout_handler);
 
-	ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface);
-	if (ifindex <= 0)
+	if (!set_ip_config_common (self, config_dict, NULL))
 		goto out;
 
-	config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex);
+	config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex);
 
 	memset (&addr, 0, sizeof (addr));
 	addr.plen = 64;
 
 	if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
 		const NMPlatformIP6Route r = {
-			.ifindex   = ifindex,
+			.ifindex   = priv->ifindex,
 			.rt_source = NM_IP_CONFIG_SOURCE_PPP,
 			.gateway   = a,
 			.table_coerced = nm_platform_route_table_coerce (priv->ip6_route_table),
@@ -587,12 +654,12 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
 		nm_ip6_config_add_address (config, &addr);
 
 		/* Push the IPv6 config and interface identifier up to the device */
-		g_signal_emit (manager, signals[IP6_CONFIG], 0, priv->ip_iface, &iid, config);
+		g_signal_emit (self, signals[IP6_CONFIG], 0, &iid, config);
 	} else
 		_LOGE ("invalid IPv6 address received!");
 
 out:
-	g_dbus_method_invocation_return_value (context, NULL);
+	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
 /*****************************************************************************/
@@ -680,8 +747,8 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (pppd_exit_code_to_str, int,
 static void
 ppp_watch_cb (GPid pid, int status, gpointer user_data)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (user_data);
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManager *self = NM_PPP_MANAGER (user_data);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 	int err;
 	const long long lpid = (long long) pid;
 
@@ -706,20 +773,19 @@ ppp_watch_cb (GPid pid, int status, gpointer user_data)
 
 	priv->pid = 0;
 	priv->ppp_watch_id = 0;
-	_ppp_cleanup (manager);
-	g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD);
+	_ppp_cleanup (self);
+	g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD);
 }
 
 static gboolean
 pppd_timed_out (gpointer data)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (data);
+	NMPPPManager *self = NM_PPP_MANAGER (data);
 
 	_LOGW ("pppd timed out or didn't initialize our dbus module");
-	_ppp_cleanup (manager);
-	_ppp_kill (manager);
+	_ppp_manager_stop (self, NULL, NULL);
 
-	g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD);
+	g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD);
 
 	return FALSE;
 }
@@ -899,7 +965,7 @@ create_pppd_cmd_line (NMPPPManager *self,
 	nm_cmd_line_add_int (cmd, 0);
 
 	nm_cmd_line_add_string (cmd, "ipparam");
-	nm_cmd_line_add_string (cmd, nm_exported_object_get_path (NM_EXPORTED_OBJECT (self)));
+	nm_cmd_line_add_string (cmd, nm_dbus_object_get_path (NM_DBUS_OBJECT (self)));
 
 	nm_cmd_line_add_string (cmd, "plugin");
 	nm_cmd_line_add_string (cmd, NM_PPPD_PLUGIN);
@@ -944,7 +1010,7 @@ pppoe_fill_defaults (NMSettingPpp *setting)
 }
 
 static gboolean
-_ppp_manager_start (NMPPPManager *manager,
+_ppp_manager_start (NMPPPManager *self,
                     NMActRequest *req,
                     const char *ppp_name,
                     guint32 timeout_secs,
@@ -964,10 +1030,10 @@ _ppp_manager_start (NMPPPManager *manager,
 	gboolean ip6_enabled = FALSE;
 	gboolean ip4_enabled = FALSE;
 
-	g_return_val_if_fail (NM_IS_PPP_MANAGER (manager), FALSE);
+	g_return_val_if_fail (NM_IS_PPP_MANAGER (self), FALSE);
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
 
-	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
 #if !WITH_PPP
 	/* PPP support disabled */
@@ -978,7 +1044,7 @@ _ppp_manager_start (NMPPPManager *manager,
 	return FALSE;
 #endif
 
-	nm_exported_object_export (NM_EXPORTED_OBJECT (manager));
+	nm_dbus_object_export (NM_DBUS_OBJECT (self));
 
 	priv->pid = 0;
 
@@ -1013,7 +1079,7 @@ _ppp_manager_start (NMPPPManager *manager,
 	ip6_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
 	ip6_enabled = g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0;
 
-	ppp_cmd = create_pppd_cmd_line (manager,
+	ppp_cmd = create_pppd_cmd_line (self,
 	                                s_ppp,
 	                                pppoe_setting,
 	                                adsl_setting,
@@ -1043,8 +1109,8 @@ _ppp_manager_start (NMPPPManager *manager,
 
 	_LOGI ("pppd started with pid %lld", (long long) priv->pid);
 
-	priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, manager);
-	priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, manager);
+	priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, self);
+	priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, self);
 	priv->act_req = g_object_ref (req);
 
 out:
@@ -1052,42 +1118,27 @@ out:
 		nm_cmd_line_destroy (ppp_cmd);
 
 	if (priv->pid <= 0)
-		nm_exported_object_unexport (NM_EXPORTED_OBJECT (manager));
+		nm_dbus_object_unexport (NM_DBUS_OBJECT (self));
 
 	return priv->pid > 0;
 }
 
 static void
-_ppp_kill (NMPPPManager *manager)
-{
-	NMPPPManagerPrivate *priv;
-
-	g_return_if_fail (NM_IS_PPP_MANAGER (manager));
-
-	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
-
-	if (priv->pid) {
-		nm_utils_kill_child_async (priv->pid, SIGTERM, LOGD_PPP, "pppd", 2000, NULL, NULL);
-		priv->pid = 0;
-	}
-}
-
-static void
-_ppp_cleanup (NMPPPManager *manager)
+_ppp_cleanup (NMPPPManager *self)
 {
 	NMPPPManagerPrivate *priv;
 
-	g_return_if_fail (NM_IS_PPP_MANAGER (manager));
+	g_return_if_fail (NM_IS_PPP_MANAGER (self));
 
-	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
-	cancel_get_secrets (manager);
+	cancel_get_secrets (self);
 
 	nm_clear_g_source (&priv->monitor_id);
 
 	if (priv->monitor_fd >= 0) {
 		/* Get the stats one last time */
-		monitor_cb (manager);
+		monitor_cb (self);
 		nm_close (priv->monitor_fd);
 		priv->monitor_fd = -1;
 	}
@@ -1098,108 +1149,133 @@ _ppp_cleanup (NMPPPManager *manager)
 
 /*****************************************************************************/
 
-typedef struct {
-	NMPPPManager *manager;
-	GSimpleAsyncResult *result;
-	GCancellable *cancellable;
-} StopContext;
+struct _NMPPPManagerStopHandle {
+	NMPPPManager *self;
+	NMPPPManagerStopCallback callback;
+	gpointer user_data;
+
+	/* this object delays shutdown, because we still need to wait until
+	 * pppd process terminated. */
+	GObject *shutdown_waitobj;
+
+	guint idle_id;
+};
 
 static void
-stop_context_complete (StopContext *ctx)
+_stop_handle_complete (NMPPPManagerStopHandle *handle, gboolean was_cancelled)
 {
-	if (ctx->cancellable)
-		g_object_unref (ctx->cancellable);
-	g_simple_async_result_complete_in_idle (ctx->result);
-	g_object_unref (ctx->result);
-	g_object_unref (ctx->manager);
-	g_slice_free (StopContext, ctx);
-}
+	gs_unref_object NMPPPManager *self = NULL;
+	NMPPPManagerStopCallback callback;
 
-static gboolean
-stop_context_complete_if_cancelled (StopContext *ctx)
-{
-	GError *error = NULL;
+	self = g_steal_pointer (&handle->self);
+	if (!self)
+		return;
 
-	if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) {
-		g_simple_async_result_take_error (ctx->result, error);
-		stop_context_complete (ctx);
-		return TRUE;
-	}
-	return FALSE;
+	if (!handle->callback)
+		return;
+
+	callback = handle->callback;
+	handle->callback = NULL;
+	callback (self, handle, was_cancelled, handle->user_data);
 }
 
-static gboolean
-_ppp_manager_stop_finish (NMPPPManager *manager,
-                          GAsyncResult *res,
-                          GError **error)
+static void
+_stop_handle_destroy (NMPPPManagerStopHandle *handle, gboolean was_cancelled)
 {
-	return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+	_stop_handle_complete (handle, was_cancelled);
+	nm_clear_g_source (&handle->idle_id);
+	g_clear_object (&handle->shutdown_waitobj);
+	g_slice_free (NMPPPManagerStopHandle, handle);
 }
 
 static void
-kill_child_ready  (pid_t pid,
-                   gboolean success,
-                   int child_status,
-                   StopContext *ctx)
+_stop_child_cb (pid_t pid,
+                gboolean success,
+                int child_status,
+                gpointer user_data)
 {
-	if (stop_context_complete_if_cancelled (ctx))
-		return;
-	stop_context_complete (ctx);
+	_stop_handle_destroy (user_data, FALSE);
 }
 
-static void
-_ppp_manager_stop_async (NMPPPManager *manager,
-                         GCancellable *cancellable,
-                         GAsyncReadyCallback callback,
-                         gpointer user_data)
+static gboolean
+_stop_idle_cb (gpointer user_data)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
-	StopContext *ctx;
+	NMPPPManagerStopHandle *handle = user_data;
 
-	nm_exported_object_unexport (NM_EXPORTED_OBJECT (manager));
+	handle->idle_id = 0;
+	_stop_handle_destroy (handle, FALSE);
+	return G_SOURCE_REMOVE;
+}
 
-	ctx = g_slice_new0 (StopContext);
-	ctx->manager = g_object_ref (manager);
-	ctx->result = g_simple_async_result_new (G_OBJECT (manager),
-	                                         callback,
-	                                         user_data,
-	                                         _ppp_manager_stop_async);
+static NMPPPManagerStopHandle *
+_ppp_manager_stop (NMPPPManager *self,
+                   NMPPPManagerStopCallback callback,
+                   gpointer user_data)
+{
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+	NMDBusObject *dbus = NM_DBUS_OBJECT (self);
+	NMPPPManagerStopHandle *handle;
 
-	/* Setup cancellable */
-	ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	if (stop_context_complete_if_cancelled (ctx))
-		return;
+	if (nm_dbus_object_is_exported (dbus))
+		nm_dbus_object_unexport (dbus);
+
+	_ppp_cleanup (self);
+
+	if (   !priv->pid
+	    && !callback) {
+		/* nothing to do further...
+		 *
+		 * In this case, we return a %NULL handle. The caller cannot cancel this
+		 * event, but clearly he is not waiting for a callback anyway. */
+		return NULL;
+	}
 
-	/* Cleanup internals */
-	_ppp_cleanup (manager);
+	handle = g_slice_new0 (NMPPPManagerStopHandle);
+	handle->self = g_object_ref (self);
+	handle->callback = callback;
+	handle->user_data = user_data;
 
-	/* If no pppd running, we're done */
 	if (!priv->pid) {
-		stop_context_complete (ctx);
-		return;
+		/* No PID. There is nothing to kill, however, invoke the callback in
+		 * an idle handler.
+		 *
+		 * Note that we don't register nm_shutdown_wait_obj_register().
+		 * In order for shutdown to work properly, the caller must always
+		 * explicitly cancel the action to go down. With the idle-handler,
+		 * cancelling the handle completes the request. */
+		handle->idle_id = g_idle_add (_stop_idle_cb, handle);
+		return handle;
 	}
 
-	/* No cancellable operation, so just wait until it returns always */
-	nm_utils_kill_child_async (priv->pid,
-	                           SIGTERM,
-	                           LOGD_PPP,
-	                           "pppd",
-	                           2000,
-	                           (NMUtilsKillChildAsyncCb) kill_child_ready,
-	                           ctx);
-	priv->pid = 0;
+	/* we really want to kill the process and delay shutdown of NetworkManager
+	 * until the process terminated. We do that, by registering an object
+	 * that delays shutdown. */
+	handle->shutdown_waitobj = g_object_new (G_TYPE_OBJECT, NULL);
+	nm_shutdown_wait_obj_register (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd");
+	nm_utils_kill_child_async (nm_steal_int (&priv->pid),
+	                           SIGTERM, LOGD_PPP, "pppd",
+	                           NM_SHUTDOWN_TIMEOUT_MS,
+	                           _stop_child_cb, handle);
+
+	return handle;
 }
 
 static void
-_ppp_manager_stop_sync (NMPPPManager *manager)
+_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle)
 {
-	NMExportedObject *exported = NM_EXPORTED_OBJECT (manager);
+	g_return_if_fail (handle);
+	g_return_if_fail (NM_IS_PPP_MANAGER (handle->self));
 
-	if (nm_exported_object_is_exported (exported))
-		nm_exported_object_unexport (exported);
+	if (handle->idle_id) {
+		/* we can complete this fake handle right away. */
+		_stop_handle_destroy (handle, TRUE);
+		return;
+	}
 
-	_ppp_cleanup (manager);
-	_ppp_kill (manager);
+	/* a real handle. Only invoke the callback (synchronously). This marks
+	 * the handle as handled, but it keeps shutdown_waitobj around, until
+	 * nm_utils_kill_child_async() returns. */
+	_stop_handle_complete (handle, TRUE);
 }
 
 /*****************************************************************************/
@@ -1240,10 +1316,11 @@ set_property (GObject *object, guint prop_id,
 /*****************************************************************************/
 
 static void
-nm_ppp_manager_init (NMPPPManager *manager)
+nm_ppp_manager_init (NMPPPManager *self)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
+	priv->ifindex = -1;
 	priv->monitor_fd = -1;
 	priv->ip4_route_table = RT_TABLE_MAIN;
 	priv->ip4_route_metric = 460;
@@ -1265,14 +1342,13 @@ static void
 dispose (GObject *object)
 {
 	NMPPPManager *self = (NMPPPManager *) object;
-	NMExportedObject *exported = NM_EXPORTED_OBJECT (self);
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
-	if (nm_exported_object_is_exported (exported))
-		nm_exported_object_unexport (exported);
-
-	_ppp_cleanup (self);
-	_ppp_kill (self);
+	/* we expect the user to first stop the manager. As fallback,
+	 * still stop. */
+	g_warn_if_fail (!priv->pid);
+	g_warn_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)));
+	_ppp_manager_stop (self, NULL, NULL);
 
 	g_clear_object (&priv->act_req);
 
@@ -1284,24 +1360,78 @@ finalize (GObject *object)
 {
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE ((NMPPPManager *) object);
 
-	g_free (priv->ip_iface);
 	g_free (priv->parent_iface);
 
 	G_OBJECT_CLASS (nm_ppp_manager_parent_class)->finalize (object);
 }
 
+static const NMDBusInterfaceInfoExtended interface_info_ppp = {
+	.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
+		NM_DBUS_INTERFACE_PPP,
+		.methods = NM_DEFINE_GDBUS_METHOD_INFOS (
+			NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+				NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+					"NeedSecrets",
+					.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
+						NM_DEFINE_GDBUS_ARG_INFO ("username", "s"),
+						NM_DEFINE_GDBUS_ARG_INFO ("password", "s"),
+					),
+				),
+				.handle = impl_ppp_manager_need_secrets,
+			),
+			NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+				NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+					"SetIp4Config",
+					.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
+						NM_DEFINE_GDBUS_ARG_INFO ("config", "a{sv}"),
+					),
+				),
+				.handle = impl_ppp_manager_set_ip4_config,
+			),
+			NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+				NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+					"SetIp6Config",
+					.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
+						NM_DEFINE_GDBUS_ARG_INFO ("config", "a{sv}"),
+					),
+				),
+				.handle = impl_ppp_manager_set_ip6_config,
+			),
+			NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+				NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+					"SetState",
+					.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
+						NM_DEFINE_GDBUS_ARG_INFO ("state", "u"),
+					),
+				),
+				.handle = impl_ppp_manager_set_state,
+			),
+			NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+				NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+					"SetIfindex",
+					.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
+						NM_DEFINE_GDBUS_ARG_INFO ("ifindex", "i"),
+					),
+				),
+				.handle = impl_ppp_manager_set_ifindex,
+			),
+		),
+	),
+};
+
 static void
 nm_ppp_manager_class_init (NMPPPManagerClass *manager_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
-	NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (manager_class);
+	NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (manager_class);
 
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
-	exported_object_class->export_path = NM_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/PPP");
+	dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/PPP");
+	dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_ppp);
 
 	obj_properties[PROP_PARENT_IFACE] =
 	     g_param_spec_string (NM_PPP_MANAGER_PARENT_IFACE, "", "",
@@ -1320,14 +1450,23 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class)
 	                  G_TYPE_NONE, 1,
 	                  G_TYPE_UINT);
 
+	signals[IFINDEX_SET] =
+	    g_signal_new (NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0,
+	                  NULL, NULL, NULL,
+	                  G_TYPE_NONE, 2,
+	                  G_TYPE_INT,
+	                  G_TYPE_STRING);
+
 	signals[IP4_CONFIG] =
 	    g_signal_new (NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
 	                  G_OBJECT_CLASS_TYPE (object_class),
 	                  G_SIGNAL_RUN_FIRST,
 	                  0,
 	                  NULL, NULL, NULL,
-	                  G_TYPE_NONE, 2,
-	                  G_TYPE_STRING,
+	                  G_TYPE_NONE, 1,
 	                  G_TYPE_OBJECT);
 
 	signals[IP6_CONFIG] =
@@ -1336,7 +1475,9 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class)
 	                  G_SIGNAL_RUN_FIRST,
 	                  0,
 	                  NULL, NULL, NULL,
-	                  G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_OBJECT);
+	                  G_TYPE_NONE, 2,
+	                  G_TYPE_POINTER,
+	                  G_TYPE_OBJECT);
 
 	signals[STATS] =
 	    g_signal_new (NM_PPP_MANAGER_SIGNAL_STATS,
@@ -1347,21 +1488,12 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class)
 	                  G_TYPE_NONE, 2,
 	                  G_TYPE_UINT /*guint32 in_bytes*/,
 	                  G_TYPE_UINT /*guint32 out_bytes*/);
-
-	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class),
-	                                        NMDBUS_TYPE_PPP_MANAGER_SKELETON,
-	                                        "NeedSecrets", impl_ppp_manager_need_secrets,
-	                                        "SetIp4Config", impl_ppp_manager_set_ip4_config,
-	                                        "SetIp6Config", impl_ppp_manager_set_ip6_config,
-	                                        "SetState", impl_ppp_manager_set_state,
-	                                        NULL);
 }
 
 NMPPPOps ppp_ops = {
 	.create               = _ppp_manager_new,
 	.set_route_parameters = _ppp_manager_set_route_parameters,
 	.start                = _ppp_manager_start,
-	.stop_async           = _ppp_manager_stop_async,
-	.stop_finish          = _ppp_manager_stop_finish,
-	.stop_sync            = _ppp_manager_stop_sync,
+	.stop                 = _ppp_manager_stop,
+	.stop_cancel          = _ppp_manager_stop_cancel,
 };
diff --git a/src/ppp/nm-ppp-manager.h b/src/ppp/nm-ppp-manager.h
index 35fb1b60..ec0ca46e 100644
--- a/src/ppp/nm-ppp-manager.h
+++ b/src/ppp/nm-ppp-manager.h
@@ -25,10 +25,18 @@
 #define NM_PPP_MANAGER_PARENT_IFACE    "parent-iface"
 
 #define NM_PPP_MANAGER_SIGNAL_STATE_CHANGED "state-changed"
+#define NM_PPP_MANAGER_SIGNAL_IFINDEX_SET   "ifindex-set"
 #define NM_PPP_MANAGER_SIGNAL_IP4_CONFIG    "ip4-config"
 #define NM_PPP_MANAGER_SIGNAL_IP6_CONFIG    "ip6-config"
 #define NM_PPP_MANAGER_SIGNAL_STATS         "stats"
 
 typedef struct _NMPPPManager NMPPPManager;
 
+typedef struct _NMPPPManagerStopHandle NMPPPManagerStopHandle;
+
+typedef void (*NMPPPManagerStopCallback) (NMPPPManager *manager,
+                                          NMPPPManagerStopHandle *handle,
+                                          gboolean was_cancelled,
+                                          gpointer user_data);
+
 #endif /* __NM_PPP_MANAGER_H__ */
diff --git a/src/ppp/nm-ppp-plugin-api.h b/src/ppp/nm-ppp-plugin-api.h
index bb53690c..558de2c2 100644
--- a/src/ppp/nm-ppp-plugin-api.h
+++ b/src/ppp/nm-ppp-plugin-api.h
@@ -21,6 +21,8 @@
 #ifndef __NM_PPP_PLUGIN_API_H__
 #define __NM_PPP_PLUGIN_API_H__
 
+#include "nm-ppp-manager.h"
+
 typedef const struct {
 	NMPPPManager *(*create) (const char *iface);
 
@@ -37,16 +39,12 @@ typedef const struct {
 	                        guint baud_override,
 	                        GError **err);
 
-	void          (*stop_async) (NMPPPManager *manager,
-	                             GCancellable *cancellable,
-	                             GAsyncReadyCallback callback,
-	                             gpointer user_data);
+	NMPPPManagerStopHandle *(*stop) (NMPPPManager *manager,
+	                                 NMPPPManagerStopCallback callback,
+	                                 gpointer user_data);
 
-	gboolean      (*stop_finish) (NMPPPManager *manager,
-	                              GAsyncResult *res,
-	                              GError **error);
+	void (*stop_cancel) (NMPPPManagerStopHandle *handle);
 
-	void          (*stop_sync) (NMPPPManager *manager);
 } NMPPPOps;
 
 #endif /* __NM_PPP_PLUGIN_API_H__ */
diff --git a/src/ppp/nm-pppd-plugin.c b/src/ppp/nm-pppd-plugin.c
index 0ac8f907..989f7433 100644
--- a/src/ppp/nm-pppd-plugin.c
+++ b/src/ppp/nm-pppd-plugin.c
@@ -28,6 +28,7 @@
 #include <pppd/ipcp.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <net/if.h>
 #include <arpa/inet.h>
 #include <dlfcn.h>
 
@@ -36,7 +37,9 @@
 #include <pppd/ipv6cp.h>
 
 #include "nm-default.h"
+
 #include "nm-dbus-interface.h"
+
 #include "nm-pppd-plugin.h"
 #include "nm-ppp-status.h"
 
@@ -50,7 +53,9 @@ static void
 nm_phasechange (void *data, int arg)
 {
 	NMPPPStatus ppp_status = NM_PPP_STATUS_UNKNOWN;
+	char new_name[IF_NAMESIZE];
 	char *ppp_phase;
+	int index;
 
 	g_return_if_fail (G_IS_DBUS_PROXY (proxy));
 
@@ -126,6 +131,25 @@ nm_phasechange (void *data, int arg)
 		                   NULL,
 		                   NULL, NULL);
 	}
+
+	if (ppp_status == PHASE_RUNNING) {
+		index = if_nametoindex (ifname);
+		/* Make a sync call to ensure that when the call
+		 * terminates the interface already has its final
+		 * name. */
+		g_dbus_proxy_call_sync (proxy,
+		                        "SetIfindex",
+		                        g_variant_new ("(i)", index),
+		                        G_DBUS_CALL_FLAGS_NONE,
+		                        25000,
+		                        NULL, NULL);
+		/* Update the name in pppd if NM changed it */
+		if (   if_indextoname (index, new_name)
+		    && !nm_streq0 (ifname, new_name)) {
+			g_message ("nm-ppp-plugin: interface name changed from '%s' to '%s'", ifname, new_name);
+			strncpy (ifname, new_name, IF_NAMESIZE);
+		}
+	}
 }
 
 static void
@@ -148,6 +172,9 @@ nm_ip_up (void *data, int arg)
 
 	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
 
+	/* Keep sending the interface name to be backwards compatible
+	 * with older versions of NM during a package upgrade, where
+	 * NM is not restarted and the pppd plugin was not loaded. */
 	g_variant_builder_add (&builder, "{sv}",
 	                       NM_PPP_IP4_CONFIG_INTERFACE,
 	                       g_variant_new_string (ifname));
@@ -242,6 +269,9 @@ nm_ip6_up (void *data, int arg)
 	g_message ("nm-ppp-plugin: (%s): ip6-up event", __func__);
 
 	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+	/* Keep sending the interface name to be backwards compatible
+	 * with older versions of NM during a package upgrade, where
+	 * NM is not restarted and the pppd plugin was not loaded. */
 	g_variant_builder_add (&builder, "{sv}",
 	                       NM_PPP_IP6_CONFIG_INTERFACE,
 	                       g_variant_new_string (ifname));
@@ -361,8 +391,6 @@ plugin_init (void)
 	GDBusConnection *bus;
 	GError *err = NULL;
 
-	nm_g_type_init ();
-
 	g_message ("nm-ppp-plugin: (%s): initializing", __func__);
 
 	bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err);