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 :)
> 
> With this code and a system keyfile connection like the following:

Pushed this to the 'adsl' branch too, thanks!

Dan

> [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]