about summary refs log tree commit diff
path: root/src/core/devices/adsl
diff options
context:
space:
mode:
authorJeremy Bicha <jeremy.bicha@canonical.com>2022-02-08 12:07:45 -0500
committerJeremy Bicha <jeremy.bicha@canonical.com>2022-02-08 12:07:45 -0500
commit7d8baf4ac0480a542f000c1201df85427a22332c (patch)
tree66284d67f52a1544900b7d7e2ba527be1bcbd02e /src/core/devices/adsl
parent88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (diff)
New upstream version 1.35.90
Diffstat (limited to 'src/core/devices/adsl')
-rw-r--r--src/core/devices/adsl/nm-atm-manager.c38
-rw-r--r--src/core/devices/adsl/nm-device-adsl.c373
2 files changed, 208 insertions, 203 deletions
diff --git a/src/core/devices/adsl/nm-atm-manager.c b/src/core/devices/adsl/nm-atm-manager.c
index bd9ed8cc..cc8d37e6 100644
--- a/src/core/devices/adsl/nm-atm-manager.c
+++ b/src/core/devices/adsl/nm-atm-manager.c
@@ -27,7 +27,7 @@
 
 typedef struct {
     NMUdevClient *udev_client;
-    GSList *      devices;
+    GSList       *devices;
 } NMAtmManagerPrivate;
 
 typedef struct {
@@ -51,7 +51,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(
     NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_ADSL_SETTING_NAME));
 
 G_MODULE_EXPORT NMDeviceFactory *
-                nm_device_factory_create(GError **error)
+nm_device_factory_create(GError **error)
 {
     return g_object_new(NM_TYPE_ATM_MANAGER, NULL);
 }
