summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2016-10-06 11:27:45 -0500
committerDan Williams <dcbw@redhat.com>2016-10-07 14:54:50 -0500
commit58e01e9c98c0482b06c51b107d2d6eb62278b48b (patch)
tree98e3d16a6776b7a7b7539393886db9c94a6c3393
parent7ae2f0f6f4ac660a0941f41021a7e6e634cb1942 (diff)
downloadNetworkManager-58e01e9c98c0482b06c51b107d2d6eb62278b48b.tar.gz
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 (cherry picked from commit 01de14b1ddcd011ebc2f4676e5950b9ec890c698)
-rw-r--r--src/devices/adsl/nm-device-adsl.c2
-rw-r--r--src/devices/nm-device-ethernet.c2
-rw-r--r--src/devices/wwan/nm-modem.c30
-rw-r--r--src/ppp-manager/nm-ppp-manager.c6
-rw-r--r--src/ppp-manager/nm-ppp-manager.h1
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 ebb7a319b4..2ab67c9a91 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -472,7 +472,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 b213a0ccfc..aef464e778 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -935,7 +935,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 2e3d63bb83..9d562be1e5 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"
@@ -491,6 +493,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,
@@ -501,6 +520,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);
@@ -530,8 +550,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 a51f7cfa6c..53fe7ea520 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -834,6 +834,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);
@@ -925,6 +926,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
@@ -1023,6 +1026,7 @@ nm_ppp_manager_start (NMPPPManager *manager,
NMActRequest *req,
const char *ppp_name,
guint32 timeout_secs,
+ guint baud_override,
GError **err)
{
NMPPPManagerPrivate *priv;
@@ -1076,7 +1080,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 188be84e4c..9a8b13dc52 100644
--- a/src/ppp-manager/nm-ppp-manager.h
+++ b/src/ppp-manager/nm-ppp-manager.h
@@ -69,6 +69,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,