diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index a5b6641abf..d1d0a9b0de 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 fd80a607a2..3604a168a8 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 d5f12b1cc2..9897424466 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -23,7 +23,9 @@ #include "nm-modem.h" +#include #include +#include #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 0f0b9a5939..1db2a794a3 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 da1fdb5539..12748176a3 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,