summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2018-10-04 03:29:43 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2018-10-27 05:49:45 +0700
commitf8edc4550671dcf0339091f5218e8275be0d2502 (patch)
tree106507a1d14140040cc10707d6658bd5f7e8dde7 /src
parentd464fe5388819f3c432797e229740277da478d7d (diff)
layer23/common: move SIM APDU caching from l1ctl.c
L1CTL implementation (i.e. l1ctl.c) is not a good place for the SIM specific stuff. Let's move it to the proper place (i.e. sim.c). As a bonus, this change fixes a possible problem of loosing the cached APDUs if two or more L2&3 applications are using a single LAPDm connection. The APDU buffer is dedicated per MS now. Change-Id: I564c610e45aa3b630ca5d1ec6bc1cace0dc9c566
Diffstat (limited to 'src')
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sim.h4
-rw-r--r--src/host/layer23/src/common/l1ctl.c16
-rw-r--r--src/host/layer23/src/common/sim.c25
3 files changed, 29 insertions, 16 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/sim.h b/src/host/layer23/include/osmocom/bb/common/sim.h
index 95d2147..8b1f830 100644
--- a/src/host/layer23/include/osmocom/bb/common/sim.h
+++ b/src/host/layer23/include/osmocom/bb/common/sim.h
@@ -176,6 +176,10 @@ struct gsm_sim {
uint8_t reset;
uint8_t chv1_remain, chv2_remain;
uint8_t unblk1_remain, unblk2_remain;
+
+ /* APDU cache (used by GSMTAP) */
+ uint8_t apdu_data[256 + 7];
+ uint16_t apdu_len;
};
struct sim_hdr {
diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c
index 6f4a6d8..b3f73a8 100644
--- a/src/host/layer23/src/common/l1ctl.c
+++ b/src/host/layer23/src/common/l1ctl.c
@@ -50,9 +50,6 @@
extern struct gsmtap_inst *gsmtap_inst;
-static int apdu_len = -1;
-static uint8_t apdu_data[256 + 7];
-
static struct msgb *osmo_l1_alloc(uint8_t msg_type)
{
struct l1ctl_hdr *l1h;
@@ -620,12 +617,6 @@ int l1ctl_tx_sim_req(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
struct msgb *msg;
uint8_t *dat;
- if (length <= sizeof(apdu_data)) {
- memcpy(apdu_data, data, length);
- apdu_len = length;
- } else
- apdu_len = -1;
-
msg = osmo_l1_alloc(L1CTL_SIM_REQ);
if (!msg)
return -1;
@@ -642,13 +633,6 @@ static int rx_l1_sim_conf(struct osmocom_ms *ms, struct msgb *msg)
uint16_t len = msgb_l2len(msg);
uint8_t *data = msg->data;
- if (apdu_len > -1 && apdu_len + len <= sizeof(apdu_data)) {
- memcpy(apdu_data + apdu_len, data, len);
- apdu_len += len;
- gsmtap_send_ex(gsmtap_inst, GSMTAP_TYPE_SIM, 0, 0, 0, 0, 0, 0,
- 0, apdu_data, apdu_len);
- }
-
LOGP(DL1C, LOGL_INFO, "SIM %s\n", osmo_hexdump(data, len));
sim_apdu_resp(ms, msg);
diff --git a/src/host/layer23/src/common/sim.c b/src/host/layer23/src/common/sim.c
index c2d6033..7f5240d 100644
--- a/src/host/layer23/src/common/sim.c
+++ b/src/host/layer23/src/common/sim.c
@@ -24,11 +24,15 @@
#include <arpa/inet.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/gsmtap.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1ctl.h>
+extern struct gsmtap_inst *gsmtap_inst;
+
static int sim_process_job(struct osmocom_ms *ms);
/*
@@ -185,6 +189,16 @@ static int sim_apdu_send(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
LOGP(DSIM, LOGL_INFO, "sending APDU (class 0x%02x, ins 0x%02x)\n",
data[0], data[1]);
+ /* Cache this APDU, so it can be sent to GSMTAP on response */
+ if (length <= sizeof(ms->sim.apdu_data)) {
+ memcpy(ms->sim.apdu_data, data, length);
+ ms->sim.apdu_len = length;
+ } else {
+ LOGP(DSIM, LOGL_NOTICE, "Cannot cache SIM APDU "
+ "(len=%u), so it won't be sent to GSMTAP\n", length);
+ ms->sim.apdu_len = 0;
+ }
+
/* adding SAP client support
* it makes more sense to do it here then in L1CTL */
if (ms->subscr.sim_type == GSM_SIM_TYPE_SAP) {
@@ -861,6 +875,17 @@ int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
struct gsm1111_response_mfdf_gsm *mfdf_gsm;
int i;
+ /* If there is cached APDU */
+ if (ms->sim.apdu_len) {
+ /* ... and APDU buffer has enough space, send it to GSMTAP */
+ if ((ms->sim.apdu_len + length) <= sizeof(ms->sim.apdu_data)) {
+ memcpy(ms->sim.apdu_data + ms->sim.apdu_len, data, length);
+ ms->sim.apdu_len += length;
+ gsmtap_send_ex(gsmtap_inst, GSMTAP_TYPE_SIM,
+ 0, 0, 0, 0, 0, 0, 0, ms->sim.apdu_data, ms->sim.apdu_len);
+ }
+ }
+
/* ignore, if current job already gone */
if (!sim->job_msg) {
LOGP(DSIM, LOGL_ERROR, "received APDU but no job, "