diff options
| author | Dan Winship <danw@gnome.org> | 2014-04-04 11:50:20 -0400 |
|---|---|---|
| committer | Dan Winship <danw@gnome.org> | 2014-04-14 10:11:05 -0400 |
| commit | 7955806a02db64b20079267743056d7d9d45af3b (patch) | |
| tree | bec0b438998d9646b81c10a328254fcdcd54bdfd | |
| parent | ebc5ea0b80072b5026d8fb220208befd00bdd2c3 (diff) | |
ppp-manager: don't use kernel pppoe (rh #1034860, rh #1061641)
The kernel PPPoE code disconnects when it receives a PADT frame, but
doesn't notify userland about it. So if the server sends a PPPoE PADT
without having sent the standard PPP LCP Termination request first,
then pppd (and thus NetworkManager) will not know that the connection
has been disconnected.
This should eventually be fixed in the kernel, but for now, work
around this by using the userland pppoe client rather than the kernel
code.
| -rw-r--r-- | configure.ac | 9 | ||||
| -rw-r--r-- | src/ppp-manager/nm-ppp-manager.c | 88 |
2 files changed, 69 insertions, 28 deletions
diff --git a/configure.ac b/configure.ac index 4f51831..74db8c1 100644 --- a/configure.ac +++ b/configure.ac @@ -546,6 +546,15 @@ fi AC_DEFINE_UNQUOTED(PPPD_PATH, "$PPPD_PATH", [Define to path of pppd binary]) AC_SUBST(PPPD_PATH) +AC_ARG_WITH(pppoe, AS_HELP_STRING([--with-pppoe=/path/to/pppoe], [path to pppoe binary])) +if test "x${with_pppoe}" = x; then + AC_PATH_PROG(PPPOE_PATH, pppoe, [], $PATH:/sbin:/usr/sbin) +else + PPPOE_PATH="$with_pppoe" +fi +AC_DEFINE_UNQUOTED(PPPOE_PATH, "$PPPOE_PATH", [Define to path of pppoe binary]) +AC_SUBST(PPPOE_PATH) + # ModemManager1 with libmm-glib AC_ARG_WITH(modem-manager-1, AS_HELP_STRING([--with-modem-manager-1], [Enable new ModemManager1 interface support]),,[with_modem_manager_1=auto]) if (test "${with_modem_manager_1}" != "no"); then diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 9ab140d..5430837 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -647,26 +647,34 @@ nm_cmd_line_add_int (NMCmdLine *cmd, int i) /*******************************************/ +static const char *pppd_binary_paths[] = { + PPPD_PATH, + "/usr/local/sbin/pppd", + "/usr/sbin/pppd", + "/sbin/pppd", + NULL +}; + +static const char *pppoe_binary_paths[] = { + PPPOE_PATH, + "/usr/local/sbin/pppoe", + "/usr/sbin/pppoe", + "/sbin/pppoe", + NULL +}; + static inline const char * -nm_find_pppd (void) +nm_find_binary (const char *paths[]) { - static const char *pppd_binary_paths[] = { - PPPD_PATH, - "/usr/local/sbin/pppd", - "/usr/sbin/pppd", - "/sbin/pppd", - NULL - }; - - const char **pppd_binary = pppd_binary_paths; - - while (*pppd_binary != NULL) { - if (**pppd_binary && g_file_test (*pppd_binary, G_FILE_TEST_EXISTS)) + const char **binary = paths; + + while (*binary != NULL) { + if (**binary && g_file_test (*binary, G_FILE_TEST_EXISTS)) break; - pppd_binary++; + binary++; } - return *pppd_binary; + return *binary; } static void @@ -788,19 +796,29 @@ create_pppd_cmd_line (NMPPPManager *self, GError **err) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); - const char *pppd_binary; + const char *pppd_binary, *pppoe_binary = NULL; NMCmdLine *cmd; gboolean ppp_debug; g_return_val_if_fail (setting != NULL, NULL); - pppd_binary = nm_find_pppd (); + pppd_binary = nm_find_binary (pppd_binary_paths); if (!pppd_binary) { g_set_error (err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR, "Could not find pppd binary."); return NULL; } + if ( pppoe + || (adsl && strcmp (nm_setting_adsl_get_protocol (adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE))) { + pppoe_binary = nm_find_binary (pppoe_binary_paths); + if (!pppoe_binary) { + g_set_error (err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR, + "Could not find pppoe binary."); + return NULL; + } + } + /* Create pppd command line */ cmd = nm_cmd_line_new (); nm_cmd_line_add_string (cmd, pppd_binary); @@ -828,21 +846,30 @@ create_pppd_cmd_line (NMPPPManager *self, } if (pppoe) { - char *dev_str; + GString *pppoe_arg; const char *pppoe_service; + char *quoted; - nm_cmd_line_add_string (cmd, "plugin"); - nm_cmd_line_add_string (cmd, "rp-pppoe.so"); + g_assert (pppoe_binary != NULL); + pppoe_arg = g_string_new (pppoe_binary); - dev_str = g_strdup_printf ("nic-%s", priv->parent_iface); - nm_cmd_line_add_string (cmd, dev_str); - g_free (dev_str); + g_string_append (pppoe_arg, " -I "); + quoted = g_shell_quote (priv->parent_iface); + g_string_append (pppoe_arg, quoted); + g_free (quoted); pppoe_service = nm_setting_pppoe_get_service (pppoe); if (pppoe_service) { - nm_cmd_line_add_string (cmd, "rp_pppoe_service"); - nm_cmd_line_add_string (cmd, pppoe_service); + g_string_append (pppoe_arg, " -S "); + quoted = g_shell_quote (pppoe_service); + g_string_append (pppoe_arg, quoted); + g_free (quoted); } + + nm_cmd_line_add_string (cmd, "pty"); + nm_cmd_line_add_string (cmd, pppoe_arg->str); + + g_string_free (pppoe_arg, TRUE); } else if (adsl) { const gchar *protocol = nm_setting_adsl_get_protocol (adsl); @@ -865,9 +892,14 @@ create_pppd_cmd_line (NMPPPManager *self, nm_cmd_line_add_string (cmd, "vc-encaps"); } else if (!strcmp (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { - nm_cmd_line_add_string (cmd, "plugin"); - nm_cmd_line_add_string (cmd, "rp-pppoe.so"); - nm_cmd_line_add_string (cmd, priv->parent_iface); + char *pppoe_arg; + + g_assert (pppoe_binary != NULL); + + pppoe_arg = g_strdup_printf ("%s -I %s", pppoe_binary, priv->parent_iface); + nm_cmd_line_add_string (cmd, "pty"); + nm_cmd_line_add_string (cmd, pppoe_arg); + g_free (pppoe_arg); } nm_cmd_line_add_string (cmd, "noipdefault"); |
