diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2019-01-25 11:24:41 +0100 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2019-01-25 11:24:41 +0100 |
| commit | bbae86d3d2997a853ca0365e8eb7a3ca7489ee09 (patch) | |
| tree | 1f7fa49b47ab13aea3effbe839559d221f6323b4 /src/devices/wwan | |
| parent | 404ebe62622150e77e311777dff8617eb974e834 (diff) | |
New upstream version 1.15.2
Diffstat (limited to 'src/devices/wwan')
| -rw-r--r-- | src/devices/wwan/libnm-wwan.ver | 1 | ||||
| -rw-r--r-- | src/devices/wwan/meson.build | 14 | ||||
| -rw-r--r-- | src/devices/wwan/nm-device-modem.c | 88 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem-broadband.c | 100 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem-ofono.c | 99 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem.c | 219 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem.h | 22 |
7 files changed, 233 insertions, 310 deletions
diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 70b954c5..ea966afe 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -6,7 +6,6 @@ global: nm_modem_complete_connection; nm_modem_deactivate; nm_modem_deactivate_async; - nm_modem_deactivate_async_finish; nm_modem_device_state_changed; nm_modem_get_capabilities; nm_modem_get_configured_mtu; diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build index 5fe6e433..482dc205 100644 --- a/src/devices/wwan/meson.build +++ b/src/devices/wwan/meson.build @@ -1,13 +1,13 @@ sources = files( 'nm-modem-broadband.c', 'nm-modem.c', - 'nm-modem-manager.c' + 'nm-modem-manager.c', ) deps = [ libsystemd_dep, mm_glib_dep, - nm_dep + nm_dep, ] if enable_ofono @@ -25,12 +25,12 @@ libnm_wwan = shared_module( ], link_depends: linker_script, install: true, - install_dir: nm_plugindir + install_dir: nm_plugindir, ) libnm_wwan_dep = declare_dependency( include_directories: include_directories('.'), - link_with: libnm_wwan + link_with: libnm_wwan, ) core_plugins += libnm_wwan @@ -43,7 +43,7 @@ test( sources = files( 'nm-device-modem.c', - 'nm-wwan-factory.c' + 'nm-wwan-factory.c', ) libnm_device_plugin_wwan = shared_module( @@ -55,7 +55,7 @@ libnm_device_plugin_wwan = shared_module( link_depends: linker_script_devices, install: true, install_dir: nm_plugindir, - install_rpath: nm_plugindir + install_rpath: nm_plugindir, ) core_plugins += libnm_device_plugin_wwan @@ -63,7 +63,7 @@ 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 + depends: libnm_device_plugin_wwan, ) # FIXME: check_so_symbols replacement diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 4119d598..bd9ee3bb 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -61,7 +61,7 @@ struct _NMDeviceModemClass { G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) -#define NM_DEVICE_MODEM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceModem, NM_IS_DEVICE_MODEM) +#define NM_DEVICE_MODEM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceModem, NM_IS_DEVICE_MODEM, NMDevice) /*****************************************************************************/ @@ -125,14 +125,40 @@ modem_prepare_result (NMModem *modem, if (success) nm_device_activate_schedule_stage2_device_config (device); else { - if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { - /* If the connect failed because the SIM PIN was wrong don't allow - * the device to be auto-activated anymore, which would risk locking - * the SIM if the incorrect PIN continues to be used. - */ + /* There are several reasons to block autoconnection at device level: + * + * - Wrong SIM-PIN: The device won't autoconnect because it doesn't make sense + * to retry the connection with the same PIN. This error also makes autoconnection + * blocked at settings level, so not even a modem unplug and replug will allow + * autoconnection again. It is somewhat redundant to block autoconnection at + * both device and setting level really. + * + * - SIM wrong or not inserted: If the modem is reporting a SIM not inserted error, + * we can block autoconnection at device level, so that if the same device is + * unplugged and replugged with a SIM (or if a SIM hotplug event happens in MM, + * recreating the device completely), we can try the autoconnection again. + * + * - Modem initialization failed: For some reason unknown to NM, the modem wasn't + * initialized correctly, which leads to an unusable device. A device unplug and + * replug may solve the issue, so make it a device-level autoconnection blocking + * reason. + */ + switch (nm_device_state_reason_check (reason)) { + case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: + case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: + case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN); + break; + case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: + case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: + nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_SIM_MISSING); + break; + case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: + nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INIT_FAILED); + break; + default: + break; } - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); } } @@ -218,7 +244,7 @@ modem_ip6_config_result (NMModem *modem, } /* Re-enable IPv6 on the interface */ - nm_device_ipv6_sysctl_set (device, "disable_ipv6", "0"); + nm_device_sysctl_ip_conf_set (device, AF_INET6, "disable_ipv6", "0"); if (config) nm_device_set_wwan_ip6_config (device, config); @@ -277,7 +303,7 @@ ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) * 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"); + nm_device_sysctl_ip_conf_set (device, AF_INET6, "disable_ipv6", "1"); } static void @@ -448,7 +474,7 @@ check_connection_available (NMDevice *device, state = nm_modem_get_state (priv->modem); if (state <= NM_MODEM_STATE_INITIALIZING) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "modem not initalized"); + "modem not initialized"); return FALSE; } @@ -483,44 +509,35 @@ deactivate (NMDevice *device) /*****************************************************************************/ -static gboolean -deactivate_async_finish (NMDevice *self, - GAsyncResult *res, - GError **error) -{ - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} - static void -modem_deactivate_async_ready (NMModem *modem, - GAsyncResult *res, - GSimpleAsyncResult *simple) +modem_deactivate_async_cb (NMModem *modem, + GError *error, + gpointer user_data) { - GError *error = NULL; + gs_unref_object NMDevice *self = NULL; + NMDeviceDeactivateCallback callback; + gpointer callback_user_data; - if (!nm_modem_deactivate_async_finish (modem, res, &error)) - g_simple_async_result_take_error (simple, error); - g_simple_async_result_complete (simple); - g_object_unref (simple); + nm_utils_user_data_unpack (user_data, &self, &callback, &callback_user_data); + callback (self, error, callback_user_data); } static void deactivate_async (NMDevice *self, GCancellable *cancellable, - GAsyncReadyCallback callback, + NMDeviceDeactivateCallback callback, gpointer user_data) { - GSimpleAsyncResult *simple; + nm_assert (G_IS_CANCELLABLE (cancellable)); + nm_assert (callback); - simple = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - deactivate_async); - nm_modem_deactivate_async (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) self)->modem, + nm_modem_deactivate_async (NM_DEVICE_MODEM_GET_PRIVATE (self)->modem, self, cancellable, - (GAsyncReadyCallback) modem_deactivate_async_ready, - simple); + modem_deactivate_async_cb, + nm_utils_user_data_pack (g_object_ref (self), + callback, + user_data)); } /*****************************************************************************/ @@ -805,7 +822,6 @@ nm_device_modem_class_init (NMDeviceModemClass *klass) device_class->check_connection_available = check_connection_available; device_class->complete_connection = complete_connection; device_class->deactivate_async = deactivate_async; - device_class->deactivate_async_finish = deactivate_async_finish; device_class->deactivate = deactivate; device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 04cb8599..82e9e2f1 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -279,11 +279,6 @@ create_gsm_connect_properties (NMConnection *connection) setting = nm_connection_get_setting_gsm (connection); properties = mm_simple_connect_properties_new (); - /* TODO: not needed */ - str = nm_setting_gsm_get_number (setting); - if (str) - mm_simple_connect_properties_set_number (properties, str); - /* Blank APN ("") means the default subscription APN */ str = nm_setting_gsm_get_apn (setting); mm_simple_connect_properties_set_apn (properties, str ?: ""); @@ -693,10 +688,6 @@ complete_connection (NMModem *_self, return FALSE; } - /* TODO: This is not needed */ - if (!nm_setting_gsm_get_number (s_gsm)) - g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - nm_utils_complete_generic (NM_PLATFORM_GET, connection, NM_SETTING_GSM_SETTING_NAME, @@ -884,7 +875,7 @@ static_stage3_ip4_done (NMModemBroadband *self) /* Fully fail if invalid IP address retrieved */ address_string = mm_bearer_ip_config_get_address (self->_priv.ipv4_config); if ( !address_string - || !nm_utils_parse_inaddr_bin (AF_INET, address_string, &address_network)) { + || !nm_utils_parse_inaddr_bin (AF_INET, address_string, NULL, &address_network)) { error = g_error_new (NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s", @@ -896,7 +887,7 @@ static_stage3_ip4_done (NMModemBroadband *self) /* Missing gateway not a hard failure */ gw_string = mm_bearer_ip_config_get_gateway (self->_priv.ipv4_config); if ( gw_string - && !nm_utils_parse_inaddr_bin (AF_INET, gw_string, &gw)) { + && !nm_utils_parse_inaddr_bin (AF_INET, gw_string, NULL, &gw)) { error = g_error_new (NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"", @@ -937,7 +928,7 @@ static_stage3_ip4_done (NMModemBroadband *self) /* DNS servers */ dns = mm_bearer_ip_config_get_dns (self->_priv.ipv4_config); for (i = 0; dns && dns[i]; i++) { - if ( nm_utils_parse_inaddr_bin (AF_INET, dns[i], &address_network) + if ( nm_utils_parse_inaddr_bin (AF_INET, dns[i], NULL, &address_network) && address_network > 0) { nm_ip4_config_add_nameserver (config, address_network); _LOGI (" DNS %s", dns[i]); @@ -1098,100 +1089,101 @@ stage3_ip6_config_request (NMModem *modem, NMDeviceStateReason *out_failure_reas typedef struct { NMModemBroadband *self; - GSimpleAsyncResult *result; + _NMModemDisconnectCallback callback; + gpointer callback_user_data; GCancellable *cancellable; gboolean warn; } DisconnectContext; static void -disconnect_context_complete (DisconnectContext *ctx) +disconnect_context_complete (DisconnectContext *ctx, GError *error) { - g_simple_async_result_complete_in_idle (ctx->result); - if (ctx->cancellable) - g_object_unref (ctx->cancellable); - g_object_unref (ctx->result); + if (ctx->callback) + ctx->callback (NM_MODEM (ctx->self), error, ctx->callback_user_data); + nm_g_object_unref (ctx->cancellable); g_object_unref (ctx->self); g_slice_free (DisconnectContext, ctx); } -static gboolean -disconnect_finish (NMModem *self, - GAsyncResult *res, - GError **error) +static void +disconnect_context_complete_on_idle (gpointer user_data, + GCancellable *cancellable) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + DisconnectContext *ctx = user_data; + gs_free_error GError *cancelled_error = NULL; + + g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error); + disconnect_context_complete (ctx, cancelled_error); } static void -simple_disconnect_ready (MMModemSimple *modem_iface, +simple_disconnect_ready (GObject *source_object, GAsyncResult *res, - DisconnectContext *ctx) + gpointer user_data) { + MMModemSimple *modem_iface = MM_MODEM_SIMPLE (source_object); + DisconnectContext *ctx = user_data; GError *error = NULL; if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { - if (ctx->warn && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { + if ( ctx->warn + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { NMModemBroadband *self = ctx->self; _LOGW ("failed to disconnect modem: %s", error->message); } - g_simple_async_result_take_error (ctx->result, error); } - disconnect_context_complete (ctx); + disconnect_context_complete (ctx, error); } static void disconnect (NMModem *modem, gboolean warn, GCancellable *cancellable, - GAsyncReadyCallback callback, + _NMModemDisconnectCallback callback, gpointer user_data) { NMModemBroadband *self = NM_MODEM_BROADBAND (modem); DisconnectContext *ctx; - GError *error = NULL; connect_context_clear (self); - ctx = g_slice_new (DisconnectContext); - ctx->cancellable = NULL; + + ctx = g_slice_new0 (DisconnectContext); ctx->self = g_object_ref (self); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - disconnect); + ctx->cancellable = nm_g_object_ref (cancellable); + ctx->callback = callback; + ctx->callback_user_data = user_data; + /* Don't bother warning on FAILED since the modem is already gone */ ctx->warn = warn; - /* Already cancelled? */ - if (g_cancellable_set_error_if_cancelled (cancellable, &error)) { - g_simple_async_result_take_error (ctx->result, error); - disconnect_context_complete (ctx); - return; - } - - /* If no simple iface, we're done */ - if (!ctx->self->_priv.simple_iface) { - disconnect_context_complete (ctx); + /* Already cancelled or no simple-iface? We are done. */ + if ( !ctx->self->_priv.simple_iface + || g_cancellable_is_cancelled (cancellable)) { + nm_utils_invoke_on_idle (disconnect_context_complete_on_idle, + ctx, + cancellable); return; } _LOGD ("notifying ModemManager about the modem disconnection"); - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - mm_modem_simple_disconnect (ctx->self->_priv.simple_iface, + mm_modem_simple_disconnect (self->_priv.simple_iface, NULL, /* bearer path; if NULL given ALL get disconnected */ cancellable, - (GAsyncReadyCallback) simple_disconnect_ready, + simple_disconnect_ready, ctx); } /*****************************************************************************/ static void -deactivate_cleanup (NMModem *_self, NMDevice *device) +deactivate_cleanup (NMModem *modem, + NMDevice *device, + gboolean stop_ppp_manager) { - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + NMModemBroadband *self = NM_MODEM_BROADBAND (modem); /* TODO: cancel SimpleConnect() if any */ @@ -1202,8 +1194,9 @@ deactivate_cleanup (NMModem *_self, NMDevice *device) self->_priv.pin_tries = 0; - /* Chain up parent's */ - NM_MODEM_CLASS (nm_modem_broadband_parent_class)->deactivate_cleanup (_self, device); + NM_MODEM_CLASS (nm_modem_broadband_parent_class)->deactivate_cleanup (modem, + device, + stop_ppp_manager); } /*****************************************************************************/ @@ -1468,7 +1461,6 @@ nm_modem_broadband_class_init (NMModemBroadbandClass *klass) modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; modem_class->stage3_ip6_config_request = stage3_ip6_config_request; modem_class->disconnect = disconnect; - modem_class->disconnect_finish = disconnect_finish; modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->set_mm_enabled = set_mm_enabled; modem_class->get_user_pass = get_user_pass; diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index ea668590..8efe0253 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -146,30 +146,36 @@ update_modem_state (NMModemOfono *self) /* Disconnect */ typedef struct { NMModemOfono *self; - GSimpleAsyncResult *result; + _NMModemDisconnectCallback callback; + gpointer callback_user_data; GCancellable *cancellable; gboolean warn; } DisconnectContext; static void -disconnect_context_complete (DisconnectContext *ctx) +disconnect_context_complete (DisconnectContext *ctx, GError *error) { - if (ctx->cancellable) - g_object_unref (ctx->cancellable); - if (ctx->result) { - g_simple_async_result_complete_in_idle (ctx->result); - g_object_unref (ctx->result); - } + if (ctx->callback) + ctx->callback (NM_MODEM (ctx->self), error, ctx->callback_user_data); + nm_g_object_unref (ctx->cancellable); g_object_unref (ctx->self); g_slice_free (DisconnectContext, ctx); } -static gboolean -disconnect_finish (NMModem *self, - GAsyncResult *result, - GError **error) +static void +disconnect_context_complete_on_idle (gpointer user_data, + GCancellable *cancellable) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); + DisconnectContext *ctx = user_data; + gs_free_error GError *error = NULL; + + if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) { + g_set_error_literal (&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + ("modem is currently not connected")); + } + disconnect_context_complete (ctx, error); } static void @@ -177,16 +183,14 @@ disconnect_done (GObject *source, GAsyncResult *result, gpointer user_data) { - DisconnectContext *ctx = (DisconnectContext*) user_data; + DisconnectContext *ctx = user_data; NMModemOfono *self = ctx->self; gs_free_error GError *error = NULL; gs_unref_variant GVariant *v = NULL; v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - if (ctx->result) - g_simple_async_result_take_error (ctx->result, g_steal_pointer (&error)); - disconnect_context_complete (ctx); + disconnect_context_complete (ctx, error); return; } @@ -196,21 +200,21 @@ disconnect_done (GObject *source, _LOGD ("modem disconnected"); update_modem_state (self); - disconnect_context_complete (ctx); + disconnect_context_complete (ctx, error); } static void disconnect (NMModem *modem, gboolean warn, GCancellable *cancellable, - GAsyncReadyCallback callback, + _NMModemDisconnectCallback callback, gpointer user_data) { NMModemOfono *self = NM_MODEM_OFONO (modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); DisconnectContext *ctx; NMModemState state = nm_modem_get_state (NM_MODEM (self)); - GError *error = NULL; + gs_free_error GError *error = NULL; _LOGD ("warn: %s modem_state: %s", warn ? "TRUE" : "FALSE", @@ -218,37 +222,19 @@ disconnect (NMModem *modem, ctx = g_slice_new0 (DisconnectContext); ctx->self = g_object_ref (self); + ctx->cancellable = nm_g_object_ref (cancellable); ctx->warn = warn; - if (callback) { - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - disconnect); - } - - if (state != NM_MODEM_STATE_CONNECTED) { - if (ctx->result) { - g_set_error_literal (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - ("modem is currently not connected")); - g_simple_async_result_take_error (ctx->result, error); - } - disconnect_context_complete (ctx); + ctx->callback = callback; + ctx->callback_user_data = user_data; + + if ( state != NM_MODEM_STATE_CONNECTED + || g_cancellable_is_cancelled (cancellable)) { + nm_utils_invoke_on_idle (disconnect_context_complete_on_idle, + ctx, + cancellable); return; } - if (g_cancellable_set_error_if_cancelled (cancellable, &error)) { - if (ctx->result) - g_simple_async_result_take_error (ctx->result, error); - else - g_clear_error (&error); - disconnect_context_complete (ctx); - return; - } - - ctx->cancellable = nm_g_object_ref (cancellable); - nm_modem_set_state (NM_MODEM (self), NM_MODEM_STATE_DISCONNECTING, nm_modem_state_to_string (NM_MODEM_STATE_DISCONNECTING)); @@ -266,7 +252,9 @@ disconnect (NMModem *modem, } static void -deactivate_cleanup (NMModem *modem, NMDevice *device) +deactivate_cleanup (NMModem *modem, + NMDevice *device, + gboolean stop_ppp_manager) { NMModemOfono *self = NM_MODEM_OFONO (modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); @@ -275,7 +263,9 @@ deactivate_cleanup (NMModem *modem, NMDevice *device) g_clear_object (&priv->ip4_config); - NM_MODEM_CLASS (nm_modem_ofono_parent_class)->deactivate_cleanup (modem, device); + NM_MODEM_CLASS (nm_modem_ofono_parent_class)->deactivate_cleanup (modem, + device, + stop_ppp_manager); } static gboolean @@ -883,7 +873,7 @@ context_property_changed (GDBusProxy *proxy, goto out; } if ( !s - || !nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) { + || !nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &address_network)) { _LOGW ("can't convert 'Address' %s to addr", s ?: ""); goto out; } @@ -897,7 +887,7 @@ context_property_changed (GDBusProxy *proxy, goto out; } if ( !s - || !nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) { + || !nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &address_network)) { _LOGW ("invalid 'Netmask': %s", s ?: ""); goto out; } @@ -911,7 +901,7 @@ context_property_changed (GDBusProxy *proxy, _LOGW ("Settings 'Gateway' missing"); goto out; } - if (!nm_utils_parse_inaddr_bin (AF_INET, s, &gateway_network)) { + if (!nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &gateway_network)) { _LOGW ("invalid 'Gateway': %s", s); goto out; } @@ -938,7 +928,7 @@ context_property_changed (GDBusProxy *proxy, } if (array) { for (iter = array; *iter; iter++) { - if ( nm_utils_parse_inaddr_bin (AF_INET, *iter, &address_network) + if ( nm_utils_parse_inaddr_bin (AF_INET, *iter, NULL, &address_network) && address_network) { _LOGI ("DNS: %s", *iter); nm_ip4_config_add_nameserver (priv->ip4_config, address_network); @@ -958,7 +948,7 @@ context_property_changed (GDBusProxy *proxy, if (g_variant_lookup (v_dict, "MessageProxy", "&s", &s)) { _LOGI ("MessageProxy: %s", s); if ( s - && nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) { + && nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &address_network)) { nm_modem_get_route_parameters (NM_MODEM (self), &ip4_route_table, &ip4_route_metric, @@ -1319,7 +1309,6 @@ nm_modem_ofono_class_init (NMModemOfonoClass *klass) modem_class->get_capabilities = get_capabilities; modem_class->disconnect = disconnect; - modem_class->disconnect_finish = disconnect_finish; modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem; diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 59b081e9..11ada549 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -706,13 +706,13 @@ nm_modem_stage3_ip4_config_start (NMModem *self, nm_modem_set_route_parameters_from_device (self, device); - method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + method = nm_utils_get_ip_config_method (connection, AF_INET); /* Only Disabled and Auto methods make sense for WWAN */ - if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) + if (nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) return NM_ACT_STAGE_RETURN_SUCCESS; - if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) != 0) { + if (!nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { _LOGE ("unhandled WWAN IPv4 method '%s'; will fail", method); NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED); return NM_ACT_STAGE_RETURN_FAILURE; @@ -823,13 +823,13 @@ nm_modem_stage3_ip6_config_start (NMModem *self, nm_modem_set_route_parameters_from_device (self, device); - method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + method = nm_utils_get_ip_config_method (connection, AF_INET6); /* Only Ignore and Auto methods make sense for WWAN */ - if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) + if (nm_streq (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) return NM_ACT_STAGE_RETURN_IP_DONE; - if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) != 0) { + if (!nm_streq (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { _LOGW ("unhandled WWAN IPv6 method '%s'; will fail", method); NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); @@ -1105,7 +1105,9 @@ nm_modem_complete_connection (NMModem *self, /*****************************************************************************/ static void -deactivate_cleanup (NMModem *self, NMDevice *device) +deactivate_cleanup (NMModem *self, + NMDevice *device, + gboolean stop_ppp_manager) { NMModemPrivate *priv; int ifindex; @@ -1126,7 +1128,8 @@ deactivate_cleanup (NMModem *self, NMDevice *device) if (priv->ppp_manager) { g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); - nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL); + if (stop_ppp_manager) + nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL, NULL); g_clear_object (&priv->ppp_manager); } @@ -1157,189 +1160,109 @@ deactivate_cleanup (NMModem *self, NMDevice *device) /*****************************************************************************/ -typedef enum { - DEACTIVATE_CONTEXT_STEP_FIRST, - DEACTIVATE_CONTEXT_STEP_CLEANUP, - DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP, - DEACTIVATE_CONTEXT_STEP_MM_DISCONNECT, - DEACTIVATE_CONTEXT_STEP_LAST -} DeactivateContextStep; - typedef struct { NMModem *self; NMDevice *device; GCancellable *cancellable; - GSimpleAsyncResult *result; - DeactivateContextStep step; - NMPPPManager *ppp_manager; - NMPPPManagerStopHandle *ppp_stop_handle; - gulong ppp_stop_cancellable_id; + NMModemDeactivateCallback callback; + gpointer callback_user_data; } DeactivateContext; static void -deactivate_context_complete (DeactivateContext *ctx) +deactivate_context_complete (DeactivateContext *ctx, GError *error) { - if (ctx->ppp_stop_handle) - nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); + NMModem *self = ctx->self; - nm_assert (!ctx->ppp_stop_handle); - nm_assert (ctx->ppp_stop_cancellable_id == 0); + _LOGD ("modem deactivation finished %s%s%s", + NM_PRINT_FMT_QUOTED (error, "with failure: ", error->message, "", "successfully")); - if (ctx->ppp_manager) - g_object_unref (ctx->ppp_manager); - if (ctx->cancellable) - g_object_unref (ctx->cancellable); - g_simple_async_result_complete_in_idle (ctx->result); - g_object_unref (ctx->result); + if (ctx->callback) + ctx->callback (ctx->self, error, ctx->callback_user_data); + nm_g_object_unref (ctx->cancellable); g_object_unref (ctx->device); g_object_unref (ctx->self); g_slice_free (DeactivateContext, ctx); } -gboolean -nm_modem_deactivate_async_finish (NMModem *self, - GAsyncResult *res, - GError **error) -{ - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} - -static void deactivate_step (DeactivateContext *ctx); - static void -disconnect_ready (NMModem *self, - GAsyncResult *res, - DeactivateContext *ctx) +_deactivate_call_disconnect_cb (NMModem *self, + GError *error, + gpointer user_data) { - GError *error = NULL; - - if (!NM_MODEM_GET_CLASS (self)->disconnect_finish (self, res, &error)) { - g_simple_async_result_take_error (ctx->result, error); - deactivate_context_complete (ctx); - return; - } - - /* Go on */ - ctx->step++; - deactivate_step (ctx); + deactivate_context_complete (user_data, error); } static void -ppp_manager_stop_ready (NMPPPManager *ppp_manager, - NMPPPManagerStopHandle *handle, - gboolean was_cancelled, - gpointer user_data) +_deactivate_call_disconnect (DeactivateContext *ctx) { - DeactivateContext *ctx = user_data; - - 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)); - } - - if (was_cancelled) - return; - - ctx->step++; - deactivate_step (ctx); + NM_MODEM_GET_CLASS (ctx->self)->disconnect (ctx->self, + FALSE, + ctx->cancellable, + _deactivate_call_disconnect_cb, + ctx); } static void -ppp_manager_stop_cancelled (GCancellable *cancellable, - gpointer user_data) +_deactivate_ppp_manager_stop_cb (NMPPPManager *ppp_manager, + NMPPPManagerStopHandle *handle, + gboolean was_cancelled, + gpointer user_data) { DeactivateContext *ctx = user_data; - nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); -} - -static void -deactivate_step (DeactivateContext *ctx) -{ - NMModem *self = ctx->self; - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - GError *error = NULL; + g_object_unref (ppp_manager); - /* Check cancellable in each step */ - if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { - g_simple_async_result_take_error (ctx->result, error); - deactivate_context_complete (ctx); - return; - } - - switch (ctx->step) { - case DEACTIVATE_CONTEXT_STEP_FIRST: - ctx->step++; - /* fall through */ - case DEACTIVATE_CONTEXT_STEP_CLEANUP: - /* Make sure we keep a ref to the PPP manager if there is one */ - if (priv->ppp_manager) - ctx->ppp_manager = g_object_ref (priv->ppp_manager); - /* Run cleanup */ - NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, ctx->device); - ctx->step++; - /* fall through */ - case DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP: - /* If we have a PPP manager, stop it */ - if (ctx->ppp_manager) { - 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++; - /* fall through */ - case DEACTIVATE_CONTEXT_STEP_MM_DISCONNECT: - /* Disconnect asynchronously */ - NM_MODEM_GET_CLASS (self)->disconnect (self, - FALSE, - ctx->cancellable, - (GAsyncReadyCallback) disconnect_ready, - ctx); - return; + if (was_cancelled) { + gs_free_error GError *error = NULL; - case DEACTIVATE_CONTEXT_STEP_LAST: - _LOGD ("modem deactivation finished"); - deactivate_context_complete (ctx); + if (!g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) + nm_assert_not_reached (); + deactivate_context_complete (ctx, error); return; } - g_assert_not_reached (); + nm_assert (!g_cancellable_is_cancelled (ctx->cancellable)); + _deactivate_call_disconnect (ctx); } void nm_modem_deactivate_async (NMModem *self, NMDevice *device, GCancellable *cancellable, - GAsyncReadyCallback callback, + NMModemDeactivateCallback callback, gpointer user_data) { + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); DeactivateContext *ctx; + NMPPPManager *ppp_manager; + + g_return_if_fail (NM_IS_MODEM (self)); + g_return_if_fail (NM_IS_DEVICE (device)); + g_return_if_fail (G_IS_CANCELLABLE (cancellable)); - ctx = g_slice_new0 (DeactivateContext); + ctx = g_slice_new (DeactivateContext); ctx->self = g_object_ref (self); ctx->device = g_object_ref (device); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - nm_modem_deactivate_async); - /* FIXME(shutdown): we always require a cancellable, otherwise we cannot - * do a coordinated shutdown. */ - ctx->cancellable = nm_g_object_ref (cancellable); + ctx->cancellable = g_object_ref (cancellable); + ctx->callback = callback; + ctx->callback_user_data = user_data; + + ppp_manager = nm_g_object_ref (priv->ppp_manager); + + NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, ctx->device, FALSE); + + if (ppp_manager) { + /* If we have a PPP manager, stop it. + * + * Pass on the reference in @ppp_manager. */ + nm_ppp_manager_stop (ppp_manager, + ctx->cancellable, + _deactivate_ppp_manager_stop_cb, + ctx); + return; + } - /* Start */ - ctx->step = DEACTIVATE_CONTEXT_STEP_FIRST; - deactivate_step (ctx); + _deactivate_call_disconnect (ctx); } /*****************************************************************************/ @@ -1348,7 +1271,7 @@ void nm_modem_deactivate (NMModem *self, NMDevice *device) { /* First cleanup */ - NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, device); + NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, device, TRUE); /* Then disconnect without waiting */ NM_MODEM_GET_CLASS (self)->disconnect (self, FALSE, NULL, NULL, NULL); } @@ -1387,7 +1310,7 @@ nm_modem_device_state_changed (NMModem *self, if (new_state == NM_DEVICE_STATE_FAILED || new_state == NM_DEVICE_STATE_DISCONNECTED) warn = FALSE; /* First cleanup */ - NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, NULL); + NM_MODEM_GET_CLASS (self)->deactivate_cleanup (self, NULL, TRUE); NM_MODEM_GET_CLASS (self)->disconnect (self, warn, NULL, NULL, NULL); } break; diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index c73745ce..f7b6bfe9 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -109,6 +109,10 @@ struct _NMModem { typedef struct _NMModem NMModem; +typedef void (*_NMModemDisconnectCallback) (NMModem *modem, + GError *error, + gpointer user_data); + typedef struct { GObjectClass parent; @@ -149,13 +153,12 @@ typedef struct { void (*disconnect) (NMModem *self, gboolean warn, GCancellable *cancellable, - GAsyncReadyCallback callback, + _NMModemDisconnectCallback callback, gpointer user_data); - gboolean (*disconnect_finish) (NMModem *self, - GAsyncResult *res, - GError **error); - void (*deactivate_cleanup) (NMModem *self, NMDevice *device); + void (*deactivate_cleanup) (NMModem *self, + NMDevice *device, + gboolean stop_ppp_manager); gboolean (*owns_port) (NMModem *self, const char *iface); } NMModemClass; @@ -236,14 +239,15 @@ void nm_modem_get_secrets (NMModem *modem, void nm_modem_deactivate (NMModem *modem, NMDevice *device); +typedef void (*NMModemDeactivateCallback) (NMModem *self, + GError *error, + gpointer user_data); + void nm_modem_deactivate_async (NMModem *self, NMDevice *device, GCancellable *cancellable, - GAsyncReadyCallback callback, + NMModemDeactivateCallback callback, gpointer user_data); -gboolean nm_modem_deactivate_async_finish (NMModem *self, - GAsyncResult *res, - GError **error); void nm_modem_device_state_changed (NMModem *modem, NMDeviceState new_state, |