about summary refs log tree commit diff
path: root/src/ppp
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
commit0dd9df69fdbd475c48a0c8d5b0a1882550fe7321 (patch)
tree249cf25643b1fe408e10679bb61613bc6540e894 /src/ppp
parent2e94a3b93171ab3fb95bf689aab1664d23988809 (diff)
parent04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff)
Update upstream source from tag 'upstream/1.11.4'
Update to upstream version '1.11.4'
with Debian dir d0638aa2e32d5bae4e8daa021b9a66b7c4d6647e
Diffstat (limited to 'src/ppp')
-rw-r--r--src/ppp/meson.build2
-rw-r--r--src/ppp/nm-ppp-manager-call.c34
-rw-r--r--src/ppp/nm-ppp-manager-call.h14
-rw-r--r--src/ppp/nm-ppp-manager.c300
-rw-r--r--src/ppp/nm-ppp-manager.h7
-rw-r--r--src/ppp/nm-ppp-plugin-api.h14
6 files changed, 186 insertions, 185 deletions
diff --git a/src/ppp/meson.build b/src/ppp/meson.build
index 20edb9d0..38f9a0f1 100644
--- a/src/ppp/meson.build
+++ b/src/ppp/meson.build
@@ -37,5 +37,5 @@ core_plugins += shared_module(
   ],
   link_depends: linker_script,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
diff --git a/src/ppp/nm-ppp-manager-call.c b/src/ppp/nm-ppp-manager-call.c
index ed70f687..3d6fee49 100644
--- a/src/ppp/nm-ppp-manager-call.c
+++ b/src/ppp/nm-ppp-manager-call.c
@@ -82,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;
 
@@ -125,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 7d1eb408..fc658bec 100644
--- a/src/ppp/nm-ppp-manager.c
+++ b/src/ppp/nm-ppp-manager.c
@@ -134,8 +134,11 @@ G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_DBUS_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);
 
 /*****************************************************************************/
 
@@ -173,8 +176,8 @@ _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);
+	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);
@@ -190,7 +193,7 @@ monitor_cb (gpointer user_data)
 			if (errno != ENODEV)
 				_LOGW ("could not read ppp stats: %s", strerror (errno));
 		} else {
-			g_signal_emit (manager, signals[STATS], 0,
+			g_signal_emit (self, signals[STATS], 0,
 			               (guint) stats.p.ppp_ibytes,
 			               (guint) stats.p.ppp_obytes);
 		}
@@ -200,9 +203,9 @@ monitor_cb (gpointer user_data)
 }
 
 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)
@@ -213,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));
 }
@@ -351,8 +354,8 @@ impl_ppp_manager_need_secrets (NMDBusObject *obj,
                                GDBusMethodInvocation *invocation,
                                GVariant *parameters)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (obj);
-	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;
@@ -371,7 +374,7 @@ impl_ppp_manager_need_secrets (NMDBusObject *obj,
 		if (extract_details_from_connection (applied_connection, NULL, &username, &password, &error)) {
 			/* Send existing secrets to the PPP plugin */
 			priv->pending_secrets_context = invocation;
-			ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, manager);
+			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);
@@ -393,7 +396,7 @@ impl_ppp_manager_need_secrets (NMDBusObject *obj,
 	                                               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 = invocation;
 
@@ -410,11 +413,11 @@ impl_ppp_manager_set_state (NMDBusObject *obj,
                             GDBusMethodInvocation *invocation,
                             GVariant *parameters)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (obj);
+	NMPPPManager *self = NM_PPP_MANAGER (obj);
 	guint32 state;
 
 	g_variant_get (parameters, "(u)", &state);
-	g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) state);
+	g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state);
 	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
@@ -427,8 +430,8 @@ impl_ppp_manager_set_ifindex (NMDBusObject *obj,
                               GDBusMethodInvocation *invocation,
                               GVariant *parameters)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (obj);
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	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;
@@ -459,7 +462,7 @@ impl_ppp_manager_set_ifindex (NMDBusObject *obj,
 
 	obj_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink));
 
-	g_signal_emit (manager, signals[IFINDEX_SET], 0, ifindex, plink->name);
+	g_signal_emit (self, signals[IFINDEX_SET], 0, ifindex, plink->name);
 	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
