Re: Support for ADSL modems



On Thu, May 5, 2011 at 1:17 AM, Dan Williams <dcbw redhat com> wrote:
>> Great, I will try to push code somewhere soonish.
>
> I'm happy to review and suggest, thanks!

Hi, I 'm sending this email while connected through my Sagem FAST 800,
with networkmanager :) :)

Unfortunately I don't have enough time to clean up or polish the code, because
I will be away tomorrow and for the weekend, but I 'm attaching my current
"ducktape and gum" approach in case you manage to take a short look while
I am away.

With this patch, I 'm able to connect with NetworkManager, if I setup
the connection
via a keyfile.

Unfortunately the current code pretty much works only for me I think, but with a
little "massage" it might become generally usable.

Cheers,
Pantelis
 cli/src/connections.c                     |   66 +++-
 cli/src/devices.c                         |    4 +
 cli/src/settings.c                        |   50 +++
 cli/src/settings.h                        |    2 +
 docs/api/generate-settings-spec.c         |    2 +
 include/NetworkManager.h                  |   18 +-
 introspection/Makefile.am                 |    1 +
 introspection/nm-device-adsl.xml          |   21 +
 libnm-glib/Makefile.am                    |    6 +
 libnm-glib/libnm-glib.ver                 |    3 +
 libnm-glib/nm-device-adsl.c               |  236 ++++++++++++
 libnm-glib/nm-device-adsl.h               |   62 +++
 libnm-glib/nm-device.c                    |    4 +
 libnm-util/Makefile.am                    |    2 +
 libnm-util/libnm-util.ver                 |   19 +
 libnm-util/nm-connection.c                |   25 ++-
 libnm-util/nm-connection.h                |    2 +
 libnm-util/nm-setting-adsl.c              |  476 +++++++++++++++++++++++
 libnm-util/nm-setting-adsl.h              |   97 +++++
 libnm-util/tests/test-general.c           |   60 +++
 libnm-util/tests/test-settings-defaults.c |    2 +
 src/Makefile.am                           |    6 +
 src/nm-device-adsl.c                      |  596 +++++++++++++++++++++++++++++
 src/nm-device-adsl.h                      |   60 +++
 src/nm-netlink-monitor.c                  |    5 +
 src/nm-udev-manager.c                     |   48 +++-
 src/ppp-manager/nm-ppp-manager.c          |   31 ++-
 src/settings/nm-settings.c                |    2 +
 28 files changed, 1883 insertions(+), 23 deletions(-)

diff --git a/cli/src/connections.c b/cli/src/connections.c
index 2646aa9..5308f04 100644
--- a/cli/src/connections.c
+++ b/cli/src/connections.c
@@ -34,6 +34,7 @@
 #include <nm-client.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-pppoe.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-gsm.h>
@@ -44,6 +45,7 @@
 #include <nm-setting-wimax.h>
 #endif
 #include <nm-device-ethernet.h>
+#include <nm-device-adsl.h>
 #include <nm-device-wifi.h>
 #if WITH_WIMAX
 #include <nm-device-wimax.h>
@@ -104,12 +106,13 @@ static NmcOutputField nmc_fields_settings_names[] = {
 	SETTING_FIELD (NM_SETTING_SERIAL_SETTING_NAME, 0),                /* 7 */
 	SETTING_FIELD (NM_SETTING_PPP_SETTING_NAME, 0),                   /* 8 */
 	SETTING_FIELD (NM_SETTING_PPPOE_SETTING_NAME, 0),                 /* 9 */
-	SETTING_FIELD (NM_SETTING_GSM_SETTING_NAME, 0),                   /* 10 */
-	SETTING_FIELD (NM_SETTING_CDMA_SETTING_NAME, 0),                  /* 11 */
-	SETTING_FIELD (NM_SETTING_BLUETOOTH_SETTING_NAME, 0),             /* 12 */
-	SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME, 0),             /* 13 */
-	SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME, 0),                   /* 14 */
-	SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME, 0),                 /* 15 */
+	SETTING_FIELD (NM_SETTING_ADSL_SETTING_NAME, 0),                  /* 10 */
+	SETTING_FIELD (NM_SETTING_GSM_SETTING_NAME, 0),                   /* 11 */
+	SETTING_FIELD (NM_SETTING_CDMA_SETTING_NAME, 0),                  /* 12 */
+	SETTING_FIELD (NM_SETTING_BLUETOOTH_SETTING_NAME, 0),             /* 13 */
+	SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME, 0),             /* 14 */
+	SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME, 0),                   /* 15 */
+	SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME, 0),                 /* 16 */
 	{NULL, NULL, 0, NULL, 0}
 };
 #define NMC_FIELDS_SETTINGS_NAMES_ALL_X  NM_SETTING_CONNECTION_SETTING_NAME","\
@@ -122,6 +125,7 @@ static NmcOutputField nmc_fields_settings_names[] = {
                                          NM_SETTING_SERIAL_SETTING_NAME","\
                                          NM_SETTING_PPP_SETTING_NAME","\
                                          NM_SETTING_PPPOE_SETTING_NAME","\
+                                         NM_SETTING_ADSL_SETTING_NAME","\
                                          NM_SETTING_GSM_SETTING_NAME","\
                                          NM_SETTING_CDMA_SETTING_NAME","\
                                          NM_SETTING_BLUETOOTH_SETTING_NAME","\
@@ -331,6 +335,15 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 		}
 
 		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[10].name)) {
+			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+			if (setting) {
+				setting_adsl_details (setting, nmc);
+				was_output = TRUE;
+				continue;
+			}
+		}
+
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[11].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
 			if (setting) {
 				setting_gsm_details (setting, nmc);
@@ -339,7 +352,7 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 			}
 		}
 
-		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[11].name)) {
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[12].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
 			if (setting) {
 				setting_cdma_details (setting, nmc);
@@ -348,7 +361,7 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 			}
 		}
 
-		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[12].name)) {
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[13].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
 			if (setting) {
 				setting_bluetooth_details (setting, nmc);
@@ -357,7 +370,7 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 			}
 		}
 
-		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[13].name)) {
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[14].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH);
 			if (setting) {
 				setting_olpc_mesh_details (setting, nmc);
@@ -366,7 +379,7 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 			}
 		}
 
-		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[14].name)) {
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[15].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
 			if (setting) {
 				setting_vpn_details (setting, nmc);
@@ -376,7 +389,7 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc)
 		}
 
 #if WITH_WIMAX
