diff options
author | Dan Williams <dcbw@redhat.com> | 2014-02-09 03:49:55 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2014-02-21 09:45:06 -0600 |
commit | 9d50e9dbd9d84f5e8df32895bc245dadf133aa39 (patch) | |
tree | a1fe5461a4a184254947dd186cd366aad9101097 | |
parent | 5c1dee10cde3cc7cf74718650702dd124d46aa75 (diff) | |
download | NetworkManager-9d50e9dbd9d84f5e8df32895bc245dadf133aa39.tar.gz |
mobile: fix removal of ethernet interfaces owned by modems
If the kernel doesn't tag a modem's ethernet interface with
DEVTYPE=wwan then NetworkManager has no idea that's a modem
(and cannot be used until connected via the control port).
Since DEVTYPE=wwan devices get ignored by NM, so should these
interfaces when NM knows they are modems.
That got broken at some point for ModemManager1, because the
data port isn't read until the modem is connected. NM only
looked for and removed the data-port-as-ethernet-device when
the modem was added, long before the MM1 data port was found.
ModemManager does provide a list of ports owned by the modem
though, which we can use at modem addition time to remove
an ethernet device that is controled by the modem.
-rw-r--r-- | src/modem-manager/nm-modem-broadband.c | 15 | ||||
-rw-r--r-- | src/modem-manager/nm-modem.c | 21 | ||||
-rw-r--r-- | src/modem-manager/nm-modem.h | 4 | ||||
-rw-r--r-- | src/nm-manager.c | 29 |
4 files changed, 58 insertions, 11 deletions
diff --git a/src/modem-manager/nm-modem-broadband.c b/src/modem-manager/nm-modem-broadband.c index 611931f6b9..5acce68f79 100644 --- a/src/modem-manager/nm-modem-broadband.c +++ b/src/modem-manager/nm-modem-broadband.c @@ -124,6 +124,20 @@ get_capabilities (NMModem *_self, *current_caps = (NMDeviceModemCapabilities) mm_modem_get_current_capabilities (self->priv->modem_iface); } +static gboolean +owns_port (NMModem *_self, const char *iface) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + const MMModemPortInfo *ports = NULL; + guint n_ports = 0, i; + gboolean owns = FALSE; + + mm_modem_peek_ports (self->priv->modem_iface, &ports, &n_ports); + for (i = 0; i < n_ports && !owns; i++) + owns = (g_strcmp0 (iface, ports[i].name) == 0); + return owns; +} + /*****************************************************************************/ static void @@ -916,6 +930,7 @@ nm_modem_broadband_class_init (NMModemBroadbandClass *klass) modem_class->check_connection_compatible = check_connection_compatible; modem_class->complete_connection = complete_connection; modem_class->act_stage1_prepare = act_stage1_prepare; + modem_class->owns_port = owns_port; /* Properties */ g_object_class_install_property diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index f427142e2b..e88ebe1bd7 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -661,6 +661,27 @@ nm_modem_get_data_port (NMModem *self) NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; } +gboolean +nm_modem_owns_port (NMModem *self, const char *iface) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + g_return_val_if_fail (iface != NULL, FALSE); + + if (NM_MODEM_GET_CLASS (self)->owns_port) + return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); + + /* Fall back to data/control ports */ + if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0)) + return TRUE; + if (priv->data_port && (strcmp (priv->data_port, iface) == 0)) + return TRUE; + if (priv->control_port && (strcmp (priv->control_port, iface) == 0)) + return TRUE; + + return FALSE; +} + /*****************************************************************************/ void diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index 531c79388e..db20407006 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -108,6 +108,8 @@ typedef struct { void (*deactivate) (NMModem *self, NMDevice *device); + gboolean (*owns_port) (NMModem *self, const char *iface); + /* Signals */ void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason); @@ -127,6 +129,8 @@ const char *nm_modem_get_control_port (NMModem *modem); const char *nm_modem_get_data_port (NMModem *modem); const char *nm_modem_get_driver (NMModem *modem); +gboolean nm_modem_owns_port (NMModem *modem, const char *iface); + void nm_modem_get_capabilities (NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps); diff --git a/src/nm-manager.c b/src/nm-manager.c index 3ae48c8538..7cb71a63c7 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -550,19 +550,22 @@ modem_added (NMModemManager *modem_manager, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *replace_device, *device = NULL; + NMDevice *device = NULL; const char *modem_iface; - GSList *iter; + GSList *iter, *remove = NULL; - /* Don't rely only on the data port; use the control port if available */ - modem_iface = nm_modem_get_data_port (modem); - if (!modem_iface) - modem_iface = nm_modem_get_control_port (modem); - g_return_if_fail (modem_iface); - - replace_device = find_device_by_ip_iface (NM_MANAGER (user_data), modem_iface); - if (replace_device) - remove_device (NM_MANAGER (user_data), replace_device, FALSE); + /* Remove ethernet devices that are actually owned by the modem, since + * they cannot be used as normal ethernet. + */ + for (iter = priv->devices; iter; iter = iter->next) { + if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_ETHERNET) { + if (nm_modem_owns_port (modem, nm_device_get_ip_iface (iter->data))) + remove = g_slist_prepend (remove, iter->data); + } + } + for (iter = remove; iter; iter = iter->next) + remove_device (self, NM_DEVICE (iter->data), FALSE); + g_slist_free (remove); /* Give Bluetooth DUN devices first chance to claim the modem */ for (iter = priv->devices; iter; iter = g_slist_next (iter)) { @@ -577,6 +580,10 @@ modem_added (NMModemManager *modem_manager, * by the Bluetooth code during the connection process. */ if (driver && !strcmp (driver, "bluetooth")) { + modem_iface = nm_modem_get_data_port (modem); + if (!modem_iface) + modem_iface = nm_modem_get_control_port (modem); + nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", modem_iface); return; } |