@@ -62,7 +62,7 @@ static gboolean
 dev_get_attrs(struct udev_device *udev_device, const char **out_path, char **out_driver)
 {
     struct udev_device *parent = NULL;
-    const char *        driver, *path;
+    const char         *driver, *path;
 
     g_return_val_if_fail(udev_device != NULL, FALSE);
     g_return_val_if_fail(out_path != NULL, FALSE);
@@ -91,7 +91,7 @@ dev_get_attrs(struct udev_device *udev_device, const char **out_path, char **out
 static void
 device_destroyed(gpointer user_data, GObject *dead)
 {
-    NMAtmManager *       self = NM_ATM_MANAGER(user_data);
+    NMAtmManager        *self = NM_ATM_MANAGER(user_data);
     NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self);
 
     priv->devices = g_slist_remove(priv->devices, dead);
@@ -101,11 +101,11 @@ static void
 adsl_add(NMAtmManager *self, struct udev_device *udev_device)
 {
     NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self);
-    const char *         ifname, *sysfs_path = NULL;
-    char *               driver         = NULL;
-    gs_free char *       atm_index_path = NULL;
+    const char          *ifname, *sysfs_path = NULL;
+    char                *driver         = NULL;
+    gs_free char        *atm_index_path = NULL;
     int                  atm_index;
-    NMDevice *           device;
+    NMDevice            *device;
 
     g_return_if_fail(udev_device != NULL);
 
@@ -153,8 +153,8 @@ static void
 adsl_remove(NMAtmManager *self, struct udev_device *udev_device)
 {
     NMAtmManagerPrivate *priv  = NM_ATM_MANAGER_GET_PRIVATE(self);
-    const char *         iface = udev_device_get_sysname(udev_device);
-    GSList *             iter;
+    const char          *iface = udev_device_get_sysname(udev_device);
+    GSList              *iter;
 
     nm_log_dbg(LOGD_PLATFORM, "(%s): removing ATM device", iface);
 
@@ -177,9 +177,9 @@ adsl_remove(NMAtmManager *self, struct udev_device *udev_device)
 static void
 start(NMDeviceFactory *factory)
 {
-    NMAtmManager *          self = NM_ATM_MANAGER(factory);
-    NMAtmManagerPrivate *   priv = NM_ATM_MANAGER_GET_PRIVATE(self);
-    struct udev_enumerate * enumerate;
+    NMAtmManager           *self = NM_ATM_MANAGER(factory);
+    NMAtmManagerPrivate    *priv = NM_ATM_MANAGER_GET_PRIVATE(self);
+    struct udev_enumerate  *enumerate;
     struct udev_list_entry *devices;
 
     enumerate = nm_udev_client_enumerate_new(priv->udev_client);
@@ -203,10 +203,10 @@ static void
 handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_data)
 {
     NMAtmManager *self = NM_ATM_MANAGER(user_data);
-    const char *  subsys;
-    const char *  ifindex;
+    const char   *subsys;
+    const char   *ifindex;
     guint64       seqnum;
-    const char *  action;
+    const char   *action;
 
     action = udev_device_get_action(device);
 
@@ -245,9 +245,9 @@ nm_atm_manager_init(NMAtmManager *self)
 static void
 dispose(GObject *object)
 {
-    NMAtmManager *       self = NM_ATM_MANAGER(object);
+    NMAtmManager        *self = NM_ATM_MANAGER(object);
     NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self);
-    GSList *             iter;
+    GSList              *iter;
 
     for (iter = priv->devices; iter; iter = iter->next)
         g_object_weak_unref(G_OBJECT(iter->data), device_destroyed, self);
@@ -261,7 +261,7 @@ dispose(GObject *object)
 static void
 nm_atm_manager_class_init(NMAtmManagerClass *klass)
 {
-    GObjectClass *        object_class  = G_OBJECT_CLASS(klass);
+    GObjectClass         *object_class  = G_OBJECT_CLASS(klass);
     NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass);
 
     object_class->dispose = dispose;
diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c
index adcf8785..79705c28 100644
--- a/src/core/devices/adsl/nm-device-adsl.c
+++ b/src/core/devices/adsl/nm-device-adsl.c
@@ -15,13 +15,12 @@
 #include <unistd.h>
 #include <stdlib.h>
 
-#include "nm-ip4-config.h"
 #include "devices/nm-device-private.h"
 #include "libnm-platform/nm-platform.h"
-#include "ppp/nm-ppp-manager-call.h"
-#include "ppp/nm-ppp-status.h"
+#include "nm-manager.h"
 #include "nm-setting-adsl.h"
 #include "nm-utils.h"
+#include "ppp/nm-ppp-mgr.h"
 
 #define _NMLOG_DEVICE_TYPE NMDeviceAdsl
 #include "devices/nm-device-logging.h"
@@ -34,15 +33,14 @@ typedef struct {
     guint carrier_poll_id;
     int   atm_index;
 
-    /* PPP */
-    NMPPPManager *ppp_manager;
+    NMPppMgr *ppp_mgr;
 
     /* RFC 2684 bridging (PPPoE over ATM) */
-    int   brfd;
-    int   nas_ifindex;
-    char *nas_ifname;
-    guint nas_update_id;
-    guint nas_update_count;
+    int      brfd;
+    int      nas_ifindex;
+    char    *nas_ifname;
+    GSource *nas_update_source;
+    guint    nas_update_count;
 } NMDeviceAdslPrivate;
 
 struct _NMDeviceAdsl {
@@ -72,7 +70,7 @@ static gboolean
 check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
 {
     NMSettingAdsl *s_adsl;
-    const char *   protocol;
+    const char    *protocol;
 
     if (!NM_DEVICE_CLASS(nm_device_adsl_parent_class)
              ->check_connection_compatible(device, connection, error))
@@ -93,11 +91,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError *
 }
 
 static gboolean
-complete_connection(NMDevice *           device,
-                    NMConnection *       connection,
-                    const char *         specific_object,
+complete_connection(NMDevice            *device,
+                    NMConnection        *connection,
+                    const char          *specific_object,
                     NMConnection *const *existing_connections,
-                    GError **            error)
+                    GError             **error)
 {
     NMSettingAdsl *s_adsl;
 
@@ -126,12 +124,12 @@ complete_connection(NMDevice *           device,
 static gboolean
 br2684_assign_vcc(NMDeviceAdsl *self, NMSettingAdsl *s_adsl)
 {
-    NMDeviceAdslPrivate *     priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+    NMDeviceAdslPrivate      *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
     struct sockaddr_atmpvc    addr;
     struct atm_backend_br2684 be;
     struct atm_qos            qos;
     int                       errsv, err, bufsize = 8192;
-    const char *              encapsulation;
+    const char               *encapsulation;
     gboolean                  is_llc;
 
     g_return_val_if_fail(priv->brfd == -1, FALSE);
@@ -216,18 +214,18 @@ error:
 }
 
 static void
-link_changed_cb(NMPlatform *    platform,
+link_changed_cb(NMPlatform     *platform,
                 int             obj_type_i,
                 int             ifindex,
                 NMPlatformLink *info,
                 int             change_type_i,
-                NMDeviceAdsl *  self)
+                NMDeviceAdsl   *self)
 {
     const NMPlatformSignalChangeType change_type = change_type_i;
 
     if (change_type == NM_PLATFORM_SIGNAL_REMOVED) {
         NMDeviceAdslPrivate *priv   = NM_DEVICE_ADSL_GET_PRIVATE(self);
-        NMDevice *           device = NM_DEVICE(self);
+        NMDevice            *device = NM_DEVICE(self);
 
         /* This only gets called for PPPoE connections and "nas" interfaces */
 
@@ -245,8 +243,8 @@ static gboolean
 pppoe_vcc_config(NMDeviceAdsl *self)
 {
     NMDeviceAdslPrivate *priv   = NM_DEVICE_ADSL_GET_PRIVATE(self);
-    NMDevice *           device = NM_DEVICE(self);
-    NMSettingAdsl *      s_adsl;
+    NMDevice            *device = NM_DEVICE(self);
+    NMSettingAdsl       *s_adsl;
 
     s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
 
@@ -271,11 +269,11 @@ pppoe_vcc_config(NMDeviceAdsl *self)
 }
 
 static gboolean
-nas_update_cb(gpointer user_data)
+nas_update_timeout_cb(gpointer user_data)
 {
-    NMDeviceAdsl *       self   = NM_DEVICE_ADSL(user_data);
+    NMDeviceAdsl        *self   = NM_DEVICE_ADSL(user_data);
     NMDeviceAdslPrivate *priv   = NM_DEVICE_ADSL_GET_PRIVATE(self);
-    NMDevice *           device = NM_DEVICE(self);
+    NMDevice            *device = NM_DEVICE(self);
 
     nm_assert(priv->nas_ifname);
 
@@ -284,46 +282,48 @@ nas_update_cb(gpointer user_data)
     nm_assert(priv->nas_ifindex <= 0);
     priv->nas_ifindex =
         nm_platform_link_get_ifindex(nm_device_get_platform(device), priv->nas_ifname);
+
+    if (priv->nas_ifindex <= 0 && priv->nas_update_count <= 10) {
+        /* Keep waiting for it to appear */
+        return G_SOURCE_CONTINUE;
+    }
+
+    nm_clear_g_source_inst(&priv->nas_update_source);
+
     if (priv->nas_ifindex <= 0) {
-        if (priv->nas_update_count <= 10) {
-            /* Keep waiting for it to appear */
-            return G_SOURCE_CONTINUE;
-        }
-        priv->nas_update_id = 0;
         _LOGW(LOGD_ADSL,
               "failed to find br2684 interface %s ifindex after timeout",
               priv->nas_ifname);
         nm_device_state_changed(device,
                                 NM_DEVICE_STATE_FAILED,
                                 NM_DEVICE_STATE_REASON_BR2684_FAILED);
-        return G_SOURCE_REMOVE;
+        return G_SOURCE_CONTINUE;
     }
 
-    priv->nas_update_id = 0;
     _LOGD(LOGD_ADSL, "using br2684 iface '%s' index %d", priv->nas_ifname, priv->nas_ifindex);
 
     if (!pppoe_vcc_config(self)) {
         nm_device_state_changed(device,
                                 NM_DEVICE_STATE_FAILED,
                                 NM_DEVICE_STATE_REASON_BR2684_FAILED);
-        return G_SOURCE_REMOVE;
+        return G_SOURCE_CONTINUE;
     }
 
     nm_device_activate_schedule_stage2_device_config(device, TRUE);
-    return G_SOURCE_REMOVE;
+    return G_SOURCE_CONTINUE;
 }
 
 static gboolean
 br2684_create_iface(NMDeviceAdsl *self)
 {
-    NMDeviceAdslPrivate *   priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+    NMDeviceAdslPrivate    *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
     struct atm_newif_br2684 ni;
     nm_auto_close int       fd = -1;
-    int                     err, errsv;
+    int                     err;
+    int                     errsv;
     guint                   num = 0;
 
-    if (nm_clear_g_source(&priv->nas_update_id))
-        nm_assert_not_reached();
+    nm_assert(!priv->nas_update_source);
 
     fd = socket(PF_ATMPVC, SOCK_DGRAM | SOCK_CLOEXEC, ATM_AAL5);
     if (fd < 0) {
@@ -358,174 +358,187 @@ br2684_create_iface(NMDeviceAdsl *self)
 
         nm_strdup_reset(&priv->nas_ifname, ni.ifname);
         _LOGD(LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname);
-        priv->nas_update_count = 0;
-        priv->nas_update_id    = g_timeout_add(100, nas_update_cb, self);
+        priv->nas_update_count  = 0;
+        priv->nas_update_source = nm_g_timeout_add_source(100, nas_update_timeout_cb, self);
         return TRUE;
     }
 }
 
-static NMActStageReturn
-act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
+/*****************************************************************************/
+
+static void
+_ppp_mgr_cleanup(NMDeviceAdsl *self)
 {
-    NMDeviceAdsl *       self = NM_DEVICE_ADSL(device);
     NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
-    NMSettingAdsl *      s_adsl;
-    const char *         protocol;
 
-    s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
-
-    g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
+    nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy);
+}
 
-    protocol = nm_setting_adsl_get_protocol(s_adsl);
-    _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
+static void
+_ppp_mgr_stage3_maybe_ready(NMDeviceAdsl *self)
+{
+    NMDevice            *device = NM_DEVICE(self);
+    NMDeviceAdslPrivate *priv   = NM_DEVICE_ADSL_GET_PRIVATE(self);
+    int                  IS_IPv4;
 
-    if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
-        /* PPPoA doesn't need anything special */
-        return NM_ACT_STAGE_RETURN_SUCCESS;
-    }
+    for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
+        const int             addr_family = IS_IPv4 ? AF_INET : AF_INET6;
+        const NMPppMgrIPData *ip_data;
 
-    if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
-        /* PPPoE needs RFC2684 bridging before we can do PPP over it */
-        if (priv->nas_ifindex <= 0) {
-            if (priv->nas_update_id == 0) {
-                if (!br2684_create_iface(self)) {
-                    NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
-                    return NM_ACT_STAGE_RETURN_FAILURE;
-                }
-            }
-            return NM_ACT_STAGE_RETURN_POSTPONE;
-        }
-        return NM_ACT_STAGE_RETURN_SUCCESS;
+        ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family);
+        if (ip_data->ip_received)
+            nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd);
     }
 
-    _LOGW(LOGD_ADSL, "unhandled ADSL protocol '%s'", protocol);
-    return NM_ACT_STAGE_RETURN_SUCCESS;
+    if (nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG)
+        nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL);
 }
 
 static void
-ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
 {
-    NMDevice *device = NM_DEVICE(user_data);
+    NMDeviceAdsl *self   = NM_DEVICE_ADSL(user_data);
+    NMDevice     *device = NM_DEVICE(self);
+    NMDeviceState device_state;
 
-    switch (status) {
-    case NM_PPP_STATUS_DISCONNECT:
-        nm_device_state_changed(device,
-                                NM_DEVICE_STATE_FAILED,
-                                NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
-        break;
-    case NM_PPP_STATUS_DEAD:
-        nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
-        break;
-    default:
-        break;
-    }
-}
+    if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED)
+        return;
 
-static void
-ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
-{
-    NMDevice *device = NM_DEVICE(user_data);
+    device_state = nm_device_get_state(device);
 
-    if (!nm_device_set_ip_ifindex(device, ifindex)) {
-        nm_device_state_changed(device,
-                                NM_DEVICE_STATE_FAILED,
-                                NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+    if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) {
+        if (device_state <= NM_DEVICE_STATE_ACTIVATED)
+            nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason);
+        return;
     }
-}
 
-static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
-{
-    NMDevice *device = NM_DEVICE(user_data);
+    if (device_state < NM_DEVICE_STATE_IP_CONFIG) {
+        if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) {
+            gs_free char         *old_name = NULL;
+            gs_free_error GError *error    = NULL;
+
+            if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) {
+                _LOGW(LOGD_DEVICE | LOGD_PPP,
+                      "could not take control of link %d: %s",
+                      callback_data->data.ifindex,
+                      error->message);
+                _ppp_mgr_cleanup(self);
+                nm_device_state_changed(device,
+                                        NM_DEVICE_STATE_FAILED,
+                                        NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+                return;
+            }
 
-    /* Ignore PPP IP4 events that come in after initial configuration */
-    if (nm_device_activate_ip4_state_in_conf(device))
-        nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+            if (old_name)
+                nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_ADSL);
+
+            nm_device_activate_schedule_stage2_device_config(device, FALSE);
+        }
+        return;
+    }
+
+    _ppp_mgr_stage3_maybe_ready(self);
 }
 
+/*****************************************************************************/
+
 static NMActStageReturn
-act_stage3_ip4_config_start(NMDevice *           device,
-                            NMIP4Config **       out_config,
-                            NMDeviceStateReason *out_failure_reason)
+act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
-    NMDeviceAdsl *       self = NM_DEVICE_ADSL(device);
+    NMDeviceAdsl        *self = NM_DEVICE_ADSL(device);
     NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
-    NMSettingAdsl *      s_adsl;
-    NMActRequest *       req;
-    GError *             err = NULL;
-    const char *         ppp_iface;
-
-    req = nm_device_get_act_request(device);
 
-    g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+    if (!priv->ppp_mgr) {
+        gs_free_error GError *error = NULL;
+        NMSettingAdsl        *s_adsl;
+        const char           *protocol;
+        NMActRequest         *req;
+        const char           *ppp_iface;
+
+        req = nm_device_get_act_request(device);
+        g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+
+        s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
+        g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
+
+        protocol = nm_setting_adsl_get_protocol(s_adsl);
+
+        _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
+
+        if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
+            /* PPPoA doesn't need anything special */
+        } else if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
+            /* PPPoE needs RFC2684 bridging before we can do PPP over it */
+            if (priv->nas_ifindex <= 0) {
+                if (!priv->nas_update_source) {
+                    if (!br2684_create_iface(self)) {
+                        NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
+                        return NM_ACT_STAGE_RETURN_FAILURE;
+                    }
+                }
+                return NM_ACT_STAGE_RETURN_POSTPONE;
+            }
+        } else
+            nm_assert(nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM));
+
+        /* PPPoE uses the NAS interface, not the ATM interface */
+        if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
+            nm_assert(priv->nas_ifname);
+            ppp_iface = priv->nas_ifname;
+            _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
+        } else {
+            ppp_iface = nm_device_get_iface(device);
+            _LOGD(LOGD_ADSL, "starting PPPoA");
+        }
 
