src: use new libosmogsm and include/osmocom/[gsm|core] path to headers
[osmocom-bb.git] / src / host / layer23 / src / mobile / subscriber.c
1 /*
2  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
3  *
4  * All Rights Reserved
5  *
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.
10  *
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.
15  *
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.
19  *
20  */
21
22 #include <stdint.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <arpa/inet.h>
26 #include <osmocom/core/talloc.h>
27 #include <osmocom/gsm/comp128.h>
28
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>
33
34 void *l23_ctx;
35
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);
39
40 /*
41  * support
42  */
43
44 char *gsm_check_imsi(const char *imsi)
45 {
46         int i;
47
48         if (!imsi || strlen(imsi) != 15)
49                 return "IMSI must have 15 digits!";
50
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!";
54         }
55
56         return NULL;
57 }
58
59 static char *sim_decode_bcd(uint8_t *data, uint8_t length)
60 {
61         int i, j = 0;
62         static char result[32], c;
63
64         for (i = 0; i < (length << 1); i++) {
65                 if ((i & 1))
66                         c = (data[i >> 1] >> 4);
67                 else
68                         c = (data[i >> 1] & 0xf);
69                 if (c == 0xf)
70                         break;
71                 result[j++] = c + '0';
72                 if (j == sizeof(result) - 1)
73                         break;
74         }
75         result[j] = '\0';
76
77         return result;
78 }
79
80 static void xor96(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc)
81 {
82         int i;
83
84         for (i=0; i < 4; i++)
85                 sres[i] = rand[i] ^ ki[i];
86         for (i=0; i < 8; i++)
87                 kc[i] = rand[i] ^ ki[i+4];
88 }
89
90 /*
91  * init/exit
92  */
93
94 int gsm_subscr_init(struct osmocom_ms *ms)
95 {
96         struct gsm_subscriber *subscr = &ms->subscr;
97
98         memset(subscr, 0, sizeof(*subscr));
99         subscr->ms = ms;
100
101         /* set TMSI / LAC invalid */
102         subscr->tmsi = 0xffffffff;
103         subscr->lac = 0x0000;
104
105         /* set key invalid */
106         subscr->key_seq = 7;
107
108         /* init lists */
109         INIT_LLIST_HEAD(&subscr->plmn_list);
110         INIT_LLIST_HEAD(&subscr->plmn_na);
111
112         /* open SIM */
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);
116
117         return 0;
118 }
119
120 int gsm_subscr_exit(struct osmocom_ms *ms)
121 {
122         struct gsm_subscriber *subscr = &ms->subscr;
123         struct llist_head *lh, *lh2;
124
125         if (subscr->sim_handle_query) {
126                 sim_close(ms, subscr->sim_handle_query);
127                 subscr->sim_handle_query = 0;
128         }
129         if (subscr->sim_handle_update) {
130                 sim_close(ms, subscr->sim_handle_update);
131                 subscr->sim_handle_update = 0;
132         }
133         if (subscr->sim_handle_key) {
134                 sim_close(ms, subscr->sim_handle_key);
135                 subscr->sim_handle_key = 0;
136         }
137
138         /* flush lists */
139         llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
140                 llist_del(lh);
141                 talloc_free(lh);
142         }
143         llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
144                 llist_del(lh);
145                 talloc_free(lh);
146         }
147
148         return 0;
149 }
150
151 /*
152  * test card
153  */
154
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)
158 {
159         struct gsm_settings *set = &ms->settings;
160         struct gsm_subscriber *subscr = &ms->subscr;
161         struct msgb *nmsg;
162         char *error;
163
164         if (subscr->sim_valid) {
165                 LOGP(DMM, LOGL_ERROR, "Cannot insert card, until current card "
166                         "is detached.\n");
167                 return -EBUSY;
168         }
169
170         error = gsm_check_imsi(set->test_imsi);
171         if (error) {
172                 LOGP(DMM, LOGL_ERROR, "%s\n", error);
173                 return -EINVAL;
174         }
175
176         /* reset subscriber */
177         gsm_subscr_exit(ms);
178         gsm_subscr_init(ms);
179
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;
189         subscr->mcc = mcc;
190         subscr->mnc = mnc;
191         subscr->lac = lac;
192         subscr->tmsi = tmsi;
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);
196
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));
200
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));
206         else
207                 LOGP(DMM, LOGL_INFO, "-> Test card not registered\n");
208
209         /* insert card */
210         nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
211         if (!nmsg)
212                 return -ENOMEM;
213         gsm48_mmr_downmsg(ms, nmsg);
214
215         return 0;
216 }
217
218 /*
219  * sim card
220  */
221
222 static int subscr_sim_iccid(struct osmocom_ms *ms, uint8_t *data,
223         uint8_t length)
224 {
225         struct gsm_subscriber *subscr = &ms->subscr;
226
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);
230
231         return 0;
232 }
233
234 static int subscr_sim_imsi(struct osmocom_ms *ms, uint8_t *data,
235         uint8_t length)
236 {
237         struct gsm_subscriber *subscr = &ms->subscr;
238         char *imsi;
239
240         /* get actual length */
241         if (length < 1)
242                 return -EINVAL;
243         if (data[0] + 1 < length) {
244                 LOGP(DMM, LOGL_NOTICE, "invalid length = %d\n", length);
245                 return -EINVAL;
246         }
247         length = data[0];
248
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",
253                         strlen(imsi) - 1);
254                 return -EINVAL;
255         }
256
257         strncpy(subscr->imsi, imsi + 1, sizeof(subscr->imsi) - 1);
258
259         LOGP(DMM, LOGL_INFO, "received IMSI %s from SIM\n", subscr->imsi);
260
261         return 0;
262 }
263
264 static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
265         uint8_t length)
266 {
267         struct gsm_subscriber *subscr = &ms->subscr;
268         struct gsm1111_ef_loci *loci;
269
270         if (length < 11)
271                 return -EINVAL;
272         loci = (struct gsm1111_ef_loci *) data;
273
274         /* TMSI */
275         subscr->tmsi = ntohl(loci->tmsi);
276
277         /* LAI */
278         gsm48_decode_lai(&loci->lai, &subscr->mcc, &subscr->mnc, &subscr->lac);
279
280         /* location update status */
281         switch (loci->lupd_status & 0x07) {
282         case 0x00:
283                 subscr->ustate = GSM_SIM_U1_UPDATED;
284                 break;
285         case 0x02:
286         case 0x03:
287                 subscr->ustate = GSM_SIM_U3_ROAMING_NA;
288                 break;
289         default:
290                 subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
291         }
292
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);
296
297         return 0;
298 }
299
300 static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
301         uint8_t length)
302 {
303         struct gsm_subscriber *subscr = &ms->subscr;
304         struct gsm1111_ef_adn *adn;
305
306         if (length < sizeof(*adn))
307                 return -EINVAL;
308         adn = (struct gsm1111_ef_adn *) (data + length - sizeof(*adn));
309
310         /* empty */
311         subscr->msisdn[0] = '\0';
312         if (adn->len_bcd <= 1)
313                 return 0;
314
315         /* number */
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);
322
323         LOGP(DMM, LOGL_INFO, "received MSISDN %s from SIM\n", subscr->msisdn);
324
325         return 0;
326 }
327
328 static int subscr_sim_kc(struct osmocom_ms *ms, uint8_t *data,
329         uint8_t length)
330 {
331         struct gsm_subscriber *subscr = &ms->subscr;
332
333         if (length < 9)
334                 return -EINVAL;
335
336         /* key */
337         memcpy(subscr->key, data, 8);
338
339         /* key sequence */
340         subscr->key_seq = data[8] & 0x07;
341
342         LOGP(DMM, LOGL_INFO, "received KEY from SIM\n");
343
344         return 0;
345 }
346
347 static int subscr_sim_plmnsel(struct osmocom_ms *ms, uint8_t *data,
348         uint8_t length)
349 {
350         struct gsm_subscriber *subscr = &ms->subscr;
351         struct gsm_sub_plmn_list *plmn;
352         struct llist_head *lh, *lh2;
353         uint8_t lai[5];
354         uint16_t dummy_lac;
355
356         /* flush list */
357         llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
358                 llist_del(lh);
359                 talloc_free(lh);
360         }
361
362         while(length >= 3) {
363                 /* end of list inside mandatory fields */
364                 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
365                         break;
366
367                 /* add to list */
368                 plmn = talloc_zero(l23_ctx, struct gsm_sub_plmn_list);
369                 if (!plmn)
370                         return -ENOMEM;
371                 lai[0] = data[0];
372                 lai[1] = data[1];
373                 lai[2] = data[2];
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);
377
378                 LOGP(DMM, LOGL_INFO, "received PLMN selector (mcc=%s mnc=%s) "
379                         "from SIM\n",
380                         gsm_print_mcc(plmn->mcc), gsm_print_mnc(plmn->mnc));
381
382                 data += 3;
383                 length -= 3;
384         }
385
386         return 0;
387 }
388
389 static int subscr_sim_hpplmn(struct osmocom_ms *ms, uint8_t *data,
390         uint8_t length)
391 {
392         struct gsm_subscriber *subscr = &ms->subscr;
393
394         if (length < 1)
395                 return -EINVAL;
396
397         /* HPLMN search interval */
398         subscr->t6m_hplmn = *data; /* multiple of 6 minutes */
399
400         LOGP(DMM, LOGL_INFO, "received HPPLMN %d (%d mins) from SIM\n",
401                 subscr->t6m_hplmn, subscr->t6m_hplmn * 6);
402
403         return 0;
404 }
405
406 static int subscr_sim_spn(struct osmocom_ms *ms, uint8_t *data,
407         uint8_t length)
408 {
409         struct gsm_subscriber *subscr = &ms->subscr;
410         int i;
411
412         /* UCS2 code not supported */
413         if (length < 17 || data[1] >= 0x80)
414                 return -ENOTSUP;
415
416         data++;
417         for (i = 0; i < 16; i++) {
418                 if (*data == 0xff)
419                         break;
420                 subscr->sim_spn[i] = *data++;
421         }
422         subscr->sim_spn[i] = '\0';
423
424         LOGP(DMM, LOGL_INFO, "received SPN %s from SIM\n", subscr->sim_spn);
425
426         return 0;
427 }
428
429 static int subscr_sim_acc(struct osmocom_ms *ms, uint8_t *data,
430         uint8_t length)
431 {
432         struct gsm_subscriber *subscr = &ms->subscr;
433         uint16_t ac;
434
435         if (length < 2)
436                 return -EINVAL;
437
438         /* cell access */
439         memcpy(&ac, data, sizeof(ac));
440         subscr->acc_class = ntohs(ac);
441
442         LOGP(DMM, LOGL_INFO, "received ACC %04x from SIM\n", subscr->acc_class);
443
444         return 0;
445 }
446
447 static int subscr_sim_fplmn(struct osmocom_ms *ms, uint8_t *data,
448         uint8_t length)
449 {
450         struct gsm_subscriber *subscr = &ms->subscr;
451         struct gsm_sub_plmn_na *na;
452         struct llist_head *lh, *lh2;
453         uint8_t lai[5];
454         uint16_t dummy_lac;
455
456         /* flush list */
457         llist_for_each_safe(lh, lh2, &subscr->plmn_na) {
458                 llist_del(lh);
459                 talloc_free(lh);
460         }
461
462         while (length >= 3) {
463                 /* end of list inside mandatory fields */
464                 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0x0ff)
465                         break;
466
467                 /* add to list */
468                 na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
469                 if (!na)
470                         return -ENOMEM;
471                 lai[0] = data[0];
472                 lai[1] = data[1];
473                 lai[2] = data[2];
474                 gsm48_decode_lai((struct gsm48_loc_area_id *)lai, &na->mcc,
475                         &na->mnc, &dummy_lac);
476                 na->cause = 0;
477                 llist_add_tail(&na->entry, &subscr->plmn_na);
478
479                 data += 3;
480                 length -= 3;
481         }
482         return 0;
483 }
484
485 static struct subscr_sim_file {
486         uint8_t         mandatory;
487         uint16_t        path[MAX_SIM_PATH_LENGTH];
488         uint16_t        file;
489         int             (*func)(struct osmocom_ms *ms, uint8_t *data,
490                                 uint8_t length);
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, { 0x7f20, 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 }
503 };
504
505 /* request file from SIM */
506 static int subscr_sim_request(struct osmocom_ms *ms)
507 {
508         struct gsm_subscriber *subscr = &ms->subscr;
509         struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
510         struct msgb *nmsg;
511         struct sim_hdr *nsh;
512         int i;
513
514         /* we are done, fire up PLMN and cell selection process */
515         if (!sf->func) {
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));
519
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,
530                                         subscr->plmn_mnc));
531                 } else
532                         LOGP(DMM, LOGL_INFO, "-> SIM card not registered\n");
533
534                 /* insert card */
535                 nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
536                 if (!nmsg)
537                         return -ENOMEM;
538                 gsm48_mmr_downmsg(ms, nmsg);
539
540                 return 0;
541         }
542
543         /* trigger SIM reading */
544         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query,
545                 SIM_JOB_READ_BINARY);
546         if (!nmsg)
547                 return -ENOMEM;
548         nsh = (struct sim_hdr *) nmsg->data;
549         i = 0;
550         while (sf->path[i]) {
551                 nsh->path[i] = sf->path[i];
552                 i++;
553         }
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);
557         sim_job(ms, nmsg);
558
559         return 0;
560 }
561
562 static void subscr_sim_query_cb(struct osmocom_ms *ms, struct msgb *msg)
563 {
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);
568         int rc;
569         struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];
570
571         /* error handling */
572         if (sh->job_type == SIM_JOB_ERROR) {
573                 uint8_t cause = payload[0];
574
575                 switch (cause) {
576                         /* unlocking required */
577                 case SIM_CAUSE_PIN1_REQUIRED:
578                         LOGP(DMM, LOGL_INFO, "PIN is required, %d tries left\n",
579                                 payload[1]);
580
581                         vty_notify(ms, NULL);
582                         vty_notify(ms, "Please give PIN for ICCID %s (you have "
583                                 "%d tries left)\n", subscr->iccid, payload[1]);
584                         subscr->sim_pin_required = 1;
585                         break;
586                 case SIM_CAUSE_PIN1_BLOCKED:
587                         LOGP(DMM, LOGL_NOTICE, "PIN is blocked\n");
588
589                         vty_notify(ms, NULL);
590                         vty_notify(ms, "PIN is blocked\n");
591                         if (payload[1]) {
592                                 vty_notify(ms, "Please give PUC for ICCID %s "
593                                         "(you have %d tries left)\n",
594                                         subscr->iccid, payload[1]);
595                         }
596                         subscr->sim_pin_required = 1;
597                         break;
598                 case SIM_CAUSE_PUC_BLOCKED:
599                         LOGP(DMM, LOGL_NOTICE, "PUC is blocked\n");
600
601                         vty_notify(ms, NULL);
602                         vty_notify(ms, "PUC is blocked\n");
603                         subscr->sim_pin_required = 1;
604                         break;
605                 default:
606                         if (sf->func && !sf->mandatory) {
607                                 LOGP(DMM, LOGL_NOTICE, "SIM reading failed, "
608                                         "ignoring!\n");
609                                 goto ignore;
610                         }
611                         LOGP(DMM, LOGL_NOTICE, "SIM reading failed\n");
612
613                         vty_notify(ms, NULL);
614                         vty_notify(ms, "SIM failed, replace SIM!\n");
615                 }
616                 msgb_free(msg);
617
618                 return;
619         }
620
621         /* if pin was successfully unlocked, then resend request */
622         if (subscr->sim_pin_required) {
623                 subscr->sim_pin_required = 0;
624                 subscr_sim_request(ms);
625                 return;
626         }
627
628         /* done when nothing more to read. this happens on PIN requests */
629         if (!sf->func)
630                 return;
631
632         /* call function do decode SIM reply */
633         rc = sf->func(ms, payload, payload_len);
634         if (rc) {
635                 LOGP(DMM, LOGL_NOTICE, "SIM reading failed, file invalid\n");
636                 if (subscr_sim_files[subscr->sim_file_index].mandatory) {
637                         vty_notify(ms, NULL);
638                         vty_notify(ms, "SIM failed, data invalid, replace "
639                                 "SIM!\n");
640                         msgb_free(msg);
641
642                         return;
643                 }
644         }
645
646 ignore:
647         msgb_free(msg);
648
649         /* trigger next file */
650         subscr->sim_file_index++;
651         subscr_sim_request(ms);
652 }
653
654 /* enter PIN */
655 void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin1, char *pin2,
656         int8_t mode)
657 {
658         struct gsm_subscriber *subscr = &ms->subscr;
659         struct msgb *nmsg;
660         uint8_t job;
661
662         /* skip, if no real valid SIM */
663         if (subscr->sim_type != GSM_SIM_TYPE_READER)
664                 return;
665
666         switch (mode) {
667         case -1:
668                 job = SIM_JOB_PIN1_DISABLE;
669                 LOGP(DMM, LOGL_INFO, "disabling PIN %s\n", pin1);
670                 break;
671         case 1:
672                 job = SIM_JOB_PIN1_ENABLE;
673                 LOGP(DMM, LOGL_INFO, "enabling PIN %s\n", pin1);
674                 break;
675         case 2:
676                 job = SIM_JOB_PIN1_CHANGE;
677                 LOGP(DMM, LOGL_INFO, "changing PIN %s to %s\n", pin1, pin2);
678                 break;
679         case 99:
680                 job = SIM_JOB_PIN1_UNBLOCK;
681                 LOGP(DMM, LOGL_INFO, "unblocking PIN %s with PUC %s\n", pin1,
682                         pin2);
683                 break;
684         default:
685                 if (!subscr->sim_pin_required) {
686                         LOGP(DMM, LOGL_ERROR, "No PIN required now\n");
687                         return;
688                 }
689                 LOGP(DMM, LOGL_INFO, "entering PIN %s\n", pin1);
690                 job = SIM_JOB_PIN1_UNLOCK;
691         }
692
693         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query, job);
694         if (!nmsg)
695                 return;
696         memcpy(msgb_put(nmsg, strlen(pin1) + 1), pin1, strlen(pin1) + 1);
697         memcpy(msgb_put(nmsg, strlen(pin2) + 1), pin2, strlen(pin2) + 1);
698         sim_job(ms, nmsg);
699 }
700
701 /* Attach SIM reader, no SIM must be currently attached */
702 int gsm_subscr_simcard(struct osmocom_ms *ms)
703 {
704         struct gsm_subscriber *subscr = &ms->subscr;
705
706         if (subscr->sim_valid) {
707                 LOGP(DMM, LOGL_ERROR, "Cannot attach card, until current card "
708                         "is detached.\n");
709                 return -EBUSY;
710         }
711
712         /* reset subscriber */
713         gsm_subscr_exit(ms);
714         gsm_subscr_init(ms);
715
716         subscr->sim_type = GSM_SIM_TYPE_READER;
717         sprintf(subscr->sim_name, "sim");
718         subscr->sim_valid = 1;
719         subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
720
721         /* start with first index */
722         subscr->sim_file_index = 0;
723         return subscr_sim_request(ms);
724 }
725
726 /* update plmn not allowed list on SIM */
727 static int subscr_write_plmn_na(struct osmocom_ms *ms)
728 {
729         struct gsm_subscriber *subscr = &ms->subscr;
730         struct msgb *nmsg;
731         struct sim_hdr *nsh;
732         struct gsm_sub_plmn_na *na, *nas[4] = { NULL, NULL, NULL, NULL };
733         int count = 0, i;
734         uint8_t *data;
735         uint8_t lai[5];
736
737         /* skip, if no real valid SIM */
738         if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
739                 return 0;
740
741         /* get tail list from "PLMN not allowed" */
742         llist_for_each_entry(na, &subscr->plmn_na, entry) {
743                 if (count < 4)
744                         nas[count] = na;
745                 else {
746                         nas[0] = nas[1];
747                         nas[1] = nas[2];
748                         nas[2] = nas[3];
749                         nas[3] = na;
750                 }
751                 count++;
752         }
753
754         /* write to SIM */
755         LOGP(DMM, LOGL_INFO, "Updating FPLMN on SIM\n");
756         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
757                 SIM_JOB_UPDATE_BINARY);
758         if (!nmsg)
759                 return -ENOMEM;
760         nsh = (struct sim_hdr *) nmsg->data;
761         data = msgb_put(nmsg, 12);
762         nsh->path[0] = 0x7f20;
763         nsh->path[1] = 0;
764         nsh->file = 0x6f7b;
765         for (i = 0; i < 4; i++) {
766                 if (nas[i]) {
767                         gsm48_encode_lai((struct gsm48_loc_area_id *)lai,
768                         nas[i]->mcc, nas[i]->mnc, 0);
769                         *data++ = lai[0];
770                         *data++ = lai[1];
771                         *data++ = lai[2];
772                 } else {
773                         *data++ = 0xff;
774                         *data++ = 0xff;
775                         *data++ = 0xff;
776                 }
777         }
778         sim_job(ms, nmsg);
779
780         return 0;
781 }
782
783 /* update LOCI on SIM */
784 int gsm_subscr_write_loci(struct osmocom_ms *ms)
785 {
786         struct gsm_subscriber *subscr = &ms->subscr;
787         struct msgb *nmsg;
788         struct sim_hdr *nsh;
789         struct gsm1111_ef_loci *loci;
790
791         /* skip, if no real valid SIM */
792         if (subscr->sim_type != GSM_SIM_TYPE_READER || !subscr->sim_valid)
793                 return 0;
794
795         LOGP(DMM, LOGL_INFO, "Updating LOCI on SIM\n");
796
797         /* write to SIM */
798         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
799                 SIM_JOB_UPDATE_BINARY);
800         if (!nmsg)
801                 return -ENOMEM;
802         nsh = (struct sim_hdr *) nmsg->data;
803         nsh->path[0] = 0x7f20;
804         nsh->path[1] = 0;
805         nsh->file = 0x6f7e;
806         loci = (struct gsm1111_ef_loci *)msgb_put(nmsg, sizeof(*loci));
807
808         /* TMSI */
809         loci->tmsi = htonl(subscr->tmsi);
810
811         /* LAI */
812         gsm48_encode_lai(&loci->lai, subscr->mcc, subscr->mnc, subscr->lac);
813
814         /* TMSI time */
815         loci->tmsi_time = 0xff;
816
817         /* location update status */
818         switch (subscr->ustate) {
819         case GSM_SIM_U1_UPDATED:
820                 loci->lupd_status = 0x00;
821                 break;
822         case GSM_SIM_U3_ROAMING_NA:
823                 loci->lupd_status = 0x03;
824                 break;
825         default:
826                 loci->lupd_status = 0x01;
827         }
828
829         sim_job(ms, nmsg);
830
831         return 0;
832 }
833
834 static void subscr_sim_update_cb(struct osmocom_ms *ms, struct msgb *msg)
835 {
836         struct sim_hdr *sh = (struct sim_hdr *) msg->data;
837         uint8_t *payload = msg->data + sizeof(*sh);
838
839         /* error handling */
840         if (sh->job_type == SIM_JOB_ERROR)
841                 LOGP(DMM, LOGL_NOTICE, "SIM update failed (cause %d)\n",
842                         *payload);
843
844         msgb_free(msg);
845 }
846
847 int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq,
848         uint8_t *rand, uint8_t no_sim)
849 {
850         struct gsm_subscriber *subscr = &ms->subscr;
851         struct msgb *nmsg;
852         struct sim_hdr *nsh;
853
854         /* not a SIM */
855         if ((subscr->sim_type != GSM_SIM_TYPE_READER
856           && subscr->sim_type != GSM_SIM_TYPE_TEST)
857          || !subscr->sim_valid || no_sim) {
858                 struct gsm48_mm_event *nmme;
859
860                 LOGP(DMM, LOGL_INFO, "Sending dummy authentication response\n");
861                 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
862                 if (!nmsg)
863                         return -ENOMEM;
864                 nmme = (struct gsm48_mm_event *) nmsg->data;
865                 nmme->sres[0] = 0x12;
866                 nmme->sres[1] = 0x34;
867                 nmme->sres[2] = 0x56;
868                 nmme->sres[3] = 0x78;
869                 gsm48_mmevent_msg(ms, nmsg);
870
871                 return 0;
872         }
873
874         /* test SIM */
875         if (subscr->sim_type == GSM_SIM_TYPE_TEST) {
876                 struct gsm48_mm_event *nmme;
877                 uint8_t sres[4];
878                 struct gsm_settings *set = &ms->settings;
879
880                 if (set->test_ki_type == GSM_SIM_KEY_COMP128)
881                         comp128(set->test_ki, rand, sres, subscr->key);
882                 else
883                         xor96(set->test_ki, rand, sres, subscr->key);
884                 /* store sequence */
885                 subscr->key_seq = key_seq;
886
887                 LOGP(DMM, LOGL_INFO, "Sending authentication response\n");
888                 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
889                 if (!nmsg)
890                         return -ENOMEM;
891                 nmme = (struct gsm48_mm_event *) nmsg->data;
892                 memcpy(nmme->sres, sres, 4);
893                 gsm48_mmevent_msg(ms, nmsg);
894
895                 return 0;
896         }
897
898         LOGP(DMM, LOGL_INFO, "Generating KEY at SIM\n");
899
900         /* command to SIM */
901         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_key, SIM_JOB_RUN_GSM_ALGO);
902         if (!nmsg)
903                 return -ENOMEM;
904         nsh = (struct sim_hdr *) nmsg->data;
905         nsh->path[0] = 0x7f20;
906         nsh->path[1] = 0;
907
908         /* random */
909         memcpy(msgb_put(nmsg, 16), rand, 16);
910
911         /* store sequence */
912         subscr->key_seq = key_seq;
913
914         sim_job(ms, nmsg);
915
916         return 0;
917 }
918
919 static void subscr_sim_key_cb(struct osmocom_ms *ms, struct msgb *msg)
920 {
921         struct gsm_subscriber *subscr = &ms->subscr;
922         struct sim_hdr *sh = (struct sim_hdr *) msg->data;
923         uint8_t *payload = msg->data + sizeof(*sh);
924         uint16_t payload_len = msg->len - sizeof(*sh);
925         struct msgb *nmsg;
926         struct sim_hdr *nsh;
927         struct gsm48_mm_event *nmme;
928         uint8_t *data;
929
930         /* error handling */
931         if (sh->job_type == SIM_JOB_ERROR) {
932                 LOGP(DMM, LOGL_NOTICE, "key generation on SIM failed "
933                         "(cause %d)\n", *payload);
934
935                 msgb_free(msg);
936
937                 return;
938         }
939
940         if (payload_len < 12) {
941                 LOGP(DMM, LOGL_NOTICE, "response from SIM too short\n");
942                 return;
943         }
944
945         /* store key */
946         memcpy(subscr->key, payload + 4, 8);
947
948         /* write to SIM */
949         LOGP(DMM, LOGL_INFO, "Updating KC on SIM\n");
950         nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
951                 SIM_JOB_UPDATE_BINARY);
952         if (!nmsg)
953                 return;
954         nsh = (struct sim_hdr *) nmsg->data;
955         nsh->path[0] = 0x7f20;
956         nsh->path[1] = 0;
957         nsh->file = 0x6f20;
958         data = msgb_put(nmsg, 9);
959         memcpy(data, subscr->key, 8);
960         data[8] = subscr->key_seq;
961         sim_job(ms, nmsg);
962
963         /* return signed response */
964         nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
965         if (!nmsg)
966                 return;
967         nmme = (struct gsm48_mm_event *) nmsg->data;
968         memcpy(nmme->sres, payload, 4);
969         gsm48_mmevent_msg(ms, nmsg);
970
971         msgb_free(msg);
972 }
973
974 /*
975  * detach
976  */
977
978 /* Detach card */
979 int gsm_subscr_remove(struct osmocom_ms *ms)
980 {
981         struct gsm_subscriber *subscr = &ms->subscr;
982         struct msgb *nmsg;
983
984         if (!subscr->sim_valid) {
985                 LOGP(DMM, LOGL_ERROR, "Cannot remove card, no card present\n");
986                 return -EINVAL;
987         }
988
989         /* remove card */
990         nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
991         if (!nmsg)
992                 return -ENOMEM;
993         gsm48_mmr_downmsg(ms, nmsg);
994
995         return 0;
996 }
997
998 /*
999  * state and lists
1000  */
1001
1002 static const char *subscr_ustate_names[] = {
1003         "U0_NULL",
1004         "U1_UPDATED",
1005         "U2_NOT_UPDATED",
1006         "U3_ROAMING_NA"
1007 };
1008
1009 /* change to new U state */
1010 void new_sim_ustate(struct gsm_subscriber *subscr, int state)
1011 {
1012         LOGP(DMM, LOGL_INFO, "(ms %s) new state %s -> %s\n", subscr->ms->name,
1013                 subscr_ustate_names[subscr->ustate],
1014                 subscr_ustate_names[state]);
1015
1016         subscr->ustate = state;
1017 }
1018
1019 /* del forbidden PLMN */
1020 int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1021         uint16_t mnc)
1022 {
1023         struct gsm_sub_plmn_na *na;
1024
1025         llist_for_each_entry(na, &subscr->plmn_na, entry) {
1026                 if (na->mcc == mcc && na->mnc == mnc) {
1027                         LOGP(DPLMN, LOGL_INFO, "Delete from list of forbidden "
1028                                 "PLMNs (mcc=%s, mnc=%s)\n",
1029                                 gsm_print_mcc(mcc), gsm_print_mnc(mnc));
1030                         llist_del(&na->entry);
1031                         talloc_free(na);
1032                         /* update plmn not allowed list on SIM */
1033                         subscr_write_plmn_na(subscr->ms);
1034                         return 0;
1035                 }
1036         }
1037
1038         return -EINVAL;
1039 }
1040
1041 /* add forbidden PLMN */
1042 int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1043                                         uint16_t mnc, uint8_t cause)
1044 {
1045         struct gsm_sub_plmn_na *na;
1046
1047         /* if already in the list, remove and add to tail */
1048         gsm_subscr_del_forbidden_plmn(subscr, mcc, mnc);
1049
1050         LOGP(DPLMN, LOGL_INFO, "Add to list of forbidden PLMNs "
1051                 "(mcc=%s, mnc=%s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc));
1052         na = talloc_zero(l23_ctx, struct gsm_sub_plmn_na);
1053         if (!na)
1054                 return -ENOMEM;
1055         na->mcc = mcc;
1056         na->mnc = mnc;
1057         na->cause = cause;
1058         llist_add_tail(&na->entry, &subscr->plmn_na);
1059
1060         /* don't add Home PLMN to SIM */
1061         if (subscr->sim_valid && gsm_match_mnc(mcc, mnc, subscr->imsi))
1062                 return -EINVAL;
1063
1064         /* update plmn not allowed list on SIM */
1065         subscr_write_plmn_na(subscr->ms);
1066
1067         return 0;
1068 }
1069
1070 /* search forbidden PLMN */
1071 int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
1072                                         uint16_t mnc)
1073 {
1074         struct gsm_sub_plmn_na *na;
1075
1076         llist_for_each_entry(na, &subscr->plmn_na, entry) {
1077                 if (na->mcc == mcc && na->mnc == mnc)
1078                         return 1;
1079         }
1080
1081         return 0;
1082 }
1083
1084 int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
1085                         void (*print)(void *, const char *, ...), void *priv)
1086 {
1087         struct gsm_subscriber *subscr = &ms->subscr;
1088         struct gsm_sub_plmn_na *temp;
1089
1090         print(priv, "MCC    |MNC    |cause\n");
1091         print(priv, "-------+-------+-------\n");
1092         llist_for_each_entry(temp, &subscr->plmn_na, entry)
1093                 print(priv, "%s    |%s%s    |#%d\n",
1094                         gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
1095                         ((temp->mnc & 0x00f) == 0x00f) ? " ":"", temp->cause);
1096
1097         return 0;
1098 }
1099
1100 /* dump subscriber */
1101 void gsm_subscr_dump(struct gsm_subscriber *subscr,
1102                         void (*print)(void *, const char *, ...), void *priv)
1103 {
1104         int i;
1105         struct gsm_sub_plmn_list *plmn_list;
1106         struct gsm_sub_plmn_na *plmn_na;
1107
1108         print(priv, "Mobile Subscriber of MS '%s':\n", subscr->ms->name);
1109
1110         if (!subscr->sim_valid) {
1111                 print(priv, " No SIM present.\n");
1112                 return;
1113         }
1114
1115         print(priv, " IMSI: %s\n", subscr->imsi);
1116         if (subscr->iccid[0])
1117                 print(priv, " ICCID: %s\n", subscr->iccid);
1118         if (subscr->sim_spn[0])
1119                 print(priv, " Service Provider Name: %s\n", subscr->sim_spn);
1120         if (subscr->msisdn[0])
1121                 print(priv, " MSISDN: %s\n", subscr->msisdn);
1122         print(priv, " Status: %s  IMSI %s", subscr_ustate_names[subscr->ustate],
1123                 (subscr->imsi_attached) ? "attached" : "detached");
1124         if (subscr->tmsi != 0xffffffff)
1125                 print(priv, "  TSMI 0x%08x", subscr->tmsi);
1126         if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
1127                 print(priv, "\n");
1128                 print(priv, "         LAI: MCC %s  MNC %s  LAC 0x%04x  "
1129                         "(%s, %s)\n", gsm_print_mcc(subscr->mcc),
1130                         gsm_print_mnc(subscr->mnc), subscr->lac,
1131                         gsm_get_mcc(subscr->mcc),
1132                         gsm_get_mnc(subscr->mcc, subscr->mnc));
1133         } else
1134                 print(priv, "  LAI: invalid\n");
1135         if (subscr->key_seq != 7) {
1136                 print(priv, " Key: sequence %d ", subscr->key_seq);
1137                 for (i = 0; i < sizeof(subscr->key); i++)
1138                         print(priv, " %02x", subscr->key[i]);
1139                 print(priv, "\n");
1140         }
1141         if (subscr->plmn_valid)
1142                 print(priv, " Registered PLMN: MCC %s  MNC %s  (%s, %s)\n",
1143                         gsm_print_mcc(subscr->plmn_mcc),
1144                         gsm_print_mnc(subscr->plmn_mnc),
1145                         gsm_get_mcc(subscr->plmn_mcc),
1146                         gsm_get_mnc(subscr->plmn_mcc, subscr->plmn_mnc));
1147         print(priv, " Access barred cells: %s\n",
1148                 (subscr->acc_barr) ? "yes" : "no");
1149         print(priv, " Access classes:");
1150         for (i = 0; i < 16; i++)
1151                 if ((subscr->acc_class & (1 << i)))
1152                         print(priv, " C%d", i);
1153         print(priv, "\n");
1154         if (!llist_empty(&subscr->plmn_list)) {
1155                 print(priv, " List of preferred PLMNs:\n");
1156                 print(priv, "        MCC    |MNC\n");
1157                 print(priv, "        -------+-------\n");
1158                 llist_for_each_entry(plmn_list, &subscr->plmn_list, entry)
1159                         print(priv, "        %s    |%s        (%s, %s)\n",
1160                         gsm_print_mcc(plmn_list->mcc),
1161                         gsm_print_mnc(plmn_list->mnc),
1162                         gsm_get_mcc(plmn_list->mcc),
1163                         gsm_get_mnc(plmn_list->mcc, plmn_list->mnc));
1164         }
1165         if (!llist_empty(&subscr->plmn_na)) {
1166                 print(priv, " List of forbidden PLMNs:\n");
1167                 print(priv, "        MCC    |MNC    |cause\n");
1168                 print(priv, "        -------+-------+-------\n");
1169                 llist_for_each_entry(plmn_na, &subscr->plmn_na, entry)
1170                         print(priv, "        %s    |%s%s    |#%d        "
1171                                 "(%s, %s)\n", gsm_print_mcc(plmn_na->mcc),
1172                                 gsm_print_mnc(plmn_na->mnc),
1173                                 ((plmn_na->mnc & 0x00f) == 0x00f) ? " ":"",
1174                                 plmn_na->cause, gsm_get_mcc(plmn_na->mcc),
1175                                 gsm_get_mnc(plmn_na->mcc, plmn_na->mnc));
1176         }
1177 }
1178