changeset 38:f5a26c1d0b93

fc-simtool smsp-dump implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Feb 2021 20:39:15 +0000
parents acf343dace04
children 2467b7acad1f
files libcommon/number_decode.c simtool/Makefile simtool/dispatch.c simtool/smsp_common.c simtool/smsp_dump.c
diffstat 5 files changed, 201 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libcommon/number_decode.c	Fri Feb 12 17:50:42 2021 +0000
+++ b/libcommon/number_decode.c	Fri Feb 12 20:39:15 2021 +0000
@@ -35,3 +35,24 @@
 	*out = '\0';
 	return(0);
 }
+
+decode_address_digits(inbuf, outbuf, ndigits)
+	u_char *inbuf;
+	char *outbuf;
+	unsigned ndigits;
+{
+	u_char *inp = inbuf;
+	char *outp = outbuf;
+	unsigned n = 0, b;
+
+	while (n < ndigits) {
+		b = *inp++;
+		*outp++ = gsm_address_digits[b & 0xF];
+		n++;
+		if (n >= ndigits)
+			break;
+		*outp++ = gsm_address_digits[b >> 4];
+		n++;
+	}
+	*outp = '\0';
+}
--- a/simtool/Makefile	Fri Feb 12 17:50:42 2021 +0000
+++ b/simtool/Makefile	Fri Feb 12 20:39:15 2021 +0000
@@ -4,7 +4,8 @@
 OBJS=	a38.o chv.o curfile.o dispatch.o dumpdir.o grcard1.o grcard2.o hlread.o\
 	main.o pbcommon.o pbdump.o pberase.o pbupd_file.o pbupd_imm.o \
 	pbupd_immhex.o readcmd.o readops.o restorebin.o savebin.o script.o \
-	select.o sysmo.o telsum.o writecmd.o writeops.o
+	select.o smsp_common.o smsp_dump.o sysmo.o telsum.o writecmd.o \
+	writeops.o
 LIBS=	../libcommon/libcommon.a
 INSTBIN=/opt/freecalypso/bin
 
--- a/simtool/dispatch.c	Fri Feb 12 17:50:42 2021 +0000
+++ b/simtool/dispatch.c	Fri Feb 12 20:39:15 2021 +0000
@@ -38,6 +38,7 @@
 extern int cmd_savebin();
 extern int cmd_save_sms_bin();
 extern int cmd_select();
+extern int cmd_smsp_dump();
 extern int cmd_spn();
 extern int cmd_telecom_sum();
 extern int cmd_uicc_dir();
@@ -101,6 +102,7 @@
 	{"save-sms-bin", 1, 1, cmd_save_sms_bin},
 	{"select", 1, 1, cmd_select},
 	{"sim-resp", 0, 0, display_sim_resp_in_hex},
+	{"smsp-dump", 0, 1, cmd_smsp_dump},
 	{"spn", 0, 0, cmd_spn},
 	{"telecom-sum", 0, 0, cmd_telecom_sum},
 	{"uicc-dir", 0, 0, cmd_uicc_dir},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simtool/smsp_common.c	Fri Feb 12 20:39:15 2021 +0000
