blob: 2bf83fac029fe32d9e6affcd58e6ee006d3625c6 [file] [log] [blame]
Harald Weltead418632012-09-10 10:49:59 +02001/* libosmosim test application - currently simply dumps a USIM */
2/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
Harald Welted54c2ee2012-01-17 18:25:50 +010021#include <stdio.h>
22#include <stdlib.h>
23#include <errno.h>
24#include <string.h>
Eric Wild94cd4ac2019-10-31 19:18:45 +010025#include <getopt.h>
Alexander Huemeraab4a242015-11-06 20:55:24 +010026#include <arpa/inet.h>
Harald Welted54c2ee2012-01-17 18:25:50 +010027
28#include <osmocom/core/msgb.h>
29#include <osmocom/core/talloc.h>
30#include <osmocom/sim/sim.h>
31#include <osmocom/gsm/tlv.h>
32
33
Harald Weltead418632012-09-10 10:49:59 +020034/* FIXME: this needs to be moved to card_fs_uicc.c */
Harald Welted54c2ee2012-01-17 18:25:50 +010035
Harald Welte053bebc2020-02-15 18:58:16 +010036static uint8_t g_class = 0x00; /* UICC/USIM */
37
Harald Welted54c2ee2012-01-17 18:25:50 +010038/* 11.1.1 */
39static struct msgb *_select_file(struct osim_chan_hdl *st, uint8_t p1, uint8_t p2,
40 const uint8_t *data, uint8_t data_len)
41{
Vadim Yanitskiy1cd99912017-05-15 21:37:16 +030042 struct msgb *msg;
Harald Weltef12d40f2017-02-08 15:46:53 +000043 uint8_t *dst;
Harald Welted54c2ee2012-01-17 18:25:50 +010044
Harald Welte053bebc2020-02-15 18:58:16 +010045 msg = osim_new_apdumsg(g_class, 0xA4, p1, p2, data_len, 256);
Harald Welted54c2ee2012-01-17 18:25:50 +010046 dst = msgb_put(msg, data_len);
47 memcpy(dst, data, data_len);
48
49 osim_transceive_apdu(st, msg);
50
51 return msg;
52}
53
54/* 11.1.1 */
55static struct msgb *select_adf(struct osim_chan_hdl *st, const uint8_t *adf, uint8_t adf_len)
56{
Harald Welted54c2ee2012-01-17 18:25:50 +010057 return _select_file(st, 0x04, 0x04, adf,adf_len);
58}
59
60/* 11.1.1 */
61static struct msgb *select_file(struct osim_chan_hdl *st, uint16_t fid)
62{
63 uint16_t cfid = htons(fid);
Harald Welte053bebc2020-02-15 18:58:16 +010064 uint8_t p2 = 0x04;
Harald Welted54c2ee2012-01-17 18:25:50 +010065
Harald Welte053bebc2020-02-15 18:58:16 +010066 /* Classic SIM cards don't support 0x04 (Return FCP) */
67 if (g_class == 0xA0)
68 p2 = 0x00;
69
70 return _select_file(st, 0x00, p2, (uint8_t *)&cfid, 2);
Harald Welted54c2ee2012-01-17 18:25:50 +010071}
72
73/* 11.1.9 */
Harald Weltef12d40f2017-02-08 15:46:53 +000074static int verify_pin(struct osim_chan_hdl *st, uint8_t pin_nr, char *pin)
Harald Welted54c2ee2012-01-17 18:25:50 +010075{
76 struct msgb *msg;
77 char *pindst;
Harald Welted54c2ee2012-01-17 18:25:50 +010078
79 if (strlen(pin) > 8)
80 return -EINVAL;
81
Harald Welte053bebc2020-02-15 18:58:16 +010082 msg = osim_new_apdumsg(g_class, 0x20, 0x00, pin_nr, 8, 0);
Harald Weltef12d40f2017-02-08 15:46:53 +000083 pindst = (char *) msgb_put(msg, 8);
Harald Welted54c2ee2012-01-17 18:25:50 +010084 memset(pindst, 0xFF, 8);
Neels Hofmeyr95fdbc12018-07-26 17:14:40 +020085 /* Do not copy the terminating \0 */
86 memcpy(pindst, pin, strlen(pin));
Harald Welted54c2ee2012-01-17 18:25:50 +010087
88 return osim_transceive_apdu(st, msg);
89}
90
91/* 11.1.5 */
92static struct msgb *read_record_nr(struct osim_chan_hdl *st, uint8_t rec_nr, uint16_t rec_size)
93{
94 struct msgb *msg;
95
Harald Welte053bebc2020-02-15 18:58:16 +010096 msg = osim_new_apdumsg(g_class, 0xB2, rec_nr, 0x04, 0, rec_size);
Harald Welted54c2ee2012-01-17 18:25:50 +010097
98 osim_transceive_apdu(st, msg);
99
100 return msg;
101}
102
Harald Welted54c2ee2012-01-17 18:25:50 +0100103/* 11.1.3 */
104static struct msgb *read_binary(struct osim_chan_hdl *st, uint16_t offset, uint16_t len)
105{
106 struct msgb *msg;
107
108 if (offset > 0x7fff || len > 256)
109 return NULL;
110
Harald Welte053bebc2020-02-15 18:58:16 +0100111 msg = osim_new_apdumsg(g_class, 0xB0, offset >> 8, offset & 0xff, 0, len & 0xff);
Harald Welted54c2ee2012-01-17 18:25:50 +0100112
113 osim_transceive_apdu(st, msg);
114
115 return msg;
116}
117
Harald Welted54c2ee2012-01-17 18:25:50 +0100118static int dump_fcp_template(struct tlv_parsed *tp)
119{
120 int i;
121
122 for (i = 0; i < ARRAY_SIZE(tp->lv); i++) {
123 if (TLVP_PRESENT(tp, i))
124 printf("Tag 0x%02x (%s): %s\n", i,
125 get_value_string(ts102221_fcp_vals, i),
126 osmo_hexdump(TLVP_VAL(tp, i), TLVP_LEN(tp, i)));
127 }
128
129 return 0;
130}
131
132static int dump_fcp_template_msg(struct msgb *msg)
133{
134 struct tlv_parsed tp;
135 int rc;
136
Harald Weltea5c92552012-09-10 21:05:42 +0200137 rc = tlv_parse(&tp, &ts102221_fcp_tlv_def, msgb_apdu_de(msg)+2, msgb_apdu_le(msg)-2, 0, 0);
Harald Welted54c2ee2012-01-17 18:25:50 +0100138 if (rc < 0)
139 return rc;
140
141 return dump_fcp_template(&tp);
142}
143
144struct osim_fcp_fd_decoded {
145 enum osim_file_type type;
146 enum osim_ef_type ef_type;
147 uint16_t rec_len;
148 uint8_t num_rec;
149};
150
151static const enum osim_file_type iso2ftype[8] = {
152 [0] = TYPE_EF,
153 [1] = TYPE_EF_INT,
154 [7] = TYPE_DF,
155};
156
157static const enum osim_ef_type iso2eftype[8] = {
158 [1] = EF_TYPE_TRANSP,
159 [2] = EF_TYPE_RECORD_FIXED,
160 [6] = EF_TYPE_RECORD_CYCLIC,
161};
162
163static int osim_fcp_fd_decode(struct osim_fcp_fd_decoded *ofd, const uint8_t *fcp, int fcp_len)
164{
165 memset(ofd, 0, sizeof(*ofd));
166
167 if (fcp_len != 2 && fcp_len != 5)
168 return -EINVAL;
169
170 ofd->type = iso2ftype[(fcp[0] >> 3) & 7];
171 if (ofd->type != TYPE_DF)
172 ofd->ef_type = iso2eftype[fcp[0] & 7];
173
174 if (fcp[1] != 0x21)
175 return -EINVAL;
176
177 if (fcp_len >= 5) {
178 ofd->rec_len = ntohs(*(uint16_t *)(fcp+2));
179 ofd->num_rec = fcp[4];
180 }
181
182 return 0;
183}
184
Harald Welte053bebc2020-02-15 18:58:16 +0100185/* TS 51.011 Section 9.3 Type of File */
186static const enum osim_file_type sim2ftype[8] = {
187 [1] = TYPE_MF,
188 [2] = TYPE_DF,
189 [4] = TYPE_EF,
190};
191
192/* TS 51.011 Section 9.3 Structure of File */
193static const enum osim_ef_type sim2eftype[8] = {
194 [0] = EF_TYPE_TRANSP,
195 [1] = EF_TYPE_RECORD_FIXED,
196 [3] = EF_TYPE_RECORD_CYCLIC,
197};
198
199/* TS 51.011 Section 9.2.1 */
200static int osim_fcp_fd_decode_sim(struct osim_fcp_fd_decoded *ofd, const uint8_t *fcp, int fcp_len)
201{
202 memset(ofd, 0, sizeof(*ofd));
203
204 if (fcp_len < 14)
205 return -EINVAL;
206
207 ofd->type = sim2ftype[fcp[6] & 7];
208 switch (ofd->type) {
209 case TYPE_EF:
210 ofd->ef_type = sim2eftype[fcp[13] & 7];
211 if (fcp_len < 13 + fcp[12])
212 return -EINVAL;
213 switch (ofd->ef_type) {
214 case EF_TYPE_RECORD_FIXED:
215 case EF_TYPE_RECORD_CYCLIC:
216 if (fcp_len < 15)
217 return -EINVAL;
218 ofd->rec_len = fcp[14];
219 ofd->num_rec = ntohs(*(uint16_t *)(fcp+2)) / ofd->rec_len;
220 break;
221 default:
222 break;
223 }
224 break;
225 case TYPE_MF:
226 case TYPE_DF:
227 if (fcp_len < 22)
228 return -EINVAL;
229 break;
230 default:
231 break;
232 }
233
234 return 0;
235}
236
237extern struct osim_card_profile *osim_cprof_sim(void *ctx);
Harald Welted54c2ee2012-01-17 18:25:50 +0100238extern struct osim_card_profile *osim_cprof_usim(void *ctx);
Harald Welte053bebc2020-02-15 18:58:16 +0100239extern struct osim_card_profile *osim_cprof_isim(void *ctx);
Harald Welted54c2ee2012-01-17 18:25:50 +0100240
241static struct msgb *try_select_adf_usim(struct osim_chan_hdl *st)
242{
243 struct tlv_parsed tp;
244 struct osim_fcp_fd_decoded ofd;
245 struct msgb *msg, *msg2;
246 uint8_t *cur;
247 int rc, i;
248
249 msg = select_file(st, 0x2f00);
Harald Welte053bebc2020-02-15 18:58:16 +0100250 if (!msg)
Harald Welted54c2ee2012-01-17 18:25:50 +0100251 return NULL;
Harald Welte053bebc2020-02-15 18:58:16 +0100252 /* return status word in case of error */
253 if (msgb_apdu_sw(msg) != 0x9000)
254 return msg;
255
256 rc = tlv_parse(&tp, &ts102221_fcp_tlv_def, msgb_apdu_de(msg)+2, msgb_apdu_le(msg)-2, 0, 0);
257 if (rc < 0) {
258 msgb_free(msg);
259 return NULL;
260 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100261
262 dump_fcp_template(&tp);
263
264 if (!TLVP_PRESENT(&tp, UICC_FCP_T_FILE_DESC) ||
265 TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC) < 5) {
266 msgb_free(msg);
267 return NULL;
268 }
269
270 rc = osim_fcp_fd_decode(&ofd, TLVP_VAL(&tp, UICC_FCP_T_FILE_DESC),
271 TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC));
272 if (rc < 0) {
273 msgb_free(msg);
274 return NULL;
275 }
276
277 if (ofd.type != TYPE_EF || ofd.ef_type != EF_TYPE_RECORD_FIXED) {
278 msgb_free(msg);
279 return NULL;
280 }
281
282 msgb_free(msg);
283
284 printf("ofd rec_len = %u, num_rec = %u\n", ofd.rec_len, ofd.num_rec);
285
286 for (i = 0; i < ofd.num_rec; i++) {
287 msg = read_record_nr(st, i+1, ofd.rec_len);
288 if (!msg)
289 return NULL;
290
291 cur = msgb_apdu_de(msg);
292 if (msgb_apdu_le(msg) < 5) {
293 msgb_free(msg);
294 return NULL;
295 }
296
297 if (cur[0] != 0x61 || cur[1] < 0x03 || cur[1] > 0x7f ||
298 cur[2] != 0x4F || cur[3] < 0x01 || cur[3] > 0x10) {
299 msgb_free(msg);
300 return NULL;
301 }
302
303 /* FIXME: actually check if it is an AID that we support, or
304 * iterate until we find one that we support */
305
306 msg2 = select_adf(st, cur+4, cur[3]);
307
308 /* attach the USIM profile, FIXME: do this based on AID match */
309 st->card->prof = osim_cprof_usim(st->card);
Harald Welte5ffb5032016-03-11 09:40:56 +0700310 st->cwd = osim_file_desc_find_name(st->card->prof->mf, "ADF.USIM");
Harald Welted54c2ee2012-01-17 18:25:50 +0100311
312 msgb_free(msg);
313
314 return msg2;
315 }
316
317 return NULL;
318}
319
320static int dump_file(struct osim_chan_hdl *chan, uint16_t fid)
321{
322 struct tlv_parsed tp;
323 struct osim_fcp_fd_decoded ffdd;
Harald Weltea0ba4d92012-09-10 10:43:15 +0200324 struct msgb *msg, *rmsg;
325 int rc, i, offset;
Harald Welted54c2ee2012-01-17 18:25:50 +0100326
327 msg = select_file(chan, fid);
Harald Weltea0ba4d92012-09-10 10:43:15 +0200328 if (!msg) {
Harald Welte835ed962020-03-19 18:00:04 +0100329 fprintf(stderr, "Unable to select file\n");
Harald Welted54c2ee2012-01-17 18:25:50 +0100330 return -EIO;
Harald Weltea0ba4d92012-09-10 10:43:15 +0200331 }
Harald Welte76749602012-09-19 20:55:54 +0200332 printf("SW: %s\n", osim_print_sw(chan->card, msgb_apdu_sw(msg)));
Harald Weltea0ba4d92012-09-10 10:43:15 +0200333 if (msgb_apdu_sw(msg) != 0x9000) {
Harald Welte835ed962020-03-19 18:00:04 +0100334 fprintf(stderr, "status 0x%04x selecting file\n", msgb_apdu_sw(msg));
Harald Welted54c2ee2012-01-17 18:25:50 +0100335 goto out;
Harald Weltea0ba4d92012-09-10 10:43:15 +0200336 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100337
Harald Welte053bebc2020-02-15 18:58:16 +0100338 if (g_class != 0xA0) {
339 rc = tlv_parse(&tp, &ts102221_fcp_tlv_def, msgb_apdu_de(msg)+2, msgb_apdu_le(msg)-2, 0, 0);
340 if (rc < 0) {
Harald Welte835ed962020-03-19 18:00:04 +0100341 fprintf(stderr, "Unable to parse FCP: %s\n", msgb_hexdump(msg));
Harald Welte053bebc2020-02-15 18:58:16 +0100342 goto out;
343 }
344
345 if (!TLVP_PRESENT(&tp, UICC_FCP_T_FILE_DESC) ||
346 TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC) < 2) {
Harald Welte835ed962020-03-19 18:00:04 +0100347 fprintf(stderr, "No file descriptor present ?!?\n");
Harald Welte053bebc2020-02-15 18:58:16 +0100348 goto out;
349 }
350
351 rc = osim_fcp_fd_decode(&ffdd, TLVP_VAL(&tp, UICC_FCP_T_FILE_DESC),
352 TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC));
353 } else {
354 rc = osim_fcp_fd_decode_sim(&ffdd, msgb_apdu_de(msg), msgb_apdu_le(msg));
Harald Weltea0ba4d92012-09-10 10:43:15 +0200355 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100356
Harald Weltea0ba4d92012-09-10 10:43:15 +0200357 if (rc < 0) {
Harald Welte835ed962020-03-19 18:00:04 +0100358 fprintf(stderr, "Unable to decode File Descriptor\n");
Harald Welted54c2ee2012-01-17 18:25:50 +0100359 goto out;
Harald Weltea0ba4d92012-09-10 10:43:15 +0200360 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100361
Harald Weltea0ba4d92012-09-10 10:43:15 +0200362 if (ffdd.type != TYPE_EF) {
Harald Welte835ed962020-03-19 18:00:04 +0100363 fprintf(stderr, "File Type != EF\n");
Harald Welted54c2ee2012-01-17 18:25:50 +0100364 goto out;
Harald Weltea0ba4d92012-09-10 10:43:15 +0200365 }
366
367 printf("EF type: %u\n", ffdd.ef_type);
Harald Welted54c2ee2012-01-17 18:25:50 +0100368
369 switch (ffdd.ef_type) {
370 case EF_TYPE_RECORD_FIXED:
371 for (i = 0; i < ffdd.num_rec; i++) {
Harald Weltea0ba4d92012-09-10 10:43:15 +0200372 rmsg = read_record_nr(chan, i+1, ffdd.rec_len);
Harald Welte95336312016-11-26 09:54:40 +0100373 if (!rmsg)
Harald Weltea0ba4d92012-09-10 10:43:15 +0200374 return -EIO;
Harald Welte76749602012-09-19 20:55:54 +0200375 printf("SW: %s\n", osim_print_sw(chan->card, msgb_apdu_sw(msg)));
Harald Welted54c2ee2012-01-17 18:25:50 +0100376 printf("Rec %03u: %s\n", i+1,
377 osmo_hexdump(msgb_apdu_de(rmsg), msgb_apdu_le(rmsg)));
378 }
379 break;
380 case EF_TYPE_TRANSP:
Philipp Maierfde9fdc2020-02-26 12:00:23 +0100381 if (g_class != 0xA0) {
382 if (!TLVP_PRESENT(&tp, UICC_FCP_T_FILE_SIZE))
383 goto out;
384 i = ntohs(*(uint16_t *)TLVP_VAL(&tp, UICC_FCP_T_FILE_SIZE));
385 printf("File size: %d bytes\n", i);
386 } else {
Harald Welte835ed962020-03-19 18:00:04 +0100387 fprintf(stderr, "Can not determine file size, invalid EF-type!\n");
Harald Weltea0ba4d92012-09-10 10:43:15 +0200388 goto out;
Philipp Maierfde9fdc2020-02-26 12:00:23 +0100389 }
Harald Weltea0ba4d92012-09-10 10:43:15 +0200390 for (offset = 0; offset < i-1; ) {
391 uint16_t remain_len = i - offset;
392 uint16_t read_len = OSMO_MIN(remain_len, 256);
393 rmsg = read_binary(chan, offset, read_len);
Harald Welted6ec9842014-10-27 20:43:06 +0100394 if (!rmsg)
Harald Weltea0ba4d92012-09-10 10:43:15 +0200395 return -EIO;
396 offset += read_len;
397 printf("Content: %s\n",
398 osmo_hexdump(msgb_apdu_de(rmsg), msgb_apdu_le(rmsg)));
399 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100400 break;
401 default:
402 goto out;
403 }
404
405out:
406 msgb_free(msg);
407 return -EINVAL;
408}
409
Eric Wild94cd4ac2019-10-31 19:18:45 +0100410static void print_help(void)
411{
412 printf( "osmo-sim-test Usage:\n"
413 " -h --help This message\n"
414 " -n --reader-num NR Open reader number NR\n"
415 );
416}
417
418static int readernum = 0;
419
420static void handle_options(int argc, char **argv)
421{
422 while (1) {
423 int option_index = 0, c;
424 const struct option long_options[] = {
425 { "help", 0, 0, 'h' },
426 { "reader-num", 1, 0, 'n' },
427 {0,0,0,0}
428 };
429
430 c = getopt_long(argc, argv, "hn:",
431 long_options, &option_index);
432 if (c == -1)
433 break;
434
435 switch (c) {
436 case 'h':
437 print_help();
438 exit(0);
439 break;
440 case 'n':
441 readernum = atoi(optarg);
442 break;
443 default:
444 exit(2);
445 break;
446 }
447 }
448
449 if (argc > optind) {
450 fprintf(stderr, "Unsupported positional arguments on command line\n");
451 exit(2);
452 }
453}
454
Harald Welte3a1a3bb2020-02-15 18:56:18 +0100455
456static void iterate_fs(struct osim_chan_hdl *chan)
457{
458 const struct osim_file_desc *prev_cwd;
459 struct osim_file_desc *ofd;
460
461 /* iterate over all files in current working directory */
462 llist_for_each_entry(ofd, &chan->cwd->child_list, list) {
463 struct msgb *m;
464 printf("\n\n================ %s (%s) ==================\n",
465 ofd->short_name, ofd->long_name);
466
467 m = select_file(chan, ofd->fid);
468 if (msgb_apdu_sw(m) != 0x9000) {
469 msgb_free(m);
470 continue;
471 }
472 dump_fcp_template_msg(m);
473 msgb_free(m);
474
475 /* If this is a DF, recurse into it */
476 switch (ofd->type) {
477 case TYPE_DF:
478 /* the select above has just changed into this directory */
479 prev_cwd = chan->cwd;
480 chan->cwd = ofd;
481 iterate_fs(chan);
482 /* "pop" the directory from the stack */
483 chan->cwd = prev_cwd;
484 break;
485 default:
486 dump_file(chan, ofd->fid);
487 break;
488 }
489 }
490}
491
492
Harald Welted54c2ee2012-01-17 18:25:50 +0100493int main(int argc, char **argv)
494{
495 struct osim_reader_hdl *reader;
496 struct osim_card_hdl *card;
497 struct osim_chan_hdl *chan;
498 struct msgb *msg;
Harald Welted54c2ee2012-01-17 18:25:50 +0100499
Eric Wild94cd4ac2019-10-31 19:18:45 +0100500 handle_options(argc, argv);
501
502 reader = osim_reader_open(OSIM_READER_DRV_PCSC, readernum, "", NULL);
Harald Welted54c2ee2012-01-17 18:25:50 +0100503 if (!reader)
504 exit(1);
Harald Welte55790aa2014-10-26 18:46:50 +0100505 card = osim_card_open(reader, OSIM_PROTO_T0);
Harald Welted54c2ee2012-01-17 18:25:50 +0100506 if (!card)
507 exit(2);
508 chan = llist_entry(card->channels.next, struct osim_chan_hdl, list);
509 if (!chan)
510 exit(3);
511
512 msg = try_select_adf_usim(chan);
Harald Welte053bebc2020-02-15 18:58:16 +0100513 if (!msg) {
Harald Welted54c2ee2012-01-17 18:25:50 +0100514 exit(4);
Harald Welte053bebc2020-02-15 18:58:16 +0100515 } else if (msgb_apdu_sw(msg) == 0x6e00) {
516 /* CLA not supported: must be classic SIM, not USIM */
517 g_class = 0xA0;
518 chan->card->prof = osim_cprof_sim(chan->card);
519 chan->cwd = chan->card->prof->mf;
520 msgb_free(msg);
521 } else if (msgb_apdu_sw(msg) == 0x9000) {
522 /* normal file */
523 dump_fcp_template_msg(msg);
524 msgb_free(msg);
525 }
Harald Welted54c2ee2012-01-17 18:25:50 +0100526
527 msg = select_file(chan, 0x6fc5);
528 dump_fcp_template_msg(msg);
Harald Welte76749602012-09-19 20:55:54 +0200529 printf("SW: %s\n", osim_print_sw(chan->card, msgb_apdu_sw(msg)));
Harald Welted54c2ee2012-01-17 18:25:50 +0100530 msgb_free(msg);
531
532 verify_pin(chan, 1, "1653");
533
534 msg = select_file(chan, 0x6f06);
535 dump_fcp_template_msg(msg);
536 msgb_free(msg);
537
Harald Welte3a1a3bb2020-02-15 18:56:18 +0100538 iterate_fs(chan);
Harald Welted54c2ee2012-01-17 18:25:50 +0100539
540 exit(0);
541}