-    s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
+        priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){
+                                             .netns         = nm_device_get_netns(device),
+                                             .parent_iface  = ppp_iface,
+                                             .callback      = _ppp_mgr_callback,
+                                             .user_data     = self,
+                                             .act_req       = req,
+                                             .ppp_username  = nm_setting_adsl_get_username(s_adsl),
+                                             .timeout_secs  = 30,
+                                             .baud_override = 0,
+                                         }),
+                                         &error);
+        if (!priv->ppp_mgr) {
+            _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
+            *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+            return NM_ACT_STAGE_RETURN_FAILURE;
+        }
 
-    g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
+        return NM_ACT_STAGE_RETURN_POSTPONE;
+    }
 
-    /* PPPoE uses the NAS interface, not the ATM interface */
-    if (nm_streq0(nm_setting_adsl_get_protocol(s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
-        nm_assert(priv->nas_ifname);
-        ppp_iface = priv->nas_ifname;
+    if (nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX)
+        return NM_ACT_STAGE_RETURN_POSTPONE;
 
-        _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
-    } else {
-        ppp_iface = nm_device_get_iface(device);
-        _LOGD(LOGD_ADSL, "starting PPPoA");
-    }
+    return NM_ACT_STAGE_RETURN_SUCCESS;
+}
 
-    priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err);
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
+{
+    NMDeviceAdsl        *self = NM_DEVICE_ADSL(device);
+    NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+    NMPppMgrState        ppp_state;
 
-    if (priv->ppp_manager) {
-        nm_ppp_manager_set_route_parameters(priv->ppp_manager,
-                                            nm_device_get_route_table(device, AF_INET),
-                                            nm_device_get_route_metric(device, AF_INET),
-                                            nm_device_get_route_table(device, AF_INET6),
-                                            nm_device_get_route_metric(device, AF_INET6));
+    if (!priv->ppp_mgr) {
+        nm_assert_not_reached();
+        return;
     }
 
-    if (!priv->ppp_manager
-        || !nm_ppp_manager_start(priv->ppp_manager,
-                                 req,
-                                 nm_setting_adsl_get_username(s_adsl),
-                                 30,
-                                 0,
-                                 &err)) {
-        _LOGW(LOGD_ADSL, "PPP failed to start: %s", err->message);
-        g_error_free(err);
+    ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr);
 
-        g_clear_object(&priv->ppp_manager);
+    nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG));
 
