FreeCalypso > hg > gsm-net-reveng
changeset 107:c6ffb176eaed
trau-decode: new program trau-parse-n
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 21 Dec 2025 20:05:22 +0000 |
| parents | 028307356ba9 |
| children | f2009a354444 |
| files | .hgignore trau-decode/Makefile trau-decode/parse-new16.c |
| diffstat | 3 files changed, 323 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Fri Nov 21 06:37:46 2025 +0000 +++ b/.hgignore Sun Dec 21 20:05:22 2025 +0000 @@ -26,6 +26,7 @@ ^trau-decode/trau-hr-dump-hex$ ^trau-decode/trau-parse$ ^trau-decode/trau-parse-hex$ +^trau-decode/trau-parse-n$ ^trau-decode/trau-sync8$ ^trau-files/.*\.dump$
--- a/trau-decode/Makefile Fri Nov 21 06:37:46 2025 +0000 +++ b/trau-decode/Makefile Sun Dec 21 20:05:22 2025 +0000 @@ -1,7 +1,8 @@ CC= gcc CFLAGS= -O2 PROGS= dump-1bit tfo-parse-fr16 trau-amr8-dump trau-amr8-dump-hex trau-extr \ - trau-hr-dump trau-hr-dump-hex trau-parse trau-parse-hex trau-sync8 + trau-hr-dump trau-hr-dump-hex trau-parse trau-parse-hex trau-parse-n \ + trau-sync8 FR_OBJS=parse-fr.o parse-fr-common.o parse-efr.o HR_OBJS=gsmhr_unpack.o hr-guts.o @@ -37,6 +38,9 @@ trau-parse-hex: crc8gen.o parse-hex16.o ${TRAU16_OBJS} ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 -lgsmefr +trau-parse-n: crc8gen.o parse-new16.o ${TRAU16_OBJS} + ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 -lgsmefr + trau-sync8: trau-sync8.c ${CC} ${CFLAGS} -o $@ $@.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/parse-new16.c Sun Dec 21 20:05:22 2025 +0000 @@ -0,0 +1,317 @@ +/* + * This program reads a 64 kbit/s timeslot recording file, examines one + * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU + * frames, and dumps whatever it finds. The present version is a new one, + * put together for the purpose of reverse-engineering Abis output from + * Nokia BTS, which exhibits more complex behaviour than what our original + * trau-parse program can analyze properly. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +static uint8_t *filebuf; +static unsigned total_size; + +static enum { + NOT_D144, + D144_SYNC, + D144_EDATA, +} d144_state; + +static void +read_ts_file(filename, subslot_arg) + char *filename, *subslot_arg; +{ + FILE *inf; + struct stat st; + int subslot, right_shift; + unsigned n; + uint8_t *dp; + int b; + + inf = fopen(filename, "r"); + if (!inf) { + perror(filename); + exit(1); + } + fstat(fileno(inf), &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", filename); + exit(1); + } + total_size = st.st_size; + if (total_size < 160) { + fprintf(stderr, "error: %s is too short\n", filename); + exit(1); + } + filebuf = malloc(total_size); + if (!filebuf) { + perror("malloc of file size"); + exit(1); + } + subslot = atoi(subslot_arg); + if (subslot < 0 || subslot > 3) { + fprintf(stderr, "error: invalid subslot argument\n"); + exit(1); + } + right_shift = (3 - subslot) * 2; + dp = filebuf; + for (n = 0; n < total_size; n++) { + b = getc(inf); + if (b < 0) { + fprintf(stderr, + "error: getc() returned EOF contrary to st_size\n"); + exit(1); + } + *dp++ = (b >> right_shift) & 3; + } + fclose(inf); +} + +static int +check_sync(pos) + unsigned pos; +{ + uint8_t *cand = filebuf + pos; + unsigned n; + + for (n = 0; n < 8; n++) { + if (cand[n]) + return 0; + } + if (!(cand[8] & 2)) + return 0; + if (cand[8] == 3 && cand[9] == 3 && cand[10] == 3 && + (d144_state == D144_SYNC || d144_state == D144_EDATA)) + return 1; + for (n = 2; n < 20; n++) { + if (!(cand[n * 8] & 2)) + return 0; + } + return 1; +} + +static void +unpack_dibits(in_frame_2bit, frame_bits) + uint8_t *in_frame_2bit, *frame_bits; +{ + int i, inb; + uint8_t *op; + + op = frame_bits; + for (i = 0; i < 160; i++) { + inb = in_frame_2bit[i]; + if (inb & 2) + *op++ = 1; + else + *op++ = 0; + if (inb & 1) + *op++ = 1; + else + *op++ = 0; + } +} + +static unsigned +bits_to_num(bits, nbits) + uint8_t *bits; + unsigned nbits; +{ + unsigned accum; + unsigned n; + + accum = 0; + for (n = 0; n < nbits; n++) { + accum <<= 1; + if (*bits) + accum |= 1; + bits++; + } + return accum; +} + +static void +dump_raw_nibbles(dibits, num_dibits) + uint8_t *dibits; + unsigned num_dibits; +{ + uint8_t *sp = dibits; + unsigned remain = num_dibits; + + if (remain >= 2) { + while (remain >= 2) { + printf("%x", (sp[0] << 2) | sp[1]); + sp += 2; + remain -= 2; + } + putchar('\n'); + } + if (remain) + printf("dribble %u%u\n", (*sp & 2) >> 1, (*sp & 1) >> 0); +} + +static int +process_frame(pos) + unsigned pos; +{ + uint8_t *frame_2b = filebuf + pos; + uint8_t frame_bits[320]; + unsigned c1_5, c6_11; + + printf("Frame at 0x%x:\n", pos); + dump_raw_nibbles(frame_2b, 160); + unpack_dibits(frame_2b, frame_bits); + printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], + frame_bits[19], frame_bits[20], frame_bits[21]); + c1_5 = bits_to_num(frame_bits + 17, 5); + switch (c1_5) { + case 0x02: + fputs(" (FR UL)", stdout); + break; + case 0x1C: + fputs(" (FR DL)", stdout); + break; + case 0x1A: + fputs(" (EFR)", stdout); + break; + case 0x10: + fputs(" (idle UL)", stdout); + break; + case 0x0E: + fputs(" (idle DL)", stdout); + break; + case 0x08: + fputs(" (data UL)", stdout); + break; + case 0x16: + fputs(" (data DL)", stdout); + break; + case 0x09: + fputs(" (HR data UL)", stdout); + break; + case 0x17: + fputs(" (HR data DL)", stdout); + break; + case 0x14: + fputs(" (D144 sync)", stdout); + break; + case 0x1F: + fputs(" (E-TRAU)", stdout); + break; + case 0x06: + fputs(" (AMR)", stdout); + break; + } + putchar('\n'); + if (c1_5 == 0x14) + d144_state = D144_SYNC; + else if (c1_5 == 0x1F && + (d144_state == D144_SYNC || d144_state == D144_EDATA)) + d144_state = D144_EDATA; + else + d144_state = NOT_D144; + switch (c1_5) { + case 0x02: + case 0x1C: + case 0x1A: + case 0x10: + case 0x0E: + c6_11 = bits_to_num(frame_bits + 22, 6); + printf(" C6-C11: %u\n", c6_11); + printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], + frame_bits[29], frame_bits[30], frame_bits[31]); + print_fr_efr_frame(frame_bits, c1_5); + printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", + frame_bits[310], frame_bits[311], frame_bits[312], + frame_bits[313], frame_bits[314], frame_bits[315]); + printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], + frame_bits[317], frame_bits[318], frame_bits[319]); + return 1; + case 0x08: + case 0x09: + case 0x16: + case 0x17: + case 0x14: + print_data_frame(frame_bits); + return 0; + case 0x1F: + print_edata_frame(frame_bits); + return 0; + case 0x06: + print_amr_frame(frame_bits); + return 1; + default: + printf(" C6-C15: %u%u%u%u%u%u%u%u%u%u\n", frame_bits[22], + frame_bits[23], frame_bits[24], frame_bits[25], + frame_bits[26], frame_bits[27], frame_bits[28], + frame_bits[29], frame_bits[30], frame_bits[31]); + printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", + frame_bits[310], frame_bits[311], frame_bits[312], + frame_bits[313], frame_bits[314], frame_bits[315]); + printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], + frame_bits[317], frame_bits[318], frame_bits[319]); + return 0; + } +} + +static void +process_filebuf() +{ + unsigned p, nf_pos = 0, nf_accum = 0; + int match, have_t_bits; + + d144_state = NOT_D144; + for (p = 0; p < total_size; ) { + if ((total_size - p) >= 160) + match = check_sync(p); + else + match = 0; + if (match) { + if (nf_accum) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + } + have_t_bits = process_frame(p); + if (have_t_bits && !filebuf[p+158] && !filebuf[p+159]) { + puts("advance of 250 us"); + p += 158; + } else + p += 160; + nf_pos = p; + nf_accum = 0; + } else { + p++; + nf_accum++; + if (nf_accum >= 160) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + nf_pos = p; + nf_accum = 0; + } + d144_state = NOT_D144; + } + } + if (nf_accum) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + } +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s r] binfile subslot\n", argv[0]); + exit(1); + } + read_ts_file(argv[1], argv[2]); + process_filebuf(); + exit(0); +}
