[RFC] ADSL: Experimental PPPoE support
- From: Pantelis Koukousoulas <pktoss gmail com>
- To: networkmanager-list gnome org
- Subject: [RFC] ADSL: Experimental PPPoE support
- Date: Tue, 17 May 2011 21:38:18 +0300
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:
[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 */
--
1.7.4.1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]