Commit Graph
15 Commits
Author SHA1 Message Date
catarrh 51e1b4ae08 Keep GSMTAP capture alive + server-side liveness logging
The GSMTAP capture thread died silently whenever a single non-SIM or
truncated GSMTAP datagram arrived (read_packet() raises ValueError,
uncaught in the loop, killing the daemon thread while UDP kept
flowing) — matching the "stops listening after a sniffer restart"
symptom.

Fixes:
- GsmtapListener.iter_messages() now catches ValueError/struct.error
  from read_packet(), drops the offending datagram (counted via a new
  `dropped` counter) and keeps listening.
- CaptureManager._capture_loop() guards the DB insert so a transient
  error can't kill the thread; a top-level guard logs
  "ERROR: capture thread stopped on error …" + traceback and clears
  the session so /api/status no longer reports a stuck "active".
- Server now logs capture liveness to stderr: "Capture started", a
  periodic "Capture alive: session=N messages=M bytes=B dropped=D"
  heartbeat (default every 60 s, configurable via log_interval), and
  "Capture stopped" (or "empty session discarded").

Tests: +5 (listener survives non-SIM/short packet, capture loop
survives insert error, logs stop-on-error, heartbeat+stop log).
Stays on 1.22.0 (backend-only).
2026-08-26 22:21:14 +03:00
catarrh 66094a0114 Surface GSMTAP BAD_FCS desync flag end-to-end
sigrok-iso7816-stream sets GSMTAP_FLAG_BAD_FCS (0x01) in the GSMTAP
header `res` byte on desynced TPDUs (mis-framed exchanges kept for
forensics). Propagate that flag through the whole pipeline so such
packets are explicitly surfaced instead of decoding as garbage:

- gsmtap.py: GSMTAP_FLAG_BAD_FCS const; GsmtapReceiver.read_packet()
  now returns (sub_type, data, flags) from the res byte.
- server/capture.py: GsmtapListener forwards the flags to the DB.
- pcap.py: _parse_gsmtap_hdr/_scan_gsmtap/extract_gsmtap and
  parse_pcap/parse_pcapng now yield a (ts, type, payload, flags)
  tuple, so the flag survives a PCAP/PCAPNG round-trip.
- server/server.py: PCAP import stores the flags.
- server/decode.py: gsmtap_flag_names() maps bit 0x01 to
  'bad FCS (desynced)'; merged into decoded errors for tpdu/atr/pps
  and rst/vcc, so the frontend ⚠ badge + Errors row flag the entry.

User-visible: desynced TPDUs show a ⚠ "bad FCS (desynced)" marker
in the trace and detail views. Tests: +4 (decode BAD_FCS markers,
PCAP flag round-trip); existing tests updated for the new tuple
arities. Version 1.22.0, SW cache simtrace-analyser-v32.
2026-08-26 18:08:25 +03:00
catarrh 7eaf7e9b53 Decode sigrok-iso7816-stream RST/VCC line events (GSMTAP 0x10/0x11)
Support the sigrok-iso7816-stream decoder (FX2 logic-analyzer passive
SIM sniffer, github.com/anttro/sigrok_iso7816_stream) which streams
GSMTAP-SIM on UDP 4729 and adds two custom sub-types for line events.

- gsmtap.py: GSMTAP_SIM_RST_EVENT (0x10) / GSMTAP_SIM_VCC_EVENT (0x11).
- capture.py: gsmtap_msg_type() maps 0x10→'rst', 0x11→'vcc' (shared by
  the listener and tests); pcap.py _SUB_TYPE_NAMES gains the same
  entries so PCAP re-imports of these captures preserve the events.
- decode.py: decode_line_event() decodes [direction, level, reserved]
  into reset asserted/de-asserted or power applied/removed + level;
  routed through decode_sniff_msg.
- database.py: reset-assert and power-removal invalidate the per-channel
  file selection (card-level transition); de-assert / power-on are
  markers only.
