fix: emit wire-shaped TPDUs in the GSMTAP stream (v3.1.1)
The GSMTAP stream sent logical APDUs, so a receiver (SIMtrace Analyser,
Wireshark) flagged almost every packet: case-4 commands carried their Le
byte ('length_mismatch: excessive') and responses were headerless packets
decoded as bogus commands ('truncated'). The ATR also arrived in the
middle of the stream.
- gsmtap.py: the tracer now emits wire-shaped TPDUs, matching a hardware
sniffer capture: case 4 -> the command without Le plus the 61XX 'bytes
available' SW (derived from the real response length), then the data as
a GET RESPONSE TPDU (00C00000<len> + data + SW, chunked at 255); case
1/2/3 -> one packet cmd + data + SW; unparseable APDUs fall back to raw
command/response packets.
- No ATR/VCC/RST/PPS events at all (no line-level access over PC/SC);
the ATR sending helper and the server-side plumbing were removed.
- Verified by replaying the bad capture's exchanges through the new
tracer: 116 packets, zero decoder warnings (previously nearly all).
- tests: the per-case wire forms, chunking, fallbacks; README/AGENTS
document the wire shape and its limits; version 3.1.1, sw simple-v236.
This commit is contained in:
@@ -28,7 +28,7 @@ from osmocom.tlv import BER_TLV_IE
|
||||
from osmocom.utils import rpad
|
||||
|
||||
|
||||
VERSION = '3.1.0'
|
||||
VERSION = '3.1.1'
|
||||
|
||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||
|
||||
@@ -2532,34 +2532,10 @@ def _handle_card_disconnect():
|
||||
_reset_proactive_log()
|
||||
|
||||
|
||||
def _send_gsmtap_atr(server):
|
||||
"""Stream the card's ATR as a GSMTAP-SIM packet (--gsmtap only).
|
||||
|
||||
Sent at every equip so a GSMTAP receiver (SIMtrace Analyser, Wireshark)
|
||||
has the session context before the first APDU of the new session."""
|
||||
sender = getattr(server, 'gsmtap', None)
|
||||
if sender is None:
|
||||
return
|
||||
rs = getattr(server, 'rs', None)
|
||||
atr = None
|
||||
if rs is not None:
|
||||
try:
|
||||
atr = (rs.identity or {}).get('ATR')
|
||||
except Exception:
|
||||
atr = None
|
||||
if not atr:
|
||||
return
|
||||
try:
|
||||
sender.send_atr(bytes.fromhex(atr))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
|
||||
def _apply_equipped_card(server):
|
||||
"""Common post-equip state refresh + TERMINAL PROFILE, shared by the
|
||||
/api/command equip branch and the auto-equip worker."""
|
||||
global _CARD_CONNECTED
|
||||
_send_gsmtap_atr(server)
|
||||
server.stk_pending = None
|
||||
server.menu_active = False
|
||||
_cancel_menu_timeout()
|
||||
|
||||
Reference in New Issue
Block a user