forked from sailfishos/ofono
Compare commits
21 Commits
mer/1.23+g
...
mer/1.23+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edd91c94eb | ||
|
|
af0ab142e1 | ||
|
|
dffc04d404 | ||
|
|
97b5fcbd87 | ||
|
|
d7e740347f | ||
|
|
1116ca2481 | ||
|
|
4ad02792db | ||
|
|
eddcb88af4 | ||
|
|
f91df7f0fd | ||
|
|
9d220ff9be | ||
|
|
deefa2c454 | ||
|
|
80224b283d | ||
|
|
07e07b6ddc | ||
|
|
bd836b4499 | ||
|
|
6c289b1432 | ||
|
|
296e46487f | ||
|
|
09e98234aa | ||
|
|
0f4cdba932 | ||
|
|
870bac93e9 | ||
|
|
246cd4e1d2 | ||
|
|
ca20b65098 |
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2020 Jolla Ltd.
|
||||
* Copyright (C) 2016-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -243,6 +243,7 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
|
||||
dc->dnses = g_strdupv(call->dnses);
|
||||
dc->gateways = g_strdupv(call->gateways);
|
||||
dc->addresses = g_strdupv(call->addresses);
|
||||
dc->pcscf = g_strdupv(call->pcscf);
|
||||
return dc;
|
||||
} else {
|
||||
return NULL;
|
||||
@@ -253,8 +254,9 @@ static void ril_data_call_destroy(struct ril_data_call *call)
|
||||
{
|
||||
g_free(call->ifname);
|
||||
g_strfreev(call->dnses);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->gateways);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->pcscf);
|
||||
}
|
||||
|
||||
void ril_data_call_free(struct ril_data_call *call)
|
||||
@@ -322,8 +324,7 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
|
||||
|
||||
/* RIL_Data_Call_Response_v9 */
|
||||
if (version >= 9) {
|
||||
/* PCSCF */
|
||||
grilio_parser_skip_string(rilp);
|
||||
call->pcscf = grilio_parser_split_utf8(rilp, " ");
|
||||
|
||||
/* RIL_Data_Call_Response_v11 */
|
||||
if (version >= 11) {
|
||||
@@ -354,16 +355,19 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor *vendor,
|
||||
|
||||
if (parsed) {
|
||||
DBG("[status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,"
|
||||
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
|
||||
"mtu=%d,address=%s,dns=%s %s,gateways=%s,pcscf=%s %s]",
|
||||
call->status, call->retry_time,
|
||||
call->cid, call->active,
|
||||
ril_protocol_from_ofono(call->prot),
|
||||
call->ifname, call->mtu,
|
||||
call->addresses ? call->addresses[0] : NULL,
|
||||
call->dnses ? call->dnses[0] : NULL,
|
||||
call->addresses ? call->addresses[0] : "",
|
||||
call->dnses ? call->dnses[0] : "",
|
||||
(call->dnses && call->dnses[0] &&
|
||||
call->dnses[1]) ? call->dnses[1] : "",
|
||||
call->gateways ? call->gateways[0] : NULL);
|
||||
call->gateways ? call->gateways[0] : "",
|
||||
call->pcscf ? call->pcscf[0] : "",
|
||||
(call->pcscf && call->pcscf[0] &&
|
||||
call->pcscf[1]) ? call->pcscf[1] : "");
|
||||
return call;
|
||||
} else {
|
||||
ril_data_call_free(call);
|
||||
@@ -429,7 +433,8 @@ static gboolean ril_data_call_equal(const struct ril_data_call *c1,
|
||||
!g_strcmp0(c1->ifname, c2->ifname) &&
|
||||
gutil_strv_equal(c1->dnses, c2->dnses) &&
|
||||
gutil_strv_equal(c1->gateways, c2->gateways) &&
|
||||
gutil_strv_equal(c1->addresses, c2->addresses);
|
||||
gutil_strv_equal(c1->addresses, c2->addresses) &&
|
||||
gutil_strv_equal(c1->pcscf, c2->pcscf);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -951,7 +956,8 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
|
||||
*
|
||||
* Makes little sense but it is what it is.
|
||||
*/
|
||||
tech = priv->network->data.ril_tech;
|
||||
tech = (setup->profile_id == RIL_DATA_PROFILE_IMS) ?
|
||||
RADIO_TECH_LTE : priv->network->data.ril_tech;
|
||||
if (tech > 2) {
|
||||
tech += 2;
|
||||
} else {
|
||||
@@ -1014,10 +1020,22 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
|
||||
g_new0(struct ril_data_request_setup, 1);
|
||||
struct ril_data_request *req = &setup->req;
|
||||
|
||||
setup->profile_id = (priv->use_data_profiles &&
|
||||
context_type == OFONO_GPRS_CONTEXT_TYPE_MMS) ?
|
||||
priv->mms_data_profile_id :
|
||||
RIL_DATA_PROFILE_DEFAULT;
|
||||
setup->profile_id = RIL_DATA_PROFILE_DEFAULT;
|
||||
if (priv->use_data_profiles) {
|
||||
switch (context_type) {
|
||||
case OFONO_GPRS_CONTEXT_TYPE_MMS:
|
||||
setup->profile_id = priv->mms_data_profile_id;
|
||||
break;
|
||||
case OFONO_GPRS_CONTEXT_TYPE_IMS:
|
||||
setup->profile_id = RIL_DATA_PROFILE_IMS;
|
||||
break;
|
||||
case OFONO_GPRS_CONTEXT_TYPE_ANY:
|
||||
case OFONO_GPRS_CONTEXT_TYPE_INTERNET:
|
||||
case OFONO_GPRS_CONTEXT_TYPE_WAP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setup->apn = g_strdup(ctx->apn);
|
||||
setup->username = g_strdup(ctx->username);
|
||||
setup->password = g_strdup(ctx->password);
|
||||
@@ -1196,6 +1214,31 @@ static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
|
||||
return req;
|
||||
}
|
||||
|
||||
static gboolean ril_data_allow_can_submit(struct ril_data *self)
|
||||
{
|
||||
if (self) {
|
||||
switch (self->priv->options.allow_data) {
|
||||
case RIL_ALLOW_DATA_ENABLED:
|
||||
return TRUE;
|
||||
case RIL_ALLOW_DATA_DISABLED:
|
||||
case RIL_ALLOW_DATA_AUTO:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean ril_data_allow_submit_request(struct ril_data *data,
|
||||
gboolean allow)
|
||||
{
|
||||
if (ril_data_allow_can_submit(data)) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, allow));
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* ril_data
|
||||
*==========================================================================*/
|
||||
@@ -1226,6 +1269,22 @@ void ril_data_remove_handler(struct ril_data *self, gulong id)
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_data_imsi_changed(struct ril_sim_settings *settings,
|
||||
void *user_data)
|
||||
{
|
||||
struct ril_data *self = RIL_DATA(user_data);
|
||||
struct ril_data_priv *priv = self->priv;
|
||||
|
||||
if (!settings->imsi) {
|
||||
/*
|
||||
* Most likely, SIM removal. In any case, no data requests
|
||||
* make sense when IMSI is unavailable.
|
||||
*/
|
||||
ril_data_cancel_all_requests(self);
|
||||
}
|
||||
ril_data_manager_check_network_mode(priv->dm);
|
||||
}
|
||||
|
||||
static void ril_data_settings_changed(struct ril_sim_settings *settings,
|
||||
void *user_data)
|
||||
{
|
||||
@@ -1308,7 +1367,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
|
||||
priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] =
|
||||
ril_sim_settings_add_imsi_changed_handler(settings,
|
||||
ril_data_settings_changed, self);
|
||||
ril_data_imsi_changed, self);
|
||||
priv->settings_event_id[SETTINGS_EVENT_PREF_MODE] =
|
||||
ril_sim_settings_add_pref_mode_changed_handler(settings,
|
||||
ril_data_settings_changed, self);
|
||||
@@ -1466,10 +1525,8 @@ static void ril_data_disallow(struct ril_data *self)
|
||||
*/
|
||||
ril_data_deactivate_all(self);
|
||||
|
||||
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
|
||||
/* Tell rild that the data is now disabled */
|
||||
ril_data_request_queue(ril_data_allow_new(self, FALSE));
|
||||
} else {
|
||||
/* Tell rild that the data is now disabled */
|
||||
if (!ril_data_allow_submit_request(self, FALSE)) {
|
||||
priv->flags &= ~RIL_DATA_FLAG_ON;
|
||||
GASSERT(!ril_data_allowed(self));
|
||||
DBG_(self, "data off");
|
||||
@@ -1779,12 +1836,14 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
|
||||
|
||||
static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
||||
{
|
||||
GSList *l;
|
||||
if (self) {
|
||||
GSList *l;
|
||||
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
struct ril_data *data = l->data;
|
||||
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
|
||||
return data;
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
struct ril_data *data = l->data;
|
||||
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1804,9 +1863,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
||||
ril_data_max_mode(data), TRUE);
|
||||
}
|
||||
|
||||
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, TRUE));
|
||||
} else {
|
||||
if (!ril_data_allow_submit_request(data, TRUE)) {
|
||||
priv->flags |= RIL_DATA_FLAG_ON;
|
||||
GASSERT(ril_data_allowed(data));
|
||||
DBG_(data, "data on");
|
||||
@@ -1830,12 +1887,7 @@ void ril_data_manager_check_data(struct ril_data_manager *self)
|
||||
|
||||
void ril_data_manager_assert_data_on(struct ril_data_manager *self)
|
||||
{
|
||||
if (self) {
|
||||
struct ril_data *data = ril_data_manager_allowed(self);
|
||||
if (data) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, TRUE));
|
||||
}
|
||||
}
|
||||
ril_data_allow_submit_request(ril_data_manager_allowed(self), TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2020 Jolla Ltd.
|
||||
* Copyright (C) 2016-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -40,6 +40,7 @@ struct ril_data_call {
|
||||
char **dnses;
|
||||
char **gateways;
|
||||
char **addresses;
|
||||
char **pcscf;
|
||||
};
|
||||
|
||||
struct ril_data_call_list {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -340,6 +340,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
|
||||
if (md->modem.config.enable_cbs) {
|
||||
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
}
|
||||
ofono_sim_auth_create(modem);
|
||||
}
|
||||
|
||||
static void ril_modem_post_online(struct ofono_modem *modem)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -444,14 +444,13 @@ static guint ril_network_poll_and_retry(struct ril_network *self, guint id,
|
||||
{
|
||||
struct ril_network_priv *priv = self->priv;
|
||||
|
||||
if (id) {
|
||||
/* Retry right away, don't wait for retry timeout to expire */
|
||||
grilio_channel_retry_request(priv->io, id);
|
||||
} else {
|
||||
/* Don't wait for retry timeout to expire */
|
||||
if (!id || !grilio_channel_retry_request(priv->io, id)) {
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
|
||||
grilio_request_set_retry_func(req, ril_network_retry);
|
||||
grilio_queue_cancel_request(priv->q, id, FALSE);
|
||||
id = grilio_queue_send_request_full(priv->q, req, code, fn,
|
||||
NULL, self);
|
||||
grilio_request_unref(req);
|
||||
@@ -697,7 +696,7 @@ struct ril_network_data_profile *ril_network_data_profile_new
|
||||
ptr += G_ALIGN8(sizeof(*profile));
|
||||
|
||||
profile->profile_id = profile_id;
|
||||
profile->type = RIL_PROFILE_3GPP;
|
||||
profile->type = RIL_PROFILE_COMMON;
|
||||
profile->auth_method = auth_method;
|
||||
profile->proto = context->proto;
|
||||
profile->enabled = TRUE;
|
||||
@@ -826,6 +825,9 @@ static void ril_network_check_data_profiles(struct ril_network *self)
|
||||
const struct ofono_gprs_primary_context* mms =
|
||||
ofono_gprs_context_settings_by_type(gprs,
|
||||
OFONO_GPRS_CONTEXT_TYPE_MMS);
|
||||
const struct ofono_gprs_primary_context* ims =
|
||||
ofono_gprs_context_settings_by_type(gprs,
|
||||
OFONO_GPRS_CONTEXT_TYPE_IMS);
|
||||
GSList *l = NULL;
|
||||
|
||||
if (internet) {
|
||||
@@ -841,6 +843,12 @@ static void ril_network_check_data_profiles(struct ril_network *self)
|
||||
ril_network_data_profile_new(mms,
|
||||
priv->mms_data_profile_id));
|
||||
}
|
||||
if (ims) {
|
||||
DBG_(self, "ims apn \"%s\"", ims->apn);
|
||||
l = g_slist_append(l,
|
||||
ril_network_data_profile_new(ims,
|
||||
RIL_DATA_PROFILE_IMS));
|
||||
}
|
||||
|
||||
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
|
||||
ril_network_data_profiles_free(l);
|
||||
|
||||
@@ -998,8 +998,9 @@ static void ril_export_entries(struct ofono_phonebook *pb,
|
||||
pbd->df_path = usim_path;
|
||||
pbd->df_size = sizeof(usim_path);
|
||||
|
||||
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
|
||||
ofono_sim_read_path(pbd->sim_context, SIM_EFPBR_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
pb_reference_data_cb, pb);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2019 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include <ofono/watch.h>
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include "simutil.h"
|
||||
#include "util.h"
|
||||
#include "ofono.h"
|
||||
@@ -86,6 +88,7 @@ struct ril_sim {
|
||||
gboolean empty_pin_query_allowed;
|
||||
gboolean inserted;
|
||||
guint idle_id; /* Used by register and SIM reset callbacks */
|
||||
guint list_apps_id;
|
||||
gulong card_event_id[SIM_CARD_EVENT_COUNT];
|
||||
gulong io_event_id[IO_EVENT_COUNT];
|
||||
guint query_pin_retries_id;
|
||||
@@ -118,12 +121,25 @@ struct ril_sim_cbd_io {
|
||||
ofono_sim_write_cb_t write;
|
||||
ofono_sim_imsi_cb_t imsi;
|
||||
ofono_query_facility_lock_cb_t query_facility_lock;
|
||||
ofono_sim_open_channel_cb_t open_channel;
|
||||
ofono_sim_close_channel_cb_t close_channel;
|
||||
gpointer ptr;
|
||||
} cb;
|
||||
gpointer data;
|
||||
guint req_id;
|
||||
};
|
||||
|
||||
struct ril_sim_session_cbd {
|
||||
struct ril_sim *sd;
|
||||
struct ril_sim_card *card;
|
||||
ofono_sim_logical_access_cb_t cb;
|
||||
gpointer data;
|
||||
int ref_count;
|
||||
int session_id;
|
||||
int cla;
|
||||
guint req_id;
|
||||
};
|
||||
|
||||
struct ril_sim_pin_cbd {
|
||||
struct ril_sim *sd;
|
||||
ofono_sim_lock_unlock_cb_t cb;
|
||||
@@ -150,6 +166,16 @@ struct ril_sim_retry_query {
|
||||
GRilIoRequest *(*new_req)(struct ril_sim *sd);
|
||||
};
|
||||
|
||||
/* TS 102.221 */
|
||||
#define APP_TEMPLATE_TAG 0x61
|
||||
#define APP_ID_TAG 0x4F
|
||||
|
||||
struct ril_sim_list_apps {
|
||||
struct ril_sim *sd;
|
||||
ofono_sim_list_apps_cb_t cb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
|
||||
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
|
||||
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
|
||||
@@ -218,6 +244,45 @@ static void ril_sim_cbd_io_start(struct ril_sim_cbd_io *cbd, GRilIoRequest* req,
|
||||
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
|
||||
}
|
||||
|
||||
static struct ril_sim_session_cbd *ril_sim_session_cbd_new(struct ril_sim *sd,
|
||||
int session_id, int cla, ofono_sim_logical_access_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = g_new0(struct ril_sim_session_cbd, 1);
|
||||
|
||||
cbd->sd = sd;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
cbd->card = ril_sim_card_ref(sd->card);
|
||||
cbd->session_id = session_id;
|
||||
cbd->cla = cla;
|
||||
cbd->ref_count = 1;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_sim_session_cbd_unref(void *data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = data;
|
||||
|
||||
if (--(cbd->ref_count) < 1) {
|
||||
ril_sim_card_sim_io_finished(cbd->card, cbd->req_id);
|
||||
ril_sim_card_unref(cbd->card);
|
||||
g_free(cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_session_cbd_start(struct ril_sim_session_cbd *cbd,
|
||||
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc cb)
|
||||
{
|
||||
struct ril_sim *sd = cbd->sd;
|
||||
const guint finished_req = cbd->req_id;
|
||||
|
||||
cbd->ref_count++;
|
||||
cbd->req_id = grilio_queue_send_request_full(sd->q, req, code, cb,
|
||||
ril_sim_session_cbd_unref, cbd);
|
||||
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
|
||||
ril_sim_card_sim_io_finished(cbd->card, finished_req);
|
||||
}
|
||||
|
||||
static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
|
||||
void *user_data)
|
||||
{
|
||||
@@ -307,30 +372,13 @@ static void ril_sim_append_path(struct ril_sim *sd, GRilIoRequest *req,
|
||||
grilio_request_append_utf8(req, hex_path);
|
||||
DBG_(sd, "%s", hex_path);
|
||||
g_free(hex_path);
|
||||
} else if (fileid == SIM_EF_ICCID_FILEID || fileid == SIM_EFPL_FILEID) {
|
||||
/*
|
||||
* Special catch-all for EF_ICCID (unique card ID)
|
||||
* and EF_PL files which exist in the root directory.
|
||||
* As the sim_info_cb function may not have yet
|
||||
* recorded the app_type for the SIM, and the path
|
||||
* for both files is the same for 2g|3g, just hard-code.
|
||||
*
|
||||
* See 'struct ef_db' in:
|
||||
* ../../src/simutil.c for more details.
|
||||
*/
|
||||
DBG_(sd, "%s", ROOTMF);
|
||||
grilio_request_append_utf8(req, ROOTMF);
|
||||
} else {
|
||||
/*
|
||||
* The only known case of this is EFPHASE_FILED (0x6FAE).
|
||||
* The ef_db table ( see /src/simutil.c ) entry for
|
||||
* EFPHASE contains a value of 0x0000 for it's
|
||||
* 'parent3g' member. This causes a NULL path to
|
||||
* be returned.
|
||||
* Catch-all for EF_ICCID, EF_PL and other files absent
|
||||
* from ef_db table in src/simutil.c, hard-code ROOTMF.
|
||||
*/
|
||||
|
||||
DBG_(sd, "returning empty path.");
|
||||
grilio_request_append_utf8(req, NULL);
|
||||
DBG_(sd, "%s (default)", ROOTMF);
|
||||
grilio_request_append_utf8(req, ROOTMF);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1422,6 +1470,294 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_list_apps_cb(void *data)
|
||||
{
|
||||
struct ril_sim_list_apps *rd = data;
|
||||
struct ril_sim *sd = rd->sd;
|
||||
const struct ril_sim_card_status *status = sd->card->status;
|
||||
struct ofono_error error;
|
||||
|
||||
GASSERT(sd->list_apps_id);
|
||||
sd->list_apps_id = 0;
|
||||
|
||||
if (status) {
|
||||
int i, n = status->num_apps;
|
||||
GByteArray *tlv = g_byte_array_sized_new(n * 20);
|
||||
|
||||
/* Reconstruct EFdir contents */
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *hex = status->apps[i].aid;
|
||||
gsize hex_len = hex ? strlen(hex) : 0;
|
||||
long aid_size;
|
||||
guint8 aid[16];
|
||||
|
||||
if (hex_len >= 2 && hex_len <= 2 * sizeof(aid) &&
|
||||
!(hex_len & 0x01) && decode_hex_own_buf(hex,
|
||||
hex_len, &aid_size, 0, aid)) {
|
||||
guint8 buf[4];
|
||||
|
||||
/*
|
||||
* TS 102.221
|
||||
* 13 Application independent files
|
||||
* 13.1 EFdir
|
||||
*
|
||||
* Application template TLV object.
|
||||
*/
|
||||
buf[0] = APP_TEMPLATE_TAG;
|
||||
buf[1] = (guint8)(aid_size + 2);
|
||||
buf[2] = APP_ID_TAG;
|
||||
buf[3] = (guint8)(aid_size);
|
||||
g_byte_array_append(tlv, buf, sizeof(buf));
|
||||
g_byte_array_append(tlv, aid, aid_size);
|
||||
}
|
||||
}
|
||||
DBG_(sd, "reporting %u apps %u bytes", n, tlv->len);
|
||||
rd->cb(ril_error_ok(&error), tlv->data, tlv->len, rd->data);
|
||||
g_byte_array_unref(tlv);
|
||||
} else {
|
||||
DBG_(sd, "no SIM card, no apps");
|
||||
rd->cb(ril_error_failure(&error), NULL, 0, rd->data);
|
||||
}
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_sim_list_apps(struct ofono_sim *sim,
|
||||
ofono_sim_list_apps_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_list_apps *rd = g_new(struct ril_sim_list_apps, 1);
|
||||
|
||||
rd->sd = sd;
|
||||
rd->cb = cb;
|
||||
rd->data = data;
|
||||
if (sd->list_apps_id) {
|
||||
g_source_remove(sd->list_apps_id);
|
||||
}
|
||||
sd->list_apps_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||
ril_sim_list_apps_cb, rd, g_free);
|
||||
}
|
||||
|
||||
static void ril_sim_open_channel_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_cbd_io *cbd = user_data;
|
||||
ofono_sim_open_channel_cb_t cb = cbd->cb.open_channel;
|
||||
struct ofono_error error;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
guint32 n, session_id;
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_uint32(&rilp, &n) && n >= 1 &&
|
||||
grilio_parser_get_uint32(&rilp, &session_id)) {
|
||||
DBG_(cbd->sd, "%u", session_id);
|
||||
cb(ril_error_ok(&error), session_id, cbd->data);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ofono_error("Open logical channel failure: %s",
|
||||
ril_error_to_string(status));
|
||||
}
|
||||
|
||||
cb(ril_error_failure(&error), 0, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sim_open_channel(struct ofono_sim *sim,
|
||||
const unsigned char *aid, unsigned int len,
|
||||
ofono_sim_open_channel_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
char *aid_hex = encode_hex(aid, len, 0);
|
||||
|
||||
DBG_(sd, "%s", aid_hex);
|
||||
grilio_request_append_utf8(req, aid_hex);
|
||||
grilio_request_append_int32(req, 0);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_OPEN_CHANNEL,
|
||||
ril_sim_open_channel_cb);
|
||||
grilio_request_unref(req);
|
||||
g_free(aid_hex);
|
||||
}
|
||||
|
||||
static void ril_sim_close_channel_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_cbd_io *cbd = user_data;
|
||||
struct ofono_error error;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
ril_error_init_ok(&error);
|
||||
} else {
|
||||
ofono_error("Close logical channel failure: %s",
|
||||
ril_error_to_string(status));
|
||||
ril_error_init_failure(&error);
|
||||
}
|
||||
cbd->cb.close_channel(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sim_close_channel(struct ofono_sim *sim, int session_id,
|
||||
ofono_sim_close_channel_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
DBG_(sd, "%u", session_id);
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, session_id);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_CLOSE_CHANNEL,
|
||||
ril_sim_close_channel_cb);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_get_results_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = user_data;
|
||||
ofono_sim_logical_access_cb_t cb = cbd->cb;
|
||||
struct ril_sim_io_response *res;
|
||||
struct ofono_error err;
|
||||
|
||||
res = ril_sim_parse_io_response(data, len);
|
||||
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
|
||||
cb(ril_error_ok(&err), res->data, res->data_len, cbd->data);
|
||||
} else if (res) {
|
||||
cb(ril_error_sim(&err, res->sw1, res->sw2), NULL, 0, cbd->data);
|
||||
} else {
|
||||
cb(ril_error_failure(&err), NULL, 0, cbd->data);
|
||||
}
|
||||
ril_sim_io_response_free(res);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_transmit(struct ril_sim_session_cbd *cbd,
|
||||
int ins, int p1, int p2, int p3, const char *hex_data,
|
||||
GRilIoChannelResponseFunc cb)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
DBG_(cbd->sd, "session=%u,cmd=%02X,%02X,%02X,%02X,%02X,%s",
|
||||
cbd->session_id, cbd->cla, ins, p1, p2, p3,
|
||||
hex_data ? hex_data : "");
|
||||
grilio_request_append_int32(req, cbd->session_id);
|
||||
grilio_request_append_int32(req, cbd->cla);
|
||||
grilio_request_append_int32(req, ins);
|
||||
grilio_request_append_int32(req, p1);
|
||||
grilio_request_append_int32(req, p2);
|
||||
grilio_request_append_int32(req, p3);
|
||||
grilio_request_append_utf8(req, hex_data);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_session_cbd_start(cbd, req,
|
||||
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, cb);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = user_data;
|
||||
ofono_sim_logical_access_cb_t cb = cbd->cb;
|
||||
struct ril_sim_io_response *res;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(cbd->sd, "");
|
||||
cbd->req_id = 0;
|
||||
res = ril_sim_parse_io_response(data, len);
|
||||
if (res && status == RIL_E_SUCCESS) {
|
||||
/*
|
||||
* TS 102 221
|
||||
* 7.3.1.1.5.2 Case 4 commands
|
||||
*
|
||||
* If the UICC receives a case 4 command, after processing
|
||||
* the data sent with the C-APDU, it shall return:
|
||||
*
|
||||
* a) procedure bytes '61 xx' instructing the transport
|
||||
* layer of the terminal to issue a GET RESPONSE command
|
||||
* with a maximum length of 'xx'; or
|
||||
* b) status indicating a warning or error condition (but
|
||||
* not SW1 SW2 = '90 00').
|
||||
*
|
||||
* The GET RESPONSE command so issued is then treated as
|
||||
* described for case 2 commands.
|
||||
*/
|
||||
if (res->sw1 == 0x61) {
|
||||
ril_sim_logical_access_transmit(cbd,
|
||||
CMD_GET_RESPONSE, 0, 0, res->sw2, NULL,
|
||||
ril_sim_logical_access_get_results_cb);
|
||||
} else if (ril_sim_io_response_ok(res)) {
|
||||
cb(ril_error_ok(&error), res->data, res->data_len,
|
||||
cbd->data);
|
||||
} else {
|
||||
cb(ril_error_sim(&error, res->sw1, res->sw2), NULL, 0,
|
||||
cbd->data);
|
||||
}
|
||||
} else {
|
||||
cb(ril_error_failure(&error), NULL, 0, cbd->data);
|
||||
}
|
||||
ril_sim_io_response_free(res);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access(struct ofono_sim *sim, int session_id,
|
||||
const unsigned char *pdu, unsigned int len,
|
||||
ofono_sim_logical_access_cb_t cb, void *data)
|
||||
{
|
||||
/* SIM Command APDU: CLA INS P1 P2 P3 Data */
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
const char* hex_data;
|
||||
char *tmp;
|
||||
struct ril_sim_session_cbd *cbd = ril_sim_session_cbd_new(sd,
|
||||
session_id, pdu[0], cb, data);
|
||||
|
||||
GASSERT(len >= 5);
|
||||
if (len > 5) {
|
||||
hex_data = tmp = encode_hex(pdu + 5, len - 5, 0);
|
||||
} else {
|
||||
tmp = NULL;
|
||||
hex_data = "";
|
||||
}
|
||||
|
||||
ril_sim_logical_access_transmit(cbd, pdu[1], pdu[2], pdu[3], pdu[4],
|
||||
hex_data, ril_sim_logical_access_cb);
|
||||
ril_sim_session_cbd_unref(cbd);
|
||||
g_free(tmp);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_binary(struct ofono_sim *sim, int session,
|
||||
int fileid, int start, int length,
|
||||
const unsigned char *path, unsigned int path_len,
|
||||
ofono_sim_read_cb_t cb, void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_binary not implemented");
|
||||
cb(ril_error_failure(&error), NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_record(struct ofono_sim *sim, int session_id,
|
||||
int fileid, int record, int length,
|
||||
const unsigned char *path, unsigned int path_len,
|
||||
ofono_sim_read_cb_t cb, void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_record not implemented");
|
||||
cb(ril_error_failure(&error), NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_info(struct ofono_sim *sim, int session_id,
|
||||
int fileid, const unsigned char *path,
|
||||
unsigned int path_len, ofono_sim_file_info_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_info not implemented");
|
||||
cb(ril_error_failure(&error), -1, -1, -1, NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_refresh_cb(GRilIoChannel *io, guint code,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
@@ -1503,6 +1839,9 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
grilio_queue_cancel_all(sd->q, FALSE);
|
||||
ofono_sim_set_data(sim, NULL);
|
||||
|
||||
if (sd->list_apps_id) {
|
||||
g_source_remove(sd->list_apps_id);
|
||||
}
|
||||
if (sd->idle_id) {
|
||||
g_source_remove(sd->idle_id);
|
||||
}
|
||||
@@ -1547,7 +1886,14 @@ const struct ofono_sim_driver ril_sim_driver = {
|
||||
.reset_passwd = ril_sim_pin_send_puk,
|
||||
.change_passwd = ril_sim_change_passwd,
|
||||
.query_pin_retries = ril_sim_query_pin_retries,
|
||||
.query_facility_lock = ril_sim_query_facility_lock
|
||||
.query_facility_lock = ril_sim_query_facility_lock,
|
||||
.list_apps = ril_sim_list_apps,
|
||||
.open_channel2 = ril_sim_open_channel,
|
||||
.close_channel = ril_sim_close_channel,
|
||||
.session_read_binary = ril_sim_session_read_binary,
|
||||
.session_read_record = ril_sim_session_read_record,
|
||||
.session_read_info = ril_sim_session_read_info,
|
||||
.logical_access = ril_sim_logical_access
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -231,6 +231,12 @@ socket=/dev/socket/rild
|
||||
#
|
||||
#lteNetworkMode=9
|
||||
|
||||
# UMTS network mode.
|
||||
#
|
||||
# Default 3 (PREF_NET_TYPE_GSM_WCDMA_AUTO)
|
||||
#
|
||||
#umtsNetworkMode=3
|
||||
|
||||
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
|
||||
#
|
||||
# Default 20000 (20 seconds)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -210,6 +211,10 @@ struct ofono_sim_driver {
|
||||
void (*logical_access)(struct ofono_sim *sim, int session_id,
|
||||
const unsigned char *pdu, unsigned int len,
|
||||
ofono_sim_logical_access_cb_t cb, void *data);
|
||||
/* Since mer/1.23+git28 */
|
||||
void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid,
|
||||
unsigned int len, ofono_sim_open_channel_cb_t cb,
|
||||
void *data);
|
||||
};
|
||||
|
||||
int ofono_sim_driver_register(const struct ofono_sim_driver *d);
|
||||
|
||||
@@ -121,6 +121,30 @@ void __ofono_dbus_queue_request(struct ofono_dbus_queue *q,
|
||||
}
|
||||
}
|
||||
|
||||
static void __ofono_dbus_queue_submit_next(struct ofono_dbus_queue *q)
|
||||
{
|
||||
struct ofono_dbus_queue_request *next = q->requests;
|
||||
|
||||
while (next) {
|
||||
struct ofono_dbus_queue_request *done;
|
||||
DBusMessage *reply = next->fn(next->msg, next->data);
|
||||
|
||||
/* The request has been sent, no reply yet */
|
||||
if (!reply)
|
||||
break;
|
||||
|
||||
/* The request has completed synchronously */
|
||||
done = next;
|
||||
next = done->next;
|
||||
q->requests = next;
|
||||
done->next = NULL;
|
||||
|
||||
/* Send the reply */
|
||||
__ofono_dbus_pending_reply(&done->msg, reply);
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
}
|
||||
}
|
||||
|
||||
/* Consumes one reference to the reply */
|
||||
void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
|
||||
DBusMessage *reply)
|
||||
@@ -150,20 +174,7 @@ void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
|
||||
/* Submit the next request if there is any */
|
||||
while (next && reply) {
|
||||
reply = next->fn(next->msg, next->data);
|
||||
if (reply) {
|
||||
/* The request has completed synchronously */
|
||||
done = next;
|
||||
next = done->next;
|
||||
q->requests = next;
|
||||
done->next = NULL;
|
||||
|
||||
/* Send the reply */
|
||||
__ofono_dbus_pending_reply(&done->msg, reply);
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
}
|
||||
}
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
}
|
||||
|
||||
void __ofono_dbus_queue_reply_ok(struct ofono_dbus_queue *q)
|
||||
@@ -250,8 +261,10 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
|
||||
* Find all other requests with the same handler and the same data
|
||||
* and complete those too (except when the handler is NULL)
|
||||
*/
|
||||
if (!handler)
|
||||
if (!handler) {
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
return;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
req = q->requests;
|
||||
@@ -274,6 +287,7 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
|
||||
|
||||
req = next;
|
||||
}
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2019 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -388,6 +388,7 @@ unsigned short __ofono_sms_get_next_ref(struct ofono_sms *sms);
|
||||
|
||||
#include <ofono/sim.h>
|
||||
|
||||
struct sim_aid;
|
||||
struct ofono_sim_aid_session;
|
||||
enum sim_app_type;
|
||||
|
||||
@@ -426,7 +427,7 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
unsigned int id);
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
|
||||
struct ofono_sim *sim, unsigned char *aid);
|
||||
struct ofono_sim *sim, const struct sim_aid *aid);
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
|
||||
struct ofono_sim *sim, enum sim_app_type type);
|
||||
@@ -436,7 +437,7 @@ int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session);
|
||||
enum sim_app_type __ofono_sim_session_get_type(
|
||||
struct ofono_sim_aid_session *session);
|
||||
|
||||
unsigned char *__ofono_sim_session_get_aid(
|
||||
const struct sim_aid *__ofono_sim_session_get_aid(
|
||||
struct ofono_sim_aid_session *session);
|
||||
|
||||
const char *__ofono_sim_get_impi(struct ofono_sim *sim);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -62,7 +63,7 @@ struct auth_request {
|
||||
};
|
||||
|
||||
struct aid_object {
|
||||
uint8_t aid[16];
|
||||
struct sim_aid aid;
|
||||
char *path;
|
||||
enum sim_app_type type;
|
||||
};
|
||||
@@ -82,7 +83,7 @@ struct ofono_sim_auth {
|
||||
/*
|
||||
* Find an application by path. 'path' should be a DBusMessage object path.
|
||||
*/
|
||||
static uint8_t *find_aid_by_path(GSList *aid_objects,
|
||||
static const struct aid_object *find_aid_by_path(GSList *aid_objects,
|
||||
const char *path)
|
||||
{
|
||||
GSList *iter = aid_objects;
|
||||
@@ -91,7 +92,7 @@ static uint8_t *find_aid_by_path(GSList *aid_objects,
|
||||
struct aid_object *obj = iter->data;
|
||||
|
||||
if (!strcmp(path, obj->path))
|
||||
return obj->aid;
|
||||
return obj;
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
}
|
||||
@@ -208,14 +209,10 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
|
||||
DBusMessage *reply = NULL;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter dict;
|
||||
const uint8_t *res = NULL;
|
||||
const uint8_t *ck = NULL;
|
||||
const uint8_t *ik = NULL;
|
||||
const uint8_t *auts = NULL;
|
||||
const uint8_t *kc = NULL;
|
||||
struct data_block res, ck, ik, auts, sres, kc;
|
||||
|
||||
if (!sim_parse_umts_authenticate(resp, len, &res, &ck, &ik,
|
||||
&auts, &kc))
|
||||
&auts, &sres, &kc))
|
||||
goto umts_end;
|
||||
|
||||
reply = dbus_message_new_method_return(sa->pending->msg);
|
||||
@@ -225,15 +222,23 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
|
||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
||||
"{say}", &dict);
|
||||
|
||||
if (auts) {
|
||||
append_dict_byte_array(&dict, "AUTS", auts, 14);
|
||||
} else {
|
||||
append_dict_byte_array(&dict, "RES", res, 8);
|
||||
append_dict_byte_array(&dict, "CK", ck, 16);
|
||||
append_dict_byte_array(&dict, "IK", ik, 16);
|
||||
if (kc)
|
||||
append_dict_byte_array(&dict, "Kc", kc, 8);
|
||||
}
|
||||
if (auts.data)
|
||||
append_dict_byte_array(&dict, "AUTS", auts.data, auts.len);
|
||||
|
||||
if (sres.data)
|
||||
append_dict_byte_array(&dict, "SRES", sres.data, sres.len);
|
||||
|
||||
if (res.data)
|
||||
append_dict_byte_array(&dict, "RES", res.data, res.len);
|
||||
|
||||
if (ck.data)
|
||||
append_dict_byte_array(&dict, "CK", ck.data, ck.len);
|
||||
|
||||
if (ik.data)
|
||||
append_dict_byte_array(&dict, "IK", ik.data, ik.len);
|
||||
|
||||
if (kc.data)
|
||||
append_dict_byte_array(&dict, "Kc", kc.data, kc.len);
|
||||
|
||||
dbus_message_iter_close_container(&iter, &dict);
|
||||
|
||||
@@ -368,6 +373,8 @@ static void get_session_cb(ofono_bool_t active, int session_id,
|
||||
error:
|
||||
__ofono_dbus_pending_reply(&sa->pending->msg,
|
||||
__ofono_error_failed(sa->pending->msg));
|
||||
__ofono_sim_remove_session_watch(sa->pending->session,
|
||||
sa->pending->watch_id);
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
}
|
||||
@@ -378,7 +385,7 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
|
||||
struct ofono_sim_auth *sa = data;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter array;
|
||||
uint8_t *aid;
|
||||
const struct aid_object *obj;
|
||||
|
||||
if (sa->pending)
|
||||
return __ofono_error_busy(msg);
|
||||
@@ -418,13 +425,20 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
|
||||
/*
|
||||
* retrieve session from SIM
|
||||
*/
|
||||
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
|
||||
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
|
||||
&obj->aid);
|
||||
sa->pending->msg = dbus_message_ref(msg);
|
||||
sa->pending->watch_id = __ofono_sim_add_session_watch(
|
||||
sa->pending->session, get_session_cb, sa, NULL);
|
||||
|
||||
return NULL;
|
||||
if (!sa->pending->watch_id) {
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
return __ofono_error_not_supported(msg);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
format_error:
|
||||
g_free(sa->pending);
|
||||
@@ -440,7 +454,7 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
|
||||
uint32_t rlen;
|
||||
uint32_t alen;
|
||||
struct ofono_sim_auth *sa = data;
|
||||
uint8_t *aid;
|
||||
const struct aid_object *obj;
|
||||
|
||||
if (sa->pending)
|
||||
return __ofono_error_busy(msg);
|
||||
@@ -465,12 +479,18 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
|
||||
/*
|
||||
* retrieve session from SIM
|
||||
*/
|
||||
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
|
||||
|
||||
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
|
||||
&obj->aid);
|
||||
sa->pending->watch_id = __ofono_sim_add_session_watch(
|
||||
sa->pending->session, get_session_cb, sa, NULL);
|
||||
|
||||
if (!sa->pending->watch_id) {
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
return __ofono_error_not_supported(msg);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -700,14 +720,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
|
||||
|
||||
ret = sprintf(new->path, "%s/", path);
|
||||
|
||||
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
|
||||
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
|
||||
new->path + ret);
|
||||
|
||||
g_dbus_register_interface(conn, new->path,
|
||||
OFONO_USIM_APPLICATION_INTERFACE,
|
||||
sim_auth_usim_app, NULL, NULL,
|
||||
sa, NULL);
|
||||
|
||||
memcpy(new->aid, r->aid, 16);
|
||||
new->aid = r->aid;
|
||||
|
||||
break;
|
||||
case SIM_APP_TYPE_ISIM:
|
||||
@@ -715,14 +736,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
|
||||
|
||||
ret = sprintf(new->path, "%s/", path);
|
||||
|
||||
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
|
||||
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
|
||||
new->path + ret);
|
||||
|
||||
g_dbus_register_interface(conn, new->path,
|
||||
OFONO_ISIM_APPLICATION_INTERFACE,
|
||||
sim_auth_isim_app, NULL, NULL,
|
||||
sa, NULL);
|
||||
|
||||
memcpy(new->aid, r->aid, 16);
|
||||
new->aid = r->aid;
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -2441,7 +2442,7 @@ struct ofono_sim_context *ofono_sim_context_create_isim(
|
||||
|
||||
if (session->record->type == SIM_APP_TYPE_ISIM) {
|
||||
return sim_fs_context_new_with_aid(sim->simfs_isim,
|
||||
session->record->aid);
|
||||
&session->record->aid);
|
||||
}
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
@@ -3667,6 +3668,26 @@ const char *__ofono_sim_get_impi(struct ofono_sim *sim)
|
||||
static void open_channel_cb(const struct ofono_error *error, int session_id,
|
||||
void *data);
|
||||
|
||||
static gboolean open_channel(struct ofono_sim_aid_session *session)
|
||||
{
|
||||
struct ofono_sim *sim = session->sim;
|
||||
const struct ofono_sim_driver *driver = sim->driver;
|
||||
const struct sim_aid *aid = &session->record->aid;
|
||||
|
||||
if (driver->open_channel2) {
|
||||
driver->open_channel2(sim, aid->aid, aid->len, open_channel_cb,
|
||||
session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (driver->open_channel && aid->len == 16) {
|
||||
driver->open_channel(sim, aid->aid, open_channel_cb, session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void close_channel_cb(const struct ofono_error *error, void *data)
|
||||
{
|
||||
struct ofono_sim_aid_session *session = data;
|
||||
@@ -3680,10 +3701,8 @@ static void close_channel_cb(const struct ofono_error *error, void *data)
|
||||
* An atom requested to open during a close, we can re-open
|
||||
* here.
|
||||
*/
|
||||
session->sim->driver->open_channel(session->sim,
|
||||
session->record->aid, open_channel_cb,
|
||||
session);
|
||||
return;
|
||||
if (open_channel(session))
|
||||
return;
|
||||
}
|
||||
|
||||
session->state = SESSION_STATE_INACTIVE;
|
||||
@@ -3758,10 +3777,12 @@ unsigned int __ofono_sim_add_session_watch(
|
||||
* If the session is inactive and there are no watchers, open
|
||||
* a new session.
|
||||
*/
|
||||
session->state = SESSION_STATE_OPENING;
|
||||
session->sim->driver->open_channel(session->sim,
|
||||
session->record->aid, open_channel_cb,
|
||||
session);
|
||||
if (open_channel(session)) {
|
||||
session->state = SESSION_STATE_OPENING;
|
||||
} else {
|
||||
g_free(item);
|
||||
return 0;
|
||||
}
|
||||
} else if (session->state == SESSION_STATE_OPEN) {
|
||||
/*
|
||||
* Session is already open and available, just call the
|
||||
@@ -3784,7 +3805,8 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
{
|
||||
__ofono_watchlist_remove_item(session->watches, id);
|
||||
|
||||
if (g_slist_length(session->watches->items) == 0) {
|
||||
if (g_slist_length(session->watches->items) == 0 &&
|
||||
session->state == SESSION_STATE_OPEN) {
|
||||
/* last watcher, close session */
|
||||
session->state = SESSION_STATE_CLOSING;
|
||||
session->sim->driver->close_channel(session->sim,
|
||||
@@ -3793,14 +3815,15 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
}
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
|
||||
struct ofono_sim *sim, unsigned char *aid)
|
||||
struct ofono_sim *sim, const struct sim_aid *aid)
|
||||
{
|
||||
GSList *iter = sim->aid_sessions;
|
||||
|
||||
while (iter) {
|
||||
struct ofono_sim_aid_session *session = iter->data;
|
||||
|
||||
if (!memcmp(session->record->aid, aid, 16))
|
||||
if (session->record->aid.len == aid->len &&
|
||||
!memcmp(session->record->aid.aid, aid, aid->len))
|
||||
return session;
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
@@ -3837,10 +3860,10 @@ enum sim_app_type __ofono_sim_session_get_type(
|
||||
return session->record->type;
|
||||
}
|
||||
|
||||
unsigned char *__ofono_sim_session_get_aid(
|
||||
const struct sim_aid *__ofono_sim_session_get_aid(
|
||||
struct ofono_sim_aid_session *session)
|
||||
{
|
||||
return session->record->aid;
|
||||
return &session->record->aid;
|
||||
}
|
||||
|
||||
GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -164,7 +165,7 @@ struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs)
|
||||
}
|
||||
|
||||
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
|
||||
unsigned char *aid)
|
||||
const struct sim_aid *aid)
|
||||
{
|
||||
struct ofono_sim_context *context = sim_fs_context_new(fs);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,6 +21,7 @@
|
||||
*/
|
||||
|
||||
struct sim_fs;
|
||||
struct sim_aid;
|
||||
|
||||
typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
|
||||
int total_length, int record_length,
|
||||
@@ -30,7 +32,7 @@ struct sim_fs *sim_fs_new(struct ofono_sim *sim,
|
||||
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
|
||||
|
||||
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
|
||||
unsigned char *aid);
|
||||
const struct sim_aid *aid);
|
||||
|
||||
unsigned int sim_fs_file_watch_add(struct ofono_sim_context *context,
|
||||
int id, ofono_sim_file_changed_cb_t cb,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1419,7 +1420,7 @@ gboolean sim_parse_3g_get_response(const unsigned char *data, int len,
|
||||
if (tlv[1] != 0x21)
|
||||
return FALSE;
|
||||
|
||||
switch (tlv[0] & 0x3) {
|
||||
switch (tlv[0] & 0x7) {
|
||||
case 1: /* Transparent */
|
||||
str = 0x00;
|
||||
break;
|
||||
@@ -1572,20 +1573,17 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
|
||||
/* Find all the application entries */
|
||||
while ((dataobj = ber_tlv_find_by_tag(buffer, 0x61, len,
|
||||
&dataobj_len)) != NULL) {
|
||||
struct sim_app_record app;
|
||||
struct sim_app_record *app;
|
||||
const unsigned char *aid, *label;
|
||||
int label_len;
|
||||
int label_len, aid_len;
|
||||
char *app_label;
|
||||
|
||||
/* Find the aid (mandatory) */
|
||||
aid = ber_tlv_find_by_tag(dataobj, 0x4f, dataobj_len,
|
||||
&app.aid_len);
|
||||
if (!aid || app.aid_len < 0x01 || app.aid_len > 0x10)
|
||||
&aid_len);
|
||||
if (!aid || aid_len < 0x01 || aid_len > 0x10)
|
||||
goto error;
|
||||
|
||||
memcpy(app.aid, aid, app.aid_len);
|
||||
|
||||
app.type = (app.aid[5] << 8) | app.aid[6];
|
||||
|
||||
/* Find the label (optional) */
|
||||
label = ber_tlv_find_by_tag(dataobj, 0x50, dataobj_len,
|
||||
&label_len);
|
||||
@@ -1594,14 +1592,21 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
|
||||
* Label field uses the extra complicated
|
||||
* encoding in 102.221 Annex A
|
||||
*/
|
||||
app.label = sim_string_to_utf8(label, label_len);
|
||||
app_label = sim_string_to_utf8(label, label_len);
|
||||
|
||||
if (app.label == NULL)
|
||||
if (app_label == NULL)
|
||||
goto error;
|
||||
} else
|
||||
app.label = NULL;
|
||||
app_label = NULL;
|
||||
|
||||
ret = g_slist_prepend(ret, g_memdup(&app, sizeof(app)));
|
||||
app = g_new0(struct sim_app_record, 1);
|
||||
|
||||
memcpy(app->aid.aid, aid, aid_len);
|
||||
app->aid.len = aid_len;
|
||||
app->label = app_label;
|
||||
app->type = (aid[5] << 8) | aid[6];
|
||||
|
||||
ret = g_slist_prepend(ret, app);
|
||||
|
||||
len -= (dataobj - buffer) + dataobj_len;
|
||||
buffer = dataobj + dataobj_len;
|
||||
@@ -1667,67 +1672,135 @@ int sim_build_gsm_authenticate(unsigned char *buffer, int len,
|
||||
return build_authenticate(buffer, rand, NULL);
|
||||
}
|
||||
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
|
||||
int len, const unsigned char **res, const unsigned char **ck,
|
||||
const unsigned char **ik, const unsigned char **auts,
|
||||
const unsigned char **kc)
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
|
||||
struct data_block *res, struct data_block *ck,
|
||||
struct data_block *ik, struct data_block *auts,
|
||||
struct data_block *sres, struct data_block *kc)
|
||||
{
|
||||
if (len < 16 || !buffer)
|
||||
const unsigned char *ptr = buffer;
|
||||
const unsigned char *end = ptr + len;
|
||||
unsigned int l;
|
||||
|
||||
if (!buffer || len < 2)
|
||||
return FALSE;
|
||||
|
||||
switch (buffer[0]) {
|
||||
memset(res, 0, sizeof(*res));
|
||||
memset(ck, 0, sizeof(*ck));
|
||||
memset(ik, 0, sizeof(*ik));
|
||||
memset(kc, 0, sizeof(*kc));
|
||||
memset(auts, 0, sizeof(*auts));
|
||||
memset(sres, 0, sizeof(*sres));
|
||||
|
||||
/*
|
||||
* TS 31.102
|
||||
* 7.1.2.1 GSM/3G security context
|
||||
*/
|
||||
switch (*ptr++) {
|
||||
case 0xdb:
|
||||
/* 'DB' + '08' + RES(16) + '10' + CK(32) + '10' + IK(32) = 43 */
|
||||
if (len < 43)
|
||||
goto umts_end;
|
||||
/*
|
||||
* Response parameters/data, case 1, 3G security context,
|
||||
* command successful:
|
||||
*
|
||||
* "Successful 3G authentication" tag = 'DB'
|
||||
* 'DB' + L3 + RES(L3) + L4 + CK(L4) + L5 + IK(L5) + 8 + Kc(8)
|
||||
*/
|
||||
l = *ptr++; /* L3 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
/* success */
|
||||
if (buffer[1] != 0x08)
|
||||
goto umts_end;
|
||||
res->data = ptr;
|
||||
res->len = l;
|
||||
ptr += l;
|
||||
|
||||
*res = buffer + 2;
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
if (buffer[10] != 0x10)
|
||||
goto umts_end;
|
||||
l = *ptr++; /* L4 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
*ck = buffer + 11;
|
||||
ck->data = ptr;
|
||||
ck->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (buffer[27] != 0x10)
|
||||
goto umts_end;
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
*ik = buffer + 28;
|
||||
l = *ptr++; /* L5 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
if (len >= 53 && kc) {
|
||||
if (buffer[44] != 0x08)
|
||||
goto umts_end;
|
||||
ik->data = ptr;
|
||||
ik->len = l;
|
||||
ptr += l;
|
||||
|
||||
*kc = buffer + 45;
|
||||
} else {
|
||||
*kc = NULL;
|
||||
if (ptr < end) {
|
||||
l = *ptr++;
|
||||
if (l != 8 || (ptr + l) != end)
|
||||
return FALSE;
|
||||
|
||||
kc->data = ptr;
|
||||
kc->len = l;
|
||||
ptr += l;
|
||||
}
|
||||
|
||||
*auts = NULL;
|
||||
return TRUE;
|
||||
|
||||
break;
|
||||
case 0xdc:
|
||||
/* 'DC' + '0E' + AUTS(14) = 16 */
|
||||
if (len < 16)
|
||||
goto umts_end;
|
||||
/*
|
||||
* Response parameters/data, case 2, 3G security context,
|
||||
* synchronisation failure:
|
||||
*
|
||||
* "Synchronisation failure" tag = 'DC'
|
||||
* 'DC' + L1 + AUTS(L1)
|
||||
*/
|
||||
l = *ptr++; /* L1 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
/* sync error */
|
||||
if (buffer[1] != 0x0e)
|
||||
goto umts_end;
|
||||
auts->data = ptr;
|
||||
auts->len = l;
|
||||
ptr += l;
|
||||
|
||||
*auts = buffer + 2;
|
||||
if (ptr != end)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 0x04:
|
||||
/*
|
||||
* Response parameters/data, case 3, GSM security context,
|
||||
* command successful:
|
||||
*
|
||||
* 4 + SRES(4) + 8 + Kc(8)
|
||||
*/
|
||||
l = 4; /* Already skipped this one */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
sres->data = ptr;
|
||||
sres->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
l = *ptr++; /* 8 */
|
||||
if (l != 8 || (ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
kc->data = ptr;
|
||||
kc->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (ptr != end)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
break;
|
||||
default:
|
||||
goto umts_end;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
umts_end:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,9 +314,13 @@ struct sim_ef_info {
|
||||
enum sim_file_access perm_update;
|
||||
};
|
||||
|
||||
struct sim_app_record {
|
||||
struct sim_aid {
|
||||
unsigned char aid[16];
|
||||
int aid_len;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
struct sim_app_record {
|
||||
struct sim_aid aid;
|
||||
char *label;
|
||||
enum sim_app_type type;
|
||||
};
|
||||
@@ -371,6 +375,11 @@ struct comprehension_tlv_builder {
|
||||
struct ber_tlv_builder *parent;
|
||||
};
|
||||
|
||||
struct data_block {
|
||||
const unsigned char *data;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
void simple_tlv_iter_init(struct simple_tlv_iter *iter,
|
||||
const unsigned char *pdu, unsigned int len);
|
||||
gboolean simple_tlv_iter_next(struct simple_tlv_iter *iter);
|
||||
@@ -526,10 +535,10 @@ int sim_build_umts_authenticate(unsigned char *buffer, int len,
|
||||
int sim_build_gsm_authenticate(unsigned char *buffer, int len,
|
||||
const unsigned char *rand);
|
||||
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
|
||||
int len, const unsigned char **res, const unsigned char **ck,
|
||||
const unsigned char **ik, const unsigned char **auts,
|
||||
const unsigned char **kc);
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
|
||||
struct data_block *res, struct data_block *ck,
|
||||
struct data_block *ik, struct data_block *auts,
|
||||
struct data_block *sres, struct data_block *kc);
|
||||
|
||||
gboolean sim_parse_gsm_authenticate(const unsigned char *buffer, int len,
|
||||
const unsigned char **sres, const unsigned char **kc);
|
||||
|
||||
@@ -417,7 +417,7 @@ static void test_reply_last_reply(DBusPendingCall *call, void *dbus)
|
||||
G_CAST(dbus, struct test_reply_data, dbus);
|
||||
|
||||
DBG("");
|
||||
test_dbus_check_error_reply(call, TEST_ERROR_FAILED);
|
||||
test_dbus_check_empty_reply(call, NULL);
|
||||
g_main_loop_quit(test->dbus.loop);
|
||||
}
|
||||
|
||||
@@ -445,6 +445,12 @@ static DBusMessage *test_reply_4(DBusMessage *msg, void *data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *test_reply_5(DBusMessage *msg, void *data)
|
||||
{
|
||||
DBG("");
|
||||
return dbus_message_new_method_return(msg);
|
||||
}
|
||||
|
||||
static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -485,10 +491,17 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
case 6:
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_4,
|
||||
msg, NULL);
|
||||
break;
|
||||
case 7:
|
||||
/* Call the same method again */
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_4,
|
||||
msg, NULL);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
/* Call the last one */
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_5,
|
||||
msg, NULL);
|
||||
|
||||
/* This completes the first one, with NULL handler */
|
||||
__ofono_dbus_queue_reply_all_fn_param(test->queue, NULL, NULL);
|
||||
g_assert(__ofono_dbus_queue_pending(test->queue));
|
||||
@@ -508,10 +521,12 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
/* This one test_reply_3 with Failed */
|
||||
__ofono_dbus_queue_reply_all_error(test->queue, NULL);
|
||||
|
||||
/* This one test_reply_4 with NotSupported */
|
||||
/* This one completes all test_reply_4 with NotSupported */
|
||||
error.type = OFONO_ERROR_TYPE_ERRNO;
|
||||
error.error = -EOPNOTSUPP;
|
||||
__ofono_dbus_queue_reply_all_error(test->queue, &error);
|
||||
|
||||
/* test_reply_5 must be already completed */
|
||||
g_assert(!__ofono_dbus_queue_pending(test->queue));
|
||||
|
||||
/* And this one does nothing */
|
||||
@@ -541,7 +556,8 @@ static void test_reply_start(struct test_dbus_context *dbus)
|
||||
test_client_call(dbus, 4, test_dbus_expect_empty_reply);
|
||||
test_client_call(dbus, 5, test_expect_failed);
|
||||
test_client_call(dbus, 6, test_expect_not_supported);
|
||||
test_client_call(dbus, 7, test_reply_last_reply);
|
||||
test_client_call(dbus, 7, test_expect_not_supported);
|
||||
test_client_call(dbus, 8, test_reply_last_reply);
|
||||
}
|
||||
|
||||
static void test_reply(void)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -491,12 +492,12 @@ static void test_application_entry_decode(void)
|
||||
app[0] = entries->next->data;
|
||||
app[1] = entries->data;
|
||||
|
||||
g_assert(app[0]->aid_len == 0x10);
|
||||
g_assert(!memcmp(app[0]->aid, &ef_dir[4], 0x10));
|
||||
g_assert(app[0]->aid.len == 0x10);
|
||||
g_assert(!memcmp(app[0]->aid.aid, &ef_dir[4], 0x10));
|
||||
g_assert(app[0]->label == NULL);
|
||||
|
||||
g_assert(app[1]->aid_len == 0x0c);
|
||||
g_assert(!memcmp(app[1]->aid, &ef_dir[37], 0x0c));
|
||||
g_assert(app[1]->aid.len == 0x0c);
|
||||
g_assert(!memcmp(app[1]->aid.aid, &ef_dir[37], 0x0c));
|
||||
g_assert(app[1]->label != NULL);
|
||||
g_assert(!strcmp(app[1]->label, "MIDPfiles"));
|
||||
|
||||
@@ -529,32 +530,34 @@ static void test_get_2g_path(void)
|
||||
static void test_auth_build_parse(void)
|
||||
{
|
||||
unsigned char auth_cmd[40];
|
||||
const unsigned char rand[16] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
|
||||
const unsigned char rand[] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
|
||||
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0e, 0x0f };
|
||||
const unsigned char sres[4] = { 0x00, 0x11, 0x22, 0x33 };
|
||||
const unsigned char sres[] = { 0x00, 0x11, 0x22, 0x33 };
|
||||
const unsigned char *sres_p;
|
||||
struct data_block sres_b;
|
||||
const unsigned char kc[8] = { 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56,
|
||||
0x78, 0x9a };
|
||||
const unsigned char *kc_p;
|
||||
struct data_block kc_b;
|
||||
const unsigned char gsm_success[] = { 0x04, 0x00, 0x11, 0x22, 0x33,
|
||||
0x08,0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
|
||||
const unsigned char autn[16] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
const unsigned char autn[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
|
||||
0x01, 0x00 };
|
||||
const unsigned char res[8] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
|
||||
const unsigned char res[] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
|
||||
0x11, 0x22 };
|
||||
const unsigned char *res_p;
|
||||
const unsigned char ck[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
struct data_block res_b;
|
||||
const unsigned char ck[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
const unsigned char *ck_p;
|
||||
const unsigned char ik[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
struct data_block ck_b;
|
||||
const unsigned char ik[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||
const unsigned char *ik_p;
|
||||
const unsigned char auts[16] = { 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
|
||||
0xbe, 0xef };
|
||||
const unsigned char *auts_p;
|
||||
struct data_block ik_b;
|
||||
const unsigned char auts[] = { 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
|
||||
0xef, 0xde, 0xea };
|
||||
struct data_block auts_b;
|
||||
|
||||
const unsigned char umts_success[] = { 0xdb, 0x08, 0xff, 0xee, 0xdd,
|
||||
0xcc, 0xbb, 0xaa, 0x11, 0x22, 0x10, 0x00, 0x11, 0x22,
|
||||
@@ -572,6 +575,8 @@ static void test_auth_build_parse(void)
|
||||
const unsigned char umts_sync_failure[] = { 0xdc, 0x0e, 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
|
||||
0xef, 0xde, 0xea };
|
||||
const unsigned char case3[] = { 0x04, 0x01, 0x02, 0x03, 0x04,
|
||||
0x08, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
|
||||
int len = 0;
|
||||
|
||||
/* test GSM auth command */
|
||||
@@ -606,31 +611,96 @@ static void test_auth_build_parse(void)
|
||||
g_assert(!memcmp(sres_p, sres, 4));
|
||||
g_assert(!memcmp(kc_p, kc, 8));
|
||||
|
||||
/* test truncated messages */
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 10,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 11,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 27,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 28,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_sync_failure, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 5,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 6,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* the extra byte won't actually be accessed */
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success,
|
||||
sizeof(umts_success) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_sync_failure,
|
||||
sizeof(umts_sync_failure) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, sizeof(case3) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* unrecognized data */
|
||||
g_assert(!sim_parse_umts_authenticate(case3 + 1, sizeof(case3) - 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* test UMTS success parse, no kc */
|
||||
g_assert(sim_parse_umts_authenticate(umts_success, sizeof(umts_success),
|
||||
&res_p, &ck_p, &ik_p, &auts_p, &kc_p));
|
||||
g_assert(!memcmp(res_p, res, 8));
|
||||
g_assert(!memcmp(ck_p, ck, 16));
|
||||
g_assert(!memcmp(ik_p, ik, 16));
|
||||
g_assert(!auts_p && !kc_p);
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert_cmpuint(res_b.len, == , sizeof(res));
|
||||
g_assert(!memcmp(res_b.data, res, sizeof(res)));
|
||||
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
|
||||
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
|
||||
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
|
||||
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
g_assert(!kc_b.len && !kc_b.data);
|
||||
|
||||
/* test UMTS sync failure */
|
||||
g_assert(sim_parse_umts_authenticate(umts_sync_failure,
|
||||
sizeof(umts_sync_failure),
|
||||
&res_p, &ck_p, &ik_p, &auts_p,
|
||||
&kc_p));
|
||||
g_assert(!memcmp(auts_p, auts, 14));
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert_cmpuint(auts_b.len, == , sizeof(auts));
|
||||
g_assert(!memcmp(auts_b.data, auts, sizeof(auts)));
|
||||
g_assert(!res_b.len && !res_b.data);
|
||||
g_assert(!ck_b.len && !ck_b.data);
|
||||
g_assert(!ik_b.len && !ik_b.data);
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!kc_b.len && !kc_b.data);
|
||||
|
||||
/* test UMTS success parse, with kc */
|
||||
g_assert(sim_parse_umts_authenticate(umts_success_kc,
|
||||
sizeof(umts_success_kc),
|
||||
&res_p, &ck_p, &ik_p, &auts_p,
|
||||
&kc_p));
|
||||
g_assert(!memcmp(res_p, res, 8));
|
||||
g_assert(!memcmp(ck_p, ck, 16));
|
||||
g_assert(!memcmp(ik_p, ik, 16));
|
||||
g_assert(!memcmp(kc_p, kc, 8));
|
||||
g_assert(!auts_p);
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert_cmpuint(res_b.len, == , sizeof(res));
|
||||
g_assert(!memcmp(res_b.data, res, sizeof(res)));
|
||||
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
|
||||
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
|
||||
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
|
||||
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
|
||||
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
|
||||
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
|
||||
/* test case3 */
|
||||
g_assert(sim_parse_umts_authenticate(case3, sizeof(case3),
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert(!res_b.len && !res_b.data);
|
||||
g_assert(!ck_b.len && !ck_b.data);
|
||||
g_assert(!ik_b.len && !ik_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
g_assert_cmpuint(sres_b.len, == , 4);
|
||||
g_assert(!memcmp(sres_b.data, case3 + 1, sres_b.len));
|
||||
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
|
||||
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
Reference in New Issue
Block a user