diff --git a/src/host/layer23/include/osmocom/bb/common/subscriber.h b/src/host/layer23/include/osmocom/bb/common/subscriber.h index 792df6293..232018db6 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 #include #include +#include /* 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 dfd44dcc0..b6fc74d88 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 dbdf82e55..d3851e0a1 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 972477303..e6591a9ce 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);