summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-05-17 17:37:07 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-05-22 16:12:09 +0200
commit9be9a2ef7ff8e31906803477dc32b13fa84ea9eb (patch)
tree3094b2553f90dc4eb4236206028c4e24dd3660ba
parentac8460c77ba51ecb6c2636cdb65169bbb27472c3 (diff)
layer23: subscriber: Implement LOCIGPRS read/write for simcard backend
-rw-r--r--src/host/layer23/include/osmocom/bb/common/subscriber.h23
-rw-r--r--src/host/layer23/src/common/subscriber.c150
-rw-r--r--src/host/layer23/src/modem/gmm.c8
-rw-r--r--src/host/layer23/src/modem/sm.c4
4 files changed, 173 insertions, 12 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/subscriber.h b/src/host/layer23/include/osmocom/bb/common/subscriber.h
index 792df629..232018db 100644
--- a/src/host/layer23/include/osmocom/bb/common/subscriber.h
+++ b/src/host/layer23/include/osmocom/bb/common/subscriber.h
@@ -6,6 +6,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm23003.h>
+#include <osmocom/gsm/gsm48.h>
/* GSM 04.08 4.1.2.2 SIM update status */
enum gsm_sub_sim_ustate {
@@ -20,6 +21,18 @@ static inline const char *gsm_sub_sim_ustate_name(enum gsm_sub_sim_ustate val)
return get_value_string(gsm_sub_sim_ustate_names, val);
}
+/* 3GPP TS 24.008 4.1.3.2 GPRS update status */
+enum gsm_sub_sim_gustate {
+ GSM_SIM_GU0_NULL,
+ GSM_SIM_GU1_UPDATED,
+ GSM_SIM_GU2_NOT_UPDATED,
+ GSM_SIM_GU3_ROAMING_NA,
+};
+extern const struct value_string gsm_sub_sim_gustate_names[];
+static inline const char *gsm_sub_sim_gustate_name(enum gsm_sub_sim_gustate val)
+{
+ return get_value_string(gsm_sub_sim_gustate_names, val);
+}
struct gsm_sub_plmn_list {
struct llist_head entry;
@@ -58,7 +71,6 @@ struct gsm_subscriber {
/* TMSI / LAI */
uint32_t tmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
- uint32_t ptmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
struct osmo_location_area_id lai; /* invalid lac: 0x0000 */
@@ -97,6 +109,14 @@ struct gsm_subscriber {
/* SMS */
char sms_sca[22];
+
+ struct {
+ uint8_t gu_state; /* GU, TS 24.008 */
+ struct gprs_ra_id rai;
+ uint32_t ptmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
+ uint32_t ptmsi_sig; /* P-TMSI signature, 3 bytes */
+ bool imsi_attached;
+ } gprs;
};
int gsm_subscr_init(struct osmocom_ms *ms);
@@ -109,6 +129,7 @@ int gsm_subscr_sap_rsp_cb(struct osmocom_ms *ms, int res_code,
int gsm_subscr_sim_pin(struct osmocom_ms *ms, const char *pin1, const char *pin2,
int8_t mode);
int gsm_subscr_write_loci(struct osmocom_ms *ms);
+int gsm_subscr_write_locigprs(struct osmocom_ms *ms);
int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq, const uint8_t *rand,
bool no_sim);
void new_sim_ustate(struct gsm_subscriber *subscr, int state);
diff --git a/src/host/layer23/src/common/subscriber.c b/src/host/layer23/src/common/subscriber.c
index dfd44dcc..b6fc74d8 100644
--- a/src/host/layer23/src/common/subscriber.c
+++ b/src/host/layer23/src/common/subscriber.c
@@ -45,6 +45,14 @@ const struct value_string gsm_sub_sim_ustate_names[] = {
{ 0, NULL }
};
+const struct value_string gsm_sub_sim_gustate_names[] = {
+ { GSM_SIM_GU0_NULL, "GU0_NULL" },
+ { GSM_SIM_GU1_UPDATED, "GU1_UPDATED" },
+ { GSM_SIM_GU2_NOT_UPDATED, "GU2_NOT_UPDATED" },
+ { GSM_SIM_GU3_ROAMING_NA, "GU3_ROAMING_NA" },
+ { 0, NULL }
+};
+
static int gsm_subscr_insert_simcard(struct osmocom_ms *ms);
static int gsm_subscr_insert_testcard(struct osmocom_ms *ms);
static int gsm_subscr_insert_sapcard(struct osmocom_ms *ms);
@@ -58,6 +66,8 @@ static int gsm_subscr_generate_kc_testcard(struct osmocom_ms *ms, uint8_t key_se
static int gsm_subscr_write_loci_simcard(struct osmocom_ms *ms);
+static int gsm_subscr_write_locigprs_simcard(struct osmocom_ms *ms);
+
static int gsm_subscr_sim_pin_simcard(struct osmocom_ms *ms, const char *pin1, const char *pin2,
int8_t mode);
@@ -105,7 +115,7 @@ int gsm_subscr_init(struct osmocom_ms *ms)
/* set TMSI / LAC invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
- subscr->ptmsi = GSM_RESERVED_TMSI;
+ subscr->gprs.ptmsi = GSM_RESERVED_TMSI;
subscr->lai.lac = 0x0000;
/* set key invalid */
@@ -305,6 +315,29 @@ int gsm_subscr_write_loci(struct osmocom_ms *ms)
}
}
+/* update LOCIGPRS on SIM */
+int gsm_subscr_write_locigprs(struct osmocom_ms *ms)
+{
+ struct gsm_subscriber *subscr = &ms->subscr;
+
+ /* skip, if no real valid SIM */
+ if (subscr->sim_type == GSM_SIM_TYPE_NONE || !subscr->sim_valid)
+ return 0;
+
+ LOGP(DMM, LOGL_INFO, "Updating LOCIGPRS on SIM\n");
+
+ switch (subscr->sim_type) {
+ case GSM_SIM_TYPE_L1PHY:
+ case GSM_SIM_TYPE_SAP:
+ return gsm_subscr_write_locigprs_simcard(ms);
+ case GSM_SIM_TYPE_TEST:
+ LOGP(DMM, LOGL_NOTICE, "Updating LOCIGPRS on test SIM: not implemented!\n");
+ return 0; /* TODO */
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
/* update plmn not allowed list on SIM */
static int subscr_write_plmn_na(struct osmocom_ms *ms)
{
@@ -444,20 +477,44 @@ void gsm_subscr_dump(struct gsm_subscriber *subscr,
if (subscr->sms_sca[0])
print(priv, " SMS Service Center Address: %s\n",
subscr->sms_sca);
+
print(priv, " Status: %s IMSI %s", gsm_sub_sim_ustate_name(subscr->ustate),
(subscr->imsi_attached) ? "attached" : "detached");
if (subscr->tmsi != GSM_RESERVED_TMSI)
print(priv, " TMSI 0x%08x", subscr->tmsi);
- if (subscr->ptmsi != GSM_RESERVED_TMSI)
- print(priv, " P-TMSI 0x%08x", subscr->ptmsi);
if (subscr->lai.lac > 0x0000 && subscr->lai.lac < 0xfffe) {
print(priv, "\n");
print(priv, " LAI: %s (%s, %s)\n",
osmo_lai_name(&subscr->lai),
gsm_get_mcc(subscr->lai.plmn.mcc),
gsm_get_mnc(&subscr->lai.plmn));
- } else
+ } else {
print(priv, " LAI: invalid\n");
+ }
+
+ print(priv, " GPRS Status: %s IMSI %s", gsm_sub_sim_gustate_name(subscr->gprs.gu_state),
+ (subscr->gprs.imsi_attached) ? "attached" : "detached");
+ if (subscr->gprs.ptmsi != GSM_RESERVED_TMSI)
+ print(priv, " PTMSI 0x%08x", subscr->tmsi);
+ if (subscr->gprs.ptmsi != GSM_RESERVED_TMSI)
+ print(priv, " PTMSI-sig 0x%06x", subscr->gprs.ptmsi_sig);
+ if (subscr->gprs.rai.lac > 0x0000 && subscr->gprs.rai.lac < 0xfffe) {
+ struct osmo_plmn_id plmn = {
+ .mcc = subscr->gprs.rai.mcc,
+ .mnc = subscr->gprs.rai.mnc,
+ .mnc_3_digits = subscr->gprs.rai.mnc_3_digits,
+ };
+ print(priv, "\n");
+ print(priv, " RAI: %s (%s, %s)\n",
+ osmo_rai_name(&subscr->gprs.rai),
+ gsm_get_mcc(plmn.mcc),
+ gsm_get_mnc(&plmn));
+ } else {
+ print(priv, " RAI: invalid\n");
+ }
+
+ if (subscr->gprs.ptmsi != GSM_RESERVED_TMSI)
+ print(priv, " P-TMSI 0x%08x", subscr->gprs.ptmsi);
if (subscr->key_seq != 7) {
print(priv, " Key: sequence %d ", subscr->key_seq);
for (i = 0; i < sizeof(subscr->key); i++)
@@ -525,7 +582,7 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
memcpy(&subscr->lai.plmn, &set->test_sim.rplmn, sizeof(struct osmo_plmn_id));
subscr->lai.lac = set->test_sim.lac;
subscr->tmsi = set->test_sim.tmsi;
- subscr->ptmsi = GSM_RESERVED_TMSI;
+ subscr->gprs.ptmsi = GSM_RESERVED_TMSI;
subscr->always_search_hplmn = set->test_sim.always_search_hplmn;
subscr->t6m_hplmn = 1; /* try to find home network every 6 min */
OSMO_STRLCPY_ARRAY(subscr->imsi, set->test_sim.imsi);
@@ -666,6 +723,42 @@ static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
return 0;
}
+static int subscr_sim_locigprs(struct osmocom_ms *ms, uint8_t *data,
+ uint8_t length)
+{
+ struct gsm_subscriber *subscr = &ms->subscr;
+ struct gsm1111_ef_locigprs *locigprs;
+
+ if (length < 11)
+ return -EINVAL;
+ locigprs = (struct gsm1111_ef_locigprs *) data;
+
+ /* P-TMSI, P-TMSI signature */
+ subscr->gprs.ptmsi = ntohl(locigprs->ptmsi);
+ subscr->gprs.ptmsi_sig = (((uint32_t)locigprs->ptmsi_sig_hi) << 8) | locigprs->ptmsi_sig_lo;
+
+ /* RAI */
+ gsm48_parse_ra(&subscr->gprs.rai, (uint8_t *)&locigprs->rai);
+
+ /* routing area update status */
+ switch (locigprs->rau_status & 0x07) {
+ case GSM1111_EF_LOCIGPRS_RAU_ST_UPDATED:
+ subscr->gprs.gu_state = GSM_SIM_GU1_UPDATED; /* TODO: use proper enums here */
+ break;
+ case GSM1111_EF_LOCIGPRS_RAU_ST_PLMN_NOT_ALLOWED:
+ case GSM1111_EF_LOCIGPRS_RAU_ST_RA_NOT_ALLOWED:
+ subscr->gprs.gu_state = GSM_SIM_GU3_ROAMING_NA;
+ break;
+ default:
+ subscr->gprs.gu_state = GSM_SIM_GU2_NOT_UPDATED;
+ }
+
+ LOGP(DMM, LOGL_INFO, "received LOCIGPRS from SIM (RAI=%s %s)\n",
+ osmo_rai_name(&subscr->gprs.rai), gsm_sub_sim_gustate_name(subscr->gprs.gu_state));
+
+ return 0;
+}
+
static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
uint8_t length)
{
@@ -885,6 +978,7 @@ static struct subscr_sim_file {
{ 1, { 0 }, 0x2fe2, SIM_JOB_READ_BINARY, subscr_sim_iccid },
{ 1, { 0x7f20, 0 }, 0x6f07, SIM_JOB_READ_BINARY, subscr_sim_imsi },
{ 1, { 0x7f20, 0 }, 0x6f7e, SIM_JOB_READ_BINARY, subscr_sim_loci },
+ { 1, { 0x7f20, 0 }, 0x6f53, SIM_JOB_READ_BINARY, subscr_sim_locigprs },
{ 0, { 0x7f20, 0 }, 0x6f20, SIM_JOB_READ_BINARY, subscr_sim_kc },
{ 0, { 0x7f20, 0 }, 0x6f30, SIM_JOB_READ_BINARY, subscr_sim_plmnsel },
{ 0, { 0x7f20, 0 }, 0x6f31, SIM_JOB_READ_BINARY, subscr_sim_hpplmn },
@@ -1200,6 +1294,52 @@ static int gsm_subscr_write_loci_simcard(struct osmocom_ms *ms)
return 0;
}
+/* update LOCIGPRS on SIM */
+int gsm_subscr_write_locigprs_simcard(struct osmocom_ms *ms)
+{
+ struct gsm_subscriber *subscr = &ms->subscr;
+ struct msgb *nmsg;
+ struct sim_hdr *nsh;
+ struct gsm1111_ef_locigprs *locigprs;
+
+ LOGP(DMM, LOGL_INFO, "Updating LOCI on SIM\n");
+
+ /* write to SIM */
+ nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
+ SIM_JOB_UPDATE_BINARY);
+ if (!nmsg)
+ return -ENOMEM;
+ nsh = (struct sim_hdr *) nmsg->data;
+ nsh->path[0] = 0x7f20;
+ nsh->path[1] = 0;
+ nsh->file = 0x6f53;
+ locigprs = (struct gsm1111_ef_locigprs *)msgb_put(nmsg, sizeof(*locigprs));
+
+ /* P-TMSI, P-TMSI signature */
+ locigprs->ptmsi = htonl(subscr->gprs.ptmsi);
+ locigprs->ptmsi_sig_hi = htonl(subscr->gprs.ptmsi) >> 8;
+ locigprs->ptmsi_sig_lo = htonl(subscr->gprs.ptmsi) & 0xff;
+
+ /* RAI */
+ gsm48_encode_ra(&locigprs->rai, &subscr->gprs.rai);
+
+ /* location update status */
+ switch (subscr->gprs.gu_state) {
+ case GSM_SIM_GU1_UPDATED:
+ locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_UPDATED;
+ break;
+ case GSM_SIM_GU3_ROAMING_NA:
+ locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_RA_NOT_ALLOWED;
+ break;
+ default:
+ locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_NOT_UPDATED;
+ }
+
+ sim_job(ms, nmsg);
+
+ return 0;
+}
+
static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg)
{
struct sim_hdr *sh = (struct sim_hdr *) msg->data;
diff --git a/src/host/layer23/src/modem/gmm.c b/src/host/layer23/src/modem/gmm.c
index dbdf82e5..d3851e0a 100644
--- a/src/host/layer23/src/modem/gmm.c
+++ b/src/host/layer23/src/modem/gmm.c
@@ -61,7 +61,7 @@ static int modem_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_
if (gmm_prim->gmmreg.attach_cnf.accepted) {
LOGP(DGMM, LOGL_NOTICE, "%s(): Rx %s: Attach success P-TMSI=0x%08x\n",
__func__, pdu_name, gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi);
- ms->subscr.ptmsi = gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi;
+ ms->subscr.gprs.ptmsi = gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi;
ms->gmmlayer.tlli = gmm_prim->gmmreg.attach_cnf.acc.allocated_tlli;
app_data.modem_state = MODEM_ST_ATTACHED;
/* Activate APN if not yet already: */
@@ -192,8 +192,8 @@ int modem_gmm_gmmreg_attach_req(const struct osmocom_ms *ms)
gmm_prim = osmo_gprs_gmm_prim_alloc_gmmreg_attach_req();
gmm_prim->gmmreg.attach_req.attach_type = OSMO_GPRS_GMM_ATTACH_TYPE_GPRS;
- gmm_prim->gmmreg.attach_req.ptmsi = subscr->ptmsi;
- gmm_prim->gmmreg.attach_req.attach_with_imsi = (subscr->ptmsi == GSM_RESERVED_TMSI);
+ gmm_prim->gmmreg.attach_req.ptmsi = subscr->gprs.ptmsi;
+ gmm_prim->gmmreg.attach_req.attach_with_imsi = (subscr->gprs.ptmsi == GSM_RESERVED_TMSI);
memcpy(gmm_prim->gmmreg.attach_req.imsi, subscr->imsi, ARRAY_SIZE(subscr->imsi));
memcpy(gmm_prim->gmmreg.attach_req.imei, ms->settings.imei, ARRAY_SIZE(ms->settings.imei));
memcpy(gmm_prim->gmmreg.attach_req.imeisv, ms->settings.imeisv, ARRAY_SIZE(ms->settings.imeisv));
@@ -210,7 +210,7 @@ int modem_gmm_gmmreg_detach_req(const struct osmocom_ms *ms)
int rc;
gmm_prim = osmo_gprs_gmm_prim_alloc_gmmreg_detach_req();
- gmm_prim->gmmreg.detach_req.ptmsi = subscr->ptmsi;
+ gmm_prim->gmmreg.detach_req.ptmsi = subscr->gprs.ptmsi;
gmm_prim->gmmreg.detach_req.detach_type = OSMO_GPRS_GMM_DETACH_MS_TYPE_GPRS;
gmm_prim->gmmreg.detach_req.poweroff_type = OSMO_GPRS_GMM_DETACH_POWEROFF_TYPE_NORMAL;
rc = osmo_gprs_gmm_prim_upper_down(gmm_prim);
diff --git a/src/host/layer23/src/modem/sm.c b/src/host/layer23/src/modem/sm.c
index 97247730..e6591a9c 100644
--- a/src/host/layer23/src/modem/sm.c
+++ b/src/host/layer23/src/modem/sm.c
@@ -76,7 +76,7 @@ static int modem_sm_handle_pdp_act_cnf(struct osmocom_ms *ms, struct osmo_gprs_s
return 0;
}
- ms->subscr.ptmsi = sm_prim->smreg.pdp_act_cnf.acc.gmm.allocated_ptmsi;
+ ms->subscr.gprs.ptmsi = sm_prim->smreg.pdp_act_cnf.acc.gmm.allocated_ptmsi;
ms->gmmlayer.tlli = sm_prim->smreg.pdp_act_cnf.acc.gmm.allocated_tlli;
netdev = osmo_tundev_get_netdev(apn->tun);
@@ -257,7 +257,7 @@ int modem_sm_smreg_pdp_act_req(const struct osmocom_ms *ms, const struct osmobb_
memcpy(sm_prim->smreg.pdp_act_req.pco, apn->pdp.pco, apn->pdp.pco_len);
sm_prim->smreg.pdp_act_req.pco_len = apn->pdp.pco_len;
OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.apn, apn->cfg.name);
- sm_prim->smreg.pdp_act_req.gmm.ptmsi = subscr->ptmsi;
+ sm_prim->smreg.pdp_act_req.gmm.ptmsi = subscr->gprs.ptmsi;
OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imsi, subscr->imsi);
OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imei, ms->settings.imei);
OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imeisv, ms->settings.imeisv);