- Add a P2 spec for AUTHENTICATE (auth context bits + specific-reference-data
flag), so P2 is displayed instead of only leaking through cmd.context.
- Fix P1 name to 'No indication' (was the misleading 'Run GSM algorithm').
- Decompose AUTN into SQN(xor)AK / AMF / MAC and AUTS into SQN(xor)AK / MAC-S
per TS 33.102; surface 'specific reference data' key flag.
- SW column now shows green (success 90/92-9F), blue (pending 61/91/6C),
amber (warning 62/63), red (error 64-6F) per ISO 7816-4 / TS 102 221.
- _decode_nai: treat all-FF records as empty instead of emitting
replacement characters; strip FF padding before the ASCII fallback.
- Only update the selected-file state on a successful SELECT (SW1 in
61/62/63/90/91/92/9E/9F); a failed SELECT (e.g. 6A82) leaves the
current file unchanged.
- Track the file structure from the FCP (GET RESPONSE after SELECT).
- Skip file decoding for record ops (READ/UPDATE/SEARCH RECORD) when the
selected file is transparent/DF, marking the result 'stale' instead of
decoding garbage — this catches silently-dropped SELECTs.
- Track the currently selected file (SELECT by FID/path) across the
session and pass it to the decoder; reset on ATR/card change; seed via
a bounded backward scan on paged views.
- Decode READ BINARY/RECORD, UPDATE BINARY/RECORD and (via GET RESPONSE)
SEARCH RECORD bodies using a FILE_DECODERS registry: IMSI, ICCID,
LI/PL, ADN-format (MSISDN/SDN/FDN/...), SMS records (SMSC + TPDU),
UST/SST/IST service tables, PLMN lists (+access tech), EF_DIR,
CBMI/R, ARR, PNN, ECC, SPN, LOCI, ACC, Phase, ISIM IMPI/DOMAIN/IMPU.
- File formats verified against TS 51.011 / TS 102 221 / TS 31.102
(PLMNwAcT is 5-byte entries; EF_SMS = status + SMSC + TPDU; ISIM
identities are 0x80 TLV).
- Offset != 0 READ BINARY/UPDATE BINARY is skipped (fragment reads).
- SEARCH RECORD results (record numbers) decoded in GET RESPONSE.
- GET RESPONSE summary now shows FCP file type/structure/size.
- New 'File data' section in the detail view.
The selected row was white (--bg-input) in light theme, nearly
indistinguishable from the unselected/hover rows. Use a blue-100 tint
(#dbeafe) in light theme only; dark theme unchanged.
Frontend:
- trace empty-state now shows connection status + capture mode (boxed,
colored) in the center, updated live via checkConnection
- capture-mode uses amber warning style (gsmtap/disabled), green for direct
- stopCapture clears currentSessionId
Server:
- gsmtap read_packet catches OSError on socket close (no more EBADF
traceback on stop)
- stop_session joins the loop and discards a session with zero messages;
/api/capture/stop reports discarded
- startup prints server version
Tests: 122 (gsmtap close, empty/non-empty capture lifecycle).
- pcap.py: _parse_tsresol now pads options to a 32-bit boundary
((-length) % 4) and uses 2** for the MSB-set (power-of-2) case, so
nanosecond if_tsresol is read correctly (was defaulting to µs and
scaling timestamps 1000x)
- database/server: set imported session started/ended from the first/last
packet timestamps (falling back to wall-clock for synthetic SPB)
- frontend: formatDuration renders hours
- tests: tsresol (ns after padded option, default µs, ns round-trip) and
session-window/fallback (119 total)
The fetch handler tried to cache every intercepted request, so a
chrome-extension:// request made cache.put() throw 'Request scheme
chrome-extension is unsupported'. Skip non-http(s) and non-GET requests,
and swallow cache-write failures.
First published version. __version__ and pyproject bumped to 1.0.0,
/api/status now returns 'version' so the PWA can check compatibility.
Tests: 107 (status includes version, package version).
Lets a public-hosted PWA reach a local simtrace2-pysniff-server
(http://127.0.0.1:8081); without it the browser blocks the preflight
before any request is sent.
Proactive commands with a body over 127 bytes (e.g. SET UP MENU with a
long item list) use a long-form length (0x81 NN / 0x82 NN NN) in their
D0 wrapper. Previously parse_tlv bailed on those, so the FETCH decoded
as a bare 'FETCH' without its command name or items.
Tests: 105 (long-form 1/2-byte, real SET UP MENU sample).
- pcap.py: parse_pcap (micro/nano, both byte orders) and parse_pcapng
(SHB byte-order, IDB linktype + if_tsresol, EPB/SPB) readers that
unwrap Ethernet/RAW/IPv4/NULL/SLL/SLL2 to UDP and extract GSMTAP-SIM
packets (APDU->tpdu, ATR->atr, PPS->pps), with a heuristic fallback
- database: insert_messages bulk-insert helper
- server: import endpoint reads raw body, auto-detects format, skips
non-GSMTAP packets; 400 'No GSMTAP data found in trace' (no session)
when empty, else creates a 'pcap' session named after the file
Tests: 102 (pcap round-trip, pcapng, no-GSMTAP, endpoint 200/400).
CLA 0x80 is the ETSI/3GPP-defined UICC/USIM class (TS 102 221 Table 10.3),
not ISO 7816-4 'proprietary'. Relabel 0x80 -> ETSI-defined (UICC/USIM),
0xA0 -> ETSI-defined (SIM/GSM), 0x00 -> inter-industry (ISO 7816-4);
drop the now-redundant note field.
The PCAP branch fell back to GSMTAP_SIM_APDU for every non-ATR message,
so PPS/CHANGE/FIDI were written as 'APDU'. Align with the UDP branch and
the server export: only atr→ATR and tpdu→APDU are written.
pcap.py: LINKTYPE_GSMTAP (155) was wrong — 155 is DLT_USER8, so
Wireshark showed 'USER 8 / DLT=155'. Now write Ethernet-encapsulated
PCAP (LINKTYPE 1): each GSMTAP message wrapped in Ethernet + IPv4 +
UDP (port 4729), with correct checksums — matching a real tcpdump
capture of GSMTAP-over-UDP and how Wireshark's gsmtap dissector is keyed.
gsmtap.py: GSMTAP_TYPE_SIM was 0x07 (WiMAX burst) — corrected to 0x04;
GSMTAP_SIM_APDU was 0x02 (PPS req) — corrected to 0x00; added PPS_REQ/
PPS_RSP. These match libosmocore/Wireshark packet-gsmtap.h.
Verified with tshark: PCAP now decodes as GSM SIM (SELECT/STATUS/ATR)
instead of 'USER 8'.
tests: pcap tests assert Ethernet linktype + framing + GSMTAP payload.
pcap.py: build_pcap(packets) — build PCAP bytes in memory (same format
as PcapWriter)
database.py: get_messages_raw() — raw elapsed/type/data without decode
server.py: GET /api/sessions/<id>/pcap generates a GSMTAP-encapsulated
PCAP (ATR/TPDU) with real timestamps and downloads it as
<session-name>.pcap (ASCII filename fallback + RFC 5987 UTF-8 for
spaces/unicode via _content_disposition)
tests: build_pcap + _content_disposition (67 total)