summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sim.h12
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/subscriber.h3
-rw-r--r--src/host/layer23/src/common/sim.c178
-rw-r--r--src/host/layer23/src/mobile/subscriber.c72
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c99
5 files changed, 276 insertions, 88 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/sim.h b/src/host/layer23/include/osmocom/bb/common/sim.h
index c1e6087a..a676b92b 100644
--- a/src/host/layer23/include/osmocom/bb/common/sim.h
+++ b/src/host/layer23/include/osmocom/bb/common/sim.h
@@ -174,8 +174,8 @@ struct gsm_sim {
int job_state;
uint8_t reset;
- uint8_t pin1[8], pin2[8];
- uint8_t pin1_len, pin2_len;
+ uint8_t chv1_remain, chv2_remain;
+ uint8_t unblk1_remain, unblk2_remain;
};
struct sim_hdr {
@@ -215,16 +215,16 @@ struct gsm1111_response_mfdf_gsm {
uint8_t rfu1;
uint8_t chv1_remain:4,
rfu2:3,
- chv1_init;
+ chv1_init:1;
uint8_t unblk1_remain:4,
rfu3:3,
- unblk1_init;
+ unblk1_init:1;
uint8_t chv2_remain:4,
rfu4:3,
- chv2_init;
+ chv2_init:1;
uint8_t unblk2_remain:4,
rfu5:3,
- unblk2_init;
+ unblk2_init:1;
uint8_t more_data[0];
} __attribute__ ((packed));
diff --git a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
index 93e70524..15af5d06 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
@@ -81,7 +81,8 @@ int gsm_subscr_init(struct osmocom_ms *ms);
int gsm_subscr_exit(struct osmocom_ms *ms);
int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc);
int gsm_subscr_simcard(struct osmocom_ms *ms);
-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);
int gsm_subscr_write_loci(struct osmocom_ms *ms);
int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq,
uint8_t *rand, uint8_t no_sim);
diff --git a/src/host/layer23/src/common/sim.c b/src/host/layer23/src/common/sim.c
index 543292ee..7c4183fe 100644
--- a/src/host/layer23/src/common/sim.c
+++ b/src/host/layer23/src/common/sim.c
@@ -411,7 +411,7 @@ static int gsm1111_tx_change_chv(struct osmocom_ms *ms, uint8_t chv_no,
buffer[1] = GSM1111_INST_CHANGE_CHV;
buffer[2] = 0x00;
buffer[3] = chv_no;
- buffer[4] = 8;
+ buffer[4] = 16;
for (i = 0; i < 8; i++) {
if (i < length_old)
buffer[5 + i] = chv_old[i];
@@ -485,7 +485,7 @@ static int gsm1111_tx_unblock_chv(struct osmocom_ms *ms, uint8_t chv_no,
buffer[1] = GSM1111_INST_UNBLOCK_CHV;
buffer[2] = 0x00;
buffer[3] = (chv_no == 1) ? 0 : chv_no;
- buffer[4] = 8;
+ buffer[4] = 16;
for (i = 0; i < 8; i++) {
if (i < length_unblk)
buffer[5 + i] = chv_unblk[i];
@@ -654,8 +654,8 @@ static int gsm1111_tx_terminal_response(struct osmocom_ms *ms, uint8_t *data,
static int sim_process_job(struct osmocom_ms *ms)
{
struct gsm_sim *sim = &ms->sim;
- uint8_t *payload;
- uint16_t payload_len;
+ uint8_t *payload, *payload2;
+ uint16_t payload_len, payload_len2;
struct sim_hdr *sh;
uint8_t cause;
int i;
@@ -734,82 +734,98 @@ static int sim_process_job(struct osmocom_ms *ms)
sim->job_state = SIM_JST_RUN_GSM_ALGO;
return gsm1111_tx_run_gsm_algo(ms, payload);
case SIM_JOB_PIN1_UNLOCK:
+ payload_len = strlen((char *)payload);
if (payload_len < 4 || payload_len > 8) {
LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN1_UNLOCK;
- memcpy(sim->pin1, payload, payload_len);
- sim->pin1_len = payload_len;
return gsm1111_tx_verify_chv(ms, 0x01, payload, payload_len);
case SIM_JOB_PIN2_UNLOCK:
+ payload_len = strlen((char *)payload);
if (payload_len < 4 || payload_len > 8) {
LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN2_UNLOCK;
- memcpy(sim->pin2, payload, payload_len);
- sim->pin2_len = payload_len;
return gsm1111_tx_verify_chv(ms, 0x02, payload, payload_len);
case SIM_JOB_PIN1_CHANGE:
- if (!sim->pin1_len) {
- LOGP(DSIM, LOGL_ERROR, "no pin set\n");
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
break;
}
- if (payload_len < 4 || payload_len > 8 || !sim->pin1_len) {
- LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN1_CHANGE;
- return gsm1111_tx_change_chv(ms, 0x01, sim->pin1, sim->pin1_len,
- payload, payload_len);
+ return gsm1111_tx_change_chv(ms, 0x01, payload, payload_len,
+ payload2, payload_len2);
case SIM_JOB_PIN2_CHANGE:
- if (!sim->pin2_len) {
- LOGP(DSIM, LOGL_ERROR, "no pin set\n");
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
break;
}
- if (payload_len < 4 || payload_len > 8) {
- LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN2_CHANGE;
- return gsm1111_tx_change_chv(ms, 0x02, sim->pin1, sim->pin1_len,
- payload, payload_len);
+ return gsm1111_tx_change_chv(ms, 0x02, payload, payload_len,
+ payload2, payload_len2);
case SIM_JOB_PIN1_DISABLE:
- if (!sim->pin1_len) {
- LOGP(DSIM, LOGL_ERROR, "no pin set\n");
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN1_DISABLE;
- return gsm1111_tx_disable_chv(ms, sim->pin1, sim->pin1_len);
+ return gsm1111_tx_disable_chv(ms, payload, payload_len);
case SIM_JOB_PIN1_ENABLE:
- if (!sim->pin1_len) {
- LOGP(DSIM, LOGL_ERROR, "no pin set\n");
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
break;
}
sim->job_state = SIM_JST_PIN1_ENABLE;
- return gsm1111_tx_enable_chv(ms, sim->pin1, sim->pin1_len);
+ return gsm1111_tx_enable_chv(ms, payload, payload_len);
case SIM_JOB_PIN1_UNBLOCK:
- if (payload_len < 12 || payload_len > 16) {
- LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len != 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
break;
}
- sim->job_state = SIM_JST_PIN1_UNLOCK;
- memcpy(sim->pin1, payload + 8, payload_len - 8);
- sim->pin1_len = payload_len;
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_UNBLOCK;
/* NOTE: CHV1 is coded 0x00 here */
- return gsm1111_tx_unblock_chv(ms, 0x00, payload, 8, payload + 8,
- payload_len - 8);
+ return gsm1111_tx_unblock_chv(ms, 0x00, payload, payload_len,
+ payload2, payload_len2);
case SIM_JOB_PIN2_UNBLOCK:
- if (payload_len < 12 || payload_len > 16) {
- LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len != 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
break;
}
- sim->job_state = SIM_JST_PIN2_UNLOCK;
- memcpy(sim->pin2, payload + 8, payload_len - 8);
- sim->pin2_len = payload_len;
- return gsm1111_tx_unblock_chv(ms, 0x02, payload, 8, payload + 8,
- payload_len - 8);
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN2_UNBLOCK;
+ return gsm1111_tx_unblock_chv(ms, 0x02, payload, payload_len,
+ payload2, payload_len2);
}
LOGP(DSIM, LOGL_ERROR, "unknown job %x, please fix\n", sh->job_type);
@@ -861,12 +877,58 @@ int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
switch (sw1) {
case GSM1111_STAT_SECURITY:
- LOGP(DSIM, LOGL_NOTICE, "SIM Security\n");
- pin_cause[0] = SIM_CAUSE_PIN1_REQUIRED;
- pin_cause[1] = 1; /* PIN retries left */
- gsm_sim_reply(ms, SIM_JOB_ERROR, pin_cause, 2);
- msgb_free(msg);
- return 0;
+ LOGP(DSIM, LOGL_NOTICE, "SIM Security\n");
+ /* error */
+ if (sw2 != GSM1111_SEC_NO_ACCESS && sw2 != GSM1111_SEC_BLOCKED)
+ goto sim_error;
+
+ /* select the right remaining counter an cause */
+ // FIXME: read status to replace "*_remain"-counters
+ switch (sim->job_state) {
+ case SIM_JST_PIN1_UNBLOCK:
+ if (sw2 == GSM1111_SEC_NO_ACCESS) {
+ pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
+ pin_cause[1] = --sim->unblk1_remain;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
+ pin_cause[1] = 0;
+ }
+ break;
+ case SIM_JST_PIN2_UNLOCK:
+ case SIM_JST_PIN2_CHANGE:
+ if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv2_remain) {
+ pin_cause[0] = SIM_CAUSE_PIN2_REQUIRED;
+ pin_cause[1] = sim->chv2_remain--;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
+ pin_cause[1] = sim->unblk2_remain;
+ }
+ break;
+ case SIM_JST_PIN2_UNBLOCK:
+ if (sw2 == GSM1111_SEC_NO_ACCESS) {
+ pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
+ pin_cause[1] = --sim->unblk2_remain;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
+ pin_cause[1] = 0;
+ }
+ case SIM_JST_PIN1_UNLOCK:
+ case SIM_JST_PIN1_CHANGE:
+ case SIM_JST_PIN1_DISABLE:
+ case SIM_JST_PIN1_ENABLE:
+ default:
+ if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv1_remain) {
+ pin_cause[0] = SIM_CAUSE_PIN1_REQUIRED;
+ pin_cause[1] = sim->chv1_remain--;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
+ pin_cause[1] = sim->unblk1_remain;
+ }
+ break;
+ }
+ gsm_sim_reply(ms, SIM_JOB_ERROR, pin_cause, 2);
+ msgb_free(msg);
+ return 0;
case GSM1111_STAT_MEM_PROBLEM:
if (sw2 >= 0x40) {
LOGP(DSIM, LOGL_NOTICE, "memory of SIM failed\n");
@@ -885,29 +947,9 @@ int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
case GSM1111_STAT_RESPONSE:
case GSM1111_STAT_RESPONSE_TOO:
LOGP(DSIM, LOGL_INFO, "command successfull\n");
- switch (sh->job_type) {
- case SIM_JOB_PIN1_CHANGE:
- memcpy(sim->pin1, payload, payload_len);
- sim->pin1_len = payload_len;
- break;
- case SIM_JOB_PIN2_CHANGE:
- memcpy(sim->pin2, payload, payload_len);
- sim->pin2_len = payload_len;
- break;
- }
break;
default:
LOGP(DSIM, LOGL_INFO, "command failed\n");
- switch (sh->job_type) {
- case SIM_JOB_PIN1_UNLOCK:
- case SIM_JOB_PIN1_UNBLOCK:
- sim->pin1_len = 0;
- break;
- case SIM_JOB_PIN2_UNLOCK:
- case SIM_JOB_PIN2_UNBLOCK:
- sim->pin2_len = 0;
- break;
- }
request_error:
cause = SIM_CAUSE_REQUEST_ERROR;
gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
@@ -939,6 +981,10 @@ int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
}
mfdf = (struct gsm1111_response_mfdf *)data;
mfdf_gsm = (struct gsm1111_response_mfdf_gsm *)(data + 13);
+ sim->chv1_remain = mfdf_gsm->chv1_remain;
+ sim->chv2_remain = mfdf_gsm->chv2_remain;
+ sim->unblk1_remain = mfdf_gsm->unblk1_remain;
+ sim->unblk2_remain = mfdf_gsm->unblk2_remain;
/* if MF was selected */
if (sim->path[0] == 0) {
/* if MF was selected, but MF is not indicated */
diff --git a/src/host/layer23/src/mobile/subscriber.c b/src/host/layer23/src/mobile/subscriber.c
index b95858f8..41ee7834 100644
--- a/src/host/layer23/src/mobile/subscriber.c
+++ b/src/host/layer23/src/mobile/subscriber.c
@@ -560,6 +560,7 @@ static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg)
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];
/* error handling */
if (sh->job_type == SIM_JOB_ERROR) {
@@ -581,10 +582,22 @@ static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg)
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 (!subscr_sim_files[subscr->sim_file_index].
- mandatory) {
+ if (sf->func && !sf->mandatory) {
LOGP(DMM, LOGL_NOTICE, "SIM reading failed, "
"ignoring!\n");
goto ignore;
@@ -599,10 +612,19 @@ static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *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) {
@@ -624,23 +646,45 @@ ignore:
}
/* 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");
- 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);
}
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index 929529cc..6b6e09e2 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -423,12 +423,105 @@ DEFUN(sim_pin, sim_pin_cmd, "sim pin MS_NAME PIN",
if (!ms)
return CMD_WARNING;
+ if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
+ vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
if (!ms->subscr.sim_pin_required) {
vty_out(vty, "No PIN is required at this time!%s", VTY_NEWLINE);
return CMD_WARNING;
}
- gsm_subscr_sim_pin(ms, (char *)argv[1]);
+ gsm_subscr_sim_pin(ms, (char *)argv[1], "", 0);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sim_disable_pin, sim_disable_pin_cmd, "sim disable-pin MS_NAME PIN",
+ "SIM actions\nDisable PIN of SIM card\nName of MS (see \"show ms\")\n"
+ "PIN number")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
+ vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ gsm_subscr_sim_pin(ms, (char *)argv[1], "", -1);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sim_enable_pin, sim_enable_pin_cmd, "sim enable-pin MS_NAME PIN",
+ "SIM actions\nEnable PIN of SIM card\nName of MS (see \"show ms\")\n"
+ "PIN number")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
+ vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ gsm_subscr_sim_pin(ms, (char *)argv[1], "", 1);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sim_change_pin, sim_change_pin_cmd, "sim change-pin MS_NAME OLD NEW",
+ "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
+ "Old PIN number\nNew PIN number")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
+ vty_out(vty, "Old PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
+ vty_out(vty, "New PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 2);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sim_unblock_pin, sim_unblock_pin_cmd, "sim unblock-pin MS_NAME PUC NEW",
+ "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
+ "Personal Unblock Key\nNew PIN number")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ if (strlen(argv[1]) != 8) {
+ vty_out(vty, "PUC must be 8 digits!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
+ vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 99);
return CMD_SUCCESS;
}
@@ -1258,6 +1351,10 @@ int ms_vty_init(void)
install_element(ENABLE_NODE, &sim_reader_cmd);
install_element(ENABLE_NODE, &sim_remove_cmd);
install_element(ENABLE_NODE, &sim_pin_cmd);
+ install_element(ENABLE_NODE, &sim_disable_pin_cmd);
+ install_element(ENABLE_NODE, &sim_enable_pin_cmd);
+ install_element(ENABLE_NODE, &sim_change_pin_cmd);
+ install_element(ENABLE_NODE, &sim_unblock_pin_cmd);
install_element(ENABLE_NODE, &network_search_cmd);
install_element(ENABLE_NODE, &network_show_cmd);
install_element(ENABLE_NODE, &network_select_cmd);