aboutsummaryrefslogtreecommitdiff
path: root/src/mm-iface-modem-voice.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-09-25 14:41:58 +0200
committerAleksander Morgado <aleksander@aleksander.es>2019-10-17 10:51:50 +0200
commit2c0281aac9430731766cd4203c638848b9434633 (patch)
tree839531a6f53ed1b43157a97de246d8088c1dafeb /src/mm-iface-modem-voice.c
parentd6f9d5e9ec36e403be9836c55c8ffd19422605ef (diff)
call: disallow non-emergency calls when in emergency-only state
Diffstat (limited to 'src/mm-iface-modem-voice.c')
-rw-r--r--src/mm-iface-modem-voice.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/mm-iface-modem-voice.c b/src/mm-iface-modem-voice.c
index 32f6a4d1..ff685aa5 100644
--- a/src/mm-iface-modem-voice.c
+++ b/src/mm-iface-modem-voice.c
@@ -39,6 +39,109 @@ mm_iface_modem_voice_bind_simple_status (MMIfaceModemVoice *self,
/*****************************************************************************/
+gboolean
+mm_iface_modem_voice_authorize_outgoing_call (MMIfaceModemVoice *self,
+ MMBaseCall *call,
+ GError **error)
+{
+ MmGdbusModemVoice *skeleton = NULL;
+ MMBaseSim *sim = NULL;
+ gboolean emergency_only = FALSE;
+ gboolean call_allowed = FALSE;
+ GError *inner_error = NULL;
+ guint i;
+ const gchar *number;
+
+ static const gchar *always_valid_emergency_numbers[] = { "112", "911" };
+ static const gchar *no_sim_valid_emergency_numbers[] = { "000", "08", "110", "999", "118", "119" };
+
+ g_assert (mm_base_call_get_direction (call) == MM_CALL_DIRECTION_OUTGOING);
+ number = mm_base_call_get_number (call);
+ g_assert (number);
+
+ g_object_get (self,
+ MM_IFACE_MODEM_VOICE_DBUS_SKELETON, &skeleton,
+ NULL);
+
+ if (!skeleton) {
+ g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "voice operations unsupported");
+ goto out;
+ }
+
+ g_object_get (skeleton,
+ "emergency-only", &emergency_only,
+ NULL);
+
+ /* Identification of emergency numbers. 3GPP TS 22.101
+ *
+ * a) 112 and 911 shall always be available.
+ * b) Any emergency call number stored on a SIM/USIM when the SIM/USIM is
+ * present.
+ * c) 000, 08, 110, 999, 118 and 119 when a SIM/USIM is not present.
+ * d) Additional emergency call numbers that may have been downloaded by
+ * the serving network when the SIM/USIM is present.
+ *
+ * In ModemManager we're not flagging any call as being "emergency" or
+ * "normal", but we can right away limit non-emergency calls if we're in
+ * "emergency-only" mode.
+ */
+
+ /* If we're not in emergency mode, the call (emergency or normal) is always allowed */
+ if (!emergency_only) {
+ mm_dbg ("voice call to %s allowed", number);
+ call_allowed = TRUE;
+ goto out;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (always_valid_emergency_numbers); i++) {
+ if (g_strcmp0 (number, always_valid_emergency_numbers[i]) == 0) {
+ mm_dbg ("voice call to %s allowed: emergency call number always valid", number);
+ call_allowed = TRUE;
+ goto out;
+ }
+ }
+
+ /* Check if we have a SIM */
+ g_object_get (self,
+ MM_IFACE_MODEM_SIM, &sim,
+ NULL);
+ if (!sim) {
+ /* If no SIM available, some additional numbers may be valid emergency numbers */
+ for (i = 0; i < G_N_ELEMENTS (no_sim_valid_emergency_numbers); i++) {
+ if (g_strcmp0 (number, no_sim_valid_emergency_numbers[i]) == 0) {
+ mm_dbg ("voice call to %s allowed: emergency call number valid when no SIM", number);
+ call_allowed = TRUE;
+ goto out;
+ }
+ }
+
+ mm_dbg ("voice call to %s NOT allowed: not a valid emergency call number when no SIM", number);
+ goto out;
+ }
+
+ /* Check if the number is programmed in EF_ECC */
+ if (mm_base_sim_is_emergency_number (sim, number)) {
+ mm_dbg ("voice call to %s allowed: emergency call number programmed in the SIM", number);
+ call_allowed = TRUE;
+ } else
+ mm_dbg ("voice call to %s NOT allowed: not a valid emergency call number programmed in the SIM", number);
+
+ out:
+
+ if (inner_error)
+ g_propagate_error (error, inner_error);
+ else if (!call_allowed)
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED,
+ "only emergency calls allowed");
+
+ g_clear_object (&skeleton);
+ g_clear_object (&sim);
+ return call_allowed;
+}
+
+/*****************************************************************************/
+
/* new calls will inherit audio settings if the modem is already in-call state */
static void update_audio_settings_in_call (MMIfaceModemVoice *self,
MMBaseCall *call);