-		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[15].name)) {
+		if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[16].name)) {
 			setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
 			if (setting) {
 				setting_wimax_details (setting, nmc);
@@ -968,6 +981,35 @@ check_modem_compatible (NMDeviceModem *device, NMConnection *connection, GError
 }
 
 static gboolean
+check_adsl_compatible (NMDeviceAdsl *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingAdsl *s_adsl;
+	const char *connection_type;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (connection_type, NM_SETTING_ADSL_SETTING_NAME)) {
+		g_set_error (error, 0, 0,
+		             "The connection was not an ADSL connection.");
+		return FALSE;
+	}
+
+	s_adsl = nm_connection_get_setting_adsl (connection);
+	if (!s_adsl) {
+		g_set_error (error, 0, 0,
+		             "The connection was not a valid ADSL connection.");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
 nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
@@ -987,6 +1029,8 @@ nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection,
 #endif
 	else if (NM_IS_DEVICE_MODEM (device))
 		return check_modem_compatible (NM_DEVICE_MODEM (device), connection, error);
+	else if (NM_IS_DEVICE_ADSL (device))
+		return check_adsl_compatible (NM_DEVICE_ADSL (device), connection, error);
 
 	g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device));
 	return FALSE;
diff --git a/cli/src/devices.c b/cli/src/devices.c
index c6228ba..7d55c43 100644
--- a/cli/src/devices.c
+++ b/cli/src/devices.c
@@ -34,6 +34,7 @@
 #include <nm-client.h>
 #include <nm-device.h>
 #include <nm-device-ethernet.h>
+#include <nm-device-adsl.h>
 #include <nm-device-wifi.h>
 #include <nm-device-modem.h>
 #include <nm-device-bt.h>
@@ -47,6 +48,7 @@
 #include <nm-vpn-connection.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-pppoe.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-gsm.h>
@@ -320,6 +322,8 @@ device_type_to_string (NMDevice *device)
 	switch (nm_device_get_device_type (device)) {
 	case NM_DEVICE_TYPE_ETHERNET:
 		return NM_SETTING_WIRED_SETTING_NAME;
+	case NM_DEVICE_TYPE_ADSL:
+		return NM_SETTING_ADSL_SETTING_NAME;
 	case NM_DEVICE_TYPE_WIFI:
 		return NM_SETTING_WIRELESS_SETTING_NAME;
 	case NM_DEVICE_TYPE_MODEM:
diff --git a/cli/src/settings.c b/cli/src/settings.c
index c238537..1283b5b 100644
--- a/cli/src/settings.c
+++ b/cli/src/settings.c
@@ -320,6 +320,26 @@ static NmcOutputField nmc_fields_setting_pppoe[] = {
                                          NM_SETTING_PPPOE_PASSWORD
 #define NMC_FIELDS_SETTING_PPPOE_COMMON  NMC_FIELDS_SETTING_PPP_ALL
 
+/* Available fields for NM_SETTING_ADSL_SETTING_NAME */
+static NmcOutputField nmc_fields_setting_adsl[] = {
+	SETTING_FIELD ("name", 10),                                /* 0 */
+	SETTING_FIELD (NM_SETTING_ADSL_USERNAME, 15),              /* 1 */
+	SETTING_FIELD (NM_SETTING_ADSL_PASSWORD, 15),              /* 2 */
+	SETTING_FIELD (NM_SETTING_ADSL_VPI, 10),                   /* 3 */
+	SETTING_FIELD (NM_SETTING_ADSL_VCI, 10),                   /* 4 */
+	SETTING_FIELD (NM_SETTING_ADSL_ENCAPSULATION, 10),         /* 5 */
+	SETTING_FIELD (NM_SETTING_ADSL_PROTOCOL, 10),              /* 6 */
+	{NULL, NULL, 0, NULL, 0}
+};
+#define NMC_FIELDS_SETTING_ADSL_ALL     "name"","\
+                                        NM_SETTING_ADSL_USERNAME","\
+                                        NM_SETTING_ADSL_PASSWORD","\
+                                        NM_SETTING_ADSL_VPI","\
+                                        NM_SETTING_ADSL_VCI","\
+                                        NM_SETTING_ADSL_ENCAPSULATION","\
+                                        NM_SETTING_ADSL_PROTOCOL
+#define NMC_FIELDS_SETTING_ADSL_COMMON  NMC_FIELDS_SETTING_ADSL_ALL
+
 /* Available fields for NM_SETTING_GSM_SETTING_NAME */
 static NmcOutputField nmc_fields_setting_gsm[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
@@ -1204,6 +1224,36 @@ setting_pppoe_details (NMSetting *setting, NmCli *nmc)
 }
 
 gboolean
+setting_adsl_details (NMSetting *setting, NmCli *nmc)
+{
+	NMSettingAdsl *s_adsl;
+	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
+	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
+	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), FALSE);
+	s_adsl = (NMSettingAdsl *) setting;
+
+	nmc->allowed_fields = nmc_fields_setting_adsl;
+	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_ADSL_ALL, nmc->allowed_fields, NULL);
+	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
+	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+
+	nmc->allowed_fields[0].value = NM_SETTING_ADSL_SETTING_NAME;
+	nmc->allowed_fields[1].value = nm_setting_adsl_get_username (s_adsl);
+	nmc->allowed_fields[2].value = nm_setting_adsl_get_password (s_adsl);
+	nmc->allowed_fields[3].value = g_strdup_printf ("%s", nm_setting_adsl_get_vpi (s_adsl));
+	nmc->allowed_fields[4].value = g_strdup_printf ("%s", nm_setting_adsl_get_vci (s_adsl));
+	nmc->allowed_fields[5].value = nm_setting_adsl_get_encapsulation (s_adsl);
+	nmc->allowed_fields[6].value = nm_setting_adsl_get_protocol (s_adsl);
+
+	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
+	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+
+	return TRUE;
+}
+
+gboolean
 setting_gsm_details (NMSetting *setting, NmCli *nmc)
 {
 	NMSettingGsm *s_gsm;
diff --git a/cli/src/settings.h b/cli/src/settings.h
index 4901bf2..61c9557 100644
--- a/cli/src/settings.h
+++ b/cli/src/settings.h
@@ -22,6 +22,7 @@
 
 #include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-8021x.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
@@ -51,6 +52,7 @@ gboolean setting_ip6_config_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_serial_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_ppp_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_pppoe_details (NMSetting *setting, NmCli *nmc);
+gboolean setting_adsl_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_gsm_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_cdma_details (NMSetting *setting, NmCli *nmc);
 gboolean setting_bluetooth_details (NMSetting *setting, NmCli *nmc);
diff --git a/docs/api/generate-settings-spec.c b/docs/api/generate-settings-spec.c
index 9c15314..4a0648e 100644
--- a/docs/api/generate-settings-spec.c
+++ b/docs/api/generate-settings-spec.c
@@ -40,6 +40,7 @@
 #include <nm-setting-olpc-mesh.h>
 #include <nm-setting-ppp.h>
 #include <nm-setting-pppoe.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-serial.h>
 #include <nm-setting-vpn.h>
 #include <nm-setting-wimax.h>
@@ -62,6 +63,7 @@ static SettingNewFunc funcs[] = {
 	nm_setting_olpc_mesh_new,
 	nm_setting_ppp_new,
 	nm_setting_pppoe_new,
+	nm_setting_adsl_new,
 	nm_setting_serial_new,
 	nm_setting_vpn_new,
 	nm_setting_wimax_new,
diff --git a/include/NetworkManager.h b/include/NetworkManager.h
index 17c3a11..2dc1db3 100644
--- a/include/NetworkManager.h
+++ b/include/NetworkManager.h
@@ -34,6 +34,7 @@
 #define	NM_DBUS_INTERFACE                   "org.freedesktop.NetworkManager"
 #define	NM_DBUS_INTERFACE_DEVICE            NM_DBUS_INTERFACE ".Device"
 #define NM_DBUS_INTERFACE_DEVICE_WIRED      NM_DBUS_INTERFACE_DEVICE ".Wired"
+#define NM_DBUS_INTERFACE_DEVICE_ADSL       NM_DBUS_INTERFACE_DEVICE ".Adsl"
 #define NM_DBUS_INTERFACE_DEVICE_WIRELESS   NM_DBUS_INTERFACE_DEVICE ".Wireless"
 #define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH  NM_DBUS_INTERFACE_DEVICE ".Bluetooth"
 #define NM_DBUS_PATH_ACCESS_POINT           NM_DBUS_PATH "/AccessPoint"
@@ -106,14 +107,15 @@ typedef enum {
  */
 typedef enum {
 	NM_DEVICE_TYPE_UNKNOWN   = 0,
-	NM_DEVICE_TYPE_ETHERNET  = 1,
-	NM_DEVICE_TYPE_WIFI      = 2,
-	NM_DEVICE_TYPE_UNUSED1   = 3,
-	NM_DEVICE_TYPE_UNUSED2   = 4,
-	NM_DEVICE_TYPE_BT        = 5,  /* Bluetooth */
-	NM_DEVICE_TYPE_OLPC_MESH = 6,
-	NM_DEVICE_TYPE_WIMAX     = 7,
-	NM_DEVICE_TYPE_MODEM     = 8,
+	NM_DEVICE_TYPE_ADSL      = 1,
+	NM_DEVICE_TYPE_ETHERNET  = 2,
+	NM_DEVICE_TYPE_WIFI      = 3,
+	NM_DEVICE_TYPE_UNUSED1   = 4,
+	NM_DEVICE_TYPE_UNUSED2   = 5,
+	NM_DEVICE_TYPE_BT        = 6,  /* Bluetooth */
+	NM_DEVICE_TYPE_OLPC_MESH = 7,
+	NM_DEVICE_TYPE_WIMAX     = 8,
+	NM_DEVICE_TYPE_MODEM     = 9,
 } NMDeviceType;
 
 /* General device capability flags */
diff --git a/introspection/Makefile.am b/introspection/Makefile.am
index 320245e..4950e7d 100644
--- a/introspection/Makefile.am
+++ b/introspection/Makefile.am
@@ -8,6 +8,7 @@ EXTRA_DIST = \
 	nm-device-wifi.xml \
 	nm-device-olpc-mesh.xml \
 	nm-device-ethernet.xml \
+	nm-device-adsl.xml \
 	nm-device-modem.xml \
 	nm-device-wimax.xml \
 	nm-device.xml \
diff --git a/introspection/nm-device-adsl.xml b/introspection/nm-device-adsl.xml
new file mode 100644
index 0000000..cf4e513
--- /dev/null
+++ b/introspection/nm-device-adsl.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0";>
+  <interface name="org.freedesktop.NetworkManager.Device.Adsl">
+
+    <property name="Carrier" type="b" access="read">
+      <tp:docstring>
+        Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not).
+      </tp:docstring>
+    </property>
+
+    <signal name="PropertiesChanged">
+        <arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
+            <tp:docstring>
+                A dictionary mapping property names to variant boxed values
+            </tp:docstring>
+        </arg>
+    </signal>
+
+  </interface>
+</node>
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index 08a61cc..5955564 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -10,6 +10,7 @@ BUILT_SOURCES = \
 	nm-client-bindings.h \
 	nm-device-bindings.h \
 	nm-device-ethernet-bindings.h \
+	nm-device-adsl-bindings.h \
 	nm-device-wifi-bindings.h \
 	nm-device-bt-bindings.h \
 	nm-settings-connection-bindings.h \
@@ -70,6 +71,7 @@ libnminclude_HEADERS = \
 	nm-client.h \
 	nm-device.h \
 	nm-device-ethernet.h \
+	nm-device-adsl.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
 	nm-access-point.h \
@@ -98,6 +100,7 @@ libnm_glib_la_csources = \
 	nm-dbus-utils.c \
 	nm-device.c \
 	nm-device-ethernet.c \
+	nm-device-adsl.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
 	nm-access-point.c \
@@ -189,6 +192,9 @@ nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
 nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
 
+nm-device-adsl-bindings.h: $(top_srcdir)/introspection/nm-device-adsl.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-client --output=$@ $<
+
 nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
 
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 64ff70a..3b17c66 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -65,6 +65,9 @@ global:
 	nm_device_ethernet_get_speed;
 	nm_device_ethernet_get_type;
 	nm_device_ethernet_new;
+	nm_device_adsl_get_carrier;
+	nm_device_adsl_get_type;
+	nm_device_adsl_new;
 	nm_device_filter_connections;
 	nm_device_get_capabilities;
 	nm_device_get_device_type;
diff --git a/libnm-glib/nm-device-adsl.c b/libnm-glib/nm-device-adsl.c
new file mode 100644
index 0000000..e0d5da5
--- /dev/null
+++ b/libnm-glib/nm-device-adsl.c
@@ -0,0 +1,236 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * author: Pantelis Koukousoulas <pktoss gmail com>
+ * Copyright 2009 - 2011 Red Hat, Inc.
+ */
+
+#include "nm-device-adsl.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+#include "nm-setting-adsl.h"
+
+#include <string.h>
+
+#include "nm-device-adsl-bindings.h"
+
+G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	gboolean carrier;
+
+	gboolean disposed;
+} NMDeviceAdslPrivate;
+
+enum {
+	PROP_0,
+	PROP_CARRIER,
+	LAST_PROP
+};
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_adsl_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceAdsl.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_adsl_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_DEVICE_ADSL,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+}
+
+/**
+ * nm_device_adsl_get_carrier:
+ * @device: a #NMDeviceAdsl
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_adsl_get_carrier (NMDeviceAdsl *device)
+{
+	NMDeviceAdslPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE_ADSL (device), FALSE);
+
+	priv = NM_DEVICE_ADSL_GET_PRIVATE (device);
+	priv->carrier = _nm_object_get_boolean_property (NM_OBJECT (device),
+		                                                NM_DBUS_INTERFACE_DEVICE_ADSL,
+		                                                DBUS_PROP_CARRIER,
+		                                                NULL);
+	return priv->carrier;
+}
+
+static gboolean
+connection_valid (NMDevice *device, NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+	NMSettingAdsl *s_adsl;
+	const char *ctype;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+
+	ctype = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (ctype, NM_SETTING_ADSL_SETTING_NAME) != 0)
+		return FALSE;
+
+	s_adsl = nm_connection_get_setting_adsl (connection);
+	if (!s_adsl)
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+nm_device_adsl_init (NMDeviceAdsl *device)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device);
+
+	priv->disposed = FALSE;
+	priv->carrier = FALSE;
+}
+
+static void
+register_for_property_changed (NMDeviceAdsl *device)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DEVICE_ADSL_CARRIER,              _nm_object_demarshal_generic, &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceAdslPrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type,
+																		n_construct_params,
+																		construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEVICE_ADSL_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+	                                         NM_DBUS_SERVICE,
+	                                         nm_object_get_path (NM_OBJECT (object)),
+	                                         NM_DBUS_INTERFACE_DEVICE_ADSL);
+
+	register_for_property_changed (NM_DEVICE_ADSL (object));
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceAdsl *device = NM_DEVICE_ADSL (object);
+
+	switch (prop_id) {
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_adsl_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_adsl_class_init (NMDeviceAdslClass *adsl_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (adsl_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (adsl_class);
+
+	g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	object_class->get_property = get_property;
+	device_class->connection_valid = connection_valid;
+
+	/* properties */
+	/**
+	 * NMDeviceAdsl:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER,
+					    "Carrier",
+					    "Carrier",
+					    FALSE,
+					    G_PARAM_READABLE));
+}
diff --git a/libnm-glib/nm-device-adsl.h b/libnm-glib/nm-device-adsl.h
new file mode 100644
index 0000000..73223cd
--- /dev/null
+++ b/libnm-glib/nm-device-adsl.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2011 Pantelis Koukousoulas <pktoss gmail com>
+ */
+
+#ifndef NM_DEVICE_ADSL_H
+#define NM_DEVICE_ADSL_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_ADSL            (nm_device_adsl_get_type ())
+#define NM_DEVICE_ADSL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl))
+#define NM_DEVICE_ADSL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+#define NM_IS_DEVICE_ADSL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL))
+#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_ADSL))
+#define NM_DEVICE_ADSL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+
+#define NM_DEVICE_ADSL_CARRIER "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceAdsl;
+
+typedef struct {
+	NMDeviceClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDeviceAdslClass;
+
+GType nm_device_adsl_get_type (void);
+
+GObject *nm_device_adsl_new (DBusGConnection *connection, const char *path);
+gboolean nm_device_adsl_get_carrier (NMDeviceAdsl *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_ADSL_H */
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 4167c9a..ac0da9d 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -27,6 +27,7 @@
 
 #include "NetworkManager.h"
 #include "nm-device-ethernet.h"
+#include "nm-device-adsl.h"
 #include "nm-device-wifi.h"
 #include "nm-device-modem.h"
 #include "nm-device-bt.h"
@@ -748,6 +749,9 @@ nm_device_new (DBusGConnection *connection, const char *path)
 	case NM_DEVICE_TYPE_ETHERNET:
 		dtype = NM_TYPE_DEVICE_ETHERNET;
 		break;
+	case NM_DEVICE_TYPE_ADSL:
+		dtype = NM_TYPE_DEVICE_ADSL;
+		break;
 	case NM_DEVICE_TYPE_WIFI:
 		dtype = NM_TYPE_DEVICE_WIFI;
 		break;
diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am
index 0a29e9c..9f452a4 100644
--- a/libnm-util/Makefile.am
+++ b/libnm-util/Makefile.am
@@ -14,6 +14,7 @@ libnm_util_include_HEADERS = 		\
 	nm-connection.h			\
 	nm-setting.h			\
 	nm-setting-8021x.h		\
+	nm-setting-adsl.h		\
 	nm-setting-bluetooth.h		\
 	nm-setting-connection.h		\
 	nm-setting-ip4-config.h		\
@@ -43,6 +44,7 @@ libnm_util_la_csources = \
 	nm-param-spec-specialized.c	\
 	nm-setting.c			\
 	nm-setting-8021x.c		\
+	nm-setting-adsl.c		\
 	nm-setting-bluetooth.c		\
 	nm-setting-connection.c		\
 	nm-setting-ip4-config.c		\
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index bb988bc..eb85e40 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -24,9 +24,11 @@ global:
 	nm_connection_get_setting_olpc_mesh;
 	nm_connection_get_setting_ppp;
 	nm_connection_get_setting_pppoe;
+	nm_connection_get_setting_pppoa;
 	nm_connection_get_setting_vpn;
 	nm_connection_get_setting_wimax;
 	nm_connection_get_setting_wired;
+	nm_connection_get_setting_adsl;
 	nm_connection_get_setting_wireless;
 	nm_connection_get_setting_wireless_security;
 	nm_connection_get_type;
@@ -146,6 +148,16 @@ global:
 	nm_setting_802_1x_set_phase2_client_cert;
 	nm_setting_802_1x_set_phase2_private_key;
 	nm_setting_802_1x_set_private_key;
+	nm_setting_adsl_error_get_type;
+	nm_setting_adsl_error_quark;
+	nm_setting_adsl_get_username;
+	nm_setting_adsl_get_password;
+	nm_setting_adsl_get_protocol;
+	nm_setting_adsl_get_encapsulation;
+	nm_setting_adsl_get_vpi;
+	nm_setting_adsl_get_vci;
+	nm_setting_adsl_get_type;
+	nm_setting_adsl_new;
 	nm_setting_bluetooth_error_get_type;
 	nm_setting_bluetooth_error_quark;
 	nm_setting_bluetooth_get_bdaddr;
@@ -292,6 +304,13 @@ global:
 	nm_setting_ppp_get_require_mppe_128;
 	nm_setting_ppp_get_type;
 	nm_setting_ppp_new;
+	nm_setting_pppoa_error_get_type;
+	nm_setting_pppoa_error_quark;
+	nm_setting_pppoa_get_password;
+	nm_setting_pppoa_get_password_flags;
+	nm_setting_pppoa_get_username;
+	nm_setting_pppoa_get_type;
+	nm_setting_pppoa_new;
 	nm_setting_pppoe_error_get_type;
 	nm_setting_pppoe_error_quark;
 	nm_setting_pppoe_get_password;
diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c
index cd9d53f..e2e5988 100644
--- a/libnm-util/nm-connection.c
+++ b/libnm-util/nm-connection.c
@@ -40,6 +40,7 @@
 #include "nm-setting-pppoe.h"
 #include "nm-setting-wimax.h"
 #include "nm-setting-wired.h"
+#include "nm-setting-adsl.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-vpn.h"
@@ -134,7 +135,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 static GHashTable *registered_settings = NULL;
 
-#define DEFAULT_MAP_SIZE 16
+#define DEFAULT_MAP_SIZE 17
 
 static struct SettingInfo {
 	const char *name;
@@ -261,6 +262,11 @@ register_default_settings (void)
 	                      NM_SETTING_PPPOE_ERROR,
 	                      3, TRUE);
 
+	register_one_setting (NM_SETTING_ADSL_SETTING_NAME,
+	                      NM_TYPE_SETTING_ADSL,
+	                      NM_SETTING_ADSL_ERROR,
+	                      3, TRUE);
+
 	register_one_setting (NM_SETTING_802_1X_SETTING_NAME,
 	                      NM_TYPE_SETTING_802_1X,
 	                      NM_SETTING_802_1X_ERROR,
@@ -1453,6 +1459,23 @@ nm_connection_get_setting_wired (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_adsl:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingAdsl the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingAdsl if the connection contains one, otherwise NULL
+ **/
+NMSettingAdsl *
+nm_connection_get_setting_adsl (NMConnection *connection)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+}
+
+/**
  * nm_connection_get_setting_wireless:
  * @connection: the #NMConnection
  *
diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h
index 87b053c..2e42265 100644
--- a/libnm-util/nm-connection.h
+++ b/libnm-util/nm-connection.h
@@ -43,6 +43,7 @@
 #include <nm-setting-vpn.h>
 #include <nm-setting-wimax.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
 
@@ -184,6 +185,7 @@ NMSettingPPP *             nm_connection_get_setting_ppp               (NMConnec
 NMSettingPPPOE *           nm_connection_get_setting_pppoe             (NMConnection *connection);
 NMSettingVPN *             nm_connection_get_setting_vpn               (NMConnection *connection);
 NMSettingWimax *           nm_connection_get_setting_wimax             (NMConnection *connection);
+NMSettingAdsl *            nm_connection_get_setting_adsl              (NMConnection *connection);
 NMSettingWired *           nm_connection_get_setting_wired             (NMConnection *connection);
 NMSettingWireless *        nm_connection_get_setting_wireless          (NMConnection *connection);
 NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security (NMConnection *connection);
diff --git a/libnm-util/nm-setting-adsl.c b/libnm-util/nm-setting-adsl.c
new file mode 100644
index 0000000..f0db252
--- /dev/null
+++ b/libnm-util/nm-setting-adsl.c
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw redhat com>
+ * Hicham HAOUARI <hicham haouari gmail com>
+ * Pantelis Koukousoulas <pktoss gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ */
+
+#include "nm-setting-adsl.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include <string.h>
+
+/**
+ * SECTION:nm-setting-adsl
+ * @short_description: Describes ADSL-based properties
+ * @include: nm-setting-adsl.h
+ *
+ * The #NMSettingAdsl object is a #NMSetting subclass that describes
+ * properties of ADSL connections.
+ */
+
+/**
+ * nm_setting_adsl_error_quark:
+ *
+ * Registers an error quark for #NMSettingAdsl if necessary.
+ *
+ * Returns: the error quark used for #NMSettingAdsl errors.
+ **/
+GQuark
+nm_setting_adsl_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-adsl-error-quark");
+	return quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+nm_setting_adsl_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			/* Unknown error. */
+			ENUM_ENTRY (NM_SETTING_ADSL_ERROR_UNKNOWN, "UnknownError"),
+			/* The specified property was invalid. */
+			ENUM_ENTRY (NM_SETTING_ADSL_ERROR_INVALID_PROPERTY, "InvalidProperty"),
+			/* The specified property was missing and is required. */
+			ENUM_ENTRY (NM_SETTING_ADSL_ERROR_MISSING_PROPERTY, "MissingProperty"),
+			{ 0, 0, 0 }
+		};
+		etype = g_enum_register_static ("NMSettingAdslError", values);
+	}
+	return etype;
+}
+
+G_DEFINE_TYPE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING)
+
+#define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate))
+
+typedef struct {
+	char *username;
+	char *password;
+	NMSettingSecretFlags password_flags;
+	char  *protocol;
+	char  *encapsulation;
+	char  *vpi;
+	char  *vci;
+} NMSettingAdslPrivate;
+
+enum {
+	PROP_0,
+	PROP_USERNAME,
+	PROP_PASSWORD,
+	PROP_PASSWORD_FLAGS,
+	PROP_PROTOCOL,
+	PROP_ENCAPSULATION,
+	PROP_VPI,
+	PROP_VCI,
+
+	LAST_PROP
+};
+
+/**
+ * nm_setting_adsl_new:
+ *
+ * Creates a new #NMSettingAdsl object with default values.
+ *
+ * Returns: the new empty #NMSettingAdsl object
+ **/
+NMSetting *
+nm_setting_adsl_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_ADSL, NULL);
+}
+
+/**
+ * nm_setting_adsl_get_username:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:username property of the setting
+ **/
+const char *
+nm_setting_adsl_get_username (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->username;
+}
+
+/**
+ * nm_setting_adsl_get_password:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:password property of the setting
+ **/
+const char *
+nm_setting_adsl_get_password (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_adsl_get_password_flags:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingAdsl:password
+ **/
+NMSettingSecretFlags
+nm_setting_adsl_get_password_flags (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->password_flags;
+}
+
+/**
+ * nm_setting_adsl_get_protocol:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:protocol property of the setting
+ **/
+const char *
+nm_setting_adsl_get_protocol (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->protocol;
+}
+
+/**
+ * nm_setting_adsl_get_encapsulation:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:encapsulation property of the setting
+ **/
+const char *
+nm_setting_adsl_get_encapsulation (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->encapsulation;
+}
+
+/**
+ * nm_setting_adsl_get_vpi:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:vpi property of the setting
+ **/
+const char *
+nm_setting_adsl_get_vpi (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->vpi;
+}
+
+/**
+ * nm_setting_adsl_get_vci:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:vci property of the setting
+ **/
+const char *
+nm_setting_adsl_get_vci (NMSettingAdsl *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+	return NM_SETTING_ADSL_GET_PRIVATE (setting)->vci;
+}
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+	NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (setting);
+
+	if (!priv->username) {
+		g_set_error (error,
+		             NM_SETTING_ADSL_ERROR,
+		             NM_SETTING_ADSL_ERROR_MISSING_PROPERTY,
+		             NM_SETTING_ADSL_USERNAME);
+		return FALSE;
+	} else if (!strlen (priv->username)) {
+		g_set_error (error,
+		             NM_SETTING_ADSL_ERROR,
+		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+		             NM_SETTING_ADSL_USERNAME);
+		return FALSE;
+	}
+
+	/* FIXME: Only PPPoA supported for now */
+	if (g_ascii_strcasecmp(priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
+		g_set_error (error,
+		             NM_SETTING_ADSL_ERROR,
+		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+		             NM_SETTING_ADSL_PROTOCOL);
+		return FALSE;
+	}
+
+	if (!g_ascii_strcasecmp(priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_VCMUX) &&
+	    !g_ascii_strcasecmp(priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_LLC) ) {
+		g_set_error (error,
+		             NM_SETTING_ADSL_ERROR,
+		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+		             NM_SETTING_ADSL_ENCAPSULATION);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+	NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (setting);
+	GPtrArray *secrets = NULL;
+
+	if (priv->password)
+		return NULL;
+
+	if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+		secrets = g_ptr_array_sized_new (1);
+		g_ptr_array_add (secrets, NM_SETTING_ADSL_PASSWORD);
+	}
+
+	return secrets;
+}
+
+static void
+nm_setting_adsl_init (NMSettingAdsl *setting)
+{
+	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_ADSL_SETTING_NAME, NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (object);
+
+	g_free (priv->username);
+	g_free (priv->password);
+	g_free (priv->protocol);
+	g_free (priv->encapsulation);
+
+	G_OBJECT_CLASS (nm_setting_adsl_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+		    const GValue *value, GParamSpec *pspec)
+{
+	NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_USERNAME:
+		g_free (priv->username);
+		priv->username = g_value_dup_string (value);
+		break;
+	case PROP_PASSWORD:
+		g_free (priv->password);
+		priv->password = g_value_dup_string (value);
+		break;
+	case PROP_PASSWORD_FLAGS:
+		priv->password_flags = g_value_get_uint (value);
+		break;
+	case PROP_PROTOCOL:
+		g_free (priv->protocol);
+		priv->protocol = g_value_dup_string (value);
+		break;
+	case PROP_ENCAPSULATION:
+		g_free (priv->encapsulation);
+		priv->encapsulation = g_value_dup_string (value);
+		break;
+	case PROP_VPI:
+
+		priv->vpi = g_value_dup_string (value);
+		break;
+	case PROP_VCI:
+		priv->vci = g_value_dup_string (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+		    GValue *value, GParamSpec *pspec)
+{
+	NMSettingAdsl *setting = NM_SETTING_ADSL (object);
+
+	switch (prop_id) {
+	case PROP_USERNAME:
+		g_value_set_string (value, nm_setting_adsl_get_username (setting));
+		break;
+	case PROP_PASSWORD:
+		g_value_set_string (value, nm_setting_adsl_get_password (setting));
+		break;
+	case PROP_PASSWORD_FLAGS:
+		g_value_set_uint (value, nm_setting_adsl_get_password_flags (setting));
+		break;
+	case PROP_PROTOCOL:
+		g_value_set_string (value, nm_setting_adsl_get_protocol (setting));
+		break;
+	case PROP_ENCAPSULATION:
+		g_value_set_string (value, nm_setting_adsl_get_encapsulation (setting));
+		break;
+	case PROP_VPI:
+		g_value_set_string (value, nm_setting_adsl_get_vpi (setting));
+		break;
+	case PROP_VCI:
+		g_value_set_string (value, nm_setting_adsl_get_vci (setting));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	g_type_class_add_private (setting_class, sizeof (NMSettingAdslPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->need_secrets = need_secrets;
+
+	/* Properties */
+
+	/**
+	 * NMSettingAdsl:username:
+	 *
+	 * Username used to authenticate with the ADSL service.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_USERNAME,
+		 g_param_spec_string (NM_SETTING_ADSL_USERNAME,
+						  "Username",
+						  "Username used to authenticate with the PPPoA service.",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingADSL:password:
+	 *
+	 * Password used to authenticate with the ADSL service.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PASSWORD,
+		 g_param_spec_string (NM_SETTING_ADSL_PASSWORD,
+						  "Password",
+						  "Password used to authenticate with the PPPoA service.",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+
+	/**
+	 * NMSettingAdsl:password-flags:
+	 *
+	 * Flags indicating how to handle #NMSettingAdsl:password:.
+	 **/
+	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
+		 g_param_spec_uint (NM_SETTING_ADSL_PASSWORD_FLAGS,
+		                    "Password Flags",
+		                    "Flags indicating how to handle the ADSL password.",
+		                    NM_SETTING_SECRET_FLAG_NONE,
+		                    NM_SETTING_SECRET_FLAGS_ALL,
+		                    NM_SETTING_SECRET_FLAG_NONE,
+		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingAdsl:protocol:
+	 *
+	 * ADSL connection protocol, can be PPPoA, PPPoE, or IPoATM.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PROTOCOL,
+		 g_param_spec_string (NM_SETTING_ADSL_PROTOCOL,
+						  "Protocol",
+						  "ADSL connection protocol.",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingAdsl:encapsulation:
+	 *
+	 * ADSL connection encapsulation, can be VCMux or LLC.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ENCAPSULATION,
+		 g_param_spec_string (NM_SETTING_ADSL_ENCAPSULATION,
+						  "Encapsulation",
+						  "Encapsulation of ADSL connection",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingAdsl:vpi:
+	 *
+	 * ADSL connection vpi.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_VPI,
+		 g_param_spec_string (NM_SETTING_ADSL_VPI,
+						  "VPI",
+						  "VPI of ADSL connection",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingAdsl:vci:
+	 *
+	 * ADSL connection vci.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_VCI,
+		 g_param_spec_string (NM_SETTING_ADSL_VCI,
+						  "VCI",
+						  "VCI of ADSL connection",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+}
diff --git a/libnm-util/nm-setting-adsl.h b/libnm-util/nm-setting-adsl.h
new file mode 100644
index 0000000..fd7408b
--- /dev/null
+++ b/libnm-util/nm-setting-adsl.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw redhat com>
+ * Hicham HAOUARI <hicham haouari gmail com>
+ * Pantelis Koukousoulas <pantelis gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTING_ADSL_H
+#define NM_SETTING_ADSL_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_ADSL            (nm_setting_adsl_get_type ())
+#define NM_SETTING_ADSL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_ADSL, NMSettingAdsl))
+#define NM_SETTING_ADSL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_ADSL, NMSettingAdslClass))
+#define NM_IS_SETTING_ADSL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_ADSL))
+#define NM_IS_SETTING_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_ADSL))
+#define NM_SETTING_ADSL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_ADSL, NMSettingAdslClass))
+
+#define NM_SETTING_ADSL_SETTING_NAME "adsl"
+
+typedef enum
+{
+	NM_SETTING_ADSL_ERROR_UNKNOWN = 0,
+	NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+	NM_SETTING_ADSL_ERROR_MISSING_PROPERTY
+} NMSettingAdslError;
+
+#define NM_TYPE_SETTING_ADSL_ERROR (nm_setting_adsl_error_get_type ()) 
+GType nm_setting_adsl_error_get_type (void);
+
+#define NM_SETTING_ADSL_ERROR nm_setting_adsl_error_quark ()
+GQuark nm_setting_adsl_error_quark (void);
+
+#define NM_SETTING_ADSL_USERNAME            "username"
+#define NM_SETTING_ADSL_PASSWORD            "password"
+#define NM_SETTING_ADSL_PASSWORD_FLAGS      "password-flags"
+#define NM_SETTING_ADSL_PROTOCOL            "protocol"
+#define NM_SETTING_ADSL_ENCAPSULATION       "encapsulation"
+#define NM_SETTING_ADSL_VPI                 "vpi"
+#define NM_SETTING_ADSL_VCI                 "vci"
+
+
+#define NM_SETTING_ADSL_PROTOCOL_PPPOA      "pppoa"
+#define NM_SETTING_ADSL_PROTOCOL_PPPOE      "pppoe"
+#define NM_SETTING_ADSL_PROTOCOL_IPOATM     "ipoatm"
+#define NM_SETTING_ADSL_ENCAPSULATION_VCMUX "vcmux"
+#define NM_SETTING_ADSL_ENCAPSULATION_LLC   "llc"
+
+typedef struct {
+	NMSetting parent;
+} NMSettingAdsl;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingAdslClass;
+
+GType nm_setting_adsl_get_type (void);
+
+NMSetting  *nm_setting_adsl_new               (void);
+const char *nm_setting_adsl_get_username      (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_password      (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_protocol      (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_encapsulation (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_vpi           (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_vci           (NMSettingAdsl *setting);
+NMSettingSecretFlags nm_setting_adsl_get_password_flags (NMSettingAdsl *setting);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_ADSL_H */
diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c
index 1ce8062..57a1876 100644
--- a/libnm-util/tests/test-general.c
+++ b/libnm-util/tests/test-general.c
@@ -903,6 +903,53 @@ test_connection_diff_no_secrets (void)
 }
 
 static void
+test_connection_diff_no_secrets_adsl (void)
+{
+	NMConnection *a, *b;
+	GHashTable *out_diffs = NULL;
+	NMSetting *s_adsl;
+	gboolean same;
+	const DiffSetting settings[] = {
+		{ NM_SETTING_ADSL_SETTING_NAME, {
+			{ NM_SETTING_ADSL_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B },
+			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+		} },
+	};
+
+	a = new_test_connection ();
+	s_adsl = nm_setting_adsl_new ();
+	g_object_set (G_OBJECT (s_adsl),
+	              NM_SETTING_ADSL_USERNAME, "thomas",
+	              NULL);
+	nm_connection_add_setting (a, s_adsl);
+
+	b = nm_connection_duplicate (a);
+
+	/* Add a secret to B */
+	s_adsl = nm_connection_get_setting (b, NM_TYPE_SETTING_ADSL);
+	g_assert (s_adsl);
+	g_object_set (G_OBJECT (s_adsl),
+	              NM_SETTING_ADSL_PASSWORD, "secretpassword",
+	              NULL);
+
+	/* Make sure the diff returns no results as secrets are ignored */
+	same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs);
+	g_assert (same == TRUE);
+	g_assert (out_diffs == NULL);
+
+	/* Now make sure the diff returns results if secrets are not ignored */
+	same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
+	g_assert (same == FALSE);
+	g_assert (out_diffs != NULL);
+	g_assert (g_hash_table_size (out_diffs) > 0);
+
+	ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+	g_object_unref (a);
+	g_object_unref (b);
+}
+
+static void
 add_generic_settings (NMConnection *connection, const char *ctype)
 {
 	NMSetting *setting;
@@ -962,6 +1009,18 @@ test_connection_good_base_types (void)
 	g_assert (success);
 	g_object_unref (connection);
 
+	/* Try an ADSL PPPoA connection */
+	connection = nm_connection_new ();
+	add_generic_settings (connection, NM_SETTING_ADSL_SETTING_NAME);
+	setting = nm_setting_adsl_new ();
+	g_object_set (setting, NM_SETTING_ADSL_USERNAME, "bob smith", NULL);
+	nm_connection_add_setting (connection, setting);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_object_unref (connection);
+
 	/* Wifi connection */
 	connection = nm_connection_new ();
 	add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
@@ -1145,6 +1204,7 @@ int main (int argc, char **argv)
 	test_connection_diff_same ();
 	test_connection_diff_different ();
 	test_connection_diff_no_secrets ();
+	test_connection_diff_no_secrets_adsl ();
 	test_connection_good_base_types ();
 	test_connection_bad_base_types ();
 
diff --git a/libnm-util/tests/test-settings-defaults.c b/libnm-util/tests/test-settings-defaults.c
index 9f38a14..f753549 100644
--- a/libnm-util/tests/test-settings-defaults.c
+++ b/libnm-util/tests/test-settings-defaults.c
@@ -34,6 +34,7 @@
 #include "nm-setting-ip6-config.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-pppoe.h"
+#include "nm-setting-adsl.h"
 #include "nm-setting-serial.h"
 #include "nm-setting-vpn.h"
 #include "nm-setting-wired.h"
@@ -120,6 +121,7 @@ int main (int argc, char **argv)
 	test_defaults (NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	test_defaults (NM_TYPE_SETTING_IP6_CONFIG, NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	test_defaults (NM_TYPE_SETTING_PPP, NM_SETTING_PPP_SETTING_NAME);
+	test_defaults (NM_TYPE_SETTING_ADSL, NM_SETTING_ADSL_SETTING_NAME);
 	test_defaults (NM_TYPE_SETTING_PPPOE, NM_SETTING_PPPOE_SETTING_NAME);
 	test_defaults (NM_TYPE_SETTING_SERIAL, NM_SETTING_SERIAL_SETTING_NAME);
 	test_defaults (NM_TYPE_SETTING_VPN, NM_SETTING_VPN_SETTING_NAME);
diff --git a/src/Makefile.am b/src/Makefile.am
index 94e1a8c..50b52d6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,8 @@ NetworkManager_SOURCES = \
 		nm-device-private.h \
 		nm-device-ethernet.c \
 		nm-device-ethernet.h \
+		nm-device-adsl.c \
+		nm-device-adsl.h \
 		nm-device-wifi.c \
 		nm-device-wifi.h \
 		nm-device-olpc-mesh.c	\
@@ -185,6 +187,9 @@ nm-device-interface-glue.h: $(top_srcdir)/introspection/nm-device.xml
 nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-server --output=$@ $<
 
+nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $<
+
 nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $<
 
@@ -217,6 +222,7 @@ BUILT_SOURCES = \
 	nm-manager-glue.h \
 	nm-device-interface-glue.h \
 	nm-device-ethernet-glue.h \
+	nm-device-adsl-glue.h \
 	nm-device-wifi-glue.h \
 	nm-device-olpc-mesh-glue.h \
 	nm-device-bt-glue.h \
diff --git a/src/nm-device-adsl.c b/src/nm-device-adsl.c
new file mode 100644
index 0000000..77e4d0a
--- /dev/null
+++ b/src/nm-device-adsl.c
@@ -0,0 +1,596 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Pantelis Koukousoulas <pktoss gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nm-glib-compat.h"
+#include "nm-device-adsl.h"
+#include "nm-device-interface.h"
+#include "nm-device-private.h"
+#include "nm-properties-changed-signal.h"
+#include "nm-glib-compat.h"
+#include "NetworkManagerUtils.h"
+#include "nm-logging.h"
+
+#include "ppp-manager/nm-ppp-manager.h"
+#include "nm-setting-adsl.h"
+
+#include "nm-device-adsl-glue.h"
+
+G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate))
+
+typedef enum
+{
+	NM_ADSL_ERROR_CONNECTION_NOT_ADSL = 0,
+	NM_ADSL_ERROR_CONNECTION_INVALID,
+	NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE,
+} NMAdslError;
+
+#define NM_ADSL_ERROR (nm_adsl_error_quark ())
+#define NM_TYPE_ADSL_ERROR (nm_adsl_error_get_type ())
+
+static GQuark
+nm_adsl_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("nm-ethernet-error");
+	return quark;
+}
+
+typedef struct {
+	gboolean            disposed;
+	gboolean            carrier;
+	guint               carrier_poll_id;
+
+	/* PPP */
+	NMPPPManager *ppp_manager;
+	NMIP4Config  *pending_ip4_config;
+} NMDeviceAdslPrivate;
+
+enum {
+	PROPERTIES_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+/* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around.
+   It's here now to keep the patch short. */
+static NMSetting *
+device_get_setting (NMDevice *device, GType setting_type)
+{
+	NMActRequest *req;
+	NMSetting *setting = NULL;
+
+	req = nm_device_get_act_request (device);
+	if (req) {
+		NMConnection *connection;
+
+		connection = nm_act_request_get_connection (req);
+		if (connection)
+			setting = nm_connection_get_setting (connection, setting_type);
+	}
+
+	return setting;
+}
+
+static void
+set_carrier(NMDeviceAdsl *self, const gboolean carrier)
+{
+	NMDeviceAdslPrivate *priv;
+	NMDeviceState state;
+
+	g_return_if_fail (NM_IS_DEVICE (self));
+
+	priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+
+	if (priv->carrier == carrier)
+		return;
+
+	priv->carrier = carrier;
+	g_object_notify (G_OBJECT (self), NM_DEVICE_ADSL_CARRIER);
+
+	state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
+	nm_log_info (LOGD_HW, "(%s): carrier now %s (device state %d)",
+	             nm_device_get_iface (NM_DEVICE (self)),
+	             carrier ? "ON" : "OFF",
+	             state);
+
+	if (state == NM_DEVICE_STATE_UNAVAILABLE) {
+		if (priv->carrier)
+			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
+	} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
+		if (!priv->carrier)
+			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
+	}
+}
+
+static gboolean
+carrier_update_cb (gpointer user_data)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data);
+
+	gchar *contents = NULL;
+	GError *error = NULL;
+	gboolean carrier = FALSE;
+	const gchar *path, *iface;
+
+	iface = nm_device_get_iface (NM_DEVICE (self));
+	path  = g_strdup_printf("/sys/class/atm/%s/carrier", iface);
+
+	if (!g_file_get_contents(path, &contents, NULL, &error)) {
+		nm_log_dbg (LOGD_DEVICE, "error reading %s: (%d) %s",
+		            path,
+		            error ? error->code : -1,
+		            error && error->message ? error->message : "(unknown)");
+		g_clear_error (&error);
+		return TRUE;
+	}
+
+	carrier = (gboolean) atoi(contents);
+	set_carrier(self, carrier);
+
+	return TRUE;
+}
+
+
+NMDevice *
+nm_device_adsl_new (const char *udi,
+                    const char *iface,
+                    const char *driver)
+{
+	g_return_val_if_fail (udi != NULL, NULL);
+
+	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ADSL,
+	                                  NM_DEVICE_INTERFACE_UDI, udi,
+	                                  NM_DEVICE_INTERFACE_IFACE, iface,
+	                                  NM_DEVICE_INTERFACE_DRIVER, driver,
+	                                  NM_DEVICE_INTERFACE_TYPE_DESC, "ADSL",
+	                                  NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_ADSL,
+	                                  NULL);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceAdslPrivate *priv;
+	NMDevice *self;
+
+	object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type,
+	                                                                    n_construct_params,
+	                                                                    construct_params);
+	if (!object)
+		return NULL;
+
+	self = NM_DEVICE (object);
+	priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+
+	priv->carrier = FALSE;
+	priv->carrier_poll_id = g_timeout_add_seconds(5, carrier_update_cb, self);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (object);
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	if (priv->carrier_poll_id) {
+		g_source_remove(priv->carrier_poll_id);
+		priv->carrier_poll_id = 0;
+	}
+
+
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (object);
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+
+	switch (prop_id) {
+	case PROP_CARRIER:
+		g_value_set_boolean (value, priv->carrier);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_adsl_init (NMDeviceAdsl * self)
+{
+}
+
+
+static guint32
+real_get_generic_capabilities (NMDevice *dev)
+{
+	guint32 caps = NM_DEVICE_CAP_NM_SUPPORTED;
+	caps |= NM_DEVICE_CAP_CARRIER_DETECT;
+	return caps;
+}
+
+static gboolean
+real_can_interrupt_activation (NMDevice *dev)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (dev);
+	gboolean interrupt = FALSE;
+
+	/* Devices that support carrier detect can interrupt activation
+	 * if the link becomes inactive.
+	 */
+	if (NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier == FALSE)
+		interrupt = TRUE;
+
+	return interrupt;
+}
+
+static gboolean
+real_is_available (NMDevice *dev)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (dev);
+
+	/* Can't do anything if there isn't a carrier */
+	if (!NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+real_check_connection_compatible (NMDevice *device,
+                                  NMConnection *connection,
+                                  GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingAdsl *s_adsl;
+	const char *connection_type;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (connection_type, NM_SETTING_ADSL_SETTING_NAME)) {
+		g_set_error (error,
+		             NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_NOT_ADSL,
+		             "The connection was not an ADSL connection.");
+		return FALSE;
+	}
+
+	s_adsl = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+	/* Wired setting is optional for PPPoE */
+	if (!s_adsl) {
+		g_set_error (error,
+		             NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_INVALID,
+		             "The connection was not a valid ADSL connection.");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+real_complete_connection (NMDevice *device,
+                          NMConnection *connection,
+                          const char *specific_object,
+                          const GSList *existing_connections,
+                          GError **error)
+{
+	NMSettingAdsl *s_adsl;
+
+	s_adsl = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+
+	/*
+	 * We can't telepathically figure out the username, so if
+	 * it wasn't given, we can't complete the connection.
+	 */
+	if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error))
+		return FALSE;
+
+	nm_utils_complete_generic (connection,
+	                           NM_SETTING_ADSL_SETTING_NAME,
+	                           existing_connections,
+	                           _("ADSL connection %d"),
+	                           NULL,
+	                           FALSE); /* No IPv6 yet by default */
+
+
+	return TRUE;
+}
+
+static void
+real_deactivate (NMDevice *device)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+
+	if (priv->pending_ip4_config) {
+		g_object_unref (priv->pending_ip4_config);
+		priv->pending_ip4_config = NULL;
+	}
+
+	if (priv->ppp_manager) {
+		g_object_unref (priv->ppp_manager);
+		priv->ppp_manager = NULL;
+	}
+}
+
+static NMConnection *
+real_get_best_auto_connection (NMDevice *dev,
+                               GSList *connections,
+                               char **specific_object)
+{
+	GSList *iter;
+
+	for (iter = connections; iter; iter = g_slist_next (iter)) {
+		NMConnection *connection = NM_CONNECTION (iter->data);
+		NMSettingConnection *s_con;
+		NMSettingAdsl *s_adsl;
+		const char *connection_type;
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+		g_assert (s_con);
+
+		connection_type = nm_setting_connection_get_connection_type (s_con);
+		if (strcmp (connection_type, NM_SETTING_ADSL_SETTING_NAME))
+			continue;
+
+		s_adsl = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+		if (!s_adsl)
+			continue;
+
+		if (!nm_setting_connection_get_autoconnect (s_con))
+			continue;
+
+		return connection;
+	}
+	return NULL;
+}
+
+static NMActStageReturn
+real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
+{
+	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (dev);
+	NMActRequest *req;
+	NMSettingAdsl *s_adsl;
+
+	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+	req = nm_device_get_act_request (NM_DEVICE (self));
+	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+	s_adsl = NM_SETTING_ADSL (device_get_setting (dev, NM_TYPE_SETTING_ADSL));
+	g_assert (s_adsl);
+
+	return ret;
+}
+
+static NMActStageReturn
+real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
+{
+	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
+	return ret;
+}
+
+static void
+ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+{
+	NMDevice *device = NM_DEVICE (user_data);
+
+	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;
+	}
+}
+
+static void
+ppp_ip4_config (NMPPPManager *ppp_manager,
+			 const char *iface,
+			 NMIP4Config *config,
+			 gpointer user_data)
+{
+	NMDevice *device = NM_DEVICE (user_data);
+
+	/* Ignore PPP IP4 events that come in after initial configuration */
+	if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG)
+		return;
+
+	nm_device_set_ip_iface (device, iface);
+	NM_DEVICE_ADSL_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
+	nm_device_activate_schedule_stage4_ip4_config_get (device);
+}
+
+static NMActStageReturn
+pppoa_stage3_ip4_config_start (NMDeviceAdsl *self, NMDeviceStateReason *reason)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+	NMConnection *connection;
+	NMSettingAdsl *s_adsl;
+	NMActRequest *req;
+	GError *err = NULL;
+	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
+
+	req = nm_device_get_act_request (NM_DEVICE (self));
+	g_assert (req);
+
+	connection = nm_act_request_get_connection (req);
+	g_assert (req);
+
+	s_adsl = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+	g_assert (s_adsl);
+
+	priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self)));
+	if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) {
+		g_signal_connect (priv->ppp_manager, "state-changed",
+					   G_CALLBACK (ppp_state_changed),
+					   self);
+		g_signal_connect (priv->ppp_manager, "ip4-config",
+					   G_CALLBACK (ppp_ip4_config),
+					   self);
+		ret = NM_ACT_STAGE_RETURN_POSTPONE;
+	} else {
+		nm_log_warn (LOGD_DEVICE, "(%s): ADSL(PPPoA) failed to start: %s",
+		             nm_device_get_iface (NM_DEVICE (self)), err->message);
+		g_error_free (err);
+
+		g_object_unref (priv->ppp_manager);
+		priv->ppp_manager = NULL;
+
+		*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+	}
+
+	return ret;
+}
+
+static NMActStageReturn
+real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+{
+	NMSettingConnection *s_con;
+	const char *connection_type;
+
+	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+	s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+
+	return pppoa_stage3_ip4_config_start (NM_DEVICE_ADSL (device), reason);
+}
+
+static NMActStageReturn
+real_act_stage4_get_ip4_config (NMDevice *device,
+                                NMIP4Config **config,
+                                NMDeviceStateReason *reason)
+{
+	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
+	NMConnection *connection;
+	NMSettingIP4Config *s_ip4;
+
+	g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+	g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
+	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+	/* PPP */
+	*config = priv->pending_ip4_config;
+	priv->pending_ip4_config = NULL;
+
+	/* Merge user-defined overrides into the IP4Config to be applied */
+	connection = nm_act_request_get_connection (nm_device_get_act_request (device));
+	g_assert (connection);
+	s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+	nm_utils_merge_ip4_config (*config, s_ip4);
+
+	return NM_ACT_STAGE_RETURN_SUCCESS;
+}
+
+static void
+nm_device_adsl_class_init (NMDeviceAdslClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate));
+
+	object_class->constructor  = constructor;
+	object_class->dispose      = dispose;
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+
+	parent_class->get_generic_capabilities = real_get_generic_capabilities;
+	parent_class->can_interrupt_activation = real_can_interrupt_activation;
+	parent_class->is_available = real_is_available;
+
+	parent_class->check_connection_compatible = real_check_connection_compatible;
+	parent_class->get_best_auto_connection = real_get_best_auto_connection;
+	parent_class->complete_connection = real_complete_connection;
+
+	parent_class->act_stage1_prepare = real_act_stage1_prepare;
+	parent_class->act_stage2_config = real_act_stage2_config;
+	parent_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
+	parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
+	parent_class->deactivate = real_deactivate;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER,
+							   "Carrier",
+							   "Carrier",
+							   FALSE,
+							   G_PARAM_READABLE));
+
+	/* Signals */
+	signals[PROPERTIES_CHANGED] =
+		nm_properties_changed_signal_new (object_class,
+		                                  G_STRUCT_OFFSET (NMDeviceAdslClass, properties_changed));
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+	                                 &dbus_glib_nm_device_adsl_object_info);
+}
diff --git a/src/nm-device-adsl.h b/src/nm-device-adsl.h
new file mode 100644
index 0000000..fe51a6a
--- /dev/null
+++ b/src/nm-device-adsl.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Pantelis Koukousoulas <pktoss gmail com>
+ * Copyright (C) 2009 - 2011 Red Hat Inc.
+ */
+
+#ifndef NM_DEVICE_ADSL_H
+#define NM_DEVICE_ADSL_H
+
+#include <glib-object.h>
+
+// Parent class
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_ADSL		(nm_device_adsl_get_type ())
+#define NM_DEVICE_ADSL(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl))
+#define NM_DEVICE_ADSL_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+#define NM_IS_DEVICE_ADSL(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL))
+#define NM_IS_DEVICE_ADSL_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_ADSL))
+#define NM_DEVICE_ADSL_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+
+#define NM_DEVICE_ADSL_CARRIER "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceAdsl;
+
+typedef struct {
+	NMDeviceClass parent;
+
+	/* Signals */
+	void (*properties_changed) (NMDeviceAdsl *device, GHashTable *properties);
+} NMDeviceAdslClass;
+
+GType nm_device_adsl_get_type (void);
+
+NMDevice *nm_device_adsl_new (const char *udi,
+                              const char *iface,
+                              const char *driver);
+
+G_END_DECLS
+
+#endif	/* NM_DEVICE_ADSL_H */
diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c
index 13b3ab9..2d2f734 100644
--- a/src/nm-netlink-monitor.c
+++ b/src/nm-netlink-monitor.c
@@ -700,6 +700,11 @@ nm_netlink_iface_to_index (const char *iface)
 
 	g_return_val_if_fail (iface != NULL, -1);
 
