From ee9c73a923909e23a649407be77e25235d769e25 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 11 May 2018 22:08:45 +0200 Subject: New upstream version 1.10.8 --- src/devices/wwan/libnm-wwan.ver | 2 +- src/devices/wwan/meson.build | 75 --------- src/devices/wwan/nm-device-modem.c | 96 ++++++----- src/devices/wwan/nm-modem-broadband.c | 65 ++++---- src/devices/wwan/nm-modem-ofono.c | 26 +-- src/devices/wwan/nm-modem.c | 294 ++++++++++++---------------------- src/devices/wwan/nm-modem.h | 19 +-- src/devices/wwan/nm-wwan-factory.c | 8 +- 8 files changed, 207 insertions(+), 378 deletions(-) delete mode 100644 src/devices/wwan/meson.build (limited to 'src/devices/wwan') diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 70b954c5..6efcb03f 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -11,10 +11,10 @@ global: nm_modem_get_capabilities; nm_modem_get_configured_mtu; nm_modem_get_control_port; + nm_modem_get_data_port; nm_modem_get_driver; nm_modem_get_iid; nm_modem_get_path; - nm_modem_get_ip_ifindex; nm_modem_get_secrets; nm_modem_get_state; nm_modem_get_type; diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build deleted file mode 100644 index 032b3585..00000000 --- a/src/devices/wwan/meson.build +++ /dev/null @@ -1,75 +0,0 @@ -sources = files( - 'nm-modem-broadband.c', - 'nm-modem.c', - 'nm-modem-manager.c' -) - -deps = [ - libsystemd_dep, - mm_glib_dep, - nm_dep -] - -if enable_ofono - sources += files('nm-modem-ofono.c') -endif - -linker_script = join_paths(meson.current_source_dir(), 'libnm-wwan.ver') - -libnm_wwan = shared_module( - 'nm-wwan', - sources: sources, - dependencies: deps, - link_args: [ - '-Wl,--version-script,@0@'.format(linker_script), - ], - link_depends: linker_script, - install: true, - install_dir: nm_pkglibdir -) - -libnm_wwan_dep = declare_dependency( - include_directories: include_directories('.'), - link_with: libnm_wwan -) - -core_plugins += libnm_wwan - -run_target( - 'check-wwan', - command: [check_exports, libnm_wwan.full_path(), linker_script], - depends: libnm_wwan -) - -sources = files( - 'nm-device-modem.c', - 'nm-wwan-factory.c' -) - -libnm_device_plugin_wwan = shared_module( - 'nm-device-plugin-wwan', - sources: sources, - dependencies: deps, - link_with: libnm_wwan, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_wwan - -run_target( - 'check-local-devices-wwan', - command: [check_exports, libnm_device_plugin_wwan.full_path(), linker_script_devices], - depends: libnm_device_plugin_wwan -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devices/wwan/libnm-wwan.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so) - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-wwan.so "$(srcdir)/src/devices/wwan/libnm-wwan.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-wwan.so) -''' diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 2a3e9ebe..b79d145d 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -32,6 +32,8 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Modem.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceModem); @@ -258,26 +260,21 @@ modem_ip6_config_result (NMModem *modem, } static void -ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); - - if (!nm_device_is_activating (device)) - return; + NMDevice *self = NM_DEVICE (user_data); + gboolean changed; - if (!nm_device_set_ip_ifindex (device, - nm_modem_get_ip_ifindex (modem))) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } + /* We set the IP iface in the device as soon as we know it, so that we + * properly ifup it if needed */ + changed = nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); /* Disable IPv6 immediately on the interface since NM handles IPv6 * internally, and leaving it enabled could allow the kernel's IPv6 * RA handling code to run before NM is ready. */ - nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); + if (changed) + nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); } static void @@ -434,7 +431,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); @@ -632,7 +629,11 @@ set_modem (NMDeviceModem *self, NMModem *modem) g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); - g_signal_connect (modem, "notify::" NM_MODEM_IP_IFINDEX, G_CALLBACK (ip_ifindex_changed_cb), self); + /* In the old ModemManager the data port is known from the very beginning; + * while in the new ModemManager the data port is set afterwards when the bearer gets + * created */ + g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); + g_signal_connect (modem, "notify::" NM_MODEM_DEVICE_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_OPERATOR_ID, G_CALLBACK (ids_changed_cb), self); @@ -707,23 +708,34 @@ nm_device_modem_new (NMModem *modem) { NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + NMDevice *device; + const char *data_port; g_return_val_if_fail (NM_IS_MODEM (modem), NULL); /* Load capabilities */ nm_modem_get_capabilities (modem, &caps, ¤t_caps); - return g_object_new (NM_TYPE_DEVICE_MODEM, - NM_DEVICE_UDI, nm_modem_get_path (modem), - NM_DEVICE_IFACE, nm_modem_get_uid (modem), - NM_DEVICE_DRIVER, nm_modem_get_driver (modem), - NM_DEVICE_TYPE_DESC, "Broadband", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, - NM_DEVICE_MODEM_MODEM, modem, - NM_DEVICE_MODEM_CAPABILITIES, caps, - NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, - NULL); + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM, + NM_DEVICE_UDI, nm_modem_get_path (modem), + NM_DEVICE_IFACE, nm_modem_get_uid (modem), + NM_DEVICE_DRIVER, nm_modem_get_driver (modem), + NM_DEVICE_TYPE_DESC, "Broadband", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, + NM_DEVICE_MODEM_MODEM, modem, + NM_DEVICE_MODEM_CAPABILITIES, caps, + NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, + NULL); + + /* If the data port is known, set it as the IP interface immediately */ + data_port = nm_modem_get_data_port (modem); + if (data_port) { + nm_device_set_ip_iface (device, data_port); + nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); + } + + return device; } static void @@ -731,41 +743,23 @@ dispose (GObject *object) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); - if (priv->modem) { + if (priv->modem) g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object)); - g_clear_object (&priv->modem); - } + g_clear_object (&priv->modem); G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_modem = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_MODEM, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ModemCapabilities", "u", NM_DEVICE_MODEM_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("CurrentCapabilities", "u", NM_DEVICE_MODEM_CURRENT_CAPABILITIES), - ), - ), - .legacy_property_changed = TRUE, -}; - static void -nm_device_modem_class_init (NMDeviceModemClass *klass) +nm_device_modem_class_init (NMDeviceModemClass *mclass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (mclass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (mclass); object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_modem); - device_class->get_generic_capabilities = get_generic_capabilities; device_class->get_type_description = get_type_description; device_class->check_connection_compatible = check_connection_compatible; @@ -808,4 +802,8 @@ nm_device_modem_class_init (NMDeviceModemClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (mclass), + NMDBUS_TYPE_DEVICE_MODEM_SKELETON, + NULL); } diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 9a3744db..dc0ce303 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -339,7 +339,7 @@ connect_context_clear (NMModemBroadband *self) ConnectContext *ctx = self->_priv.ctx; g_clear_error (&ctx->first_error); - g_clear_pointer (&ctx->ip_types, g_array_unref); + g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); nm_clear_g_cancellable (&ctx->cancellable); g_clear_object (&ctx->connection); g_clear_object (&ctx->connect_properties); @@ -385,10 +385,9 @@ connect_ready (MMModemSimple *simple_iface, g_dbus_error_strip_remote_error (error); ctx->first_error = error; } else - g_clear_error (&error); + g_error_free (error); - if ( ctx->ip_type_tries == 0 - && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { + if (ctx->ip_type_tries == 0 && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { /* Try one more time */ ctx->ip_type_tries++; } else { @@ -411,20 +410,21 @@ connect_ready (MMModemSimple *simple_iface, if (self->_priv.ipv6_config) ip6_method = get_bearer_ip_method (self->_priv.ipv6_config); - if (!nm_modem_set_data_port (NM_MODEM (self), - NM_PLATFORM_GET, - mm_bearer_get_interface (self->_priv.bearer), - ip4_method, - ip6_method, - mm_bearer_get_ip_timeout (self->_priv.bearer), - &error)) { - _LOGW ("failed to connect modem: %s", error->message); - g_error_free (error); + if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && + ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { + _LOGW ("failed to connect modem: invalid bearer IP configuration"); nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; } + g_object_set (self, + NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->_priv.bearer), + NM_MODEM_IP4_METHOD, ip4_method, + NM_MODEM_IP6_METHOD, ip6_method, + NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->_priv.bearer), + NULL); + ctx->step++; connect_context_step (self); } @@ -663,7 +663,7 @@ check_connection_compatible (NMModem *_self, NMConnection *connection) static gboolean complete_connection (NMModem *_self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -1409,34 +1409,35 @@ nm_modem_broadband_init (NMModemBroadband *self) NMModem * nm_modem_broadband_new (GObject *object, GError **error) { + NMModem *modem; MMObject *modem_object; MMModem *modem_iface; - const char *const*drivers; - gs_free char *driver = NULL; + gchar *drivers; g_return_val_if_fail (MM_IS_OBJECT (object), NULL); modem_object = MM_OBJECT (object); /* Ensure we have the 'Modem' interface and the primary port at least */ modem_iface = mm_object_peek_modem (modem_object); - g_return_val_if_fail (modem_iface, NULL); - g_return_val_if_fail (mm_modem_get_primary_port (modem_iface), NULL); + g_return_val_if_fail (!!modem_iface, NULL); + g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL); /* Build a single string with all drivers listed */ - drivers = mm_modem_get_drivers (modem_iface); - if (drivers) - driver = g_strjoinv (", ", (char **) drivers); - - return g_object_new (NM_TYPE_MODEM_BROADBAND, - NM_MODEM_PATH, mm_object_get_path (modem_object), - NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), - NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), - NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), - NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), - NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), - NM_MODEM_BROADBAND_MODEM, modem_object, - NM_MODEM_DRIVER, driver, - NULL); + drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface)); + + modem = g_object_new (NM_TYPE_MODEM_BROADBAND, + NM_MODEM_PATH, mm_object_get_path (modem_object), + NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), + NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), + NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */ + NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), + NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), + NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), + NM_MODEM_BROADBAND_MODEM, modem_object, + NM_MODEM_DRIVER, drivers, + NULL); + g_free (drivers); + return modem; } static void diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index a1c6aef2..811c3afb 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -836,7 +836,6 @@ context_property_changed (GDBusProxy *proxy, guint32 address_network, gateway_network; guint32 ip4_route_table, ip4_route_metric; int ifindex; - GError *error = NULL; _LOGD ("PropertyChanged: %s", property); @@ -861,26 +860,27 @@ context_property_changed (GDBusProxy *proxy, _LOGW ("Settings 'Interface' missing"); goto out; } + if (!interface || !interface[0]) { + _LOGW ("Settings 'Interface'; empty"); + goto out; + } - _LOGD ("Interface: %s", interface); - if (!nm_modem_set_data_port (NM_MODEM (self), - NM_PLATFORM_GET, - interface, - NM_MODEM_IP_METHOD_STATIC, - NM_MODEM_IP_METHOD_UNKNOWN, - 0, - &error)) { - _LOGW ("failed to connect to modem: %s", error->message); - g_clear_error (&error); + ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, interface); + if (ifindex <= 0) { + _LOGW ("Interface \"%s\" not found", interface); goto out; } - ifindex = nm_modem_get_ip_ifindex (NM_MODEM (self)); - nm_assert (ifindex > 0); + _LOGD ("Interface: %s", interface); + g_object_set (self, + NM_MODEM_DATA_PORT, interface, + NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC, + NULL); /* TODO: verify handling of ip4_config; check other places it's used... */ g_clear_object (&priv->ip4_config); + priv->ip4_config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex); diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 61b7247e..010a2b60 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -44,10 +44,13 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMModem, PROP_CONTROL_PORT, - PROP_IP_IFINDEX, + PROP_DATA_PORT, PROP_PATH, PROP_UID, PROP_DRIVER, + PROP_IP4_METHOD, + PROP_IP6_METHOD, + PROP_IP_TIMEOUT, PROP_STATE, PROP_DEVICE_ID, PROP_SIM_ID, @@ -76,12 +79,7 @@ typedef struct _NMModemPrivate { char *driver; char *control_port; char *data_port; - - /* TODO: ip_iface is solely used for nm_modem_owns_port(). - * We should rework the code that it's not necessary */ - char *ip_iface; - - int ip_ifindex; + char *ppp_iface; NMModemIPMethod ip4_method; NMModemIPMethod ip6_method; NMUtilsIPv6IfaceId iid; @@ -98,7 +96,7 @@ typedef struct _NMModemPrivate { guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; - guint mm_ip_timeout; + guint32 mm_ip_timeout; guint32 ip4_route_table; guint32 ip4_route_metric; @@ -154,10 +152,6 @@ _nmlog_prefix (char *prefix, NMModem *self) _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } G_STMT_END -/*****************************************************************************/ - -static void _set_ip_ifindex (NMModem *self, int ifindex, const char *ifname); - /*****************************************************************************/ /* State/enabled/connected */ @@ -456,28 +450,20 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) +set_data_port (NMModem *self, const char *new_data_port) { - NMModem *self = NM_MODEM (user_data); - - nm_assert (ifindex >= 0); - nm_assert (NM_MODEM_GET_PRIVATE (self)->ppp_manager == ppp_manager); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - if (ifindex <= 0 && iface) { - /* this might happen, if the ifname was already deleted - * and we failed to resolve ifindex. - * - * Forget about the name. */ - iface = NULL; + if (g_strcmp0 (priv->data_port, new_data_port) != 0) { + g_free (priv->data_port); + priv->data_port = g_strdup (new_data_port); + _notify (self, PROP_DATA_PORT); } - _set_ip_ifindex (self, ifindex, iface); } static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { @@ -489,6 +475,9 @@ ppp_ip4_config (NMPPPManager *ppp_manager, guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ gboolean dns_workaround = FALSE; + /* Notify about the new data port to use */ + set_data_port (self, iface); + /* Work around a PPP bug (#1732) which causes many mobile broadband * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. * Apparently fixed in ppp-2.4.5 but we've had some reports that this is @@ -530,12 +519,16 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static void ppp_ip6_config (NMPPPManager *ppp_manager, + const char *iface, const NMUtilsIPv6IfaceId *iid, NMIP6Config *config, gpointer user_data) { NMModem *self = NM_MODEM (user_data); + /* Notify about the new data port to use */ + set_data_port (self, iface); + NM_MODEM_GET_PRIVATE (self)->iid = *iid; nm_modem_emit_ip6_config_result (self, config, NULL); @@ -564,18 +557,6 @@ port_speed_is_zero (const char *port) { struct termios options; nm_auto_close int fd = -1; - gs_free char *path = NULL; - - nm_assert (port); - - if (port[0] != '/') { - if ( !port[0] - || strchr (port, '/') - || NM_IN_STRSET (port, ".", "..")) - return FALSE; - path = g_build_path ("/sys/class/tty", port, NULL); - port = path; - } fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC); if (fd < 0) @@ -617,12 +598,6 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_FAILURE; } - if (!priv->data_port) { - _LOGE ("error starting PPP (no data port)"); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, * use the default one (30s) */ if (priv->mm_ip_timeout > 0) { @@ -654,7 +629,9 @@ ppp_stage3_ip_config_start (NMModem *self, ip_timeout, baud_override, &error)) { _LOGE ("error starting PPP: %s", error->message); g_error_free (error); + g_clear_object (&priv->ppp_manager); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -662,9 +639,6 @@ ppp_stage3_ip_config_start (NMModem *self, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1091,20 +1065,12 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { - NMModemClass *klass; - - klass = NM_MODEM_GET_CLASS (self); - if (!klass->complete_connection) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "Modem class %s had no complete_connection method", - G_OBJECT_TYPE_NAME (self)); - return FALSE; - } - - return klass->complete_connection (self, connection, existing_connections, error); + if (NM_MODEM_GET_CLASS (self)->complete_connection) + return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); + return FALSE; } /*****************************************************************************/ @@ -1129,10 +1095,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); - g_clear_object (&priv->ppp_manager); - } + g_clear_object (&priv->ppp_manager); if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1151,12 +1114,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device) } } } - - nm_clear_g_free (&priv->data_port); - priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - _set_ip_ifindex (self, -1, NULL); + + g_free (priv->ppp_iface); + priv->ppp_iface = NULL; } /*****************************************************************************/ @@ -1407,117 +1369,17 @@ nm_modem_get_control_port (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->control_port; } -int -nm_modem_get_ip_ifindex (NMModem *self) -{ - NMModemPrivate *priv; - - g_return_val_if_fail (NM_IS_MODEM (self), 0); - - priv = NM_MODEM_GET_PRIVATE (self); - - /* internally we track an unset ip_ifindex as -1. - * For the caller of nm_modem_get_ip_ifindex(), this - * shall be zero too. */ - return priv->ip_ifindex != -1 ? priv->ip_ifindex : 0; -} - -static void -_set_ip_ifindex (NMModem *self, int ifindex, const char *ifname) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - nm_assert (ifindex >= -1); - nm_assert ((ifindex > 0) == !!ifname); - - if (!nm_streq0 (priv->ip_iface, ifname)) { - g_free (priv->ip_iface); - priv->ip_iface = g_strdup (ifname); - } - - if (priv->ip_ifindex != ifindex) { - priv->ip_ifindex = ifindex; - _notify (self, PROP_IP_IFINDEX); - } -} - -gboolean -nm_modem_set_data_port (NMModem *self, - NMPlatform *platform, - const char *data_port, - NMModemIPMethod ip4_method, - NMModemIPMethod ip6_method, - guint timeout, - GError **error) +const char * +nm_modem_get_data_port (NMModem *self) { - NMModemPrivate *priv; - gboolean is_ppp; - int ifindex = -1; - - g_return_val_if_fail (NM_IS_MODEM (self), FALSE); - g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); - g_return_val_if_fail (!error || !*error, FALSE); - - priv = NM_MODEM_GET_PRIVATE (self); - - if ( priv->ppp_manager - || priv->data_port - || priv->ip_ifindex != -1) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot set data port in activated state"); - /* this really shouldn't happen. Assert. */ - g_return_val_if_reached (FALSE); - } - - if (!data_port) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "missing data port"); - return FALSE; - } - - is_ppp = (ip4_method == NM_MODEM_IP_METHOD_PPP) - || (ip6_method == NM_MODEM_IP_METHOD_PPP); - if (is_ppp) { - if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "conflicting ip methods"); - return FALSE; - } - } else if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || ( ip4_method == NM_MODEM_IP_METHOD_UNKNOWN - && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "invalid ip methods"); - return FALSE; - } - - if (!is_ppp) { - ifindex = nm_platform_if_nametoindex (platform, data_port); - if (ifindex <= 0) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s", data_port); - return FALSE; - } - if (!nm_platform_process_events_ensure_link (platform, ifindex, data_port)) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s in platform cache", data_port); - return FALSE; - } - } + g_return_val_if_fail (NM_IS_MODEM (self), NULL); - priv->mm_ip_timeout = timeout; - priv->ip4_method = ip4_method; - priv->ip6_method = ip6_method; - if (is_ppp) { - priv->data_port = g_strdup (data_port); - _set_ip_ifindex (self, -1, NULL); - } else { - priv->data_port = NULL; - _set_ip_ifindex (self, ifindex, data_port); - } - return TRUE; + /* The ppp_iface takes precedence over the data interface when PPP is used, + * since data_iface is the TTY over which PPP is run, and that TTY can't + * do IP. The caller really wants the thing that's doing IP. + */ + return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? + NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; } gboolean @@ -1530,10 +1392,15 @@ nm_modem_owns_port (NMModem *self, const char *iface) if (NM_MODEM_GET_CLASS (self)->owns_port) return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); - return NM_IN_STRSET (iface, - priv->ip_iface, - priv->data_port, - priv->control_port); + /* 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; } gboolean @@ -1633,8 +1500,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModem *self = NM_MODEM (object); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object); switch (prop_id) { case PROP_PATH: @@ -1646,12 +1512,21 @@ get_property (GObject *object, guint prop_id, case PROP_CONTROL_PORT: g_value_set_string (value, priv->control_port); break; - case PROP_IP_IFINDEX: - g_value_set_int (value, nm_modem_get_ip_ifindex (self)); + case PROP_DATA_PORT: + g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); break; case PROP_UID: g_value_set_string (value, priv->uid); break; + case PROP_IP4_METHOD: + g_value_set_uint (value, priv->ip4_method); + break; + case PROP_IP6_METHOD: + g_value_set_uint (value, priv->ip6_method); + break; + case PROP_IP_TIMEOUT: + g_value_set_uint (value, priv->mm_ip_timeout); + break; case PROP_STATE: g_value_set_int (value, priv->state); break; @@ -1694,10 +1569,23 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->control_port = g_value_dup_string (value); break; + case PROP_DATA_PORT: + g_free (priv->data_port); + priv->data_port = g_value_dup_string (value); + break; case PROP_UID: /* construct-only */ priv->uid = g_value_dup_string (value); break; + case PROP_IP4_METHOD: + priv->ip4_method = g_value_get_uint (value); + break; + case PROP_IP6_METHOD: + priv->ip6_method = g_value_get_uint (value); + break; + case PROP_IP_TIMEOUT: + priv->mm_ip_timeout = g_value_get_uint (value); + break; case PROP_STATE: /* construct-only */ priv->state = g_value_get_int (value); @@ -1735,7 +1623,6 @@ nm_modem_init (NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; - priv->ip_ifindex = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 700; priv->ip6_route_table = RT_TABLE_MAIN; @@ -1751,7 +1638,7 @@ constructed (GObject *object) priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object)); - g_return_if_fail (priv->control_port); + g_return_if_fail (priv->data_port || priv->control_port); } /*****************************************************************************/ @@ -1776,7 +1663,6 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->control_port); g_free (priv->data_port); - g_free (priv->ip_iface); g_free (priv->device_id); g_free (priv->sim_id); g_free (priv->sim_operator_id); @@ -1825,11 +1711,33 @@ nm_modem_class_init (NMModemClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IP_IFINDEX] = - g_param_spec_int (NM_MODEM_IP_IFINDEX, "", "", - 0, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DATA_PORT] = + g_param_spec_string (NM_MODEM_DATA_PORT, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP4_METHOD] = + g_param_spec_uint (NM_MODEM_IP4_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP6_METHOD] = + g_param_spec_uint (NM_MODEM_IP6_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP_TIMEOUT] = + g_param_spec_uint (NM_MODEM_IP_TIMEOUT, "", "", + 0, 360, 20, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATE] = g_param_spec_int (NM_MODEM_STATE, "", "", diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index 3e281c0c..9546e4a1 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -37,7 +37,10 @@ #define NM_MODEM_PATH "path" #define NM_MODEM_DRIVER "driver" #define NM_MODEM_CONTROL_PORT "control-port" -#define NM_MODEM_IP_IFINDEX "ip-ifindex" +#define NM_MODEM_DATA_PORT "data-port" +#define NM_MODEM_IP4_METHOD "ip4-method" +#define NM_MODEM_IP6_METHOD "ip6-method" +#define NM_MODEM_IP_TIMEOUT "ip-timeout" #define NM_MODEM_STATE "state" #define NM_MODEM_DEVICE_ID "device-id" #define NM_MODEM_SIM_ID "sim-id" @@ -126,7 +129,7 @@ typedef struct { gboolean (*complete_connection) (NMModem *modem, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error); NMActStageReturn (*act_stage1_prepare) (NMModem *modem, @@ -164,21 +167,13 @@ GType nm_modem_get_type (void); const char *nm_modem_get_path (NMModem *modem); const char *nm_modem_get_uid (NMModem *modem); const char *nm_modem_get_control_port (NMModem *modem); -int nm_modem_get_ip_ifindex (NMModem *modem); +const char *nm_modem_get_data_port (NMModem *modem); const char *nm_modem_get_driver (NMModem *modem); const char *nm_modem_get_device_id (NMModem *modem); const char *nm_modem_get_sim_id (NMModem *modem); const char *nm_modem_get_sim_operator_id (NMModem *modem); gboolean nm_modem_get_iid (NMModem *modem, NMUtilsIPv6IfaceId *out_iid); -gboolean nm_modem_set_data_port (NMModem *self, - NMPlatform *platform, - const char *data_port, - NMModemIPMethod ip4_method, - NMModemIPMethod ip6_method, - guint timeout, - GError **error); - gboolean nm_modem_owns_port (NMModem *modem, const char *iface); void nm_modem_get_capabilities (NMModem *self, @@ -189,7 +184,7 @@ gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *conn gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error); void nm_modem_get_route_parameters (NMModem *self, diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index f0aae040..663102de 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -80,7 +80,7 @@ modem_added_cb (NMModemManager *manager, { NMWwanFactory *self = NM_WWAN_FACTORY (user_data); NMDevice *device; - const char *driver; + const char *driver, *port; /* Do nothing if the modem was consumed by some other plugin */ if (nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (self), G_OBJECT (modem))) @@ -93,8 +93,10 @@ modem_added_cb (NMModemManager *manager, * by the Bluetooth code during the connection process. */ if (driver && strstr (driver, "bluetooth")) { - nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", - nm_modem_get_control_port (modem)); + port = nm_modem_get_data_port (modem); + if (!port) + port = nm_modem_get_control_port (modem); + nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", port); return; } -- cgit 1.3.0-6-gf8a5 From 04bc9e1cd3544445d883ad29ea108c1645c8e7b7 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Mon, 4 Jun 2018 00:07:45 +0200 Subject: New upstream version 1.11.4 --- src/devices/wwan/libnm-wwan.ver | 2 +- src/devices/wwan/meson.build | 75 +++++++ src/devices/wwan/nm-device-modem.c | 96 ++++----- src/devices/wwan/nm-modem-broadband.c | 69 ++++--- src/devices/wwan/nm-modem-ofono.c | 27 ++- src/devices/wwan/nm-modem.c | 356 +++++++++++++++++++++++----------- src/devices/wwan/nm-modem.h | 19 +- src/devices/wwan/nm-wwan-factory.c | 9 +- 8 files changed, 424 insertions(+), 229 deletions(-) create mode 100644 src/devices/wwan/meson.build (limited to 'src/devices/wwan') diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 6efcb03f..70b954c5 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -11,10 +11,10 @@ global: nm_modem_get_capabilities; nm_modem_get_configured_mtu; nm_modem_get_control_port; - nm_modem_get_data_port; nm_modem_get_driver; nm_modem_get_iid; nm_modem_get_path; + nm_modem_get_ip_ifindex; nm_modem_get_secrets; nm_modem_get_state; nm_modem_get_type; diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build new file mode 100644 index 00000000..abf58594 --- /dev/null +++ b/src/devices/wwan/meson.build @@ -0,0 +1,75 @@ +sources = files( + 'nm-modem-broadband.c', + 'nm-modem.c', + 'nm-modem-manager.c' +) + +deps = [ + libsystemd_dep, + mm_glib_dep, + nm_dep +] + +if enable_ofono + sources += files('nm-modem-ofono.c') +endif + +linker_script = join_paths(meson.current_source_dir(), 'libnm-wwan.ver') + +libnm_wwan = shared_module( + 'nm-wwan', + sources: sources, + dependencies: deps, + link_args: [ + '-Wl,--version-script,@0@'.format(linker_script), + ], + link_depends: linker_script, + install: true, + install_dir: nm_plugindir +) + +libnm_wwan_dep = declare_dependency( + include_directories: include_directories('.'), + link_with: libnm_wwan +) + +core_plugins += libnm_wwan + +run_target( + 'check-wwan', + command: [check_exports, libnm_wwan.full_path(), linker_script], + depends: libnm_wwan +) + +sources = files( + 'nm-device-modem.c', + 'nm-wwan-factory.c' +) + +libnm_device_plugin_wwan = shared_module( + 'nm-device-plugin-wwan', + sources: sources, + dependencies: deps, + link_with: libnm_wwan, + link_args: ldflags_linker_script_devices, + link_depends: linker_script_devices, + install: true, + install_dir: nm_plugindir +) + +core_plugins += libnm_device_plugin_wwan + +run_target( + 'check-local-devices-wwan', + command: [check_exports, libnm_device_plugin_wwan.full_path(), linker_script_devices], + depends: libnm_device_plugin_wwan +) + +# FIXME: check_so_symbols replacement +''' +check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devices/wwan/libnm-wwan.la + $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so "$(srcdir)/linker-script-devices.ver" + $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so) + $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-wwan.so "$(srcdir)/src/devices/wwan/libnm-wwan.ver" + $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-wwan.so) +''' diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index b79d145d..2a3e9ebe 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -32,8 +32,6 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" -#include "introspection/org.freedesktop.NetworkManager.Device.Modem.h" - #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceModem); @@ -260,21 +258,26 @@ modem_ip6_config_result (NMModem *modem, } static void -data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *self = NM_DEVICE (user_data); - gboolean changed; + NMDevice *device = NM_DEVICE (user_data); + + if (!nm_device_is_activating (device)) + return; - /* We set the IP iface in the device as soon as we know it, so that we - * properly ifup it if needed */ - changed = nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); + if (!nm_device_set_ip_ifindex (device, + nm_modem_get_ip_ifindex (modem))) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } /* Disable IPv6 immediately on the interface since NM handles IPv6 * internally, and leaving it enabled could allow the kernel's IPv6 * RA handling code to run before NM is ready. */ - if (changed) - nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); + nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); } static void @@ -431,7 +434,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); @@ -629,11 +632,7 @@ set_modem (NMDeviceModem *self, NMModem *modem) g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); - /* In the old ModemManager the data port is known from the very beginning; - * while in the new ModemManager the data port is set afterwards when the bearer gets - * created */ - g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); - + g_signal_connect (modem, "notify::" NM_MODEM_IP_IFINDEX, G_CALLBACK (ip_ifindex_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_DEVICE_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_OPERATOR_ID, G_CALLBACK (ids_changed_cb), self); @@ -708,34 +707,23 @@ nm_device_modem_new (NMModem *modem) { NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; - NMDevice *device; - const char *data_port; g_return_val_if_fail (NM_IS_MODEM (modem), NULL); /* Load capabilities */ nm_modem_get_capabilities (modem, &caps, ¤t_caps); - device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM, - NM_DEVICE_UDI, nm_modem_get_path (modem), - NM_DEVICE_IFACE, nm_modem_get_uid (modem), - NM_DEVICE_DRIVER, nm_modem_get_driver (modem), - NM_DEVICE_TYPE_DESC, "Broadband", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, - NM_DEVICE_MODEM_MODEM, modem, - NM_DEVICE_MODEM_CAPABILITIES, caps, - NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, - NULL); - - /* If the data port is known, set it as the IP interface immediately */ - data_port = nm_modem_get_data_port (modem); - if (data_port) { - nm_device_set_ip_iface (device, data_port); - nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); - } - - return device; + return g_object_new (NM_TYPE_DEVICE_MODEM, + NM_DEVICE_UDI, nm_modem_get_path (modem), + NM_DEVICE_IFACE, nm_modem_get_uid (modem), + NM_DEVICE_DRIVER, nm_modem_get_driver (modem), + NM_DEVICE_TYPE_DESC, "Broadband", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, + NM_DEVICE_MODEM_MODEM, modem, + NM_DEVICE_MODEM_CAPABILITIES, caps, + NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, + NULL); } static void @@ -743,23 +731,41 @@ dispose (GObject *object) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); - if (priv->modem) + if (priv->modem) { g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object)); - g_clear_object (&priv->modem); + g_clear_object (&priv->modem); + } G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object); } +static const NMDBusInterfaceInfoExtended interface_info_device_modem = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_DEVICE_MODEM, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( + &nm_signal_info_property_changed_legacy, + ), + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ModemCapabilities", "u", NM_DEVICE_MODEM_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("CurrentCapabilities", "u", NM_DEVICE_MODEM_CURRENT_CAPABILITIES), + ), + ), + .legacy_property_changed = TRUE, +}; + static void -nm_device_modem_class_init (NMDeviceModemClass *mclass) +nm_device_modem_class_init (NMDeviceModemClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (mclass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (mclass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_modem); + device_class->get_generic_capabilities = get_generic_capabilities; device_class->get_type_description = get_type_description; device_class->check_connection_compatible = check_connection_compatible; @@ -802,8 +808,4 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (mclass), - NMDBUS_TYPE_DEVICE_MODEM_SKELETON, - NULL); } diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index dc0ce303..e5678b96 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -286,7 +286,7 @@ create_gsm_connect_properties (NMConnection *connection) /* Blank APN ("") means the default subscription APN */ str = nm_setting_gsm_get_apn (setting); - mm_simple_connect_properties_set_apn (properties, str ? str : ""); + mm_simple_connect_properties_set_apn (properties, str ?: ""); str = nm_setting_gsm_get_network_id (setting); if (str) @@ -339,7 +339,7 @@ connect_context_clear (NMModemBroadband *self) ConnectContext *ctx = self->_priv.ctx; g_clear_error (&ctx->first_error); - g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); + g_clear_pointer (&ctx->ip_types, g_array_unref); nm_clear_g_cancellable (&ctx->cancellable); g_clear_object (&ctx->connection); g_clear_object (&ctx->connect_properties); @@ -385,9 +385,10 @@ connect_ready (MMModemSimple *simple_iface, g_dbus_error_strip_remote_error (error); ctx->first_error = error; } else - g_error_free (error); + g_clear_error (&error); - if (ctx->ip_type_tries == 0 && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { + if ( ctx->ip_type_tries == 0 + && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { /* Try one more time */ ctx->ip_type_tries++; } else { @@ -410,21 +411,20 @@ connect_ready (MMModemSimple *simple_iface, if (self->_priv.ipv6_config) ip6_method = get_bearer_ip_method (self->_priv.ipv6_config); - if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && - ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { - _LOGW ("failed to connect modem: invalid bearer IP configuration"); + if (!nm_modem_set_data_port (NM_MODEM (self), + NM_PLATFORM_GET, + mm_bearer_get_interface (self->_priv.bearer), + ip4_method, + ip6_method, + mm_bearer_get_ip_timeout (self->_priv.bearer), + &error)) { + _LOGW ("failed to connect modem: %s", error->message); + g_error_free (error); nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; } - g_object_set (self, - NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->_priv.bearer), - NM_MODEM_IP4_METHOD, ip4_method, - NM_MODEM_IP6_METHOD, ip6_method, - NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->_priv.bearer), - NULL); - ctx->step++; connect_context_step (self); } @@ -663,7 +663,7 @@ check_connection_compatible (NMModem *_self, NMConnection *connection) static gboolean complete_connection (NMModem *_self, NMConnection *connection, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -924,7 +924,6 @@ static_stage3_ip4_done (NMModemBroadband *self) _LOGI (" address %s/%d", address_string, address.plen); - nm_modem_get_route_parameters (NM_MODEM (self), &ip4_route_table, &ip4_route_metric, @@ -1283,7 +1282,6 @@ get_sim_ready (MMModem *modem, GError *error = NULL; MMSim *new_sim; - new_sim = mm_modem_get_sim_finish (modem, res, &error); if (new_sim != self->_priv.sim_iface) { g_clear_object (&self->_priv.sim_iface); @@ -1409,35 +1407,34 @@ nm_modem_broadband_init (NMModemBroadband *self) NMModem * nm_modem_broadband_new (GObject *object, GError **error) { - NMModem *modem; MMObject *modem_object; MMModem *modem_iface; - gchar *drivers; + const char *const*drivers; + gs_free char *driver = NULL; g_return_val_if_fail (MM_IS_OBJECT (object), NULL); modem_object = MM_OBJECT (object); /* Ensure we have the 'Modem' interface and the primary port at least */ modem_iface = mm_object_peek_modem (modem_object); - g_return_val_if_fail (!!modem_iface, NULL); - g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL); + g_return_val_if_fail (modem_iface, NULL); + g_return_val_if_fail (mm_modem_get_primary_port (modem_iface), NULL); /* Build a single string with all drivers listed */ - drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface)); - - modem = g_object_new (NM_TYPE_MODEM_BROADBAND, - NM_MODEM_PATH, mm_object_get_path (modem_object), - NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), - NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), - NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */ - NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), - NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), - NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), - NM_MODEM_BROADBAND_MODEM, modem_object, - NM_MODEM_DRIVER, drivers, - NULL); - g_free (drivers); - return modem; + drivers = mm_modem_get_drivers (modem_iface); + if (drivers) + driver = g_strjoinv (", ", (char **) drivers); + + return g_object_new (NM_TYPE_MODEM_BROADBAND, + NM_MODEM_PATH, mm_object_get_path (modem_object), + NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), + NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), + NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), + NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), + NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), + NM_MODEM_BROADBAND_MODEM, modem_object, + NM_MODEM_DRIVER, driver, + NULL); } static void diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index 811c3afb..8b81ac41 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -278,7 +278,6 @@ deactivate_cleanup (NMModem *modem, NMDevice *device) NM_MODEM_CLASS (nm_modem_ofono_parent_class)->deactivate_cleanup (modem, device); } - static gboolean check_connection_compatible (NMModem *modem, NMConnection *connection) @@ -836,6 +835,7 @@ context_property_changed (GDBusProxy *proxy, guint32 address_network, gateway_network; guint32 ip4_route_table, ip4_route_metric; int ifindex; + GError *error = NULL; _LOGD ("PropertyChanged: %s", property); @@ -860,27 +860,26 @@ context_property_changed (GDBusProxy *proxy, _LOGW ("Settings 'Interface' missing"); goto out; } - if (!interface || !interface[0]) { - _LOGW ("Settings 'Interface'; empty"); - goto out; - } - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, interface); - if (ifindex <= 0) { - _LOGW ("Interface \"%s\" not found", interface); + _LOGD ("Interface: %s", interface); + if (!nm_modem_set_data_port (NM_MODEM (self), + NM_PLATFORM_GET, + interface, + NM_MODEM_IP_METHOD_STATIC, + NM_MODEM_IP_METHOD_UNKNOWN, + 0, + &error)) { + _LOGW ("failed to connect to modem: %s", error->message); + g_clear_error (&error); goto out; } - _LOGD ("Interface: %s", interface); - g_object_set (self, - NM_MODEM_DATA_PORT, interface, - NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC, - NULL); + ifindex = nm_modem_get_ip_ifindex (NM_MODEM (self)); + nm_assert (ifindex > 0); /* TODO: verify handling of ip4_config; check other places it's used... */ g_clear_object (&priv->ip4_config); - priv->ip4_config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex); diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 010a2b60..fbe99cc3 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -44,13 +44,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMModem, PROP_CONTROL_PORT, - PROP_DATA_PORT, + PROP_IP_IFINDEX, PROP_PATH, PROP_UID, PROP_DRIVER, - PROP_IP4_METHOD, - PROP_IP6_METHOD, - PROP_IP_TIMEOUT, PROP_STATE, PROP_DEVICE_ID, PROP_SIM_ID, @@ -79,7 +76,12 @@ typedef struct _NMModemPrivate { char *driver; char *control_port; char *data_port; - char *ppp_iface; + + /* TODO: ip_iface is solely used for nm_modem_owns_port(). + * We should rework the code that it's not necessary */ + char *ip_iface; + + int ip_ifindex; NMModemIPMethod ip4_method; NMModemIPMethod ip6_method; NMUtilsIPv6IfaceId iid; @@ -96,7 +98,7 @@ typedef struct _NMModemPrivate { guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; - guint32 mm_ip_timeout; + guint mm_ip_timeout; guint32 ip4_route_table; guint32 ip4_route_metric; @@ -152,6 +154,10 @@ _nmlog_prefix (char *prefix, NMModem *self) _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } G_STMT_END +/*****************************************************************************/ + +static void _set_ip_ifindex (NMModem *self, int ifindex, const char *ifname); + /*****************************************************************************/ /* State/enabled/connected */ @@ -199,7 +205,7 @@ nm_modem_set_state (NMModem *self, _LOGI ("modem state changed, '%s' --> '%s' (reason: %s)", nm_modem_state_to_string (old_state), nm_modem_state_to_string (new_state), - reason ? reason : "none"); + reason ?: "none"); priv->state = new_state; _notify (self, PROP_STATE); @@ -450,20 +456,28 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -set_data_port (NMModem *self, const char *new_data_port) +ppp_ifindex_set (NMPPPManager *ppp_manager, + int ifindex, + const char *iface, + gpointer user_data) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModem *self = NM_MODEM (user_data); + + nm_assert (ifindex >= 0); + nm_assert (NM_MODEM_GET_PRIVATE (self)->ppp_manager == ppp_manager); - if (g_strcmp0 (priv->data_port, new_data_port) != 0) { - g_free (priv->data_port); - priv->data_port = g_strdup (new_data_port); - _notify (self, PROP_DATA_PORT); + if (ifindex <= 0 && iface) { + /* this might happen, if the ifname was already deleted + * and we failed to resolve ifindex. + * + * Forget about the name. */ + iface = NULL; } + _set_ip_ifindex (self, ifindex, iface); } static void ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, NMIP4Config *config, gpointer user_data) { @@ -475,9 +489,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager, guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ gboolean dns_workaround = FALSE; - /* Notify about the new data port to use */ - set_data_port (self, iface); - /* Work around a PPP bug (#1732) which causes many mobile broadband * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. * Apparently fixed in ppp-2.4.5 but we've had some reports that this is @@ -519,16 +530,12 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static void ppp_ip6_config (NMPPPManager *ppp_manager, - const char *iface, const NMUtilsIPv6IfaceId *iid, NMIP6Config *config, gpointer user_data) { NMModem *self = NM_MODEM (user_data); - /* Notify about the new data port to use */ - set_data_port (self, iface); - NM_MODEM_GET_PRIVATE (self)->iid = *iid; nm_modem_emit_ip6_config_result (self, config, NULL); @@ -557,6 +564,18 @@ port_speed_is_zero (const char *port) { struct termios options; nm_auto_close int fd = -1; + gs_free char *path = NULL; + + nm_assert (port); + + if (port[0] != '/') { + if ( !port[0] + || strchr (port, '/') + || NM_IN_STRSET (port, ".", "..")) + return FALSE; + path = g_build_path ("/sys/class/tty", port, NULL); + port = path; + } fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC); if (fd < 0) @@ -598,6 +617,12 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_FAILURE; } + if (!priv->data_port) { + _LOGE ("error starting PPP (no data port)"); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, * use the default one (30s) */ if (priv->mm_ip_timeout > 0) { @@ -629,9 +654,7 @@ ppp_stage3_ip_config_start (NMModem *self, ip_timeout, baud_override, &error)) { _LOGE ("error starting PPP: %s", error->message); g_error_free (error); - g_clear_object (&priv->ppp_manager); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -639,6 +662,9 @@ ppp_stage3_ip_config_start (NMModem *self, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, + G_CALLBACK (ppp_ifindex_set), + self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1065,12 +1091,20 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error) { - if (NM_MODEM_GET_CLASS (self)->complete_connection) - return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); - return FALSE; + NMModemClass *klass; + + klass = NM_MODEM_GET_CLASS (self); + if (!klass->complete_connection) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "Modem class %s had no complete_connection method", + G_OBJECT_TYPE_NAME (self)); + return FALSE; + } + + return klass->complete_connection (self, connection, existing_connections, error); } /*****************************************************************************/ @@ -1095,7 +1129,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - g_clear_object (&priv->ppp_manager); + if (priv->ppp_manager) { + g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); + nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL); + g_clear_object (&priv->ppp_manager); + } if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1114,11 +1152,12 @@ deactivate_cleanup (NMModem *self, NMDevice *device) } } } + + nm_clear_g_free (&priv->data_port); + priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - - g_free (priv->ppp_iface); - priv->ppp_iface = NULL; + _set_ip_ifindex (self, -1, NULL); } /*****************************************************************************/ @@ -1138,11 +1177,19 @@ typedef struct { GSimpleAsyncResult *result; DeactivateContextStep step; NMPPPManager *ppp_manager; + NMPPPManagerStopHandle *ppp_stop_handle; + gulong ppp_stop_cancellable_id; } DeactivateContext; static void deactivate_context_complete (DeactivateContext *ctx) { + if (ctx->ppp_stop_handle) + nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); + + nm_assert (!ctx->ppp_stop_handle); + nm_assert (ctx->ppp_stop_cancellable_id == 0); + if (ctx->ppp_manager) g_object_unref (ctx->ppp_manager); if (ctx->cancellable) @@ -1184,25 +1231,36 @@ disconnect_ready (NMModem *self, static void ppp_manager_stop_ready (NMPPPManager *ppp_manager, - GAsyncResult *res, - DeactivateContext *ctx) + NMPPPManagerStopHandle *handle, + gboolean was_cancelled, + gpointer user_data) { - NMModem *self = ctx->self; - GError *error = NULL; + DeactivateContext *ctx = user_data; - if (!nm_ppp_manager_stop_finish (ppp_manager, res, &error)) { - _LOGW ("cannot stop PPP manager: %s", - error->message); - g_simple_async_result_take_error (ctx->result, error); - deactivate_context_complete (ctx); - return; + nm_assert (ctx->ppp_stop_handle == handle); + ctx->ppp_stop_handle = NULL; + + if (ctx->ppp_stop_cancellable_id) { + g_cancellable_disconnect (ctx->cancellable, + nm_steal_int (&ctx->ppp_stop_cancellable_id)); } - /* Go on */ + if (was_cancelled) + return; + ctx->step++; deactivate_step (ctx); } +static void +ppp_manager_stop_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + DeactivateContext *ctx = user_data; + + nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); +} + static void deactivate_step (DeactivateContext *ctx) { @@ -1232,10 +1290,16 @@ deactivate_step (DeactivateContext *ctx) case DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP: /* If we have a PPP manager, stop it */ if (ctx->ppp_manager) { - nm_ppp_manager_stop_async (ctx->ppp_manager, - ctx->cancellable, - (GAsyncReadyCallback) ppp_manager_stop_ready, - ctx); + nm_assert (!ctx->ppp_stop_handle); + if (ctx->cancellable) { + ctx->ppp_stop_cancellable_id = g_cancellable_connect (ctx->cancellable, + G_CALLBACK (ppp_manager_stop_cancelled), + ctx, + NULL); + } + ctx->ppp_stop_handle = nm_ppp_manager_stop (ctx->ppp_manager, + ppp_manager_stop_ready, + ctx); return; } ctx->step++; @@ -1274,7 +1338,9 @@ nm_modem_deactivate_async (NMModem *self, callback, user_data, nm_modem_deactivate_async); - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + /* FIXME(shutdown): we always require a cancellable, otherwise we cannot + * do a coordinated shutdown. */ + ctx->cancellable = nm_g_object_ref (cancellable); /* Start */ ctx->step = DEACTIVATE_CONTEXT_STEP_FIRST; @@ -1369,17 +1435,117 @@ nm_modem_get_control_port (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->control_port; } -const char * -nm_modem_get_data_port (NMModem *self) +int +nm_modem_get_ip_ifindex (NMModem *self) { - g_return_val_if_fail (NM_IS_MODEM (self), NULL); + NMModemPrivate *priv; - /* The ppp_iface takes precedence over the data interface when PPP is used, - * since data_iface is the TTY over which PPP is run, and that TTY can't - * do IP. The caller really wants the thing that's doing IP. - */ - return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? - NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; + g_return_val_if_fail (NM_IS_MODEM (self), 0); + + priv = NM_MODEM_GET_PRIVATE (self); + + /* internally we track an unset ip_ifindex as -1. + * For the caller of nm_modem_get_ip_ifindex(), this + * shall be zero too. */ + return priv->ip_ifindex != -1 ? priv->ip_ifindex : 0; +} + +static void +_set_ip_ifindex (NMModem *self, int ifindex, const char *ifname) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + nm_assert (ifindex >= -1); + nm_assert ((ifindex > 0) == !!ifname); + + if (!nm_streq0 (priv->ip_iface, ifname)) { + g_free (priv->ip_iface); + priv->ip_iface = g_strdup (ifname); + } + + if (priv->ip_ifindex != ifindex) { + priv->ip_ifindex = ifindex; + _notify (self, PROP_IP_IFINDEX); + } +} + +gboolean +nm_modem_set_data_port (NMModem *self, + NMPlatform *platform, + const char *data_port, + NMModemIPMethod ip4_method, + NMModemIPMethod ip6_method, + guint timeout, + GError **error) +{ + NMModemPrivate *priv; + gboolean is_ppp; + int ifindex = -1; + + g_return_val_if_fail (NM_IS_MODEM (self), FALSE); + g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + priv = NM_MODEM_GET_PRIVATE (self); + + if ( priv->ppp_manager + || priv->data_port + || priv->ip_ifindex != -1) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot set data port in activated state"); + /* this really shouldn't happen. Assert. */ + g_return_val_if_reached (FALSE); + } + + if (!data_port) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "missing data port"); + return FALSE; + } + + is_ppp = (ip4_method == NM_MODEM_IP_METHOD_PPP) + || (ip6_method == NM_MODEM_IP_METHOD_PPP); + if (is_ppp) { + if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP) + || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "conflicting ip methods"); + return FALSE; + } + } else if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) + || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) + || ( ip4_method == NM_MODEM_IP_METHOD_UNKNOWN + && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "invalid ip methods"); + return FALSE; + } + + if (!is_ppp) { + ifindex = nm_platform_if_nametoindex (platform, data_port); + if (ifindex <= 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot find network interface %s", data_port); + return FALSE; + } + if (!nm_platform_process_events_ensure_link (platform, ifindex, data_port)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot find network interface %s in platform cache", data_port); + return FALSE; + } + } + + priv->mm_ip_timeout = timeout; + priv->ip4_method = ip4_method; + priv->ip6_method = ip6_method; + if (is_ppp) { + priv->data_port = g_strdup (data_port); + _set_ip_ifindex (self, -1, NULL); + } else { + priv->data_port = NULL; + _set_ip_ifindex (self, ifindex, data_port); + } + return TRUE; } gboolean @@ -1392,15 +1558,10 @@ nm_modem_owns_port (NMModem *self, const char *iface) 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; + return NM_IN_STRSET (iface, + priv->ip_iface, + priv->data_port, + priv->control_port); } gboolean @@ -1500,7 +1661,8 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object); + NMModem *self = NM_MODEM (object); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); switch (prop_id) { case PROP_PATH: @@ -1512,21 +1674,12 @@ get_property (GObject *object, guint prop_id, case PROP_CONTROL_PORT: g_value_set_string (value, priv->control_port); break; - case PROP_DATA_PORT: - g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); + case PROP_IP_IFINDEX: + g_value_set_int (value, nm_modem_get_ip_ifindex (self)); break; case PROP_UID: g_value_set_string (value, priv->uid); break; - case PROP_IP4_METHOD: - g_value_set_uint (value, priv->ip4_method); - break; - case PROP_IP6_METHOD: - g_value_set_uint (value, priv->ip6_method); - break; - case PROP_IP_TIMEOUT: - g_value_set_uint (value, priv->mm_ip_timeout); - break; case PROP_STATE: g_value_set_int (value, priv->state); break; @@ -1569,23 +1722,10 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->control_port = g_value_dup_string (value); break; - case PROP_DATA_PORT: - g_free (priv->data_port); - priv->data_port = g_value_dup_string (value); - break; case PROP_UID: /* construct-only */ priv->uid = g_value_dup_string (value); break; - case PROP_IP4_METHOD: - priv->ip4_method = g_value_get_uint (value); - break; - case PROP_IP6_METHOD: - priv->ip6_method = g_value_get_uint (value); - break; - case PROP_IP_TIMEOUT: - priv->mm_ip_timeout = g_value_get_uint (value); - break; case PROP_STATE: /* construct-only */ priv->state = g_value_get_int (value); @@ -1623,6 +1763,7 @@ nm_modem_init (NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; + priv->ip_ifindex = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 700; priv->ip6_route_table = RT_TABLE_MAIN; @@ -1638,7 +1779,7 @@ constructed (GObject *object) priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object)); - g_return_if_fail (priv->data_port || priv->control_port); + g_return_if_fail (priv->control_port); } /*****************************************************************************/ @@ -1663,6 +1804,7 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->control_port); g_free (priv->data_port); + g_free (priv->ip_iface); g_free (priv->device_id); g_free (priv->sim_id); g_free (priv->sim_operator_id); @@ -1711,33 +1853,11 @@ nm_modem_class_init (NMModemClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_DATA_PORT] = - g_param_spec_string (NM_MODEM_DATA_PORT, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP4_METHOD] = - g_param_spec_uint (NM_MODEM_IP4_METHOD, "", "", - NM_MODEM_IP_METHOD_UNKNOWN, - NM_MODEM_IP_METHOD_AUTO, - NM_MODEM_IP_METHOD_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP6_METHOD] = - g_param_spec_uint (NM_MODEM_IP6_METHOD, "", "", - NM_MODEM_IP_METHOD_UNKNOWN, - NM_MODEM_IP_METHOD_AUTO, - NM_MODEM_IP_METHOD_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP_TIMEOUT] = - g_param_spec_uint (NM_MODEM_IP_TIMEOUT, "", "", - 0, 360, 20, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP_IFINDEX] = + g_param_spec_int (NM_MODEM_IP_IFINDEX, "", "", + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATE] = g_param_spec_int (NM_MODEM_STATE, "", "", diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index 9546e4a1..3e281c0c 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -37,10 +37,7 @@ #define NM_MODEM_PATH "path" #define NM_MODEM_DRIVER "driver" #define NM_MODEM_CONTROL_PORT "control-port" -#define NM_MODEM_DATA_PORT "data-port" -#define NM_MODEM_IP4_METHOD "ip4-method" -#define NM_MODEM_IP6_METHOD "ip6-method" -#define NM_MODEM_IP_TIMEOUT "ip-timeout" +#define NM_MODEM_IP_IFINDEX "ip-ifindex" #define NM_MODEM_STATE "state" #define NM_MODEM_DEVICE_ID "device-id" #define NM_MODEM_SIM_ID "sim-id" @@ -129,7 +126,7 @@ typedef struct { gboolean (*complete_connection) (NMModem *modem, NMConnection *connection, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error); NMActStageReturn (*act_stage1_prepare) (NMModem *modem, @@ -167,13 +164,21 @@ GType nm_modem_get_type (void); const char *nm_modem_get_path (NMModem *modem); const char *nm_modem_get_uid (NMModem *modem); const char *nm_modem_get_control_port (NMModem *modem); -const char *nm_modem_get_data_port (NMModem *modem); +int nm_modem_get_ip_ifindex (NMModem *modem); const char *nm_modem_get_driver (NMModem *modem); const char *nm_modem_get_device_id (NMModem *modem); const char *nm_modem_get_sim_id (NMModem *modem); const char *nm_modem_get_sim_operator_id (NMModem *modem); gboolean nm_modem_get_iid (NMModem *modem, NMUtilsIPv6IfaceId *out_iid); +gboolean nm_modem_set_data_port (NMModem *self, + NMPlatform *platform, + const char *data_port, + NMModemIPMethod ip4_method, + NMModemIPMethod ip6_method, + guint timeout, + GError **error); + gboolean nm_modem_owns_port (NMModem *modem, const char *iface); void nm_modem_get_capabilities (NMModem *self, @@ -184,7 +189,7 @@ gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *conn gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error); void nm_modem_get_route_parameters (NMModem *self, diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index 663102de..a561b58a 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -80,7 +80,7 @@ modem_added_cb (NMModemManager *manager, { NMWwanFactory *self = NM_WWAN_FACTORY (user_data); NMDevice *device; - const char *driver, *port; + const char *driver; /* Do nothing if the modem was consumed by some other plugin */ if (nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (self), G_OBJECT (modem))) @@ -93,10 +93,8 @@ modem_added_cb (NMModemManager *manager, * by the Bluetooth code during the connection process. */ if (driver && strstr (driver, "bluetooth")) { - port = nm_modem_get_data_port (modem); - if (!port) - port = nm_modem_get_control_port (modem); - nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", port); + nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", + nm_modem_get_control_port (modem)); return; } @@ -107,7 +105,6 @@ modem_added_cb (NMModemManager *manager, g_object_unref (device); } - static NMDevice * create_device (NMDeviceFactory *factory, const char *iface, -- cgit 1.3.0-6-gf8a5