-        NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
-        return NM_ACT_STAGE_RETURN_FAILURE;
+    if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) {
+        nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL);
+        return;
     }
 
-    g_signal_connect(priv->ppp_manager,
-                     NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
-                     G_CALLBACK(ppp_state_changed),
-                     self);
-    g_signal_connect(priv->ppp_manager,
-                     NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
-                     G_CALLBACK(ppp_ifindex_set),
-                     self);
-    g_signal_connect(priv->ppp_manager,
-                     NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
-                     G_CALLBACK(ppp_ip4_config),
-                     self);
-    return NM_ACT_STAGE_RETURN_POSTPONE;
-}
-
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice *           device,
-                           int                  addr_family,
-                           gpointer *           out_config,
-                           NMDeviceStateReason *out_failure_reason)
-{
-    if (addr_family == AF_INET)
-        return act_stage3_ip4_config_start(device, (NMIP4Config **) out_config, out_failure_reason);
-
-    return NM_DEVICE_CLASS(nm_device_adsl_parent_class)
-        ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+    _ppp_mgr_stage3_maybe_ready(self);
 }
 
 static void
@@ -533,23 +546,15 @@ adsl_cleanup(NMDeviceAdsl *self)
 {
     NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
 
-    if (priv->ppp_manager) {
-        g_signal_handlers_disconnect_by_func(priv->ppp_manager,
-                                             G_CALLBACK(ppp_state_changed),
-                                             self);
-        g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ip4_config), self);
-        nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
-        g_clear_object(&priv->ppp_manager);
-    }
+    _ppp_mgr_cleanup(self);
 
     g_signal_handlers_disconnect_by_func(nm_device_get_platform(NM_DEVICE(self)),
                                          G_CALLBACK(link_changed_cb),
                                          self);
 