+	//FIXME: Gross hack for now, otherwise
+	//NM refuses to activate our device
+	if (!strcmp(iface,"ueagle-atm0")) 
+		return 0;
+
 	self = nm_netlink_monitor_get ();
 	priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
 
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c
index 41a4e15..c222068 100644
--- a/src/nm-udev-manager.c
+++ b/src/nm-udev-manager.c
@@ -38,6 +38,7 @@
 #include "nm-device-wifi.h"
 #include "nm-device-olpc-mesh.h"
 #include "nm-device-ethernet.h"
+#include "nm-device-adsl.h"
 #if WITH_WIMAX
 #include "nm-device-wimax.h"
 #endif
@@ -413,6 +414,13 @@ is_wimax (const char *driver)
 	return g_strcmp0 (driver, "i2400m_usb") == 0;
 }
 
+static gboolean
+is_atm (GUdevDevice *device)
+{
+	const gchar *subsys = g_udev_device_get_subsystem(device);
+	return (!strcmp (subsys,"atm"));
+}
+
 static GObject *
 device_creator (NMUdevManager *manager,
                 GUdevDevice *udev_device,
@@ -459,6 +467,12 @@ device_creator (NMUdevManager *manager,
 		}
 	}
 
+	// If the device is atm it doesn't have an interface index
+	if (is_atm (udev_device)) {
+		device = (GObject *) nm_device_adsl_new (path, ifname, driver);
+		goto out;
+	}
+
 	ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex");
 	if (ifindex <= 0) {
 		nm_log_warn (LOGD_HW, "%s: device had invalid ifindex %d; ignoring...", path, (guint32) ifindex);
@@ -541,11 +555,29 @@ net_add (NMUdevManager *self, GUdevDevice *device)
 }
 
 static void
