2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <arpa/inet.h>
26 #include <osmocom/core/talloc.h>
27 #include <osmocom/gsm/comp128.h>
29 #include <osmocom/bb/common/logging.h>
30 #include <osmocom/bb/common/osmocom_data.h>
31 #include <osmocom/bb/common/networks.h>
32 #include <osmocom/bb/mobile/vty.h>
36 static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg);
37 static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg);
38 static void subscr_sim_key_cb(struct osmocom_ms *ms, struct msgb *msg);
44 char *gsm_check_imsi(const char *imsi)
48 if (!imsi || strlen(imsi) != 15)
49 return "IMSI must have 15 digits!";
51 for (i = 0; i < strlen(imsi); i++) {
52 if (imsi[i] < '0' || imsi[i] > '9')
53 return "IMSI must have digits 0 to 9 only!";
59 static char *sim_decode_bcd(uint8_t *data, uint8_t length)
62 static char result[32], c;
64 for (i = 0; i < (length << 1); i++) {
66 c = (data[i >> 1] >> 4);
68 c = (data[i >> 1] & 0xf);
71 result[j++] = c + '0';
72 if (j == sizeof(result) - 1)
80 static void xor96(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc)
85 sres[i] = rand[i] ^ ki[i];
87 kc[i] = rand[i] ^ ki[i+4];
94 int gsm_subscr_init(struct osmocom_ms *ms)
96 struct gsm_subscriber *subscr = &ms->subscr;
98 memset(subscr, 0, sizeof(*subscr));
101 /* set TMSI / LAC invalid */
102 subscr->tmsi = 0xffffffff;
103 subscr->lac = 0x0000;
105 /* set key invalid */
109 INIT_LLIST_HEAD(&subscr->plmn_list);
110 INIT_LLIST_HEAD(&subscr->plmn_na);
113 subscr->sim_handle_query = sim_open(ms, subscr_sim_query_cb);
114 subscr->sim_handle_update = sim_open(ms, subscr_sim_update_cb);
115 subscr->sim_handle_key = sim_open(ms, subscr_sim_key_cb);
120 int gsm_subscr_exit(struct osmocom_ms *ms)
122 struct gsm_subscriber *subscr = &ms->subscr;
123 struct llist_head *lh, *lh2;
125 if (subscr->sim_handle_query) {
126 sim_close(ms, subscr->sim_handle_query);
127 subscr->sim_handle_query = 0;
129 if (subscr->sim_handle_update) {
130 sim_close(ms, subscr->sim_handle_update);
131 subscr->sim_handle_update = 0;
133 if (subscr->sim_handle_key) {
134 sim_close(ms, subscr->sim_handle_key);
135 subscr->sim_handle_key = 0;
139 llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
143 llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
155 /* Attach test card, no SIM must be currently attached */
156 int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
157 uint16_t lac, uint32_t tmsi)
159 struct gsm_settings *set = &ms->settings;
160 struct gsm_subscriber *subscr = &ms->subscr;
164 if (subscr->sim_valid) {
165 LOGP(DMM, LOGL_ERROR, "Cannot insert card, until current card "
170 error = gsm_check_imsi(set->test_imsi);
172 LOGP(DMM, LOGL_ERROR, "%s\n", error);
176 /* reset subscriber */
180 subscr->sim_type = GSM_SIM_TYPE_TEST;
181 sprintf(subscr->sim_name, "test");
182 subscr->sim_valid = 1;
183 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
184 subscr->acc_barr = set->test_barr; /* we may access barred cell */
185 subscr->acc_class = 0xffff; /* we have any access class */
186 subscr->plmn_valid = set->test_rplmn_valid;
187 subscr->plmn_mcc = mcc;
188 subscr->plmn_mnc = mnc;
193 subscr->always_search_hplmn = set->test_always;
194 subscr->t6m_hplmn = 1; /* try to find home network every 6 min */
195 strcpy(subscr->imsi, set->test_imsi);
197 LOGP(DMM, LOGL_INFO, "(ms %s) Inserting test card (IMSI=%s %s, %s)\n",
198 ms->name, subscr->imsi, gsm_imsi_mcc(subscr->imsi),
199 gsm_imsi_mnc(subscr->imsi));
201 if (subscr->plmn_valid)
202 LOGP(DMM, LOGL_INFO, "-> Test card registered to %s %s 0x%04x"
203 "(%s, %s)\n", gsm_print_mcc(mcc),
204 gsm_print_mnc(mnc), lac, gsm_get_mcc(mcc),
205 gsm_get_mnc(mcc, mnc));
207 LOGP(DMM, LOGL_INFO, "-> Test card not registered\n");
210 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
213 gsm48_mmr_downmsg(ms, nmsg);
222 static int subscr_sim_iccid(struct osmocom_ms *ms, uint8_t *data,
225 struct gsm_subscriber *subscr = &ms->subscr;
227 strcpy(subscr->iccid, sim_decode_bcd(data, length));
228 sprintf(subscr->sim_name, "sim-%s", subscr->iccid);
229 LOGP(DMM, LOGL_INFO, "received ICCID %s from SIM\n", subscr->iccid);
234 static int subscr_sim_imsi(struct osmocom_ms *ms, uint8_t *data,
237 struct gsm_subscriber *subscr = &ms->subscr;
240 /* get actual length */
243 if (data[0] + 1 < length) {
244 LOGP(DMM, LOGL_NOTICE, "invalid length = %d\n", length);
249 /* decode IMSI, skip first digit (parity) */
250 imsi = sim_decode_bcd(data + 1, length);
251 if (strlen(imsi) - 1 > GSM_IMSI_LENGTH - 1 || strlen(imsi) - 1 < 6) {
252 LOGP(DMM, LOGL_NOTICE, "IMSI invalid length = %d\n",
257 strncpy(subscr->imsi, imsi + 1, sizeof(subscr->imsi) - 1);
259 LOGP(DMM, LOGL_INFO, "received IMSI %s from SIM\n", subscr->imsi);
264 static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
267 struct gsm_subscriber *subscr = &ms->subscr;
268 struct gsm1111_ef_loci *loci;
272 loci = (struct gsm1111_ef_loci *) data;
275 subscr->tmsi = ntohl(loci->tmsi);
278 gsm48_decode_lai(&loci->lai, &subscr->mcc, &subscr->mnc, &subscr->lac);
280 /* location update status */
281 switch (loci->lupd_status & 0x07) {
283 subscr->ustate = GSM_SIM_U1_UPDATED;
287 subscr->ustate = GSM_SIM_U3_ROAMING_NA;
290 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
293 LOGP(DMM, LOGL_INFO, "received LOCI from SIM (mcc=%s mnc=%s lac=0x%04x "
294 "U%d)\n", gsm_print_mcc(subscr->mcc),
295 gsm_print_mnc(subscr->mnc), subscr->lac, subscr->ustate);
300 static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
303 struct gsm_subscriber *subscr = &ms->subscr;
304 struct gsm1111_ef_adn *adn;
306 if (length < sizeof(*adn))
308 adn = (struct gsm1111_ef_adn *) (data + length - sizeof(*adn));
311 subscr->msisdn[0] = '\0';
312 if (adn->len_bcd <= 1)
316 if (adn->ton_npi == 1)
317 strcpy(subscr->msisdn, "+");
318 if (adn->ton_npi == 2)
319 strcpy(subscr->msisdn, "0");
320 strncat(subscr->msisdn, sim_decode_bcd(adn->number, adn->len_bcd - 1),
321 sizeof(subscr->msisdn) - 2);
323 LOGP(DMM, LOGL_INFO, "received MSISDN %s from SIM\n", subscr->msisdn);
328 static int subscr_sim_kc(struct osmocom_ms *ms, uint8_t *data,
331 struct gsm_subscriber *subscr = &ms->subscr;
337 memcpy(subscr->key, data, 8);
340 subscr->key_seq = data[8] & 0x07;
342 LOGP(DMM, LOGL_INFO, "received KEY from SIM\n");
347 static int subscr_sim_plmnsel(struct osmocom_ms *ms, uint8_t *data,
350 struct gsm_subscriber *subscr = &ms->subscr;
351 struct gsm_sub_plmn_list *plmn;
352 struct llist_head *lh, *lh2;
357 llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
363 /* end of list inside mandatory fields */
364 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
368 plmn = talloc_zero(l23_ctx, struct gsm_sub_plmn_list);
374 gsm48_decode_lai((struct gsm48_loc_area_id *)lai, &plmn->mcc,
375 &plmn->mnc, &dummy_lac);
376 llist_add_tail(&plmn->entry, &subscr->plmn_list);
378 LOGP(DMM, LOGL_INFO, "received PLMN selector (mcc=%s mnc=%s) "
380 gsm_print_mcc(plmn->mcc), gsm_print_mnc(plmn->mnc));
389 static int subscr_sim_hpplmn(struct osmocom_ms *ms, uint8_t *data,
392 struct gsm_subscriber *subscr = &ms->subscr;
397 /* HPLMN search interval */
398 subscr->t6m_hplmn = *data; /* multiple of 6 minutes */
400 LOGP(DMM, LOGL_INFO, "received HPPLMN %d (%d mins) from SIM\n",
401 subscr->t6m_hplmn, subscr->t6m_hplmn * 6);
406 static int subscr_sim_spn(struct osmocom_ms *ms, uint8_t *data,
409 struct gsm_subscriber *subscr = &ms->subscr;
412 /* UCS2 code not supported */
413 if (length < 17 || data[1] >= 0x80)
417 for (i = 0; i < 16; i++) {
420 subscr->sim_spn[i] = *data++;
422 subscr->sim_spn[i] = '\0';
424 LOGP(DMM, LOGL_INFO, "received SPN %s from SIM\n", subscr->sim_spn);
429 static int subscr_sim_acc(struct osmocom_ms *ms, uint8_t *data,
432 struct gsm_subscriber *subscr = &ms->subscr;
439 memcpy(&ac, data, sizeof(ac));
440 subscr->acc_class = ntohs(ac);
442 LOGP(DMM, LOGL_INFO, "received ACC %04x from SIM\n", subscr->acc_class);
447 static int subscr_sim_fplmn(struct osmocom_ms *ms, uint8_t *data,
450 struct gsm_subscriber *subscr = &ms->subscr;
451 struct gsm_sub_plmn_na *na;
452 struct llist_head *lh, *lh2;
457 llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
462 while (length >= 3) {
463 /* end of list inside mandatory fields */
464 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
468 na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
474 gsm48_decode_lai((struct gsm48_loc_area_id *)lai, &na->mcc,
475 &na->mnc, &dummy_lac);
477 llist_add_tail(&na->entry, &subscr->plmn_na);
485 static struct subscr_sim_file {
487 uint16_t path[MAX_SIM_PATH_LENGTH];
489 int (*func)(struct osmocom_ms *ms, uint8_t *data,
491 } subscr_sim_files[] = {
492 { 1, { 0 }, 0x2fe2, subscr_sim_iccid },
493 { 1, { 0x7f20, 0 }, 0x6f07, subscr_sim_imsi },
494 { 1, { 0x7f20, 0 }, 0x6f7e, subscr_sim_loci },
495 { 0, { 0x7f10, 0 }, 0x6f40, subscr_sim_msisdn },
496 { 0, { 0x7f20, 0 }, 0x6f20, subscr_sim_kc },
497 { 0, { 0x7f20, 0 }, 0x6f30, subscr_sim_plmnsel },
498 { 0, { 0x7f20, 0 }, 0x6f31, subscr_sim_hpplmn },
499 { 0, { 0x7f20, 0 }, 0x6f46, subscr_sim_spn },
500 { 0, { 0x7f20, 0 }, 0x6f78, subscr_sim_acc },
501 { 0, { 0x7f20, 0 }, 0x6f7b, subscr_sim_fplmn },
502 { 0, { 0 }, 0, NULL }
505 /* request file from SIM */
506 static int subscr_sim_request(struct osmocom_ms *ms)
508 struct gsm_subscriber *subscr = &ms->subscr;
509 struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
514 /* we are done, fire up PLMN and cell selection process */
516 LOGP(DMM, LOGL_INFO, "(ms %s) Done reading SIM card "
517 "(IMSI=%s %s, %s)\n", ms->name, subscr->imsi,
518 gsm_imsi_mcc(subscr->imsi), gsm_imsi_mnc(subscr->imsi));
520 /* if LAI is valid, set RPLMN */
521 if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
522 subscr->plmn_valid = 1;
523 subscr->plmn_mcc = subscr->mcc;
524 subscr->plmn_mnc = subscr->mnc;
525 LOGP(DMM, LOGL_INFO, "-> SIM card registered to %s %s "
526 "(%s, %s)\n", gsm_print_mcc(subscr->plmn_mcc),
527 gsm_print_mnc(subscr->plmn_mnc),
528 gsm_get_mcc(subscr->plmn_mcc),
529 gsm_get_mnc(subscr->plmn_mcc,
532 LOGP(DMM, LOGL_INFO, "-> SIM card not registered\n");
535 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
538 gsm48_mmr_downmsg(ms, nmsg);
543 /* trigger SIM reading */
544 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query,
545 SIM_JOB_READ_BINARY);
548 nsh = (struct sim_hdr *) nmsg->data;
550 while (sf->path[i]) {
551 nsh->path[i] = sf->path[i];
554 nsh->path[i] = 0; /* end of path */
555 nsh->file = sf->file;
556 LOGP(DMM, LOGL_INFO, "Requesting SIM file 0x%04x\n", nsh->file);
562 static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg)
564 struct gsm_subscriber *subscr = &ms->subscr;
565 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
566 uint8_t *payload = msg->data + sizeof(*sh);
567 uint16_t payload_len = msg->len - sizeof(*sh);
569 struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
573 if (sh->job_type == SIM_JOB_ERROR) {
574 uint8_t cause = payload[0];
577 /* unlocking required */
578 case SIM_CAUSE_PIN1_REQUIRED:
579 LOGP(DMM, LOGL_INFO, "PIN is required, %d tries left\n",
582 vty_notify(ms, NULL);
583 vty_notify(ms, "Please give PIN for ICCID %s (you have "
584 "%d tries left)\n", subscr->iccid, payload[1]);
585 subscr->sim_pin_required = 1;
587 case SIM_CAUSE_PIN1_BLOCKED:
588 LOGP(DMM, LOGL_NOTICE, "PIN is blocked\n");
590 vty_notify(ms, NULL);
591 vty_notify(ms, "PIN is blocked\n");
593 vty_notify(ms, "Please give PUC for ICCID %s "
594 "(you have %d tries left)\n",
595 subscr->iccid, payload[1]);
597 subscr->sim_pin_required = 1;
599 case SIM_CAUSE_PUC_BLOCKED:
600 LOGP(DMM, LOGL_NOTICE, "PUC is blocked\n");
602 vty_notify(ms, NULL);
603 vty_notify(ms, "PUC is blocked\n");
604 subscr->sim_pin_required = 1;
607 if (sf->func && !sf->mandatory) {
608 LOGP(DMM, LOGL_NOTICE, "SIM reading failed, "
612 LOGP(DMM, LOGL_NOTICE, "SIM reading failed\n");
614 vty_notify(ms, NULL);
615 vty_notify(ms, "SIM failed, replace SIM!\n");
618 subscr->sim_valid = 0;
619 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
622 gsm48_mmr_downmsg(ms, nmsg);
629 /* if pin was successfully unlocked, then resend request */
630 if (subscr->sim_pin_required) {
631 subscr->sim_pin_required = 0;
632 subscr_sim_request(ms);
636 /* done when nothing more to read. this happens on PIN requests */
640 /* call function do decode SIM reply */
641 rc = sf->func(ms, payload, payload_len);
643 LOGP(DMM, LOGL_NOTICE, "SIM reading failed, file invalid\n");
644 if (subscr_sim_files[subscr->sim_file_index].mandatory) {
645 vty_notify(ms, NULL);
646 vty_notify(ms, "SIM failed, data invalid, replace "
657 /* trigger next file */
658 subscr->sim_file_index++;
659 subscr_sim_request(ms);
663 void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin1, char *pin2,
666 struct gsm_subscriber *subscr = &ms->subscr;
670 /* skip, if no real valid SIM */
671 if (subscr->sim_type != GSM_SIM_TYPE_READER)
676 job = SIM_JOB_PIN1_DISABLE;
677 LOGP(DMM, LOGL_INFO, "disabling PIN %s\n", pin1);
680 job = SIM_JOB_PIN1_ENABLE;
681 LOGP(DMM, LOGL_INFO, "enabling PIN %s\n", pin1);
684 job = SIM_JOB_PIN1_CHANGE;
685 LOGP(DMM, LOGL_INFO, "changing PIN %s to %s\n", pin1, pin2);
688 job = SIM_JOB_PIN1_UNBLOCK;
689 LOGP(DMM, LOGL_INFO, "unblocking PIN %s with PUC %s\n", pin1,
693 if (!subscr->sim_pin_required) {
694 LOGP(DMM, LOGL_ERROR, "No PIN required now\n");
697 LOGP(DMM, LOGL_INFO, "entering PIN %s\n", pin1);
698 job = SIM_JOB_PIN1_UNLOCK;
701 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query, job);
704 memcpy(msgb_put(nmsg, strlen(pin1) + 1), pin1, strlen(pin1) + 1);
705 memcpy(msgb_put(nmsg, strlen(pin2) + 1), pin2, strlen(pin2) + 1);
709 /* Attach SIM reader, no SIM must be currently attached */
710 int gsm_subscr_simcard(struct osmocom_ms *ms)
712 struct gsm_subscriber *subscr = &ms->subscr;
714 if (subscr->sim_valid) {
715 LOGP(DMM, LOGL_ERROR, "Cannot attach card, until current card "
720 /* reset subscriber */
724 subscr->sim_type = GSM_SIM_TYPE_READER;
725 sprintf(subscr->sim_name, "sim");
726 subscr->sim_valid = 1;
727 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
729 /* start with first index */
730 subscr->sim_file_index = 0;
731 return subscr_sim_request(ms);
734 /* update plmn not allowed list on SIM */
735 static int subscr_write_plmn_na(struct osmocom_ms *ms)
737 struct gsm_subscriber *subscr = &ms->subscr;
740 struct gsm_sub_plmn_na *na, *nas[4] = { NULL, NULL, NULL, NULL };
745 /* skip, if no real valid SIM */
746 if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
749 /* get tail list from "PLMN not allowed" */
750 llist_for_each_entry(na, &subscr->plmn_na, entry) {
763 LOGP(DMM, LOGL_INFO, "Updating FPLMN on SIM\n");
764 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
765 SIM_JOB_UPDATE_BINARY);
768 nsh = (struct sim_hdr *) nmsg->data;
769 data = msgb_put(nmsg, 12);
770 nsh->path[0] = 0x7f20;
773 for (i = 0; i < 4; i++) {
775 gsm48_encode_lai((struct gsm48_loc_area_id *)lai,
776 nas[i]->mcc, nas[i]->mnc, 0);
791 /* update LOCI on SIM */
792 int gsm_subscr_write_loci(struct osmocom_ms *ms)
794 struct gsm_subscriber *subscr = &ms->subscr;
797 struct gsm1111_ef_loci *loci;
799 /* skip, if no real valid SIM */
800 if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
803 LOGP(DMM, LOGL_INFO, "Updating LOCI on SIM\n");
806 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
807 SIM_JOB_UPDATE_BINARY);
810 nsh = (struct sim_hdr *) nmsg->data;
811 nsh->path[0] = 0x7f20;
814 loci = (struct gsm1111_ef_loci *)msgb_put(nmsg, sizeof(*loci));
817 loci->tmsi = htonl(subscr->tmsi);
820 gsm48_encode_lai(&loci->lai, subscr->mcc, subscr->mnc, subscr->lac);
823 loci->tmsi_time = 0xff;
825 /* location update status */
826 switch (subscr->ustate) {
827 case GSM_SIM_U1_UPDATED:
828 loci->lupd_status = 0x00;
830 case GSM_SIM_U3_ROAMING_NA:
831 loci->lupd_status = 0x03;
834 loci->lupd_status = 0x01;
842 static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg)
844 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
845 uint8_t *payload = msg->data + sizeof(*sh);
848 if (sh->job_type == SIM_JOB_ERROR)
849 LOGP(DMM, LOGL_NOTICE, "SIM update failed (cause %d)\n",
855 int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq,
856 uint8_t *rand, uint8_t no_sim)
858 struct gsm_subscriber *subscr = &ms->subscr;
863 if ((subscr->sim_type != GSM_SIM_TYPE_READER
864 && subscr->sim_type != GSM_SIM_TYPE_TEST)
865 || !subscr->sim_valid || no_sim) {
866 struct gsm48_mm_event *nmme;
868 LOGP(DMM, LOGL_INFO, "Sending dummy authentication response\n");
869 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
872 nmme = (struct gsm48_mm_event *) nmsg->data;
873 nmme->sres[0] = 0x12;
874 nmme->sres[1] = 0x34;
875 nmme->sres[2] = 0x56;
876 nmme->sres[3] = 0x78;
877 gsm48_mmevent_msg(ms, nmsg);
883 if (subscr->sim_type == GSM_SIM_TYPE_TEST) {
884 struct gsm48_mm_event *nmme;
886 struct gsm_settings *set = &ms->settings;
888 if (set->test_ki_type == GSM_SIM_KEY_COMP128)
889 comp128(set->test_ki, rand, sres, subscr->key);
891 xor96(set->test_ki, rand, sres, subscr->key);
893 subscr->key_seq = key_seq;
895 LOGP(DMM, LOGL_INFO, "Sending authentication response\n");
896 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
899 nmme = (struct gsm48_mm_event *) nmsg->data;
900 memcpy(nmme->sres, sres, 4);
901 gsm48_mmevent_msg(ms, nmsg);
906 LOGP(DMM, LOGL_INFO, "Generating KEY at SIM\n");
909 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_key, SIM_JOB_RUN_GSM_ALGO);
912 nsh = (struct sim_hdr *) nmsg->data;
913 nsh->path[0] = 0x7f20;
917 memcpy(msgb_put(nmsg, 16), rand, 16);
920 subscr->key_seq = key_seq;
927 static void subscr_sim_key_cb(struct osmocom_ms *ms, struct msgb *msg)
929 struct gsm_subscriber *subscr = &ms->subscr;
930 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
931 uint8_t *payload = msg->data + sizeof(*sh);
932 uint16_t payload_len = msg->len - sizeof(*sh);
935 struct gsm48_mm_event *nmme;
939 if (sh->job_type == SIM_JOB_ERROR) {
940 LOGP(DMM, LOGL_NOTICE, "key generation on SIM failed "
941 "(cause %d)\n", *payload);
948 if (payload_len < 12) {
949 LOGP(DMM, LOGL_NOTICE, "response from SIM too short\n");
954 memcpy(subscr->key, payload + 4, 8);
957 LOGP(DMM, LOGL_INFO, "Updating KC on SIM\n");
958 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
959 SIM_JOB_UPDATE_BINARY);
962 nsh = (struct sim_hdr *) nmsg->data;
963 nsh->path[0] = 0x7f20;
966 data = msgb_put(nmsg, 9);
967 memcpy(data, subscr->key, 8);
968 data[8] = subscr->key_seq;
971 /* return signed response */
972 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
975 nmme = (struct gsm48_mm_event *) nmsg->data;
976 memcpy(nmme->sres, payload, 4);
977 gsm48_mmevent_msg(ms, nmsg);
987 int gsm_subscr_remove(struct osmocom_ms *ms)
989 struct gsm_subscriber *subscr = &ms->subscr;
992 if (!subscr->sim_valid) {
993 LOGP(DMM, LOGL_ERROR, "Cannot remove card, no card present\n");
998 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
1001 gsm48_mmr_downmsg(ms, nmsg);
1010 static const char *subscr_ustate_names[] = {
1017 /* change to new U state */
1018 void new_sim_ustate(struct gsm_subscriber *subscr, int state)
1020 LOGP(DMM, LOGL_INFO, "(ms %s) new state %s -> %s\n", subscr->ms->name,
1021 subscr_ustate_names[subscr->ustate],
1022 subscr_ustate_names[state]);
1024 subscr->ustate = state;
1027 /* del forbidden PLMN */
1028 int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1031 struct gsm_sub_plmn_na *na;
1033 llist_for_each_entry(na, &subscr->plmn_na, entry) {
1034 if (na->mcc == mcc && na->mnc == mnc) {
1035 LOGP(DPLMN, LOGL_INFO, "Delete from list of forbidden "
1036 "PLMNs (mcc=%s, mnc=%s)\n",
1037 gsm_print_mcc(mcc), gsm_print_mnc(mnc));
1038 llist_del(&na->entry);
1040 /* update plmn not allowed list on SIM */
1041 subscr_write_plmn_na(subscr->ms);
1049 /* add forbidden PLMN */
1050 int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1051 uint16_t mnc, uint8_t cause)
1053 struct gsm_sub_plmn_na *na;
1055 /* if already in the list, remove and add to tail */
1056 gsm_subscr_del_forbidden_plmn(subscr, mcc, mnc);
1058 LOGP(DPLMN, LOGL_INFO, "Add to list of forbidden PLMNs "
1059 "(mcc=%s, mnc=%s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc));
1060 na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
1066 llist_add_tail(&na->entry, &subscr->plmn_na);
1068 /* don't add Home PLMN to SIM */
1069 if (subscr->sim_valid && gsm_match_mnc(mcc, mnc, subscr->imsi))
1072 /* update plmn not allowed list on SIM */
1073 subscr_write_plmn_na(subscr->ms);
1078 /* search forbidden PLMN */
1079 int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1082 struct gsm_sub_plmn_na *na;
1084 llist_for_each_entry(na, &subscr->plmn_na, entry) {
1085 if (na->mcc == mcc && na->mnc == mnc)
1092 int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
1093 void (*print)(void *, const char *, ...), void *priv)
1095 struct gsm_subscriber *subscr = &ms->subscr;
1096 struct gsm_sub_plmn_na *temp;
1098 print(priv, "MCC |MNC |cause\n");
1099 print(priv, "-------+-------+-------\n");
1100 llist_for_each_entry(temp, &subscr->plmn_na, entry)
1101 print(priv, "%s |%s%s |#%d\n",
1102 gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
1103 ((temp->mnc & 0x00f) == 0x00f) ? " ":"", temp->cause);
1108 /* dump subscriber */
1109 void gsm_subscr_dump(struct gsm_subscriber *subscr,
1110 void (*print)(void *, const char *, ...), void *priv)
1113 struct gsm_sub_plmn_list *plmn_list;
1114 struct gsm_sub_plmn_na *plmn_na;
1116 print(priv, "Mobile Subscriber of MS '%s':\n", subscr->ms->name);
1118 if (!subscr->sim_valid) {
1119 print(priv, " No SIM present.\n");
1123 print(priv, " IMSI: %s\n", subscr->imsi);
1124 if (subscr->iccid[0])
1125 print(priv, " ICCID: %s\n", subscr->iccid);
1126 if (subscr->sim_spn[0])
1127 print(priv, " Service Provider Name: %s\n", subscr->sim_spn);
1128 if (subscr->msisdn[0])
1129 print(priv, " MSISDN: %s\n", subscr->msisdn);
1130 print(priv, " Status: %s IMSI %s", subscr_ustate_names[subscr->ustate],
1131 (subscr->imsi_attached) ? "attached" : "detached");
1132 if (subscr->tmsi != 0xffffffff)
1133 print(priv, " TSMI 0x%08x", subscr->tmsi);
1134 if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
1136 print(priv, " LAI: MCC %s MNC %s LAC 0x%04x "
1137 "(%s, %s)\n", gsm_print_mcc(subscr->mcc),
1138 gsm_print_mnc(subscr->mnc), subscr->lac,
1139 gsm_get_mcc(subscr->mcc),
1140 gsm_get_mnc(subscr->mcc, subscr->mnc));
1142 print(priv, " LAI: invalid\n");
1143 if (subscr->key_seq != 7) {
1144 print(priv, " Key: sequence %d ", subscr->key_seq);
1145 for (i = 0; i < sizeof(subscr->key); i++)
1146 print(priv, " %02x", subscr->key[i]);
1149 if (subscr->plmn_valid)
1150 print(priv, " Registered PLMN: MCC %s MNC %s (%s, %s)\n",
1151 gsm_print_mcc(subscr->plmn_mcc),
1152 gsm_print_mnc(subscr->plmn_mnc),
1153 gsm_get_mcc(subscr->plmn_mcc),
1154 gsm_get_mnc(subscr->plmn_mcc, subscr->plmn_mnc));
1155 print(priv, " Access barred cells: %s\n",
1156 (subscr->acc_barr) ? "yes" : "no");
1157 print(priv, " Access classes:");
1158 for (i = 0; i < 16; i++)
1159 if ((subscr->acc_class & (1 << i)))
1160 print(priv, " C%d", i);
1162 if (!llist_empty(&subscr->plmn_list)) {
1163 print(priv, " List of preferred PLMNs:\n");
1164 print(priv, " MCC |MNC\n");
1165 print(priv, " -------+-------\n");
1166 llist_for_each_entry(plmn_list, &subscr->plmn_list, entry)
1167 print(priv, " %s |%s (%s, %s)\n",
1168 gsm_print_mcc(plmn_list->mcc),
1169 gsm_print_mnc(plmn_list->mnc),
1170 gsm_get_mcc(plmn_list->mcc),
1171 gsm_get_mnc(plmn_list->mcc, plmn_list->mnc));
1173 if (!llist_empty(&subscr->plmn_na)) {
1174 print(priv, " List of forbidden PLMNs:\n");
1175 print(priv, " MCC |MNC |cause\n");
1176 print(priv, " -------+-------+-------\n");
1177 llist_for_each_entry(plmn_na, &subscr->plmn_na, entry)
1178 print(priv, " %s |%s%s |#%d "
1179 "(%s, %s)\n", gsm_print_mcc(plmn_na->mcc),
1180 gsm_print_mnc(plmn_na->mnc),
1181 ((plmn_na->mnc & 0x00f) == 0x00f) ? " ":"",
1182 plmn_na->cause, gsm_get_mcc(plmn_na->mcc),
1183 gsm_get_mnc(plmn_na->mcc, plmn_na->mnc));