- frontend: RST/VCC labels (RESET ASSERTED / VCC OFF, …), a detail-view
  branch (Event + Level + raw), and list styling (.apdu-type.rst/.vcc).

README notes the custom sub-type compatibility. Tests: +8 (line-event
vectors, sniff routing, subtype + PCAP round-trip mappings) — 359
total. Version 1.21.0, SW cache simtrace-analyser-v31.
2026-08-26 17:29:36 +03:00
catarrh acbd2bda4a README: document C-APDU decoding of secured-packet payloads 2026-08-24 22:55:06 +03:00
catarrh 6f058392f8 README: document client-side secured-packet decryption 2026-08-24 21:23:05 +03:00
catarrh 174df8a8ad Fix CAT registries per TS 102 223 V18.3/TS 31.111 V18.12; decode all ENVELOPE types
Spec audit found three registries drifted from an old release, plus
missing command/envelope coverage:

- EVENT_TYPES: correct from '14' up — Access Technology Change
  (multiple), IMS Registration/Incoming data, Profile Container ('19),
  Secured Profile Container, Poll Interval Negotiation, Data Connection
  Status Change, CAG cell selection, Slices Status Change ('1F);
  '20-'22 reserved. Old table wrongly showed LTE D2D/ECall/SCEF names.
- TR_RESULTS: session/user results live at '10-'14 ('14 = USSD/SS
  transaction terminated), not '0A-'0E; single '20 = ME currently
  unable (per-cause details are additional-info bytes); add '22-'27,
  '3A BIP error; unshift '3B-'3D; '39 permanent-problem wording.
- ENVELOPE_TYPES: add D9 USSD Download, DA/DB MMS, DC Terminal
  Applications, DD Geo Location Reporting, DE Envelope Container,
  DF ProSe Report, E0 5G ProSe Report, E1-E3 reserved, E4 GSMA.
- CAT_COMMAND_TYPES: add '79 LSI COMMAND; F0-FE render as Proprietary.
- PLI_QUALIFIERS: add '07 ESN, '1A Supported RATs.

Phase 2:
- _decode_envelope: MENU SELECTION (item id + help request), TIMER
  EXPIRATION (id + semi-octet h/m:s value), CALL CONTROL (address +
  CCP), USSD DOWNLOAD (DCS text), GEO LOCATION REPORTING, ENVELOPE
  CONTAINER (recursive inner dispatch); unknown inner TLVs preserved
  in raw_tlv for every type.
- Device Identities now decode to names (Keypad/Display/UICC/
  Terminal/Network/Card reader n/Channel n/eCAT client) in proactive
  commands and envelopes; frontend renders "src → dst".

Tags verified against ETSI TS 101 220 registry (help request '15/'95,
timer id/value '24/'A4, USSD string '0A/'8A). Tests: +16 spec-derived
fixtures, one stale expectation corrected — 306 total. Version 1.13.0,
SW cache simtrace-analyser-v16.
2026-08-22 23:35:20 +03:00
catarrh d9133ffa57 Document decoder features, server options, recovery flags in README
- Add Features section: APDU decoder coverage (CLA/SFI-aware P1/P2,
  UICC-specific status words, CAT proactive/TR/ENVELOPE, SMS TPDU,
  SCP80 OTA secured packets + PoR, ATR/FCP) and simtrace-analyser
  PWA bullets (map/list views, session deep links, PCAP import,
  EN/RU i18n).
- Document server CLI: --host/--port/--db/--capture/--gsmtap-port/
  --web-dir; add --capture disabled example (three capture modes,
  was two).
- Add missing sniffer recovery flags: --reconnect-delay-min/max,
  --backoff-factor.
2026-08-21 22:53:53 +03:00
catarrh b900a8a3e1 Merge simtrace-analyser PWA into frontend/ (monorepo); serve it same-origin
- frontend/: simtrace-analyser PWA (index.html, sw.js, manifest.json,
  icons, tests/index.test.html) copied in fresh
- server.py: static file serving (_STATIC_MIME, _serve_static) with
  path-traversal guard; injects window.SIMTRACE_EMBEDDED='1' into
  index.html so the PWA defaults to a relative API base
- server __main__: --web-dir (default <repo>/frontend)
- frontend: embedded same-origin mode; sw.js relative precache paths +
  cache v4; GitHub link + version-warn point at simtrace2-pysniff
- version 1.1.0 everywhere (__version__, pyproject, PWA_VERSION,
  manifest); MIN_SERVER_VERSION stays 1.0.0
- README/scripts/.gitignore updated

Tests: 107.
2026-08-14 16:26:28 +03:00
catarrh 0d9d6f7157 README: fix PCAP/GSMTAP output wording, add Related section
PCAP is now Ethernet/IP/UDP/GSMTAP (not raw LINKTYPE 155). Cross-reference
simtrace-analyser with a Try-it-now link.
2026-08-12 21:50:30 +03:00
catarrh 17eeda27f3 Merge simtrace-analyser-server into simtrace2_pysniff.server
Add simtrace2-pysniff-server CLI — HTTP API for simtrace-analyser PWA.
Two capture modes: GSMTAP UDP listener (compatible with simtrace2-sniff)
or direct SIMtrace2 hardware capture. SQLite storage with sessions +
messages tables. REST API with CORS.

server/ sub-package: database.py, capture.py, server.py, __main__.py

README updated with server usage section.
pyproject.toml: simtrace2-pysniff-server script entry added.
2026-08-12 15:59:51 +03:00
catarrh f8e9cb1018 SIGHUP: ignore only when in background (stdin not a tty)
Use sys.stdin.isatty() to auto-detect: foreground sessions still
respond to SIGHUP (terminal close kills the process as expected),
background/piped processes ignore it and survive.
2026-08-11 01:02:07 +03:00
catarrh fb5c1fbf6a Ignore SIGHUP — survive terminal closure in background
__main__.py: add signal.SIGHUP → SIG_IGN before setting up
SIGINT/SIGTERM handlers. Sniffer no longer dies when the terminal
closes or the shell session ends.

README: add Background / Daemon section with nohup examples.
2026-08-11 00:37:41 +03:00
catarrh ad8d661caa README: add Prerequisites, separate Install/Running sections
Split Quick Start into Prerequisites (Python/PyUSB/libusb/hardware),
Install (clone + pip), and Running (startup script vs Python module).
Startup script section includes env var override examples.
Added dependency table note — PCAP/GSMTAP/hex dump use only stdlib.
2026-08-10 23:55:34 +03:00
catarrh ec129c4463 Add --format option: timestamp and atr-time TPDU output modes
dump.py: tpdu_timestamp_prefix(), tpdu_atr_time_prefix(),
  format_message() accepts tpdu_prefix parameter,
  FileDumper supports fmt + ATR time tracking

__main__.py: --format/-f flag (hex|timestamp|atr-time),
  atr_time_start tracking in message loop

sniff-start.sh: pass through --format/-f and FORMAT env var
2026-08-10 23:53:38 +03:00
catarrh 73b0277ef7 Initial commit: simtrace2-pysniff v0.1.0
Python-based SIMtrace2 sniffer — drop-in replacement for simtrace2-sniff.
Single dependency (pyusb), auto-reconnect, GSMTAP/PCAP output, library API.

Modules:
  protocol.py — SIMtrace2 USB sniffing protocol parser
  device.py   — USB discovery + SniffSession with exponential backoff reconnect
  gsmtap.py   — GSMTAP UDP sender for Wireshark
  pcap.py     — PCAP file writer (LINKTYPE_GSMTAP)
  dump.py     — hex dump formatters + file output
  __main__.py — CLI entry point

Startup script sniff-start.sh handles udev permission checks and shows
install instructions. udev rule uses TAG+=uaccess (systemd-logind ACL).
2026-08-10 23:17:04 +03:00