+adsl_add (NMUdevManager *self, GUdevDevice *device)
+{
+	g_return_if_fail (device != NULL);
+
+	nm_log_dbg (LOGD_HW, "adsl_add: ATM Device detected from udev. Adding ..");
+
+	g_signal_emit (self, signals[DEVICE_ADDED], 0, device, device_creator);
+}
+
+static void
 net_remove (NMUdevManager *self, GUdevDevice *device)
 {
 	g_signal_emit (self, signals[DEVICE_REMOVED], 0, device);
 }
 
+static void
+adsl_remove (NMUdevManager *self, GUdevDevice *device)
+{
+	nm_log_dbg (LOGD_HW, "adsl_remove: Removing ATM Device");
+
+	g_signal_emit (self, signals[DEVICE_REMOVED], 0, device);
+}
+
 void
 nm_udev_manager_query_devices (NMUdevManager *self)
 {
@@ -561,6 +593,13 @@ nm_udev_manager_query_devices (NMUdevManager *self)
 		g_object_unref (G_UDEV_DEVICE (iter->data));
 	}
 	g_list_free (devices);
+
+	devices = g_udev_client_query_by_subsystem(priv->client, "atm");
+	for (iter = devices; iter; iter = g_list_next (iter)) {
+		adsl_add (self, G_UDEV_DEVICE (iter->data));
+		g_object_unref (G_UDEV_DEVICE(iter->data));
+	}
+	g_list_free (devices);
 }
 
 static void
