Re: [RFC] ADSL: Experimental PPPoE support



On Tue, 2011-05-17 at 21:38 +0300, Pantelis Koukousoulas wrote:
> This is a first cut at experimental PPPoE support for ADSL devices.
> There are several shortcuts and the code is ugly, but it works so
> it can be used as a strawman to improve upon.
> 
> Happily waiting for comments / testing / suggestions :)

I rebased the 'adsl' branch to git master and wrote some code to talk
the ioctls directly instead of using br2684ctl.  As Dave Woodhouse
pointed out, br2684ctl isn't that complicated so we might as well just
talk to the kernel.  However, I don't have an ADSL connection to test
with (I only have a modem for basic hardware detection support) so if
anyone can test out the code on the 'adsl' branch that would be great.
Make sure to run NM with "--log-level=debug" or to set "level=debug" in
the [logging] section of NetworkManager.conf so we can more easily debug
any failures.

Any testing help appreciated; the more testing we get the earlier we can
merge this to master and get ADSL support working for everyone.

Thanks!
Dan

> With this code and a system keyfile connection like the following:
> 
> [connection]
> id=OTENETPPPOE
> uuid=34d04e69-fdd9-4231-af2c-25ed1f34dc2e
> type=adsl
> timestamp=1304621332
> 
> [adsl]
> username=myusername myisp com
> password=mypassword
> vpi=8
> vci=35
> encapsulation=llc
> protocol=pppoe
> 
> [ipv6]
> method=ignore
> 
> [ipv4]
> method=auto
> 
> I can connect successfully via pppoe, as evidenced by the following
> extract from the logs:
> 
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 1 of 5 (Device Prepare) scheduled...
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 1 of 5 (Device Prepare) started...
> NetworkManager[1495]: <info> starting RFC 2684 Bridge
> NetworkManager[1495]: <debug> [1305654571.49055] [nm-br2684-manager.c:403] nm_br2684_manager_start(): command line: /usr/sbin/br2684ctl -c 0 -e 0 -p 1 -a 8.35
> NetworkManager[1495]: <info> br2684ctl started with pid 1721
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 1 of 5 (Device Prepare) complete.
> NetworkManager[1495]: <debug> [1305654571.62289] [nm-udev-manager.c:622] handle_uevent(): UDEV event: action 'add' subsys 'net' device 'nas0'
> NetworkManager[1495]: <warn> /sys/devices/virtual/net/nas0: couldn't determine device driver; ignoring...
> NetworkManager[1495]: <debug> [1305654571.63491] [nm-netlink-monitor.c:117] link_msg_handler(): netlink link message: iface idx 62 flags 0x1002
> br2684ctl[1721]: Interface "nas0" created sucessfully
> br2684ctl[1721]: Communicating over ATM 0.8.35, encapsulation: LLC
> br2684ctl[1721]: Interface configured
> br2684ctl[1721]: RFC 1483/2684 bridge daemon started
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 2 of 5 (Device Configure) scheduled...
> NetworkManager[1495]: <debug> [1305654576.48874] [nm-netlink-monitor.c:117] link_msg_handler(): netlink link message: iface idx 62 flags 0x11043
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 2 of 5 (Device Configure) starting...
> NetworkManager[1495]: <info> (ueagle-atm0): device state change: prepare -> config (reason 'none') [40 50 0]
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 2 of 5 (Device Configure) successful.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 3 of 5 (IP Configure Start) scheduled.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 2 of 5 (Device Configure) complete.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 3 of 5 (IP Configure Start) started...
> NetworkManager[1495]: <info> (ueagle-atm0): device state change: config -> ip-config (reason 'none') [50 70 0]
> NetworkManager[1495]: <info> starting PPP connection
> NetworkManager[1495]: <debug> [1305654576.59215] [nm-ppp-manager.c:1056] nm_ppp_manager_start(): command line: /usr/sbin/pppd nodetach lock nodefaultroute debug user myuser myisp com plugin rp-pppoe.so nas0 noipdefault noauth usepeerdns lcp-echo-failure 0 lcp-echo-interval 0 ipparam /org/freedesktop/NetworkManager/PPP/2 plugin /opt/nmadsl/lib/pppd/2.4.5/nm-pppd-plugin.so
> NetworkManager[1495]: <info> pppd started with pid 1733
> NetworkManager[1495]: <debug> [1305654576.62016] [NetworkManagerUtils.c:848] nm_utils_get_proc_sys_net_value(): (ueagle-atm0): error reading /proc/sys/net/ipv6/conf/ueagle-atm0/accept_ra: (4) Failed to open file '/proc/sys/net/ipv6/conf/ueagle-atm0/accept_ra': No such file or directory
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 3 of 5 (IP Configure Start) complete.
> Plugin rp-pppoe.so loaded.
> Plugin /opt/nmadsl/lib/pppd/2.4.5/nm-pppd-plugin.so loaded.
> ** Message: nm-ppp-plugin: (plugin_init): initializing
> ** Message: nm-ppp-plugin: (nm_phasechange): status 3 / phase 'serial connection'
> Send PPPOE Discovery V1T1 PADI session 0x0 length 12
>  dst ff:ff:ff:ff:ff:ff  src 0:60:4c:8c:5b:d6
>  [service-name] [host-uniq  c5 06 00 00]
> Recv PPPOE Discovery V1T1 PADO session 0x0 length 50
>  dst 0:60:4c:8c:5b:d6  src 0:90:1a:41:65:24
>  [AC-name bras-ari1-1440] [host-uniq  c5 06 00 00] [service-name] [AC-cookie  cc d1 10 3e 4b c8 e9 de b3 c9 73 c7 1d b4 4d 30]
> Send PPPOE Discovery V1T1 PADR session 0x0 length 32
>  dst 0:90:1a:41:65:24  src 0:60:4c:8c:5b:d6
>  [service-name] [host-uniq  c5 06 00 00] [AC-cookie  cc d1 10 3e 4b c8 e9 de b3 c9 73 c7 1d b4 4d 30]
> Recv PPPOE Discovery V1T1 PADS session 0x130d length 50
>  dst 0:60:4c:8c:5b:d6  src 0:90:1a:41:65:24
>  [service-name] [host-uniq  c5 06 00 00] [AC-name bras-ari1-1440] [AC-cookie  cc d1 10 3e 4b c8 e9 de b3 c9 73 c7 1d b4 4d 30]
> PADS: Service-Name: ''
> PPP session is 4877
> Connected to 00:90:1a:41:65:24 via interface nas0
> using channel 32
> Using interface ppp0
> Connect: ppp0 <--> nas0
> ** Message: nm-ppp-plugin: (nm_phasechange): status 5 / phase 'establish'
> sent [LCP ConfReq id=0x1 <mru 1492> <magic 0x2de132c2>]
> NetworkManager[1495]: <debug> [1305654576.314811] [nm-netlink-monitor.c:117] link_msg_handler(): netlink link message: iface idx 63 flags 0x1090
> NetworkManager[1495]: <debug> [1305654576.314939] [nm-udev-manager.c:622] handle_uevent(): UDEV event: action 'add' subsys 'net' device 'ppp0'
> NetworkManager[1495]: <debug> [1305654576.314991] [nm-udev-manager.c:525] net_add(): ignoring interface with type 512
> rcvd [LCP ConfReq id=0x11 <mru 1492> <auth pap> <magic 0x701d0b64>]
> sent [LCP ConfAck id=0x11 <mru 1492> <auth pap> <magic 0x701d0b64>]
> rcvd [LCP ConfAck id=0x1 <mru 1492> <magic 0x2de132c2>]
> ** Message: nm-ppp-plugin: (nm_phasechange): status 6 / phase 'authenticate'
> ** Message: nm-ppp-plugin: (get_credentials): passwd-hook, requesting credentials...
> NetworkManager[1495]: <debug> [1305654576.420633] [nm-agent-manager.c:1044] nm_agent_manager_get_secrets(): Secrets requested for connection /org/freedesktop/NetworkManager/Settings/0 (adsl)
> NetworkManager[1495]: <debug> [1305654576.420743] [nm-settings-connection.c:717] nm_settings_connection_get_secrets(): (34d04e69-fdd9-4231-af2c-25ed1f34dc2e/adsl:1) secrets requested flags 0x1 hint 'password'
> NetworkManager[1495]: <debug> [1305654576.421675] [nm-agent-manager.c:959] get_start(): (0x91fde80/adsl) system settings secrets sufficient
> NetworkManager[1495]: <debug> [1305654576.422178] [nm-settings-connection.c:573] agent_secrets_done_cb(): (34d04e69-fdd9-4231-af2c-25ed1f34dc2e/adsl:1) existing secrets returned
> NetworkManager[1495]: <debug> [1305654576.422419] [nm-settings-connection.c:579] agent_secrets_done_cb(): (34d04e69-fdd9-4231-af2c-25ed1f34dc2e/adsl:1) secrets request completed
> NetworkManager[1495]: <debug> [1305654576.424015] [nm-settings-connection.c:618] agent_secrets_done_cb(): (34d04e69-fdd9-4231-af2c-25ed1f34dc2e/adsl:1) new agent secrets processed
> ** Message: nm-ppp-plugin: (get_credentials): got credentials from NetworkManager
> sent [PAP AuthReq id=0x1 user="myuser myisp com" password=<hidden>]
> rcvd [PAP AuthAck id=0x1 ""]
> PAP authentication succeeded
> peer from calling number 00:90:1A:41:65:24 authorized
> ** Message: nm-ppp-plugin: (nm_phasechange): status 8 / phase 'network'
> sent [IPCP ConfReq id=0x1 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
> rcvd [IPCP ConfNak id=0x1 <addr 94.70.77.249> <ms-dns1 195.170.0.1> <ms-dns2 195.170.2.2>]
> sent [IPCP ConfReq id=0x2 <addr 94.70.77.249> <ms-dns1 195.170.0.1> <ms-dns2 195.170.2.2>]
> rcvd [IPCP ConfAck id=0x2 <addr 94.70.77.249> <ms-dns1 195.170.0.1> <ms-dns2 195.170.2.2>]
> rcvd [IPCP ConfReq id=0x40 <addr 80.106.108.12>]
> sent [IPCP ConfAck id=0x40 <addr 80.106.108.12>]
> NetworkManager[1495]: <debug> [1305654576.812559] [nm-netlink-monitor.c:117] link_msg_handler(): netlink link message: iface idx 63 flags 0x110D1
> local  IP address 94.70.77.249
> remote IP address 80.106.108.12
> primary   DNS address 195.170.0.1
> secondary DNS address 195.170.2.2
> ** Message: nm-ppp-plugin: (nm_phasechange): status 9 / phase 'running'
> ** Message: nm-ppp-plugin: (nm_ip_up): ip-up event
> ** Message: nm-ppp-plugin: (nm_ip_up): sending Ip4Config to NetworkManager...
> NetworkManager[1495]: <info> PPP manager(IP Config Get) reply received.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 4 of 5 (IP4 Configure Get) scheduled...
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 4 of 5 (IP4 Configure Get) started...
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 5 of 5 (IP Configure Commit) scheduled...
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 4 of 5 (IP4 Configure Get) complete.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 5 of 5 (IP Configure Commit) started...
> NetworkManager[1495]: <debug> [1305654576.818828] [nm-system.c:222] sync_addresses(): (ppp0): syncing addresses (family 2)
> Script /etc/ppp/ip-up started (pid 1736)
> Script /etc/ppp/ip-up finished (pid 1736), status = 0x0
> NetworkManager[1495]: <info> (ueagle-atm0): device state change: ip-config -> activated (reason 'none') [70 100 0]
> NetworkManager[1495]: <info> Policy set 'CONNPPPOE' (ppp0) as default for IPv4 routing and DNS.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) successful, device activated.
> NetworkManager[1495]: <info> Activation (ueagle-atm0) Stage 5 of 5 (IP Configure Commit) complete.
> 
> Signed-off-by: Pantelis Koukousoulas <pktoss gmail com>
> ---
>  configure.ac                           |    1 +
>  include/NetworkManager.h               |    3 +
>  src/Makefile.am                        |    2 +
>  src/br2684-manager/Makefile.am         |   25 ++
>  src/br2684-manager/nm-br2684-manager.c |  427 ++++++++++++++++++++++++++++++++
>  src/br2684-manager/nm-br2684-manager.h |   64 +++++
>  src/logging/nm-logging.c               |    3 +-
>  src/logging/nm-logging.h               |    1 +
>  src/nm-device-adsl.c                   |   47 ++++-
>  src/nm-device.c                        |    2 +
>  src/ppp-manager/nm-ppp-manager.c       |   47 ++--
>  11 files changed, 599 insertions(+), 23 deletions(-)
>  create mode 100644 src/br2684-manager/Makefile.am
>  create mode 100644 src/br2684-manager/nm-br2684-manager.c
>  create mode 100644 src/br2684-manager/nm-br2684-manager.h
> 
> diff --git a/configure.ac b/configure.ac
> index b18ccc0..1679828 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -603,6 +603,7 @@ src/ip6-manager/Makefile
>  src/supplicant-manager/Makefile
>  src/supplicant-manager/tests/Makefile
>  src/ppp-manager/Makefile
> +src/br2684-manager/Makefile
>  src/dnsmasq-manager/Makefile
>  src/modem-manager/Makefile
>  src/bluez-manager/Makefile
> diff --git a/include/NetworkManager.h b/include/NetworkManager.h
> index f2e4727..5c9ffc3 100644
> --- a/include/NetworkManager.h
> +++ b/include/NetworkManager.h
> @@ -415,6 +415,9 @@ typedef enum {
>  	/* The Bluetooth connection failed or timed out */
>  	NM_DEVICE_STATE_REASON_BT_FAILED = 44,
>  
> +	/* Problem with the RFC 2684 Ethernet over ADSL bridge */
> +	NM_DEVICE_STATE_REASON_BR2684_FAILED = 45,
> +
>  	/* Unused */
>  	NM_DEVICE_STATE_REASON_LAST = 0xFFFF
>  } NMDeviceStateReason;
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 50b52d6..f0bc6d7 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -6,6 +6,7 @@ SUBDIRS= \
>  	ip6-manager \
>  	supplicant-manager \
>  	ppp-manager \
> +	br2684-manager \
>  	backends \
>  	dnsmasq-manager \
>  	modem-manager \
> @@ -267,6 +268,7 @@ NetworkManager_LDADD = \
>  	./supplicant-manager/libsupplicant-manager.la \
>  	./dnsmasq-manager/libdnsmasq-manager.la \
>  	./ppp-manager/libppp-manager.la \
> +	./br2684-manager/libbr2684-manager.la \
>  	./modem-manager/libmodem-manager.la \
>  	./bluez-manager/libbluez-manager.la \
>  	./settings/libsettings.la \
> diff --git a/src/br2684-manager/Makefile.am b/src/br2684-manager/Makefile.am
> new file mode 100644
> index 0000000..9a6bb03
> --- /dev/null
> +++ b/src/br2684-manager/Makefile.am
> @@ -0,0 +1,25 @@
> +INCLUDES = \
> +	-I${top_srcdir} \
> +	-I${top_srcdir}/include \
> +	-I${top_srcdir}/libnm-util \
> +	-I${top_srcdir}/src \
> +	-I${top_srcdir}/src/logging \
> +	-I${top_builddir}/marshallers
> +
> +noinst_LTLIBRARIES = libbr2684-manager.la
> +
> +libbr2684_manager_la_SOURCES = \
> +	nm-br2684-manager.c \
> +	nm-br2684-manager.h
> +
> +$(libbr2684_manager_la_OBJECTS): 
> +							   
> +libbr2684_manager_la_CPPFLAGS = \
> +	$(GLIB_CFLAGS) \
> +	-DG_DISABLE_DEPRECATED \
> +	-DSYSCONFDIR=\"$(sysconfdir)\" \
> +	-DLIBDIR=\"$(libdir)\"
> +
> +libbr2684_manager_la_LIBADD = \
> +	$(top_builddir)/src/logging/libnm-logging.la \
> +	$(GLIB_LIBS)
> diff --git a/src/br2684-manager/nm-br2684-manager.c b/src/br2684-manager/nm-br2684-manager.c
> new file mode 100644
> index 0000000..68c83a6
> --- /dev/null
> +++ b/src/br2684-manager/nm-br2684-manager.c
> @@ -0,0 +1,427 @@
> +/* -*- 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>
> + */
> +
> +#include <config.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <sys/wait.h>
> +
> +#include "nm-br2684-manager.h"
> +#include "nm-setting-adsl.h"
> +#include "nm-logging.h"
> +
> +typedef struct {
> +	gboolean disposed;
> +
> +	gboolean iface_up;
> +	guint32  iface_poll_id;
> +	guint32  br2684_watch_id;
> +	GPid     pid;
> +} NMBr2684ManagerPrivate;
> +
> +#define NM_BR2684_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BR2684_MANAGER, NMBr2684ManagerPrivate))
> +
> +G_DEFINE_TYPE (NMBr2684Manager, nm_br2684_manager, G_TYPE_OBJECT)
> +
> +enum {
> +	STATE_CHANGED,
> +
> +	LAST_SIGNAL
> +};
> +
> +static guint signals[LAST_SIGNAL] = { 0 };
> +
> +enum {
> +	PROP_0,
> +	LAST_PROP
> +};
> +
> +typedef enum {
> +	NM_BR2684_MANAGER_ERROR_UNKOWN
> +} NMBr2684ManagerError;
> +
> +GQuark
> +nm_br2684_manager_error_quark (void)
> +{
> +	static GQuark quark;
> +
> +	if (!quark)
> +		quark = g_quark_from_static_string ("nm_br2684_manager_error");
> +
> +	return quark;
> +}
> +
> +static void
> +nm_br2684_manager_init (NMBr2684Manager *manager)
> +{
> +}
> +
> +static gboolean
> +iface_update_cb (gpointer user_data)
> +{
> +	NMBr2684Manager *self = NM_BR2684_MANAGER (user_data);
> +	NMBr2684ManagerPrivate *priv = NM_BR2684_MANAGER_GET_PRIVATE (self);
> +
> +	gchar *contents = NULL;
> +	GError *error = NULL;
> +	const gchar *path = "/sys/devices/virtual/net/nas0/ifindex";
> +
> +	if (!g_file_get_contents(path, &contents, NULL, &error)) {
> +		g_clear_error (&error);
> +		if (priv->iface_up) {
> +			priv->iface_up = FALSE;
> +			g_signal_emit(self, signals[STATE_CHANGED], 0, 0);
> +		}
> +
> +		return TRUE;
> +	}
> +
> +	if (!priv->iface_up) {
> +		priv->iface_up = TRUE;
> +		g_signal_emit(self, signals[STATE_CHANGED], 0, 1);
> +	}
> +
> +	return TRUE;
> +}
> +
> +static GObject *
> +constructor (GType type,
> +		   guint n_construct_params,
> +		   GObjectConstructParam *construct_params)
> +{
> +	GObject *object;
> +	NMBr2684Manager *self;
> +	NMBr2684ManagerPrivate *priv;
> +
> +	object = G_OBJECT_CLASS (nm_br2684_manager_parent_class)->constructor (type,
> +	                                                                       n_construct_params,
> +	                                                                       construct_params);
> +
> +	if (!object)
> +		return NULL;
> +
> +	self = NM_BR2684_MANAGER (object);
> +	priv = NM_BR2684_MANAGER_GET_PRIVATE (self);
> +
> +	priv->iface_up = FALSE;
> +	priv->iface_poll_id = g_timeout_add_seconds(5, iface_update_cb, self);
> +
> +	return object;
> +}
> +
> +static gboolean
> +ensure_killed (gpointer data)
> +{
> +	int pid = GPOINTER_TO_INT (data);
> +
> +	if (kill (pid, 0) == 0)
> +		kill (pid, SIGKILL);
> +
> +	/* ensure the child is reaped */
> +	nm_log_dbg (LOGD_BR2684, "waiting for br2684ctl pid %d to exit", pid);
> +	waitpid (pid, NULL, 0);
> +	nm_log_dbg (LOGD_BR2684, "br2684ctl pid %d cleaned up", pid);
> +
> +	return FALSE;
> +}
> +
> +static void br2684_cleanup (NMBr2684Manager *manager)
> +{
> +	NMBr2684ManagerPrivate *priv;
> +
> +	g_return_if_fail (NM_IS_BR2684_MANAGER (manager));
> +
> +	priv = NM_BR2684_MANAGER_GET_PRIVATE (manager);
> +
> +	nm_log_dbg (LOGD_BR2684, "br2684ctl cleanup (pid: %d)", priv->pid);
> +
> +	if (priv->br2684_watch_id) {
> +		g_source_remove (priv->br2684_watch_id);
> +		priv->br2684_watch_id = 0;
> +	}
> +
> +	if (priv->pid) {
> +		if (kill (priv->pid, SIGTERM) == 0)
> +			g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (priv->pid));
> +		else {
> +			kill (priv->pid, SIGKILL);
> +
> +			/* ensure the child is reaped */
> +			nm_log_dbg (LOGD_BR2684, "waiting for br2684ctl pid %d to exit", priv->pid);
> +			waitpid (priv->pid, NULL, 0);
> +			nm_log_dbg (LOGD_BR2684, "br2684ctl pid %d cleaned up", priv->pid);
> +		}
> +
> +		priv->pid = 0;
> +	}
> +}
> +
> +static void
> +dispose (GObject *object)
> +{
> +	NMBr2684ManagerPrivate *priv = NM_BR2684_MANAGER_GET_PRIVATE (object);
> +
> +	nm_log_dbg (LOGD_BR2684, "in Br2684Manager::dispose()");
> +
> +	if (priv->disposed == FALSE) {
> +		priv->disposed = TRUE;
> +
> +		br2684_cleanup(NM_BR2684_MANAGER (object));
> +
> +		if (priv->iface_poll_id) {
> +			g_source_remove(priv->iface_poll_id);
> +			priv->iface_poll_id = 0;
> +		}
> +	}
> +
> +	G_OBJECT_CLASS (nm_br2684_manager_parent_class)->dispose (object);
> +}
> +
> +static void
> +nm_br2684_manager_class_init (NMBr2684ManagerClass *manager_class)
> +{
> +	GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
> +
> +	g_type_class_add_private (manager_class, sizeof (NMBr2684ManagerPrivate));
> +
> +	object_class->constructor = constructor;
> +	object_class->dispose = dispose;
> +
> +	/* signals */
> +	signals[STATE_CHANGED] =
> +		g_signal_new ("state-changed",
> +				    G_OBJECT_CLASS_TYPE (object_class),
> +				    G_SIGNAL_RUN_FIRST,
> +				    G_STRUCT_OFFSET (NMBr2684ManagerClass, state_changed),
> +				    NULL, NULL,
> +				    g_cclosure_marshal_VOID__UINT,
> +				    G_TYPE_NONE, 1,
> +				    G_TYPE_UINT);
> +}
> +
> +/************************************************/
> +
> +static inline const char *
> +nm_find_br2684ctl (void)
> +{
> +	static const char *br2684ctl_binary_paths[] = {
> +		"/usr/local/sbin/br2684ctl",
> +		"/usr/sbin/br2684ctl",
> +		"/sbin/br2684ctl",
> +	};
> +
> +	const char  **br2684ctl_binary = br2684ctl_binary_paths;
> +
> +	while (*br2684ctl_binary != NULL) {
> +		if (g_file_test (*br2684ctl_binary, G_FILE_TEST_EXISTS))
> +			break;
> +		br2684ctl_binary++;
> +	}
> +
> +	return *br2684ctl_binary;
> +}
> +
> +typedef struct {
> +	GPtrArray *array;
> +	GStringChunk *chunk;
> +} NMCmdLine;
> +
> +static NMCmdLine *
> +nm_cmd_line_new (void)
> +{
> +	NMCmdLine *cmd;
> +
> +	cmd = g_slice_new (NMCmdLine);
> +	cmd->array = g_ptr_array_new ();
> +	cmd->chunk = g_string_chunk_new (1024);
> +
> +	return cmd;
> +}
> +
> +static void
> +nm_cmd_line_destroy (NMCmdLine *cmd)
> +{
> +	g_ptr_array_free (cmd->array, TRUE);
> +	g_string_chunk_free (cmd->chunk);
> +	g_slice_free (NMCmdLine, cmd);
> +}
> +
> +static char *
> +nm_cmd_line_to_str (NMCmdLine *cmd)
> +{
> +	char *str;
> +
> +	g_ptr_array_add (cmd->array, NULL);
> +	str = g_strjoinv (" ", (gchar **) cmd->array->pdata);
> +	g_ptr_array_remove_index (cmd->array, cmd->array->len - 1);
> +
> +	return str;
> +}
> +
> +static void
> +nm_cmd_line_add_string (NMCmdLine *cmd, const char *str)
> +{
> +	g_ptr_array_add (cmd->array, g_string_chunk_insert (cmd->chunk, str));
> +}
> +
> +static void
> +nm_cmd_line_add_int (NMCmdLine *cmd, int i)
> +{
> +	char *str;
> +
> +	str = g_strdup_printf ("%d", i);
> +	nm_cmd_line_add_string (cmd, str);
> +	g_free (str);
> +}
> +
> +static NMCmdLine *
> +create_br2684ctl_cmd_line (NMBr2684Manager *manager,
> +                           NMSettingAdsl *s_adsl,
> +                           GError **err)
> +{
> +	const char *b2864_binary;
> +	const char *encapsulation, *protocol, *vpi, *vci;
> +	gchar *vpivci;
> +	gboolean is_llc, is_pppoe;
> +	NMCmdLine *cmd;
> +
> +	b2864_binary = nm_find_br2684ctl ();
> +	if (!b2864_binary) {
> +		g_set_error (err, NM_BR2684_MANAGER_ERROR, NM_BR2684_MANAGER_ERROR,
> +		                               "Could not find br2684ctl binary.");
> +	}
> +
> +	cmd = nm_cmd_line_new ();
> +	nm_cmd_line_add_string (cmd, b2864_binary);
> +	nm_cmd_line_add_string (cmd, "-c");
> +	nm_cmd_line_add_int (cmd, 0); // interface number (for now force nas0)
> +
> +	encapsulation = nm_setting_adsl_get_encapsulation (s_adsl);
> +	is_llc = !strcmp (encapsulation, "llc");
> +
> +	protocol = nm_setting_adsl_get_protocol (s_adsl);
> +	is_pppoe = !strcmp (protocol, "pppoe");
> +
> +	vpi = nm_setting_adsl_get_vpi (s_adsl);
> +	vci = nm_setting_adsl_get_vci (s_adsl);
> +	vpivci = g_strdup_printf("%s.%s", vpi, vci);
> +
> +	nm_cmd_line_add_string (cmd, "-e");
> +	nm_cmd_line_add_int (cmd, is_llc ? 0 : 1);
> +	nm_cmd_line_add_string (cmd, "-p");
> +	nm_cmd_line_add_int (cmd, is_pppoe ? 1 : 0);
> +	nm_cmd_line_add_string (cmd, "-a");
> +	nm_cmd_line_add_string (cmd, vpivci);
> +
> +	g_free(vpivci);
> +
> +	return cmd;
> +}
> +
> +static void
> +br2684_child_setup (gpointer user_data G_GNUC_UNUSED)
> +{
> +	/* We are in the child process at this point */
> +	pid_t pid = getpid ();
> +	setpgid (pid, pid);
> +}
> +
> +static void
> +br2684_watch_cb (GPid pid, gint status, gpointer user_data)
> +{
> +	NMBr2684Manager *manager = NM_BR2684_MANAGER (user_data);
> +	NMBr2684ManagerPrivate *priv = NM_BR2684_MANAGER_GET_PRIVATE (manager);
> +	guint err;
> +
> +	g_assert (pid == priv->pid);
> +
> +	if (WIFEXITED (status)) {
> +		err = WEXITSTATUS (status);
> +	} else if (WIFSTOPPED (status)) {
> +		nm_log_info (LOGD_BR2684, "br2684ctl pid %d stopped unexpectedly with signal %d", priv->pid, WSTOPSIG (status));
> +	} else if (WIFSIGNALED (status)) {
> +		nm_log_info (LOGD_BR2684, "br2684ctl pid %d died with signal %d", priv->pid, WTERMSIG (status));
> +	} else
> +		nm_log_info (LOGD_BR2684, "br2684ctl pid %d died from an unknown cause", priv->pid);
> +
> +	nm_log_dbg (LOGD_BR2684, "br2684ctl pid %d cleaned up", priv->pid);
> +	priv->pid = 0;
> +}
> +
> +
> +/* API Functions */
> +
> +gboolean nm_br2684_manager_start (NMBr2684Manager *manager,
> +                                  NMActRequest *req,
> +                                  guint32 timeout_secs,
> +                                  GError **err)
> +{
> +	NMBr2684ManagerPrivate *priv;
> +	NMConnection *connection;
> +	NMSettingAdsl *adsl_setting;
> +	NMCmdLine *b2684_cmd;
> +	char *cmd_str;
> +
> +	g_return_val_if_fail (NM_IS_BR2684_MANAGER (manager), FALSE);
> +	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
> +
> +	priv = NM_BR2684_MANAGER_GET_PRIVATE (manager);
> +	priv->pid = 0;
> +
> +	connection = nm_act_request_get_connection (req);
> +	g_assert (connection);
> +
> +	adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
> +
> +	b2684_cmd = create_br2684ctl_cmd_line (manager, adsl_setting, err);
> +	if (!b2684_cmd)
> +		goto out;
> +
> +	g_ptr_array_add (b2684_cmd->array, NULL);
> +
> +	nm_log_info (LOGD_BR2684, "starting RFC 2684 Bridge");
> +
> +	cmd_str = nm_cmd_line_to_str (b2684_cmd);
> +	nm_log_dbg (LOGD_BR2684, "command line: %s", cmd_str);
> +	g_free (cmd_str);
> +
> +	priv->pid = 0;
> +	if (!g_spawn_async (NULL, (char **) b2684_cmd->array->pdata, NULL,
> +	                    G_SPAWN_DO_NOT_REAP_CHILD,
> +	                    br2684_child_setup,
> +	                    NULL, &priv->pid, err))
> +		goto out;
> +
> +	nm_log_info (LOGD_BR2684, "br2684ctl started with pid %d", priv->pid);
> +
> +	priv->br2684_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) br2684_watch_cb, manager);
> +
> +out:
> +	if (b2684_cmd)
> +		nm_cmd_line_destroy (b2684_cmd);
> +
> +	return (priv->pid > 0);
> +}
> +
> +NMBr2684Manager *nm_br2684_manager_new ()
> +{
> +	return (NMBr2684Manager *) g_object_new (NM_TYPE_BR2684_MANAGER,
> +	                                         NULL);
> +}
> diff --git a/src/br2684-manager/nm-br2684-manager.h b/src/br2684-manager/nm-br2684-manager.h
> new file mode 100644
> index 0000000..dc73639
> --- /dev/null
> +++ b/src/br2684-manager/nm-br2684-manager.h
> @@ -0,0 +1,64 @@
> +/* -*- 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>
> + */
> +
> +#ifndef NM_BR2684_MANAGER_H
> +#define NM_BR2864_MANAGER_H
> +
> +#include <glib.h>
> +#include <glib-object.h>
> +
> +#include "nm-activation-request.h"
> +#include "nm-connection.h"
> +#include "nm-ip4-config.h"
> +
> +#define NM_TYPE_BR2684_MANAGER            (nm_br2684_manager_get_type ())
> +#define NM_BR2684_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BR2684_MANAGER, NMBr2684Manager))
> +#define NM_BR2684_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BR2684_MANAGER, NMBr2684ManagerClass))
> +#define NM_IS_BR2684_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BR2684_MANAGER))
> +#define NM_IS_BR2684_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_BR2684_MANAGER))
> +#define NM_BR2684_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BR2684_MANAGER, NMBr2684ManagerClass))
> +
> +typedef struct {
> +	GObject parent;
> +} NMBr2684Manager;
> +
> +typedef struct {
> +	GObjectClass parent;
> +
> +	/* Signals */
> +	void (*state_changed) (NMBr2684Manager *manager, guint state);
> +} NMBr2684ManagerClass;
> +
> +GType nm_br2684_manager_get_type (void);
> +
> +NMBr2684Manager *nm_br2684_manager_new (void);
> +
> +gboolean nm_br2684_manager_start (NMBr2684Manager *manager,
> +                                  NMActRequest *req,
> +                                  guint32 timeout_secs,
> +                                  GError **err);
> +
> +
> +#define NM_BR2684_MANAGER_ERROR nm_br2684_manager_error_quark()
> +#define NM_TYPE_BR2684_MANAGER_ERROR (nm_br2684_manager_error_get_type ())
> +
> +GQuark nm_br2684_manager_error_quark (void);
> +
> +#endif /* NM_BR2684_MANAGER_H */
> diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c
> index 1e289d3..5b7637b 100644
> --- a/src/logging/nm-logging.c
> +++ b/src/logging/nm-logging.c
> @@ -44,7 +44,7 @@ static guint32 log_domains = \
>  	LOGD_DHCP4 | LOGD_DHCP6 | LOGD_PPP | LOGD_IP4 | LOGD_IP6 | LOGD_AUTOIP4 | \
>  	LOGD_DNS | LOGD_VPN | LOGD_SHARING | LOGD_SUPPLICANT | LOGD_AGENTS | \
>  	LOGD_SETTINGS | LOGD_SUSPEND | LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | \
> -	LOGD_WIMAX;
> +	LOGD_WIMAX | LOGD_BR2684;
>  
>  typedef struct {
>  	guint32 num;
> @@ -85,6 +85,7 @@ static const LogDesc domain_descs[] = {
>  	{ LOGD_DEVICE,    "DEVICE" },
>  	{ LOGD_OLPC_MESH, "OLPC" },
>  	{ LOGD_WIMAX,     "WIMAX" },
> +	{ LOGD_BR2684,    "BR2684" },
>  	{ 0, NULL }
>  };
>  
> diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h
> index 44e49a7..cd05ada 100644
> --- a/src/logging/nm-logging.h
> +++ b/src/logging/nm-logging.h
> @@ -52,6 +52,7 @@ enum {
>  	LOGD_DEVICE     = 0x00200000, /* Device state and activation */
>  	LOGD_OLPC_MESH  = 0x00400000,
>  	LOGD_WIMAX      = 0x00800000,
> +	LOGD_BR2684     = 0x01000000,
>  };
>  
>  #define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6)
> diff --git a/src/nm-device-adsl.c b/src/nm-device-adsl.c
> index 77e4d0a..8850558 100644
> --- a/src/nm-device-adsl.c
> +++ b/src/nm-device-adsl.c
> @@ -31,8 +31,10 @@
>  #include "nm-glib-compat.h"
>  #include "NetworkManagerUtils.h"
>  #include "nm-logging.h"
> +#include "nm-system.h"
>  
>  #include "ppp-manager/nm-ppp-manager.h"
> +#include "br2684-manager/nm-br2684-manager.h"
>  #include "nm-setting-adsl.h"
>  
>  #include "nm-device-adsl-glue.h"
> @@ -68,6 +70,9 @@ typedef struct {
>  	/* PPP */
>  	NMPPPManager *ppp_manager;
>  	NMIP4Config  *pending_ip4_config;
> +
> +	/* RFC 2684 bridging (PPPoE over ATM) */
> +	NMBr2684Manager *br2684_manager;
>  } NMDeviceAdslPrivate;
>  
>  enum {
> @@ -222,7 +227,6 @@ dispose (GObject *object)
>  		priv->carrier_poll_id = 0;
>  	}
>  
> -
>  	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
>  }
>  
> @@ -316,7 +320,7 @@ real_check_connection_compatible (NMDevice *device,
>  	}
>  
>  	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,
> @@ -371,6 +375,11 @@ real_deactivate (NMDevice *device)
>  		g_object_unref (priv->ppp_manager);
>  		priv->ppp_manager = NULL;
>  	}
> +
> +	if (priv->br2684_manager) {
> +		g_object_unref (priv->br2684_manager);
> +		priv->br2684_manager = NULL;
> +	}
>  }
>  
>  static NMConnection *
> @@ -405,13 +414,29 @@ real_get_best_auto_connection (NMDevice *dev,
>  	return NULL;
>  }
>  
> +static void
> +br2684_state_changed (NMBr2684Manager *manager, guint status, gpointer user_data)
> +{
> +	NMDevice *device = NM_DEVICE (user_data);
> +
> +	if (status) {
> +		nm_system_device_set_up_down_with_iface ("nas0", TRUE, NULL);
> +		nm_device_activate_schedule_stage2_device_config (device);
> +	} else {
> +		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BR2684_FAILED);
> +	}
> +}
> +
>  static NMActStageReturn
>  real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
>  {
>  	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
>  	NMDeviceAdsl *self = NM_DEVICE_ADSL (dev);
> +	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
>  	NMActRequest *req;
>  	NMSettingAdsl *s_adsl;
> +	GError *err = NULL;
> +	const char *protocol;
>  
>  	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
>  
> @@ -421,6 +446,22 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
>  	s_adsl = NM_SETTING_ADSL (device_get_setting (dev, NM_TYPE_SETTING_ADSL));
>  	g_assert (s_adsl);
>  
> +	protocol = nm_setting_adsl_get_protocol (s_adsl);
> +	if (!strcmp (protocol, "pppoe")) {
> +		priv->br2684_manager = nm_br2684_manager_new();
> +		if (!nm_br2684_manager_start (priv->br2684_manager, req, 30, &err)) {
> +			nm_log_warn (LOGD_DEVICE, "(%s): RFC 2684 bridge failed to start: %s",
> +					             nm_device_get_iface (NM_DEVICE (self)), err->message);
> +			ret = NM_ACT_STAGE_RETURN_FAILURE;
> +			goto out;
> +		}
> +		g_signal_connect (priv->br2684_manager, "state-changed",
> +					   G_CALLBACK (br2684_state_changed),
> +					   self);
> +		ret = NM_ACT_STAGE_RETURN_POSTPONE;
> +	}
> +
> +out:
>  	return ret;
>  }
>  
> @@ -494,7 +535,7 @@ pppoa_stage3_ip4_config_start (NMDeviceAdsl *self, NMDeviceStateReason *reason)
>  					   self);
>  		ret = NM_ACT_STAGE_RETURN_POSTPONE;
>  	} else {
> -		nm_log_warn (LOGD_DEVICE, "(%s): ADSL(PPPoA) failed to start: %s",
> +		nm_log_warn (LOGD_DEVICE, "(%s): ADSL failed to start: %s",
>  		             nm_device_get_iface (NM_DEVICE (self)), err->message);
>  		g_error_free (err);
>  
> diff --git a/src/nm-device.c b/src/nm-device.c
> index 34e1b3a..32897e2 100644
> --- a/src/nm-device.c
> +++ b/src/nm-device.c
> @@ -3824,6 +3824,8 @@ reason_to_string (NMDeviceStateReason reason)
>  		return "modem-not-found";
>  	case NM_DEVICE_STATE_REASON_BT_FAILED:
>  		return "bluetooth-failed";
> +	case NM_DEVICE_STATE_REASON_BR2684_FAILED:
> +		return "br2684 bridge failed";
>  	default:
>  		break;
>  	}
> diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
> index 0704c3a..e4580c0 100644
> --- a/src/ppp-manager/nm-ppp-manager.c
> +++ b/src/ppp-manager/nm-ppp-manager.c
> @@ -796,7 +796,7 @@ static NMCmdLine *
>  create_pppd_cmd_line (NMPPPManager *self,
>                        NMSettingPPP *setting, 
>                        NMSettingPPPOE *pppoe,
> -                      NMSettingAdsl  *adsl_pppoa,
> +                      NMSettingAdsl  *adsl,
>                        const char *ppp_name,
>                        GError **err)
>  {
> @@ -849,27 +849,36 @@ 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 (!strcmp (encapsulation, "llc"))
> -			nm_cmd_line_add_string (cmd, "llc-encaps");
> +	} else if (adsl) {
> +		const gchar *protocol = nm_setting_adsl_get_protocol (adsl);
> +
> +		if (!strcmp (protocol, "pppoa")) {
> +			const char *vpi;
> +			const char *vci;
> +			const gchar *encapsulation;
> +			gchar *vpivci;
> +
> +			vpi = nm_setting_adsl_get_vpi (adsl);
> +			vci = nm_setting_adsl_get_vci (adsl);
> +			encapsulation = nm_setting_adsl_get_encapsulation (adsl);
> +			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 (!strcmp (encapsulation, "llc"))
> +				nm_cmd_line_add_string (cmd, "llc-encaps");
> +
> +			g_free (vpivci);
> +		} else if (!strcmp (protocol, "pppoe")) {
> +			nm_cmd_line_add_string (cmd, "plugin");
> +			nm_cmd_line_add_string (cmd, "rp-pppoe.so");
> +			nm_cmd_line_add_string (cmd, "nas0");
> +		}
>  
>  		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 */




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