-    nm_close(priv->brfd);
-    priv->brfd = -1;
+    nm_clear_fd(&priv->brfd);
 
-    nm_clear_g_source(&priv->nas_update_id);
+    nm_clear_g_source_inst(&priv->nas_update_source);
 
     /* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet,
      * so it gets leaked.  It does get destroyed when it's no longer in use,
@@ -572,7 +577,7 @@ carrier_update_cb(gpointer user_data)
 {
     NMDeviceAdsl *self = NM_DEVICE_ADSL(user_data);
     int           carrier;
-    char *        path;
+    char         *path;
 
     path    = g_strdup_printf("/sys/class/atm/%s/carrier",
                            NM_ASSERT_VALID_PATH_COMPONENT(nm_device_get_iface(NM_DEVICE(self))));
@@ -627,7 +632,7 @@ nm_device_adsl_init(NMDeviceAdsl *self)
 static void
 constructed(GObject *object)
 {
-    NMDeviceAdsl *       self = NM_DEVICE_ADSL(object);
+    NMDeviceAdsl        *self = NM_DEVICE_ADSL(object);
     NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
 
     G_OBJECT_CLASS(nm_device_adsl_parent_class)->constructed(object);
@@ -681,9 +686,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_adsl = {
 static void
 nm_device_adsl_class_init(NMDeviceAdslClass *klass)
 {
-    GObjectClass *     object_class      = G_OBJECT_CLASS(klass);
+    GObjectClass      *object_class      = G_OBJECT_CLASS(klass);
     NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
-    NMDeviceClass *    device_class      = NM_DEVICE_CLASS(klass);
+    NMDeviceClass     *device_class      = NM_DEVICE_CLASS(klass);
 
     object_class->constructed  = constructed;
     object_class->dispose      = dispose;
@@ -699,9 +704,9 @@ nm_device_adsl_class_init(NMDeviceAdslClass *klass)
     device_class->check_connection_compatible = check_connection_compatible;
     device_class->complete_connection         = complete_connection;
 
-    device_class->act_stage2_config          = act_stage2_config;
-    device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
-    device_class->deactivate                 = deactivate;
+    device_class->act_stage2_config    = act_stage2_config;
+    device_class->act_stage3_ip_config = act_stage3_ip_config;
+    device_class->deactivate           = deactivate;
 
     obj_properties[PROP_ATM_INDEX] =
         g_param_spec_int(NM_DEVICE_ADSL_ATM_INDEX,