[PATCH] wwan/ppp: send explicit port speed to pppd when port speed is zero (rh #1281731)



Some TTY drivers or devices appear to ignore port speed and always
report zero.  Technically this means the port is hung up and control
lines should be disconnected, but with USB devices many of the serial
port attributes are meaningless and ignored by some devices.

pppd requires the port's speed to be greater than zero, and will
exit immediately when that is not the case, even though these
modems will work fine.  Passing an explicit speed to pppd in this
case works around the issue, as pppd attempts to set that speed
on the port and doesn't actually care if that operation fails.

https://bugzilla.redhat.com/show_bug.cgi?id=1281731
---
 src/devices/adsl/nm-device-adsl.c |  2 +-
 src/devices/nm-device-ethernet.c  |  2 +-
 src/devices/wwan/nm-modem.c       | 30 +++++++++++++++++++++++++++++-
 src/ppp-manager/nm-ppp-manager.c  |  6 +++++-
 src/ppp-manager/nm-ppp-manager.h  |  1 +
 5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c
index a5b6641..d1d0a9b 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -477,7 +477,7 @@ act_stage3_ip4_config_start (NMDevice *device,
        }
 
        priv->ppp_manager = nm_ppp_manager_new (ppp_iface);
-       if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) {
+       if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, 0, 
&err)) {
                g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
                                  G_CALLBACK (ppp_state_changed),
                                  self);
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index fd80a60..3604a16 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -937,7 +937,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas
        g_assert (s_pppoe);
 
        priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self)));
-       if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, &err)) 
{
+       if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, 0, 
&err)) {
                g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
                                  G_CALLBACK (ppp_state_changed),
                                  self);
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index d5f12b1..9897424 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -23,7 +23,9 @@
 
 #include "nm-modem.h"
 
+#include <fcntl.h>
 #include <string.h>
+#include <termios.h>
 
 #include "nm-core-internal.h"
 #include "nm-platform.h"
@@ -492,6 +494,23 @@ ppp_stats (NMPPPManager *ppp_manager,
        }
 }
 
+static gboolean
+port_speed_is_zero (const char *port)
+{
+    struct termios options;
+    gs_fd_close int fd = -1;
+
+    fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY);
+    if (fd < 0)
+               return FALSE;
+
+    memset (&options, 0, sizeof (struct termios));
+    if (tcgetattr (fd, &options) != 0)
+        return FALSE;
+
+    return cfgetospeed (&options) == B0;
+}
+
 static NMActStageReturn
 ppp_stage3_ip_config_start (NMModem *self,
                             NMActRequest *req,
@@ -502,6 +521,7 @@ ppp_stage3_ip_config_start (NMModem *self,
        GError *error = NULL;
        NMActStageReturn ret;
        guint ip_timeout = 30;
+       guint baud_override = 0;
 
        g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
        g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
@@ -531,8 +551,16 @@ ppp_stage3_ip_config_start (NMModem *self,
                ip_timeout = priv->mm_ip_timeout;
        }
 
+       /* Some tty drivers and modems ignore port speed, but pppd requires the
+        * port speed to be > 0 or it exits. If the port speed is 0 pass an
+        * explicit speed to pppd to prevent the exit.
+        * https://bugzilla.redhat.com/show_bug.cgi?id=1281731
+        */
+       if (port_speed_is_zero (priv->data_port))
+               baud_override = 57600;
+
        priv->ppp_manager = nm_ppp_manager_new (priv->data_port);
-       if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) {
+       if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, baud_override, &error)) {
                g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
                                  G_CALLBACK (ppp_state_changed),
                                  self);
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 0f0b9a5..1db2a79 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -707,6 +707,7 @@ create_pppd_cmd_line (NMPPPManager *self,
                       NMSettingPppoe *pppoe,
                       NMSettingAdsl  *adsl,
                       const char *ppp_name,
+                      guint baud_override,
                       GError **err)
 {
        NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
@@ -798,6 +799,8 @@ create_pppd_cmd_line (NMPPPManager *self,
 
        if (nm_setting_ppp_get_baud (setting))
                nm_cmd_line_add_int (cmd, nm_setting_ppp_get_baud (setting));
+       else if (baud_override)
+               nm_cmd_line_add_int (cmd, (int) baud_override);
 
        /* noauth by default, because we certainly don't have any information
         * with which to verify anything the peer gives us if we ask it to
@@ -896,6 +899,7 @@ nm_ppp_manager_start (NMPPPManager *manager,
                       NMActRequest *req,
                       const char *ppp_name,
                       guint32 timeout_secs,
+                      guint baud_override,
                       GError **err)
 {
        NMPPPManagerPrivate *priv;
@@ -949,7 +953,7 @@ nm_ppp_manager_start (NMPPPManager *manager,
 
        adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
 
-       ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, adsl_setting, ppp_name, err);
+       ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, adsl_setting, ppp_name, baud_override, 
err);
        if (!ppp_cmd)
                goto out;
 
diff --git a/src/ppp-manager/nm-ppp-manager.h b/src/ppp-manager/nm-ppp-manager.h
index da1fdb5..1274817 100644
--- a/src/ppp-manager/nm-ppp-manager.h
+++ b/src/ppp-manager/nm-ppp-manager.h
@@ -44,6 +44,7 @@ gboolean nm_ppp_manager_start (NMPPPManager *manager,
                                NMActRequest *req,
                                const char *ppp_name,
                                guint32 timeout_secs,
+                               guint baud_override,
                                GError **err);
 
 void     nm_ppp_manager_stop        (NMPPPManager *manager,
-- 
2.7.4


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