@@ -581,18 +620,23 @@ handle_uevent (GUdevClient *client,
 	nm_log_dbg (LOGD_HW, "UDEV event: action '%s' subsys '%s' device '%s'",
 	            action, subsys, g_udev_device_get_name (device));
 
-	g_return_if_fail (!strcmp (subsys, "rfkill") || !strcmp (subsys, "net"));
+	g_return_if_fail (!strcmp (subsys, "rfkill") || !strcmp (subsys, "net") ||
+					  !strcmp (subsys, "atm"));
 
 	if (!strcmp (action, "add")) {
 		if (!strcmp (subsys, "rfkill"))
 			rfkill_add (self, device);
 		else if (!strcmp (subsys, "net"))
 			net_add (self, device);
+		else if (!strcmp (subsys, "atm"))
+			adsl_add (self, device);
 	} else if (!strcmp (action, "remove")) {
 		if (!strcmp (subsys, "rfkill"))
 			rfkill_remove (self, device);
 		else if (!strcmp (subsys, "net"))
 			net_remove (self, device);
+		else if (!strcmp (subsys, "atm"))
+			adsl_remove (self, device);
 	}
 
 	recheck_killswitches (self);
@@ -602,7 +646,7 @@ static void
 nm_udev_manager_init (NMUdevManager *self)
 {
 	NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self);
-	const char *subsys[3] = { "rfkill", "net", NULL };
+	const char *subsys[4] = { "rfkill", "net", "atm", NULL };
 	GList *switches, *iter;
 	guint32 i;
 
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 767b931..4de3e80 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -47,6 +47,7 @@
 #include "nm-setting-connection.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-pppoe.h"
+#include "nm-setting-adsl.h"
 #include "nm-setting-gsm.h"
 #include "nm-setting-cdma.h"
 #include "nm-dbus-manager.h"
@@ -391,6 +392,9 @@ extract_details_from_connection (NMConnection *connection,
 	if (NM_IS_SETTING_PPPOE (setting)) {
 		*username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting));
 		*password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting));
