#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
-#include <osmocore/talloc.h>
-#include <osmocore/comp128.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/comp128.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/osmocom_data.h>
for (i = 0; i < (length << 1); i++) {
if ((i & 1))
- c = (data[i >> 1] >> 4) + '0';
+ c = (data[i >> 1] >> 4);
else
- c = (data[i >> 1] & 0xf) + '0';
+ c = (data[i >> 1] & 0xf);
if (c == 0xf)
break;
- result[j++] = c;
+ result[j++] = c + '0';
if (j == sizeof(result) - 1)
break;
}
*/
/* Attach test card, no SIM must be currently attached */
-int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc)
+int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
+ uint16_t lac, uint32_t tmsi)
{
struct gsm_settings *set = &ms->settings;
struct gsm_subscriber *subscr = &ms->subscr;
subscr->plmn_valid = set->test_rplmn_valid;
subscr->plmn_mcc = mcc;
subscr->plmn_mnc = mnc;
+ subscr->mcc = mcc;
+ subscr->mnc = mnc;
+ subscr->lac = lac;
+ subscr->tmsi = tmsi;
subscr->always_search_hplmn = set->test_always;
subscr->t6m_hplmn = 1; /* try to find home network every 6 min */
strcpy(subscr->imsi, set->test_imsi);
gsm_imsi_mnc(subscr->imsi));
if (subscr->plmn_valid)
- LOGP(DMM, LOGL_INFO, "-> Test card registered to %s %s "
- "(%s, %s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc),
- gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc));
+ LOGP(DMM, LOGL_INFO, "-> Test card registered to %s %s 0x%04x"
+ "(%s, %s)\n", gsm_print_mcc(mcc),
+ gsm_print_mnc(mnc), lac, gsm_get_mcc(mcc),
+ gsm_get_mnc(mcc, mnc));
else
LOGP(DMM, LOGL_INFO, "-> Test card not registered\n");
uint8_t length)
{
struct gsm_subscriber *subscr = &ms->subscr;
+ char *imsi;
/* get actual length */
if (length < 1)
return -EINVAL;
}
length = data[0];
- if ((length << 1) > GSM_IMSI_LENGTH - 1 || (length << 1) < 6) {
+
+ /* decode IMSI, skip first digit (parity) */
+ imsi = sim_decode_bcd(data + 1, length);
+ if (strlen(imsi) - 1 > GSM_IMSI_LENGTH - 1 || strlen(imsi) - 1 < 6) {
LOGP(DMM, LOGL_NOTICE, "IMSI invalid length = %d\n",
- length << 1);
+ strlen(imsi) - 1);
return -EINVAL;
}
- strncpy(subscr->imsi, sim_decode_bcd(data + 1, length),
- sizeof(subscr->imsi - 1));
+ strncpy(subscr->imsi, imsi + 1, sizeof(subscr->imsi) - 1);
LOGP(DMM, LOGL_INFO, "received IMSI %s from SIM\n", subscr->imsi);
subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
}
- LOGP(DMM, LOGL_INFO, "received LOCI from SIM\n");
+ LOGP(DMM, LOGL_INFO, "received LOCI from SIM (mcc=%s mnc=%s lac=0x%04x "
+ "U%d)\n", gsm_print_mcc(subscr->mcc),
+ gsm_print_mnc(subscr->mnc), subscr->lac, subscr->ustate);
return 0;
}
/* HPLMN search interval */
subscr->t6m_hplmn = *data; /* multiple of 6 minutes */
- LOGP(DMM, LOGL_INFO, "received HPPLMN %d from SIM\n",
- subscr->t6m_hplmn);
+ LOGP(DMM, LOGL_INFO, "received HPPLMN %d (%d mins) from SIM\n",
+ subscr->t6m_hplmn, subscr->t6m_hplmn * 6);
return 0;
}
{ 1, { 0 }, 0x2fe2, subscr_sim_iccid },
{ 1, { 0x7f20, 0 }, 0x6f07, subscr_sim_imsi },
{ 1, { 0x7f20, 0 }, 0x6f7e, subscr_sim_loci },
- { 0, { 0x7f20, 0 }, 0x6f40, subscr_sim_msisdn },
+ { 0, { 0x7f10, 0 }, 0x6f40, subscr_sim_msisdn },
{ 0, { 0x7f20, 0 }, 0x6f20, subscr_sim_kc },
{ 0, { 0x7f20, 0 }, 0x6f30, subscr_sim_plmnsel },
{ 0, { 0x7f20, 0 }, 0x6f31, subscr_sim_hpplmn },
uint8_t *payload = msg->data + sizeof(*sh);
uint16_t payload_len = msg->len - sizeof(*sh);
int rc;
+ struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
+ struct msgb *nmsg;
/* error handling */
if (sh->job_type == SIM_JOB_ERROR) {
vty_notify(ms, NULL);
vty_notify(ms, "PIN is blocked\n");
+ if (payload[1]) {
+ vty_notify(ms, "Please give PUC for ICCID %s "
+ "(you have %d tries left)\n",
+ subscr->iccid, payload[1]);
+ }
+ subscr->sim_pin_required = 1;
+ break;
+ case SIM_CAUSE_PUC_BLOCKED:
+ LOGP(DMM, LOGL_NOTICE, "PUC is blocked\n");
+
+ vty_notify(ms, NULL);
+ vty_notify(ms, "PUC is blocked\n");
+ subscr->sim_pin_required = 1;
break;
default:
+ if (sf->func && !sf->mandatory) {
+ LOGP(DMM, LOGL_NOTICE, "SIM reading failed, "
+ "ignoring!\n");
+ goto ignore;
+ }
LOGP(DMM, LOGL_NOTICE, "SIM reading failed\n");
vty_notify(ms, NULL);
vty_notify(ms, "SIM failed, replace SIM!\n");
+
+ /* detach simcard */
+ subscr->sim_valid = 0;
+ nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
+ if (!nmsg)
+ return;
+ gsm48_mmr_downmsg(ms, nmsg);
}
msgb_free(msg);
return;
}
- /* call function do decode SIM reply */
- rc = subscr_sim_files[subscr->sim_file_index].func(ms, payload,
- payload_len);
+ /* if pin was successfully unlocked, then resend request */
+ if (subscr->sim_pin_required) {
+ subscr->sim_pin_required = 0;
+ subscr_sim_request(ms);
+ return;
+ }
+
+ /* done when nothing more to read. this happens on PIN requests */
+ if (!sf->func)
+ return;
+ /* call function do decode SIM reply */
+ rc = sf->func(ms, payload, payload_len);
if (rc) {
LOGP(DMM, LOGL_NOTICE, "SIM reading failed, file invalid\n");
if (subscr_sim_files[subscr->sim_file_index].mandatory) {
}
}
+ignore:
msgb_free(msg);
/* trigger next file */
}
/* enter PIN */
-void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin)
+void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin1, char *pin2,
+ int8_t mode)
{
struct gsm_subscriber *subscr = &ms->subscr;
struct msgb *nmsg;
+ uint8_t job;
- if (!subscr->sim_pin_required) {
- LOGP(DMM, LOGL_ERROR, "No PIN required now\n");
+ /* skip, if no real valid SIM */
+ if (subscr->sim_type != GSM_SIM_TYPE_READER)
return;
+
+ switch (mode) {
+ case -1:
+ job = SIM_JOB_PIN1_DISABLE;
+ LOGP(DMM, LOGL_INFO, "disabling PIN %s\n", pin1);
+ break;
+ case 1:
+ job = SIM_JOB_PIN1_ENABLE;
+ LOGP(DMM, LOGL_INFO, "enabling PIN %s\n", pin1);
+ break;
+ case 2:
+ job = SIM_JOB_PIN1_CHANGE;
+ LOGP(DMM, LOGL_INFO, "changing PIN %s to %s\n", pin1, pin2);
+ break;
+ case 99:
+ job = SIM_JOB_PIN1_UNBLOCK;
+ LOGP(DMM, LOGL_INFO, "unblocking PIN %s with PUC %s\n", pin1,
+ pin2);
+ break;
+ default:
+ if (!subscr->sim_pin_required) {
+ LOGP(DMM, LOGL_ERROR, "No PIN required now\n");
+ return;
+ }
+ LOGP(DMM, LOGL_INFO, "entering PIN %s\n", pin1);
+ job = SIM_JOB_PIN1_UNLOCK;
}
- subscr->sim_pin_required = 0;
- LOGP(DMM, LOGL_INFO, "Unlocking PIN %s\n", pin);
- nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
- SIM_JOB_PIN1_UNLOCK);
+ nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query, job);
if (!nmsg)
return;
- memcpy(msgb_put(nmsg, strlen(pin)), pin, strlen(pin));
+ memcpy(msgb_put(nmsg, strlen(pin1) + 1), pin1, strlen(pin1) + 1);
+ memcpy(msgb_put(nmsg, strlen(pin2) + 1), pin2, strlen(pin2) + 1);
sim_job(ms, nmsg);
}
}
print(priv, " IMSI: %s\n", subscr->imsi);
+ if (subscr->iccid[0])
+ print(priv, " ICCID: %s\n", subscr->iccid);
+ if (subscr->sim_spn[0])
+ print(priv, " Service Provider Name: %s\n", subscr->sim_spn);
if (subscr->msisdn[0])
print(priv, " MSISDN: %s\n", subscr->msisdn);
print(priv, " Status: %s IMSI %s", subscr_ustate_names[subscr->ustate],
(subscr->imsi_attached) ? "attached" : "detached");
if (subscr->tmsi != 0xffffffff)
- print(priv, " TSMI %08x", subscr->tmsi);
- if (subscr->lac > 0x0000 && subscr->lac < 0xfffe)
- print(priv, " LAI: MCC %s MNC %s LAC 0x%04x (%s, %s)\n",
- gsm_print_mcc(subscr->mcc),
+ print(priv, " TSMI 0x%08x", subscr->tmsi);
+ if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
+ print(priv, "\n");
+ print(priv, " LAI: MCC %s MNC %s LAC 0x%04x "
+ "(%s, %s)\n", gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac,
gsm_get_mcc(subscr->mcc),
gsm_get_mnc(subscr->mcc, subscr->mnc));
- else
+ } else
print(priv, " LAI: invalid\n");
if (subscr->key_seq != 7) {
- print(priv, " Key: sequence %d ");
+ print(priv, " Key: sequence %d ", subscr->key_seq);
for (i = 0; i < sizeof(subscr->key); i++)
print(priv, " %02x", subscr->key[i]);
print(priv, "\n");
print(priv, " MCC |MNC\n");
print(priv, " -------+-------\n");
llist_for_each_entry(plmn_list, &subscr->plmn_list, entry)
- print(priv, " %s |%s\n",
+ print(priv, " %s |%s (%s, %s)\n",
gsm_print_mcc(plmn_list->mcc),
- gsm_print_mnc(plmn_list->mnc));
+ gsm_print_mnc(plmn_list->mnc),
+ gsm_get_mcc(plmn_list->mcc),
+ gsm_get_mnc(plmn_list->mcc, plmn_list->mnc));
}
if (!llist_empty(&subscr->plmn_na)) {
print(priv, " List of forbidden PLMNs:\n");
print(priv, " MCC |MNC |cause\n");
print(priv, " -------+-------+-------\n");
llist_for_each_entry(plmn_na, &subscr->plmn_na, entry)
- print(priv, " %s |%s%s |#%d\n",
- gsm_print_mcc(plmn_na->mcc),
+ print(priv, " %s |%s%s |#%d "
+ "(%s, %s)\n", gsm_print_mcc(plmn_na->mcc),
gsm_print_mnc(plmn_na->mnc),
((plmn_na->mnc & 0x00f) == 0x00f) ? " ":"",
- plmn_na->cause);
+ plmn_na->cause, gsm_get_mcc(plmn_na->mcc),
+ gsm_get_mnc(plmn_na->mcc, plmn_na->mnc));
}
}