diff options
| author | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
| commit | 80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch) | |
| tree | e3b229aa94e8dcf0590f2317664176e7b8f7607b /src/devices/wwan/nm-device-modem.c | |
| parent | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff) | |
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src/devices/wwan/nm-device-modem.c')
| -rw-r--r-- | src/devices/wwan/nm-device-modem.c | 957 |
1 files changed, 0 insertions, 957 deletions
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c deleted file mode 100644 index f77de85a..00000000 --- a/src/devices/wwan/nm-device-modem.c +++ /dev/null @@ -1,957 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2009 - 2019 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-device-modem.h" - -#include "nm-modem.h" -#include "nm-ip4-config.h" -#include "devices/nm-device-private.h" -#include "nm-rfkill-manager.h" -#include "settings/nm-settings-connection.h" -#include "nm-modem-broadband.h" -#include "NetworkManagerUtils.h" -#include "nm-core-internal.h" - -#include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceModem); - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceModem, - PROP_MODEM, - PROP_CAPABILITIES, - PROP_CURRENT_CAPABILITIES, - PROP_DEVICE_ID, - PROP_OPERATOR_CODE, - PROP_APN, ); - -typedef struct { - NMModem * modem; - NMDeviceModemCapabilities caps; - NMDeviceModemCapabilities current_caps; - char * device_id; - char * operator_code; - char * apn; - bool rf_enabled : 1; - NMDeviceStageState stage1_state : 3; -} NMDeviceModemPrivate; - -struct _NMDeviceModem { - NMDevice parent; - NMDeviceModemPrivate _priv; -}; - -struct _NMDeviceModemClass { - NMDeviceClass parent; -}; - -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, NMDevice) - -/*****************************************************************************/ - -static void -ppp_failed(NMModem *modem, guint i_reason, gpointer user_data) -{ - NMDevice * device = NM_DEVICE(user_data); - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDeviceStateReason reason = i_reason; - - switch (nm_device_get_state(device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET); - else if (nm_device_activate_ip6_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET6); - else if (nm_device_activate_ip4_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else if (nm_device_activate_ip6_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - _LOGW(LOGD_MB, - "PPP failure in unexpected state %u", - (guint) nm_device_get_state(device)); - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } -} - -static void -modem_prepare_result(NMModem *modem, gboolean success, guint i_reason, gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMDeviceStateReason reason = i_reason; - - if (nm_device_get_state(device) != NM_DEVICE_STATE_PREPARE - || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING) { - nm_assert_not_reached(); - success = FALSE; - } - - if (!success) { - /* 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); - return; - } - - priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED; - nm_device_activate_schedule_stage1_device_prepare(device, FALSE); -} - -static void -modem_auth_requested(NMModem *modem, gpointer user_data) -{ - NMDevice *device = NM_DEVICE(user_data); - - /* Auth requests (PIN, PAP/CHAP passwords, etc) only get handled - * during activation. - */ - if (!nm_device_is_activating(device)) - return; - - nm_device_state_changed(device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); -} - -static void -modem_auth_result(NMModem *modem, GError *error, gpointer user_data) -{ - NMDevice * device = NM_DEVICE(user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_NEED_AUTH); - - if (error) { - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - return; - } - - priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; - nm_device_activate_schedule_stage1_device_prepare(device, FALSE); -} - -static void -modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data) -{ - NMDeviceModem *self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - - g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE); - - if (error) { - _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config)); - nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL); - } -} - -static void -modem_ip6_config_result(NMModem * modem, - NMIP6Config *config, - gboolean do_slaac, - GError * error, - gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - gs_unref_object NMIP6Config *ignored = NULL; - gboolean got_config = !!config; - - g_return_if_fail(nm_device_activate_ip6_state_in_conf(device) == TRUE); - - if (error) { - _LOGW(LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - /* Re-enable IPv6 on the interface */ - nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0"); - - if (config) - nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config)); - - if (do_slaac == FALSE) { - if (got_config) - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - else { - _LOGW(LOGD_MB | LOGD_IP6, - "retrieving IPv6 configuration failed: SLAAC not requested and no addresses"); - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - return; - } - - /* Start SLAAC now that we have a link-local address from the modem */ - ret = - NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->act_stage3_ip_config_start(device, AF_INET6, (gpointer *) &ignored, &failure_reason); - - nm_assert(ignored == NULL); - - switch (ret) { - case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_ip_method_failed(device, AF_INET6, failure_reason); - break; - case NM_ACT_STAGE_RETURN_IP_FAIL: - /* all done */ - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - break; - case NM_ACT_STAGE_RETURN_POSTPONE: - /* let SLAAC run */ - break; - default: - /* Should never get here since we've assured that the IPv6 method - * will either be "auto" or "ignored" when starting IPv6 configuration. - */ - nm_assert_not_reached(); - } -} - -static void -ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *device = NM_DEVICE(user_data); - - if (!nm_device_is_activating(device)) - return; - - 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. - */ - nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "1"); -} - -static void -operator_code_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * operator_code = nm_modem_get_operator_code(modem); - - if (g_strcmp0(priv->operator_code, operator_code) != 0) { - g_free(priv->operator_code); - priv->operator_code = g_strdup(operator_code); - _notify(self, PROP_OPERATOR_CODE); - } -} - -static void -apn_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * apn = nm_modem_get_apn(modem); - - if (g_strcmp0(priv->apn, apn) != 0) { - g_free(priv->apn); - priv->apn = g_strdup(apn); - _notify(self, PROP_APN); - } -} - -static void -ids_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - nm_device_recheck_available_connections(NM_DEVICE(user_data)); -} - -static void -modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_data) -{ - NMModemState new_state = new_state_i; - NMModemState old_state = old_state_i; - NMDevice * device = NM_DEVICE(user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - NMDeviceState dev_state = nm_device_get_state(device); - - if (new_state <= NM_MODEM_STATE_DISABLING && old_state > NM_MODEM_STATE_DISABLING - && priv->rf_enabled) { - /* Called when the ModemManager modem enabled state is changed externally - * to NetworkManager (eg something using MM's D-Bus API directly). - */ - if (nm_device_is_activating(device) || dev_state == NM_DEVICE_STATE_ACTIVATED) { - /* user-initiated action, hence DISCONNECTED not FAILED */ - nm_device_state_changed(device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - return; - } - } - - if (new_state < NM_MODEM_STATE_CONNECTING && old_state >= NM_MODEM_STATE_CONNECTING - && dev_state >= NM_DEVICE_STATE_NEED_AUTH && dev_state <= NM_DEVICE_STATE_ACTIVATED) { - /* Fail the device if the modem disconnects unexpectedly while the - * device is activating/activated. */ - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); - return; - } - - if (new_state > NM_MODEM_STATE_LOCKED && old_state == NM_MODEM_STATE_LOCKED) { - /* If the modem is now unlocked, enable/disable it according to the - * device's enabled/disabled state. - */ - nm_modem_set_mm_enabled(priv->modem, priv->rf_enabled); - - if (dev_state == NM_DEVICE_STATE_NEED_AUTH) { - /* The modem was unlocked externally to NetworkManager, - * deactivate so the default connection can be - * automatically activated again */ - nm_device_state_changed(device, - NM_DEVICE_STATE_DEACTIVATING, - NM_DEVICE_STATE_REASON_MODEM_AVAILABLE); - } - - /* Now allow connections without a PIN to be available */ - nm_device_recheck_available_connections(device); - } - - nm_device_queue_recheck_available(device, - NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, - NM_DEVICE_STATE_REASON_MODEM_FAILED); -} - -static void -modem_removed_cb(NMModem *modem, gpointer user_data) -{ - g_signal_emit_by_name(NM_DEVICE(user_data), NM_DEVICE_REMOVED); -} - -/*****************************************************************************/ - -static gboolean -owns_iface(NMDevice *device, const char *iface) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - g_return_val_if_fail(priv->modem, FALSE); - - return nm_modem_owns_port(priv->modem, iface); -} - -/*****************************************************************************/ - -static void -device_state_changed(NMDevice * device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - - g_return_if_fail(priv->modem); - - if (new_state == NM_DEVICE_STATE_UNAVAILABLE && old_state < NM_DEVICE_STATE_UNAVAILABLE) { - /* Log initial modem state */ - _LOGI(LOGD_MB, - "modem state '%s'", - nm_modem_state_to_string(nm_modem_get_state(priv->modem))); - } - nm_modem_device_state_changed(priv->modem, new_state, old_state); -} - -static NMDeviceCapabilities -get_generic_capabilities(NMDevice *device) -{ - return NM_DEVICE_CAP_IS_NON_KERNEL; -} - -static const char * -get_type_description(NMDevice *device) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - if (NM_FLAGS_HAS(priv->current_caps, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)) - return "gsm"; - if (NM_FLAGS_HAS(priv->current_caps, NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)) - return "cdma"; - return NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_type_description(device); -} - -static gboolean -check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) -{ - GError *local = NULL; - - if (!NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->check_connection_compatible(device, connection, error)) - return FALSE; - - if (!nm_modem_check_connection_compatible(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, - connection, - error ? &local : NULL)) { - if (error) { - g_set_error(error, - NM_UTILS_ERROR, - g_error_matches(local, - NM_UTILS_ERROR, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE) - ? NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE - : NM_UTILS_ERROR_UNKNOWN, - "modem is incompatible with connection: %s", - local->message); - g_error_free(local); - } - return FALSE; - } - return TRUE; -} - -static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, - NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - NMModemState state; - - if (!priv->rf_enabled) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "RFKILL for modem enabled"); - return FALSE; - } - - if (!priv->modem) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "modem not available"); - return FALSE; - } - - 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 initialized"); - return FALSE; - } - - if (state == NM_MODEM_STATE_LOCKED) { - if (!nm_connection_get_setting_gsm(connection)) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "modem is locked without pin available"); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, - NMConnection *const *existing_connections, - GError ** error) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - return nm_modem_complete_connection(priv->modem, - nm_device_get_iface(device), - connection, - existing_connections, - error); -} - -static void -deactivate(NMDevice *device) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - nm_modem_deactivate(priv->modem, device); - priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; -} - -/*****************************************************************************/ - -static void -modem_deactivate_async_cb(NMModem *modem, GError *error, gpointer user_data) -{ - gs_unref_object NMDevice * self = NULL; - NMDeviceDeactivateCallback callback; - gpointer callback_user_data; - - 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, - NMDeviceDeactivateCallback callback, - gpointer user_data) -{ - nm_assert(G_IS_CANCELLABLE(cancellable)); - nm_assert(callback); - - nm_modem_deactivate_async(NM_DEVICE_MODEM_GET_PRIVATE(self)->modem, - self, - cancellable, - modem_deactivate_async_cb, - nm_utils_user_data_pack(g_object_ref(self), callback, user_data)); -} - -/*****************************************************************************/ - -static NMActStageReturn -act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - NMActRequest * req; - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - if (priv->stage1_state == NM_DEVICE_STAGE_STATE_INIT) { - priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING; - return nm_modem_act_stage1_prepare(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, - req, - out_failure_reason); - } - - if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING) - return NM_ACT_STAGE_RETURN_POSTPONE; - - nm_assert(priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - nm_assert_addr_family(addr_family); - - if (addr_family == AF_INET) { - return nm_modem_stage3_ip4_config_start(priv->modem, - device, - NM_DEVICE_CLASS(nm_device_modem_parent_class), - out_failure_reason); - } else { - return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - } -} - -static void -ip4_config_pre_commit(NMDevice *device, NMIP4Config *config) -{ - nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config); -} - -static gboolean -get_ip_iface_identifier(NMDevice *device, NMUtilsIPv6IfaceId *out_iid) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - gboolean success; - - g_return_val_if_fail(priv->modem, FALSE); - success = nm_modem_get_iid(priv->modem, out_iid); - if (!success) - success = - NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid); - return success; -} - -/*****************************************************************************/ - -static gboolean -get_enabled(NMDevice *device) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - NMModemState modem_state = nm_modem_get_state(priv->modem); - - return priv->rf_enabled && (modem_state >= NM_MODEM_STATE_LOCKED); -} - -static void -set_enabled(NMDevice *device, gboolean enabled) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - - /* Called only by the Manager in response to rfkill switch changes or - * global user WWAN enable/disable preference changes. - */ - priv->rf_enabled = enabled; - - if (priv->modem) { - /* Sync the ModemManager modem enabled/disabled with rfkill/user preference */ - nm_modem_set_mm_enabled(priv->modem, enabled); - } - - if (enabled == FALSE) { - nm_device_state_changed(device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_NONE); - } -} - -static gboolean -is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - NMModemState modem_state; - - if (!priv->rf_enabled) - return FALSE; - - g_assert(priv->modem); - modem_state = nm_modem_get_state(priv->modem); - if (modem_state <= NM_MODEM_STATE_INITIALIZING) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -static void -set_modem(NMDeviceModem *self, NMModem *modem) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - - g_return_if_fail(modem != NULL); - - priv->modem = nm_modem_claim(modem); - - g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self); - g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self); - g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self); - g_signal_connect(modem, NM_MODEM_IP6_CONFIG_RESULT, G_CALLBACK(modem_ip6_config_result), self); - g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self); - g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self); - 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); - 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); - g_signal_connect(modem, - "notify::" NM_MODEM_OPERATOR_CODE, - G_CALLBACK(operator_code_changed_cb), - self); - g_signal_connect(modem, "notify::" NM_MODEM_APN, G_CALLBACK(apn_changed_cb), self); -} - -static guint32 -get_dhcp_timeout_for_device(NMDevice *device, int addr_family) -{ - /* DHCP is always done by the modem firmware, not by the network, and - * by the time we get around to DHCP the firmware should already know - * the IP addressing details. So the DHCP timeout can be much shorter. - */ - return 15; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_MODEM: - g_value_set_object(value, priv->modem); - break; - case PROP_CAPABILITIES: - g_value_set_uint(value, priv->caps); - break; - case PROP_CURRENT_CAPABILITIES: - g_value_set_uint(value, priv->current_caps); - break; - case PROP_DEVICE_ID: - g_value_set_string(value, priv->device_id); - break; - case PROP_OPERATOR_CODE: - g_value_set_string(value, priv->operator_code); - break; - case PROP_APN: - g_value_set_string(value, priv->apn); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_MODEM: - /* construct-only */ - set_modem(NM_DEVICE_MODEM(object), g_value_get_object(value)); - break; - case PROP_CAPABILITIES: - priv->caps = g_value_get_uint(value); - break; - case PROP_CURRENT_CAPABILITIES: - priv->current_caps = g_value_get_uint(value); - break; - case PROP_DEVICE_ID: - /* construct-only */ - priv->device_id = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_device_modem_init(NMDeviceModem *self) -{} - -NMDevice * -nm_device_modem_new(NMModem *modem) -{ - NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; - NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; - - 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, - NM_DEVICE_MODEM_DEVICE_ID, - nm_modem_get_device_id(modem), - NULL); -} - -static void -dispose(GObject *object) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(object); - - if (priv->modem) { - g_signal_handlers_disconnect_by_data(priv->modem, NM_DEVICE_MODEM(object)); - nm_clear_pointer(&priv->modem, nm_modem_unclaim); - } - - nm_clear_g_free(&priv->device_id); - nm_clear_g_free(&priv->operator_code); - nm_clear_g_free(&priv->apn); - - 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), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DeviceId", - "s", - NM_DEVICE_MODEM_DEVICE_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("OperatorCode", - "s", - NM_DEVICE_MODEM_OPERATOR_CODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Apn", "s", NM_DEVICE_MODEM_APN), ), ), - .legacy_property_changed = TRUE, -}; - -static void -nm_device_modem_class_init(NMDeviceModemClass *klass) -{ - 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; - device_class->check_connection_available = check_connection_available; - device_class->complete_connection = complete_connection; - device_class->deactivate_async = deactivate_async; - device_class->deactivate = deactivate; - device_class->act_stage1_prepare = act_stage1_prepare; - device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->ip4_config_pre_commit = ip4_config_pre_commit; - device_class->get_enabled = get_enabled; - device_class->set_enabled = set_enabled; - device_class->owns_iface = owns_iface; - device_class->is_available = is_available; - device_class->get_ip_iface_identifier = get_ip_iface_identifier; - device_class->get_configured_mtu = nm_modem_get_configured_mtu; - device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; - - device_class->state_changed = device_state_changed; - - obj_properties[PROP_MODEM] = - g_param_spec_object(NM_DEVICE_MODEM_MODEM, - "", - "", - NM_TYPE_MODEM, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CAPABILITIES] = - g_param_spec_uint(NM_DEVICE_MODEM_CAPABILITIES, - "", - "", - 0, - G_MAXUINT32, - NM_DEVICE_MODEM_CAPABILITY_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CURRENT_CAPABILITIES] = - g_param_spec_uint(NM_DEVICE_MODEM_CURRENT_CAPABILITIES, - "", - "", - 0, - G_MAXUINT32, - NM_DEVICE_MODEM_CAPABILITY_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DEVICE_ID] = - g_param_spec_string(NM_DEVICE_MODEM_DEVICE_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_OPERATOR_CODE] = - g_param_spec_string(NM_DEVICE_MODEM_OPERATOR_CODE, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_APN] = g_param_spec_string(NM_DEVICE_MODEM_APN, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} |