@@ -0,0 +1,33 @@
+/*
+ * This module implements some common functions for working with EF_SMSP.
+ */
+
+#include <stdio.h>
+#include "curfile.h"
+#include "file_id.h"
+
+select_ef_smsp()
+{
+	int rc;
+
+	rc = select_op(DF_TELECOM);
+	if (rc < 0)
+		return(rc);
+	rc = select_op(EF_SMSP);
+	if (rc < 0)
+		return(rc);
+	rc = parse_ef_select_response();
+	if (rc < 0)
+		return(rc);
+	if (curfile_structure != 0x01) {
+		fprintf(stderr, "error: EF_SMSP is not linear fixed\n");
+		return(-1);
+	}
+	if (curfile_record_len < 28) {
+		fprintf(stderr,
+	"error: EF_SMSP has record length of %u bytes, less than minimum 28\n",
+			curfile_record_len);
+		return(-1);
+	}
+	return(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simtool/smsp_dump.c	Fri Feb 12 20:39:15 2021 +0000
@@ -0,0 +1,143 @@
+/*
+ * This module implements intelligent dumping of EF_SMSP (smsp-dump).
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "simresp.h"
+#include "curfile.h"
+
+static
+check_blank_area(dp, endp)
+	u_char *dp, *endp;
+{
+	while (dp < endp)
+		if (*dp++ != 0xFF)
+			return(-1);
+	return(0);
+}
+
+static void
+dump_da_field(binaddr, outf)
+	u_char *binaddr;
+	FILE *outf;
+{
+	char digits[21];
+
+	fputs("DA=", outf);
+	if (binaddr[0] < 1 || binaddr[0] > 20) {
+malformed:	fputs("malformed ", outf);
+		return;
+	}
+	if ((binaddr[0] & 1) && (binaddr[(binaddr[0] >> 1) + 2] & 0xF0) != 0xF0)
+		goto malformed;
+	if (check_blank_area(binaddr + 2 + ((binaddr[0] + 1) >> 1),
+			     binaddr + 12) < 0)
+		goto malformed;
+	/* all checks passed */
+	decode_address_digits(binaddr + 2, digits, binaddr[0]);
+	fprintf(outf, "%s,0x%02X ", digits, binaddr[1]);
+}
+
+static void
+dump_sca_field(binaddr, outf)
+	u_char *binaddr;
+	FILE *outf;
+{
+	char digits[21];
+	int rc;
+
+	fputs("SC=", outf);
+	if (binaddr[0] < 2 || binaddr[0] > 11) {
+malformed:	fputs("malformed ", outf);
+		return;
+	}
+	rc = decode_phone_number(binaddr + 2, binaddr[0] - 1, digits);
+	if (rc < 0)
+		goto malformed;
+	rc = check_blank_area(binaddr + 1 + binaddr[0], binaddr + 12);
+	if (rc < 0)
+		goto malformed;
+	/* all checks passed */
+	fprintf(outf, "%s,0x%02X ", digits, binaddr[1]);
+}
+
+static void
+dump_record(recno, outf)
+	unsigned recno;
+	FILE *outf;
+{
+	int rc;
+	unsigned textlen;
+	u_char *fixp;
+
+	fprintf(outf, "#%u: ", recno);
+	if (sim_resp_data_len > 28) {
+		rc = validate_alpha_field(sim_resp_data,
+					  sim_resp_data_len - 28,
+					  &textlen);
+		if (rc < 0) {
+malformed:		fprintf(outf, "malformed record\n");
+			return;
+		}
+	} else
+		textlen = 0;
+	fixp = sim_resp_data + sim_resp_data_len - 28;
+	if ((fixp[0] & 0xE0) != 0xE0)
+		goto malformed;
+	if ((fixp[0] & 0x01) && check_blank_area(fixp + 1, fixp + 13) < 0)
+		goto malformed;
+	if ((fixp[0] & 0x02) && check_blank_area(fixp + 13, fixp + 25) < 0)
+		goto malformed;
+	if ((fixp[0] & 0x04) && fixp[25] != 0xFF)
+		goto malformed;
+	if ((fixp[0] & 0x08) && fixp[26] != 0xFF)
+		goto malformed;
+	if ((fixp[0] & 0x10) && fixp[27] != 0xFF)
+		goto malformed;
+	/* basic checks passed, emit present fields */
+	if (!(fixp[0] & 0x01))
+		dump_da_field(fixp + 1, outf);
+	if (!(fixp[0] & 0x02))
+		dump_sca_field(fixp + 13, outf);
+	if (!(fixp[0] & 0x04))
+		fprintf(outf, "PID=0x%02X ", fixp[25]);
+	if (!(fixp[0] & 0x08))
+		fprintf(outf, "DCS=0x%02X ", fixp[26]);
+	if (!(fixp[0] & 0x10))
+		fprintf(outf, "VP=%u ", fixp[27]);
+	print_alpha_field(sim_resp_data, textlen, outf);
+	putc('\n', outf);
+}
+
+cmd_smsp_dump(argc, argv)
+	char **argv;
+{
+	int rc;
+	FILE *outf;
+	unsigned recno;
+
+	rc = select_ef_smsp();
+	if (rc < 0)
+		return(rc);
+	if (argv[1]) {
+		outf = fopen(argv[1], "w");
+		if (!outf) {
+			perror(argv[1]);
+			return(-1);
+		}
+	} else
+		outf = stdout;
+	for (recno = 1; recno <= curfile_record_count; recno++) {
+		rc = readrec_op(recno, 0x04, curfile_record_len);
+		if (rc < 0) {
+			if (argv[1])
+				fclose(outf);
+			return(rc);
+		}
+		dump_record(recno, outf);
+	}
+	if (argv[1])
+		fclose(outf);
+	return(0);
+}