@@ -498,8 +501,8 @@ impl_ppp_manager_set_ip4_config (NMDBusObject *obj,
                                  GDBusMethodInvocation *invocation,
                                  GVariant *parameters)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (obj);
-	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;
@@ -512,7 +515,7 @@ impl_ppp_manager_set_ip4_config (NMDBusObject *obj,
 
 	nm_clear_g_source (&priv->ppp_timeout_handler);
 
-	if (!set_ip_config_common (manager, config_dict, &mtu))
+	if (!set_ip_config_common (self, config_dict, &mtu))
 		goto out;
 
 	config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex);
@@ -564,7 +567,7 @@ impl_ppp_manager_set_ip4_config (NMDBusObject *obj,
 	}
 
 	/* Push the IP4 config up to the device */
-	g_signal_emit (manager, signals[IP4_CONFIG], 0, config);
+	g_signal_emit (self, signals[IP4_CONFIG], 0, config);
 
 out:
 	g_dbus_method_invocation_return_value (invocation, NULL);
@@ -608,8 +611,8 @@ impl_ppp_manager_set_ip6_config (NMDBusObject *obj,
                                  GDBusMethodInvocation *invocation,
                                  GVariant *parameters)
 {
-	NMPPPManager *manager = NM_PPP_MANAGER (obj);
-	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;
@@ -623,7 +626,7 @@ impl_ppp_manager_set_ip6_config (NMDBusObject *obj,
 
 	nm_clear_g_source (&priv->ppp_timeout_handler);
 
-	if (!set_ip_config_common (manager, config_dict, NULL))
+	if (!set_ip_config_common (self, config_dict, NULL))
 		goto out;
 
 	config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex);
@@ -651,7 +654,7 @@ impl_ppp_manager_set_ip6_config (NMDBusObject *obj,
 		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, &iid, config);
+		g_signal_emit (self, signals[IP6_CONFIG], 0, &iid, config);
 	} else
 		_LOGE ("invalid IPv6 address received!");
 
@@ -744,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;
 
@@ -770,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;
 }
@@ -1008,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,
@@ -1028,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 */
@@ -1042,7 +1044,7 @@ _ppp_manager_start (NMPPPManager *manager,
 	return FALSE;
 #endif
 
-	nm_dbus_object_export (NM_DBUS_OBJECT (manager));
+	nm_dbus_object_export (NM_DBUS_OBJECT (self));
 
 	priv->pid = 0;
 
@@ -1077,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,
@@ -1107,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:
@@ -1116,42 +1118,27 @@ out:
 		nm_cmd_line_destroy (ppp_cmd);
 
 	if (priv->pid <= 0)
-		nm_dbus_object_unexport (NM_DBUS_OBJECT (manager));
+		nm_dbus_object_unexport (NM_DBUS_OBJECT (self));
 
 	return priv->pid > 0;
 }
 
 static void
-_ppp_kill (NMPPPManager *manager)
+_ppp_cleanup (NMPPPManager *self)
 {
 	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)
-{
-	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;
 	}
@@ -1162,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_dbus_object_unexport (NM_DBUS_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);
 
-	/* Cleanup internals */
-	_ppp_cleanup (manager);
+	_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;
+	}
+
+	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)
 {
-	NMDBusObject *dbus = NM_DBUS_OBJECT (manager);
+	g_return_if_fail (handle);
+	g_return_if_fail (NM_IS_PPP_MANAGER (handle->self));
 
-	if (nm_dbus_object_is_exported (dbus))
-		nm_dbus_object_unexport (dbus);
+	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);
 }
 
 /*****************************************************************************/
@@ -1304,9 +1316,9 @@ 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;
@@ -1330,14 +1342,13 @@ static void
 dispose (GObject *object)
 {
 	NMPPPManager *self = (NMPPPManager *) object;
-	NMDBusObject *dbus = NM_DBUS_OBJECT (self);
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
 
-	if (nm_dbus_object_is_exported (dbus))
-		nm_dbus_object_unexport (dbus);
-
-	_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);
 
@@ -1483,7 +1494,6 @@ 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 5457726e..ec0ca46e 100644
--- a/src/ppp/nm-ppp-manager.h
+++ b/src/ppp/nm-ppp-manager.h
@@ -32,4 +32,11 @@
 
 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__ */