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 <osmocore/talloc.h>
28 #include <osmocom/bb/common/logging.h>
29 #include <osmocom/bb/common/osmocom_data.h>
30 #include <osmocom/bb/common/networks.h>
31 #include <osmocom/bb/mobile/vty.h>
35 static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg);
36 static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg);
37 static void subscr_sim_key_cb(struct osmocom_ms *ms, struct msgb *msg);
43 char *gsm_check_imsi(const char *imsi)
47 if (!imsi || strlen(imsi) != 15)
48 return "IMSI must have 15 digits!";
50 for (i = 0; i < strlen(imsi); i++) {
51 if (imsi[i] < '0' || imsi[i] > '9')
52 return "IMSI must have digits 0 to 9 only!";
58 static char *sim_decode_bcd(uint8_t *data, uint8_t length)
61 static char result[32], c;
63 for (i = 0; i < (length << 1); i++) {
65 c = (data[i >> 1] >> 4) + '0';
67 c = (data[i >> 1] & 0xf) + '0';
71 if (j == sizeof(result) - 1)
83 int gsm_subscr_init(struct osmocom_ms *ms)
85 struct gsm_subscriber *subscr = &ms->subscr;
87 memset(subscr, 0, sizeof(*subscr));
90 /* set TMSI / LAC invalid */
91 subscr->tmsi = 0xffffffff;
98 INIT_LLIST_HEAD(&subscr->plmn_list);
99 INIT_LLIST_HEAD(&subscr->plmn_na);
102 subscr->sim_handle_query = sim_open(ms, subscr_sim_query_cb);
103 subscr->sim_handle_update = sim_open(ms, subscr_sim_update_cb);
104 subscr->sim_handle_key = sim_open(ms, subscr_sim_key_cb);
105 subscr->sim_state = SUBSCR_SIM_NULL;
110 int gsm_subscr_exit(struct osmocom_ms *ms)
112 struct gsm_subscriber *subscr = &ms->subscr;
113 struct llist_head *lh, *lh2;
115 if (subscr->sim_handle_query) {
116 sim_close(ms, subscr->sim_handle_query);
117 subscr->sim_handle_query = 0;
119 if (subscr->sim_handle_update) {
120 sim_close(ms, subscr->sim_handle_update);
121 subscr->sim_handle_update = 0;
123 if (subscr->sim_handle_key) {
124 sim_close(ms, subscr->sim_handle_key);
125 subscr->sim_handle_key = 0;
129 llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
133 llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
145 /* Attach test card, no SIM must be currently attached */
146 int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc)
148 struct gsm_settings *set = &ms->settings;
149 struct gsm_subscriber *subscr = &ms->subscr;
153 if (subscr->sim_valid) {
154 LOGP(DMM, LOGL_ERROR, "Cannot insert card, until current card "
159 error = gsm_check_imsi(set->test_imsi);
161 LOGP(DMM, LOGL_ERROR, "%s\n", error);
165 /* reset subscriber */
169 subscr->sim_type = GSM_SIM_TYPE_TEST;
170 sprintf(subscr->sim_name, "test");
171 subscr->sim_valid = 1;
172 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
173 subscr->acc_barr = set->test_barr; /* we may access barred cell */
174 subscr->acc_class = 0xffff; /* we have any access class */
175 subscr->plmn_valid = set->test_rplmn_valid;
176 subscr->plmn_mcc = mcc;
177 subscr->plmn_mnc = mnc;
178 subscr->always_search_hplmn = set->test_always;
179 subscr->t6m_hplmn = 1; /* try to find home network every 6 min */
180 strcpy(subscr->imsi, set->test_imsi);
182 LOGP(DMM, LOGL_INFO, "(ms %s) Inserting test card (IMSI=%s %s, %s)\n",
183 ms->name, subscr->imsi, gsm_imsi_mcc(subscr->imsi),
184 gsm_imsi_mnc(subscr->imsi));
186 if (subscr->plmn_valid)
187 LOGP(DMM, LOGL_INFO, "-> Test card registered to %s %s "
188 "(%s, %s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc),
189 gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc));
191 LOGP(DMM, LOGL_INFO, "-> Test card not registered\n");
194 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
197 gsm48_mmr_downmsg(ms, nmsg);
206 static int subscr_sim_iccid(struct osmocom_ms *ms, uint8_t *data,
209 struct gsm_subscriber *subscr = &ms->subscr;
211 strcpy(subscr->iccid, sim_decode_bcd(data, length));
212 sprintf(subscr->sim_name, "sim-%s", subscr->iccid);
213 LOGP(DMM, LOGL_INFO, "received ICCID %s from SIM\n", subscr->iccid);
218 static int subscr_sim_imsi(struct osmocom_ms *ms, uint8_t *data,
221 struct gsm_subscriber *subscr = &ms->subscr;
223 /* get actual length */
226 if (data[0] + 1 < length) {
227 LOGP(DMM, LOGL_NOTICE, "invalid length = %d\n", length);
231 if ((length << 1) > GSM_IMSI_LENGTH - 1 || (length << 1) < 6) {
232 LOGP(DMM, LOGL_NOTICE, "IMSI invalid length = %d\n",
237 strncpy(subscr->imsi, sim_decode_bcd(data + 1, length),
238 sizeof(subscr->imsi - 1));
240 LOGP(DMM, LOGL_INFO, "received IMSI %s from SIM\n", subscr->imsi);
245 static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
248 struct gsm_subscriber *subscr = &ms->subscr;
249 struct gsm1111_ef_loci *loci;
253 loci = (struct gsm1111_ef_loci *) data;
256 subscr->tmsi = ntohl(loci->tmsi);
259 gsm48_decode_lai(&loci->lai, &subscr->mcc, &subscr->mnc, &subscr->lac);
261 /* location update status */
262 switch (loci->lupd_status & 0x07) {
264 subscr->ustate = GSM_SIM_U1_UPDATED;
268 subscr->ustate = GSM_SIM_U3_ROAMING_NA;
271 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
274 LOGP(DMM, LOGL_INFO, "received LOCI from SIM\n");
279 static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
282 struct gsm_subscriber *subscr = &ms->subscr;
283 struct gsm1111_ef_adn *adn;
285 if (length < sizeof(*adn))
287 adn = (struct gsm1111_ef_adn *) (data + length - sizeof(*adn));
290 subscr->msisdn[0] = '\0';
291 if (adn->len_bcd <= 1)
295 if (adn->ton_npi == 1)
296 strcpy(subscr->msisdn, "+");
297 if (adn->ton_npi == 2)
298 strcpy(subscr->msisdn, "0");
299 strncat(subscr->msisdn, sim_decode_bcd(adn->number, adn->len_bcd - 1),
300 sizeof(subscr->msisdn) - 2);
302 LOGP(DMM, LOGL_INFO, "received MSISDN %s from SIM\n", subscr->msisdn);
307 static int subscr_sim_kc(struct osmocom_ms *ms, uint8_t *data,
310 struct gsm_subscriber *subscr = &ms->subscr;
316 memcpy(subscr->key, data, 8);
319 subscr->key_seq = data[8] & 0x07;
321 LOGP(DMM, LOGL_INFO, "received KEY from SIM\n");
326 static int subscr_sim_plmnsel(struct osmocom_ms *ms, uint8_t *data,
329 struct gsm_subscriber *subscr = &ms->subscr;
330 struct gsm_sub_plmn_list *plmn;
331 struct llist_head *lh, *lh2;
336 llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
342 /* end of list inside mandatory fields */
343 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
347 plmn = talloc_zero(l23_ctx, struct gsm_sub_plmn_list);
353 gsm48_decode_lai((struct gsm48_loc_area_id *)lai, &plmn->mcc,
354 &plmn->mnc, &dummy_lac);
355 llist_add_tail(&plmn->entry, &subscr->plmn_list);
357 LOGP(DMM, LOGL_INFO, "received PLMN selector (mcc=%s mnc=%s) "
359 gsm_print_mcc(plmn->mcc), gsm_print_mnc(plmn->mnc));
368 static int subscr_sim_hpplmn(struct osmocom_ms *ms, uint8_t *data,
371 struct gsm_subscriber *subscr = &ms->subscr;
376 /* HPLMN search interval */
377 subscr->t6m_hplmn = *data; /* multiple of 6 minutes */
379 LOGP(DMM, LOGL_INFO, "received HPPLMN %d from SIM\n",
385 static int subscr_sim_spn(struct osmocom_ms *ms, uint8_t *data,
388 struct gsm_subscriber *subscr = &ms->subscr;
391 /* UCS2 code not supported */
392 if (length < 17 || data[1] >= 0x80)
396 for (i = 0; i < 16; i++) {
399 subscr->sim_spn[i] = *data++;
401 subscr->sim_spn[i] = '\0';
403 LOGP(DMM, LOGL_INFO, "received SPN %s from SIM\n", subscr->sim_spn);
408 static int subscr_sim_acc(struct osmocom_ms *ms, uint8_t *data,
411 struct gsm_subscriber *subscr = &ms->subscr;
418 memcpy(&ac, data, sizeof(ac));
419 subscr->acc_class = ntohs(ac);
421 LOGP(DMM, LOGL_INFO, "received ACC %04x from SIM\n", subscr->acc_class);
426 static int subscr_sim_fplmn(struct osmocom_ms *ms, uint8_t *data,
429 struct gsm_subscriber *subscr = &ms->subscr;
430 struct gsm_sub_plmn_na *na;
431 struct llist_head *lh, *lh2;
436 llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
441 while (length >= 3) {
442 /* end of list inside mandatory fields */
443 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
447 na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
453 gsm48_decode_lai((struct gsm48_loc_area_id *)lai, &na->mcc,
454 &na->mnc, &dummy_lac);
456 llist_add_tail(&na->entry, &subscr->plmn_na);
464 static struct subscr_sim_file {
466 uint16_t path[MAX_SIM_PATH_LENGTH];
468 int (*func)(struct osmocom_ms *ms, uint8_t *data,
470 } subscr_sim_files[] = {
471 { 1, { 0 }, 0x2fe2, subscr_sim_iccid },
472 { 1, { 0x7f20, 0 }, 0x6f07, subscr_sim_imsi },
473 { 1, { 0x7f20, 0 }, 0x6f7e, subscr_sim_loci },
474 { 0, { 0x7f20, 0 }, 0x6f40, subscr_sim_msisdn },
475 { 0, { 0x7f20, 0 }, 0x6f20, subscr_sim_kc },
476 { 0, { 0x7f20, 0 }, 0x6f30, subscr_sim_plmnsel },
477 { 0, { 0x7f20, 0 }, 0x6f31, subscr_sim_hpplmn },
478 { 0, { 0x7f20, 0 }, 0x6f46, subscr_sim_spn },
479 { 0, { 0x7f20, 0 }, 0x6f78, subscr_sim_acc },
480 { 0, { 0x7f20, 0 }, 0x6f7b, subscr_sim_fplmn },
481 { 0, { 0 }, 0, NULL }
484 /* request file from SIM */
485 static int subscr_sim_request(struct osmocom_ms *ms)
487 struct gsm_subscriber *subscr = &ms->subscr;
488 struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
493 /* we are done, fire up PLMN and cell selection process */
495 LOGP(DMM, LOGL_INFO, "(ms %s) Done reading SIM card "
496 "(IMSI=%s %s, %s)\n", ms->name, subscr->imsi,
497 gsm_imsi_mcc(subscr->imsi), gsm_imsi_mnc(subscr->imsi));
499 /* if LAI is valid, set RPLMN */
500 if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
501 subscr->plmn_valid = 1;
502 subscr->plmn_mcc = subscr->mcc;
503 subscr->plmn_mnc = subscr->mnc;
504 LOGP(DMM, LOGL_INFO, "-> SIM card registered to %s %s "
505 "(%s, %s)\n", gsm_print_mcc(subscr->plmn_mcc),
506 gsm_print_mnc(subscr->plmn_mnc),
507 gsm_get_mcc(subscr->plmn_mcc),
508 gsm_get_mnc(subscr->plmn_mcc,
511 LOGP(DMM, LOGL_INFO, "-> SIM card not registered\n");
514 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
517 gsm48_mmr_downmsg(ms, nmsg);
522 /* trigger SIM reading */
523 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query,
524 SIM_JOB_READ_BINARY);
527 nsh = (struct sim_hdr *) nmsg->data;
529 while (sf->path[i]) {
530 nsh->path[i] = sf->path[i];
533 nsh->path[i] = 0; /* end of path */
534 nsh->file = sf->file;
535 LOGP(DMM, LOGL_INFO, "Requesting SIM file 0x%04x\n", nsh->file);
541 static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg)
543 struct gsm_subscriber *subscr = &ms->subscr;
544 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
545 uint8_t *payload = msg->data + sizeof(*sh);
546 uint16_t payload_len = msg->len - sizeof(*sh);
550 if (sh->job_type == SIM_JOB_ERROR) {
551 uint8_t cause = payload[0];
554 /* unlocking required */
555 case SIM_CAUSE_PIN1_REQUIRED:
556 LOGP(DMM, LOGL_INFO, "PIN is required, %d tries left\n",
559 vty_notify(ms, NULL);
560 vty_notify(ms, "Please give PIN for ICCID %s (you have "
561 "%d tries left)\n", subscr->iccid, payload[1]);
562 subscr->sim_pin_required = 1;
564 case SIM_CAUSE_PIN1_BLOCKED:
565 LOGP(DMM, LOGL_NOTICE, "PIN is blocked\n");
567 vty_notify(ms, NULL);
568 vty_notify(ms, "PIN is blocked\n");
571 LOGP(DMM, LOGL_NOTICE, "SIM reading failed\n");
573 vty_notify(ms, NULL);
574 vty_notify(ms, "SIM failed, replace SIM!\n");
581 /* call function do decode SIM reply */
582 rc = subscr_sim_files[subscr->sim_file_index].func(ms, payload,
586 LOGP(DMM, LOGL_NOTICE, "SIM reading failed, file invalid\n");
587 if (subscr_sim_files[subscr->sim_file_index].mandatory) {
588 vty_notify(ms, NULL);
589 vty_notify(ms, "SIM failed, data invalid, replace "
599 /* trigger next file */
600 subscr->sim_file_index++;
601 subscr_sim_request(ms);
605 void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin)
607 struct gsm_subscriber *subscr = &ms->subscr;
610 if (!subscr->sim_pin_required) {
611 LOGP(DMM, LOGL_ERROR, "No PIN required now\n");
615 subscr->sim_pin_required = 0;
616 LOGP(DMM, LOGL_INFO, "Unlocking PIN %s\n", pin);
617 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
618 SIM_JOB_PIN1_UNLOCK);
621 memcpy(msgb_put(nmsg, strlen(pin)), pin, strlen(pin));
625 /* Attach SIM reader, no SIM must be currently attached */
626 int gsm_subscr_simcard(struct osmocom_ms *ms)
628 struct gsm_subscriber *subscr = &ms->subscr;
630 if (subscr->sim_valid) {
631 LOGP(DMM, LOGL_ERROR, "Cannot attach card, until current card "
636 /* reset subscriber */
640 subscr->sim_type = GSM_SIM_TYPE_READER;
641 sprintf(subscr->sim_name, "sim");
642 subscr->sim_valid = 1;
643 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
645 /* start with first index */
646 subscr->sim_file_index = 0;
647 return subscr_sim_request(ms);
650 /* update plmn not allowed list on SIM */
651 static int subscr_write_plmn_na(struct osmocom_ms *ms)
653 struct gsm_subscriber *subscr = &ms->subscr;
656 struct gsm_sub_plmn_na *na, *nas[4] = { NULL, NULL, NULL, NULL };
661 /* skip, if no real valid SIM */
662 if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
665 /* get tail list from "PLMN not allowed" */
666 llist_for_each_entry(na, &subscr->plmn_na, entry) {
679 LOGP(DMM, LOGL_INFO, "Updating FPLMN on SIM\n");
680 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
681 SIM_JOB_UPDATE_BINARY);
684 nsh = (struct sim_hdr *) nmsg->data;
685 data = msgb_put(nmsg, 12);
686 nsh->path[0] = 0x7f20;
689 for (i = 0; i < 4; i++) {
691 gsm48_encode_lai((struct gsm48_loc_area_id *)lai,
692 nas[i]->mcc, nas[i]->mnc, 0);
707 /* update LOCI on SIM */
708 int gsm_subscr_write_loci(struct osmocom_ms *ms)
710 struct gsm_subscriber *subscr = &ms->subscr;
713 struct gsm1111_ef_loci *loci;
715 /* skip, if no real valid SIM */
716 if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
719 LOGP(DMM, LOGL_INFO, "Updating LOCI on SIM\n");
722 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
723 SIM_JOB_UPDATE_BINARY);
726 nsh = (struct sim_hdr *) nmsg->data;
727 nsh->path[0] = 0x7f20;
730 loci = (struct gsm1111_ef_loci *)msgb_put(nmsg, sizeof(*loci));
733 loci->tmsi = htonl(subscr->tmsi);
736 gsm48_encode_lai(&loci->lai, subscr->mcc, subscr->mnc, subscr->lac);
739 loci->tmsi_time = 0xff;
741 /* location update status */
742 switch (subscr->ustate) {
743 case GSM_SIM_U1_UPDATED:
744 loci->lupd_status = 0x00;
746 case GSM_SIM_U3_ROAMING_NA:
747 loci->lupd_status = 0x03;
750 loci->lupd_status = 0x01;
758 static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg)
760 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
761 uint8_t *payload = msg->data + sizeof(*sh);
764 if (sh->job_type == SIM_JOB_ERROR)
765 LOGP(DMM, LOGL_NOTICE, "SIM update failed (cause %d)\n",
771 int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq,
774 struct gsm_subscriber *subscr = &ms->subscr;
779 if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid) {
780 struct gsm48_mm_event *nmme;
782 LOGP(DMM, LOGL_INFO, "Sending fake authentication response\n");
783 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
786 nmme = (struct gsm48_mm_event *)msgb_put(nmsg, sizeof(*nmme));
787 nmme->sres[0] = 0x12;
788 nmme->sres[1] = 0x34;
789 nmme->sres[2] = 0x56;
790 nmme->sres[3] = 0x78;
791 gsm48_mmevent_msg(ms, nmsg);
794 LOGP(DMM, LOGL_INFO, "Generating KEY at SIM\n");
797 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_key, SIM_JOB_RUN_GSM_ALGO);
800 nsh = (struct sim_hdr *) nmsg->data;
801 nsh->path[0] = 0x7f20;
805 memcpy(msgb_put(nmsg, 16), rand, 16);
808 subscr->key_seq = key_seq;
815 static void subscr_sim_key_cb(struct osmocom_ms *ms, struct msgb *msg)
817 struct gsm_subscriber *subscr = &ms->subscr;
818 struct sim_hdr *sh = (struct sim_hdr *) msg->data;
819 uint8_t *payload = msg->data + sizeof(*sh);
820 uint16_t payload_len = msg->len - sizeof(*sh);
823 struct gsm48_mm_event *nmme;
827 if (sh->job_type == SIM_JOB_ERROR) {
828 LOGP(DMM, LOGL_NOTICE, "key generation on SIM failed "
829 "(cause %d)\n", *payload);
836 if (payload_len < 12) {
837 LOGP(DMM, LOGL_NOTICE, "response from SIM too short\n");
842 memcpy(subscr->key, payload + 4, 8);
845 LOGP(DMM, LOGL_INFO, "Updating KC on SIM\n");
846 nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
847 SIM_JOB_UPDATE_BINARY);
850 nsh = (struct sim_hdr *) nmsg->data;
851 nsh->path[0] = 0x7f20;
854 data = msgb_put(nmsg, 9);
855 memcpy(data, subscr->key, 8);
856 data[8] = subscr->key_seq;
859 /* return signed response */
860 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
863 nmme = (struct gsm48_mm_event *)msgb_put(nmsg, sizeof(*nmme));
864 nmme->sres[0] = 0x12;
865 nmme->sres[1] = 0x34;
866 nmme->sres[2] = 0x56;
867 nmme->sres[3] = 0x78;
868 gsm48_mmevent_msg(ms, nmsg);
878 int gsm_subscr_remove(struct osmocom_ms *ms)
880 struct gsm_subscriber *subscr = &ms->subscr;
883 if (!subscr->sim_valid) {
884 LOGP(DMM, LOGL_ERROR, "Cannot remove card, no card present\n");
889 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
892 gsm48_mmr_downmsg(ms, nmsg);
901 static const char *subscr_ustate_names[] = {
908 /* change to new U state */
909 void new_sim_ustate(struct gsm_subscriber *subscr, int state)
911 LOGP(DMM, LOGL_INFO, "(ms %s) new state %s -> %s\n", subscr->ms->name,
912 subscr_ustate_names[subscr->ustate],
913 subscr_ustate_names[state]);
915 subscr->ustate = state;
918 /* del forbidden PLMN */
919 int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
922 struct gsm_sub_plmn_na *na;
924 llist_for_each_entry(na, &subscr->plmn_na, entry) {
925 if (na->mcc == mcc && na->mnc == mnc) {
926 LOGP(DPLMN, LOGL_INFO, "Delete from list of forbidden "
927 "PLMNs (mcc=%s, mnc=%s)\n",
928 gsm_print_mcc(mcc), gsm_print_mnc(mnc));
929 llist_del(&na->entry);
931 /* update plmn not allowed list on SIM */
932 subscr_write_plmn_na(subscr->ms);
940 /* add forbidden PLMN */
941 int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
942 uint16_t mnc, uint8_t cause)
944 struct gsm_sub_plmn_na *na;
946 /* if already in the list, remove and add to tail */
947 gsm_subscr_del_forbidden_plmn(subscr, mcc, mnc);
949 LOGP(DPLMN, LOGL_INFO, "Add to list of forbidden PLMNs "
950 "(mcc=%s, mnc=%s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc));
951 na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
957 llist_add_tail(&na->entry, &subscr->plmn_na);
959 /* don't add Home PLMN to SIM */
960 if (subscr->sim_valid && gsm_match_mnc(mcc, mnc, subscr->imsi))
963 /* update plmn not allowed list on SIM */
964 subscr_write_plmn_na(subscr->ms);
969 /* search forbidden PLMN */
970 int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
973 struct gsm_sub_plmn_na *na;
975 llist_for_each_entry(na, &subscr->plmn_na, entry) {
976 if (na->mcc == mcc && na->mnc == mnc)
983 int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
984 void (*print)(void *, const char *, ...), void *priv)
986 struct gsm_subscriber *subscr = &ms->subscr;
987 struct gsm_sub_plmn_na *temp;
989 print(priv, "MCC |MNC |cause\n");
990 print(priv, "-------+-------+-------\n");
991 llist_for_each_entry(temp, &subscr->plmn_na, entry)
992 print(priv, "%s |%s%s |#%d\n",
993 gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
994 ((temp->mnc & 0x00f) == 0x00f) ? " ":"", temp->cause);
999 /* dump subscriber */
1000 void gsm_subscr_dump(struct gsm_subscriber *subscr,
1001 void (*print)(void *, const char *, ...), void *priv)
1004 struct gsm_sub_plmn_list *plmn_list;
1005 struct gsm_sub_plmn_na *plmn_na;
1007 print(priv, "Mobile Subscriber of MS '%s':\n", subscr->ms->name);
1009 if (!subscr->sim_valid) {
1010 print(priv, " No SIM present.\n");
1014 print(priv, " IMSI: %s\n", subscr->imsi);
1015 if (subscr->msisdn[0])
1016 print(priv, " MSISDN: %s\n", subscr->msisdn);
1017 print(priv, " Status: %s IMSI %s", subscr_ustate_names[subscr->ustate],
1018 (subscr->imsi_attached) ? "attached" : "detached");
1019 if (subscr->tmsi != 0xffffffff)
1020 print(priv, " TSMI %08x", subscr->tmsi);
1021 if (subscr->lac > 0x0000 && subscr->lac < 0xfffe)
1022 print(priv, " LAI: MCC %s MNC %s LAC 0x%04x (%s, %s)\n",
1023 gsm_print_mcc(subscr->mcc),
1024 gsm_print_mnc(subscr->mnc), subscr->lac,
1025 gsm_get_mcc(subscr->mcc),
1026 gsm_get_mnc(subscr->mcc, subscr->mnc));
1028 print(priv, " LAI: invalid\n");
1029 if (subscr->key_seq != 7) {
1030 print(priv, " Key: sequence %d ");
1031 for (i = 0; i < sizeof(subscr->key); i++)
1032 print(priv, " %02x", subscr->key[i]);
1035 if (subscr->plmn_valid)
1036 print(priv, " Registered PLMN: MCC %s MNC %s (%s, %s)\n",
1037 gsm_print_mcc(subscr->plmn_mcc),
1038 gsm_print_mnc(subscr->plmn_mnc),
1039 gsm_get_mcc(subscr->plmn_mcc),
1040 gsm_get_mnc(subscr->plmn_mcc, subscr->plmn_mnc));
1041 print(priv, " Access barred cells: %s\n",
1042 (subscr->acc_barr) ? "yes" : "no");
1043 print(priv, " Access classes:");
1044 for (i = 0; i < 16; i++)
1045 if ((subscr->acc_class & (1 << i)))
1046 print(priv, " C%d", i);
1048 if (!llist_empty(&subscr->plmn_list)) {
1049 print(priv, " List of preferred PLMNs:\n");
1050 print(priv, " MCC |MNC\n");
1051 print(priv, " -------+-------\n");
1052 llist_for_each_entry(plmn_list, &subscr->plmn_list, entry)
1053 print(priv, " %s |%s\n",
1054 gsm_print_mcc(plmn_list->mcc),
1055 gsm_print_mnc(plmn_list->mnc));
1057 if (!llist_empty(&subscr->plmn_na)) {
1058 print(priv, " List of forbidden PLMNs:\n");
1059 print(priv, " MCC |MNC |cause\n");
1060 print(priv, " -------+-------+-------\n");
1061 llist_for_each_entry(plmn_na, &subscr->plmn_na, entry)
1062 print(priv, " %s |%s%s |#%d\n",
1063 gsm_print_mcc(plmn_na->mcc),
1064 gsm_print_mnc(plmn_na->mnc),
1065 ((plmn_na->mnc & 0x00f) == 0x00f) ? " ":"",