+	} else if (NM_IS_SETTING_ADSL (setting)) {
+		*username = nm_setting_adsl_get_username (NM_SETTING_ADSL (setting));
+		*password = nm_setting_adsl_get_password (NM_SETTING_ADSL (setting));
 	} else if (NM_IS_SETTING_GSM (setting)) {
 		*username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting));
 		*password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting));
@@ -792,6 +796,7 @@ static NMCmdLine *
 create_pppd_cmd_line (NMPPPManager *self,
                       NMSettingPPP *setting, 
                       NMSettingPPPOE *pppoe,
+                      NMSettingAdsl  *adsl_pppoa,
                       const char *ppp_name,
                       GError **err)
 {
@@ -844,6 +849,27 @@ create_pppd_cmd_line (NMPPPManager *self,
 			nm_cmd_line_add_string (cmd, "rp_pppoe_service");
 			nm_cmd_line_add_string (cmd, pppoe_service);
 		}
+	} else if (adsl_pppoa) {
+		const char *vpi;
+		const char *vci;
+		const gchar *encapsulation;
+		gchar *vpivci;
+
+		vpi = nm_setting_adsl_get_vpi (adsl_pppoa);
+		vci = nm_setting_adsl_get_vci (adsl_pppoa);
+		encapsulation = nm_setting_adsl_get_encapsulation (adsl_pppoa);
+		vpivci = g_strdup_printf("%s.%s", vpi, vci);
+
+		nm_cmd_line_add_string (cmd, "plugin");
+		nm_cmd_line_add_string (cmd, "pppoatm.so");
+		nm_cmd_line_add_string (cmd, vpivci);
+
+		if (!g_ascii_strcasecmp(encapsulation, "llc"))
+			nm_cmd_line_add_string (cmd, "llc-encaps");
+
+		nm_cmd_line_add_string (cmd, "noipdefault");
+
+		g_free (vpivci);
 	} else {
 		nm_cmd_line_add_string (cmd, priv->parent_iface);
 		/* Don't send some random address as the local address */
@@ -965,6 +991,7 @@ nm_ppp_manager_start (NMPPPManager *manager,
 	NMSettingPPP *s_ppp;
 	gboolean s_ppp_created = FALSE;
 	NMSettingPPPOE *pppoe_setting;
+	NMSettingAdsl *adsl_setting;
 	NMCmdLine *ppp_cmd;
 	char *cmd_str;
 	struct stat st;
@@ -1006,7 +1033,9 @@ nm_ppp_manager_start (NMPPPManager *manager,
 	if (pppoe_setting)
 		pppoe_fill_defaults (s_ppp);
 
-	ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, ppp_name, err);
+	adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+
+	ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, adsl_setting, ppp_name, err);
 	if (!ppp_cmd)
 		goto out;
 
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 87fa4b6..78aa31c 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -49,6 +49,7 @@
 #include <nm-setting-serial.h>
 #include <nm-setting-vpn.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
 
@@ -1688,6 +1689,7 @@ nm_settings_class_init (NMSettingsClass *class)
 	dbus_g_error_domain_register (NM_SETTING_PPP_ERROR, NULL, NM_TYPE_SETTING_PPP_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_PPPOE_ERROR, NULL, NM_TYPE_SETTING_PPPOE_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_SERIAL_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_ADSL_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_VPN_ERROR, NULL, NM_TYPE_SETTING_VPN_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_WIRED_ERROR, NULL, NM_TYPE_SETTING_WIRED_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_WIRELESS_SECURITY_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]