summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-08-01 09:27:27 +0200
committerAleksander Morgado <aleksander@aleksander.es>2019-08-05 15:07:06 +0200
commit97ffa4d85ce1a9e6f6c5516e89101d31841f0222 (patch)
treee88d23e6914038812d15819c2f153e9cef5298cd
parent94998d9a519450fdbabf570a2b6213c74e88359d (diff)
base-bearer: if method is PPP, require explicit bearer disconnectionmm-1-8
Never automatically flag the bearer as disconnected if it's using PPP, because we could end up using the TTY at the same time as pppd, with the wrong CLOCAL settings. So, whenever we detect that the bearer requires PPP, we will ignore all disconnection reports generated by ModemManager itself. (cherry picked from commit 5f29bd64de8127cb326488d68a2a2b64a45e1f45)
-rw-r--r--src/mm-base-bearer.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c
index f9a12c83..f9da0c24 100644
--- a/src/mm-base-bearer.c
+++ b/src/mm-base-bearer.c
@@ -82,6 +82,9 @@ struct _MMBaseBearerPrivate {
gchar *path;
/* Status of this bearer */
MMBearerStatus status;
+ /* Whether we must ignore all disconnection updates if they're
+ * detected by ModemManager itself. */
+ gboolean ignore_disconnection_reports;
/* Configuration of the bearer */
MMBearerProperties *config;
/* Default IP family of this bearer */
@@ -373,6 +376,8 @@ bearer_update_status (MMBaseBearer *self,
* interface when going into disconnected state. */
if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED) {
bearer_reset_interface_status (self);
+ /* Cleanup flag to ignore disconnection reports */
+ self->priv->ignore_disconnection_reports = FALSE;
/* Stop statistics */
bearer_stats_stop (self);
/* Stop connection monitoring */
@@ -396,6 +401,16 @@ bearer_update_status_connected (MMBaseBearer *self,
MM_GDBUS_BEARER (self),
mm_bearer_ip_config_get_dictionary (ipv6_config));
+ /* If PPP is involved in the requested IP config, we must ignore
+ * all disconnection reports found via CGACT? polling or CGEV URCs.
+ * In this case, upper layers should always explicitly disconnect
+ * the bearer when ownership of the TTY is given back to MM. */
+ if ((ipv4_config && mm_bearer_ip_config_get_method (ipv4_config) == MM_BEARER_IP_METHOD_PPP) ||
+ (ipv6_config && mm_bearer_ip_config_get_method (ipv6_config) == MM_BEARER_IP_METHOD_PPP)) {
+ mm_dbg ("PPP is required for connection, will ignore disconnection reports");
+ self->priv->ignore_disconnection_reports = TRUE;
+ }
+
/* Start statistics */
bearer_stats_start (self);
@@ -1238,13 +1253,46 @@ report_connection_status (MMBaseBearer *self,
bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTED);
}
+/*
+ * This method is used exclusively in two different scenarios:
+ * a) to report disconnections detected by ModemManager itself (e.g. based on
+ * CGACT polling or CGEV URCs), applicable to bearers using both NET and
+ * PPP data ports.
+ * b) to report failed or successful connection attempts by plugins using NET
+ * data ports that rely on vendor-specific URCs (e.g. Icera, MBM, Option
+ * HSO).
+ *
+ * The method is also subclass-able because plugins may require specific
+ * cleanup operations to be done when a bearer is reported as disconnected.
+ * (e.g. the QMI or MBIM implementations require removing signal handlers).
+ *
+ * For all the scenarios involving a) the plugins are required to call the
+ * parent report_connection_status() implementation to report the
+ * DISCONNECTED state. For scenarios involving b) the parent reporting is not
+ * expected at all. In other words, the parent report_connection_status()
+ * is exclusively used in processing disconnections detected by ModemManager
+ * itself.
+ *
+ * If the bearer has been connected and it has required PPP method, we will
+ * ignore all disconnection reports because we cannot disconnect a PPP-based
+ * bearer before the upper layers have stopped using the TTY. In this case,
+ * we must wait for upper layers to detect the disconnection themselves (e.g.
+ * pppd should detect it) and disconnect the bearer through DBus.
+ */
void
-mm_base_bearer_report_connection_status (MMBaseBearer *self,
- MMBearerConnectionStatus status)
+mm_base_bearer_report_connection_status (MMBaseBearer *self,
+ MMBearerConnectionStatus status)
{
+ if ((status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) && self->priv->ignore_disconnection_reports) {
+ mm_info ("ignoring disconnection report for bearer '%s'", self->priv->path);
+ return;
+ }
+
return MM_BASE_BEARER_GET_CLASS (self)->report_connection_status (self, status);
}
+/*****************************************************************************/
+
static void
set_property (GObject *object,
guint prop_id,