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] [email protected] 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 [email protected] 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="[email protected]" 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 <[email protected]> --- 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 <[email protected]> + */ + +#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 <[email protected]> + */ + +#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 _______________________________________________ networkmanager-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/networkmanager-list
