FreeCalypso > hg > freecalypso-tools
view uptools/sms-pdu-decode/sms-pdu-decode.c @ 505:7bf0d909c87e
fc-loadtool flash ID check: change of reset after the check logic
This change only affects those flash configurations that have ID checks
enabled.  The logic for resetting the flash after the ID check has been
changed as follows:
1) If the check fails, we return without attempting to reset the flash.
2) If the check is successful, we reset the flash using the configured
method (could be AMD or Intel or Intel W30) instead of always doing an
AMD flash reset as the original code did.
| author | Mychaela Falconia <falcon@freecalypso.org> | 
|---|---|
| date | Mon, 27 May 2019 19:58:01 +0000 | 
| parents | 542c6d733772 | 
| children | 9f7a263ad7f0 | 
line wrap: on
 line source
#include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> char *infname; FILE *inf; int ascii_ext_mode, global_hexdump_mode, keep_raw_pdu; char input_line[1024]; u_char pdu[176], first_octet; unsigned pdu_length, pdu_ptr; int dcs_distilled; handle_sca() { unsigned sca_len; char digits[21]; sca_len = pdu[0]; pdu_ptr = 1; if (!sca_len) return(0); if (sca_len < 2 || sca_len > 11) { printf("Decode-Error: invalid SCA length\n"); return(-1); } if (pdu_ptr + sca_len > pdu_length) { printf("Decode-Error: SCA goes past PDU end\n"); return(-1); } pdu_ptr += sca_len; decode_address_digits(pdu + 2, digits, sc_addr_ndigits(pdu)); printf("SCA: %s%s (type 0x%02X)\n", pdu[1] == 0x91 ? "+" : "", digits, pdu[1]); return(0); } handle_first_octet() { if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before FO\n"); return(-1); } first_octet = pdu[pdu_ptr++]; printf("First-Octet: 0x%02X\n", first_octet); return(0); } handle_mr() { if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before MR\n"); return(-1); } printf("MR: 0x%02X\n", pdu[pdu_ptr++]); return(0); } handle_user_addr(direction) char *direction; { unsigned addr_field_len, alpha_nsep; char digits[21]; u_char alpha_gsm7[11], alpha_decoded[23]; if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before %s address\n", direction); return(-1); } if (pdu[pdu_ptr] > 20) { printf("Decode-Error: %s address > 20 digits\n", direction); return(-1); } addr_field_len = ((pdu[pdu_ptr] + 1) >> 1) + 2; if (pdu_ptr + addr_field_len > pdu_length) { printf("Decode-Error: %s address goes past PDU end\n", direction); return(-1); } if (!pdu[pdu_ptr]) printf("%s: empty-addr (type 0x%02X)\n", direction, pdu[pdu_ptr+1]); else if ((pdu[pdu_ptr+1] & 0x70) == 0x50 && alpha_addr_valid(pdu[pdu_ptr], &alpha_nsep)) { gsm7_unpack(pdu + pdu_ptr + 2, alpha_gsm7, alpha_nsep); gsm7_to_ascii_or_ext(alpha_gsm7, alpha_nsep, alpha_decoded, (unsigned *) 0, ascii_ext_mode, 0, (unsigned *) 0); printf("%s: \"%s\" (type 0x%02X)\n", direction, alpha_decoded, pdu[pdu_ptr+1]); } else { decode_address_digits(pdu + pdu_ptr + 2, digits, pdu[pdu_ptr]); printf("%s: %s%s (type 0x%02X)\n", direction, pdu[pdu_ptr+1] == 0x91 ? "+" : "", digits, pdu[pdu_ptr+1]); } pdu_ptr += addr_field_len; return(0); } handle_pid() { if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before PID\n"); return(-1); } printf("PID: 0x%02X\n", pdu[pdu_ptr++]); return(0); } handle_dcs() { u_char dcs; char *strtype; if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before DCS\n"); return(-1); } dcs = pdu[pdu_ptr++]; dcs_distilled = sms_dcs_classify(dcs); switch (dcs_distilled) { case 7: strtype = "7-bit"; break; case 8: strtype = "raw octets"; break; case 9: strtype = "compressed"; break; case 16: strtype = "UCS-2"; break; } printf("DCS: 0x%02X (%s)\n", dcs, strtype); return(0); } handle_scts() { char str[21]; if (pdu_ptr + 7 > pdu_length) { printf("Decode-Error: end of PDU before SCTS\n"); return(-1); } gsm_timestamp_decode(pdu + pdu_ptr, str); printf("SC-Timestamp: %s\n", str); pdu_ptr += 7; return(0); } handle_vp_abs() { char str[21]; if (pdu_ptr + 7 > pdu_length) { printf("Decode-Error: end of PDU before VP-abs\n"); return(-1); } gsm_timestamp_decode(pdu + pdu_ptr, str); printf("VP-Absolute: %s\n", str); pdu_ptr += 7; return(0); } handle_vp_rel() { unsigned vprel, hours, min; if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before VP-rel\n"); return(-1); } vprel = pdu[pdu_ptr++]; if (vprel <= 143) { min = (vprel + 1) * 5; goto hhmm; } else if (vprel <= 167) { min = (vprel - 143) * 30 + 12 * 60; goto hhmm; } else if (vprel <= 196) { printf("VP-Relative: %u days\n", vprel - 166); return(0); } else { printf("VP-Relative: %u weeks\n", vprel - 192); return(0); } hhmm: hours = min / 60; min %= 60; printf("VP-Relative: "); if (hours) printf(" %u hour%s", hours, hours != 1 ? "s" : ""); if (min) printf(" %u min", min); putchar('\n'); return(0); } handle_vp_enh() { if (pdu_ptr + 7 > pdu_length) { printf("Decode-Error: end of PDU before VP-enh\n"); return(-1); } printf("VP-Enhanced: %02X %02X %02X %02X %02X %02X %02X\n", pdu[pdu_ptr], pdu[pdu_ptr+1], pdu[pdu_ptr+2], pdu[pdu_ptr+3], pdu[pdu_ptr+4], pdu[pdu_ptr+5], pdu[pdu_ptr+6]); pdu_ptr += 7; return(0); } handle_vp() { int rc; switch (first_octet & 0x18) { case 0x00: rc = 0; break; case 0x08: rc = handle_vp_enh(); break; case 0x10: rc = handle_vp_rel(); break; case 0x18: rc = handle_vp_abs(); break; } return(rc); } process_pdu() { unsigned udl, udl_octets; unsigned udhl, udh_octets, udh_chars, ud_chars; u_char ud7[160], decode_buf[321]; int do_hexdump; unsigned decoded_len, badchars; if (handle_sca() < 0) return(-1); if (handle_first_octet() < 0) return(-1); if (first_octet & 2) { printf("Decode-Error: MTI not supported\n"); return(-1); } if (first_octet & 1) { if (handle_mr() < 0) return(-1); } if (handle_user_addr(first_octet & 1 ? "To" : "From") < 0) return(-1); if (handle_pid() < 0) return(-1); if (handle_dcs() < 0) return(-1); if (first_octet & 1) { if (handle_vp() < 0) return(-1); } else { if (handle_scts() < 0) return(-1); } if (pdu_ptr >= pdu_length) { printf("Decode-Error: end of PDU before UDL\n"); return(-1); } udl = pdu[pdu_ptr++]; if (dcs_distilled == 7) { if (udl > 160) { printf("Decode-Error: UDL %u > 160\n", udl); return(-1); } udl_octets = (udl * 7 + 7) / 8; } else { if (udl > 140) { printf("Decode-Error: UDL %u > 140\n", udl); return(-1); } udl_octets = udl; } if (pdu_length - pdu_ptr != udl_octets) { printf("Decode-Error: UD length in PDU %u != expected %u\n", pdu_length - pdu_ptr, udl_octets); return(-1); } if (first_octet & 0x40) { if (!udl) { printf("Decode-Error: UDHI set with UDL=0\n"); return(-1); } udhl = pdu[pdu_ptr]; udh_octets = udhl + 1; if (udh_octets > udl_octets) { printf("Decode-Error: UDHL exceeds UDL\n"); return(-1); } printf("UDH-Length: %u\n", udhl); if (dcs_distilled == 7) udh_chars = (udh_octets * 8 + 6) / 7; else udh_chars = udh_octets; } else { udhl = 0; udh_octets = 0; udh_chars = 0; } if (udh_chars >= udl) { ud_chars = 0; printf("Length: 0\n"); } else { ud_chars = udl - udh_chars; if (dcs_distilled == 7) gsm7_unpack(pdu + pdu_ptr, ud7, udl); if (global_hexdump_mode) do_hexdump = 1; else switch (dcs_distilled) { case 7: do_hexdump = 0; break; case 8: case 9: do_hexdump = 1; break; case 16: if (ud_chars & 1) do_hexdump = 1; else do_hexdump = 0; break; } if (do_hexdump) printf("Length: %u (raw)\n", ud_chars); else { switch (dcs_distilled) { case 7: gsm7_to_ascii_or_ext(ud7 + udh_chars, ud_chars, decode_buf, &decoded_len, ascii_ext_mode, 1, &badchars); break; case 16: ucs2_to_ascii_or_ext(pdu + pdu_ptr + udh_chars, ud_chars, decode_buf, &decoded_len, ascii_ext_mode, 1, &badchars); break; } printf("Length: %u", ud_chars); if (decoded_len != ud_chars) printf("->%u", decoded_len); if (badchars) printf(" (%u bad char%s)", badchars, badchars != 1 ? "s" : ""); putchar('\n'); } } if (udhl) { printf("\nUDH:\n"); msg_bits_hexdump(pdu + pdu_ptr + 1, udhl); } if (!ud_chars) return(0); putchar('\n'); if (do_hexdump) { if (dcs_distilled == 7) msg_bits_hexdump(ud7 + udh_chars, ud_chars); else msg_bits_hexdump(pdu + pdu_ptr + udh_chars, ud_chars); } else puts(decode_buf); return(0); } process_cmdline(argc, argv) char **argv; { int c; extern int optind; while ((c = getopt(argc, argv, "ehpu")) != EOF) switch (c) { case 'e': ascii_ext_mode = 1; continue; case 'h': global_hexdump_mode = 1; continue; case 'p': keep_raw_pdu = 1; continue; case 'u': ascii_ext_mode = 2; continue; default: fprintf(stderr, "%s: invalid option\n", argv[0]); exit(1); } if (argc > optind) infname = argv[optind]; } swallow_empty_line() { int c; c = getc(inf); if (c != '\n') ungetc(c, inf); } main(argc, argv) char **argv; { char *nl; int lineno, cc; process_cmdline(argc, argv); if (infname) { inf = fopen(infname, "r"); if (!inf) { perror(infname); exit(1); } } else { inf = stdin; infname = "stdin"; } for (lineno = 1; fgets(input_line, sizeof input_line, inf); lineno++) { nl = index(input_line, '\n'); if (!nl) { fprintf(stderr, "%s line %d: no newline\n", infname, lineno); exit(1); } *nl = '\0'; cc = decode_hex_line(input_line, pdu, sizeof pdu); if (cc <= 0) { puts(input_line); continue; } pdu_length = cc; if (keep_raw_pdu) printf("%s\n\n", input_line); process_pdu(); putchar('\n'); swallow_empty_line(); } exit(0); }
