Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/simtrace2/+/42749?usp=email )
Change subject: contrib: extend wireshark lua dissector ......................................................................
contrib: extend wireshark lua dissector
Still no reassembly, but enough to work with bug report pcaps
Change-Id: Ic78824d6122191c7d16152cea643a238c33f49b1 --- M contrib/simtrace.lua 1 file changed, 501 insertions(+), 140 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/49/42749/1
diff --git a/contrib/simtrace.lua b/contrib/simtrace.lua index 598a4e2..fd2277b 100644 --- a/contrib/simtrace.lua +++ b/contrib/simtrace.lua @@ -6,6 +6,9 @@ -- can be found in the Wireshark Help->About Wireshark->Folders tab -- Windows: %APPDATA%\Wireshark\plugins. -- Unix-like systems: ~/.local/lib/wireshark/plugins. +-- +-- tshark works too: +-- tshark -r capture.pcapng -X lua_script:/path/to/simtrace.lua
usb_simtrace_protocol = Proto("USB_simtrace", "USB simtrace protocol")
@@ -34,31 +37,105 @@ [0x0300] = "SNIFF_CHANGE", [0x0301] = "SNIFF_FIDI", [0x0302] = "SNIFF_ATR", +[0x0303] = "SNIFF_PPS", [0x0304] = "SNIFF_TPDU", -[0x0303] = "SNIFF_PPS" }
-local msgtype = ProtoField.uint16("usb_simtrace.msgtype", "Message Type", base.HEX_DEC, control_commands) +local msg_class_names = { + [0] = "GENERIC", + [1] = "CARDEM", + [2] = "MODEM", + [3] = "SNIFF", +} + +-- ISO 7816 / GSM SIM instruction +local ins_names = { + [0x04] = "DEACTIVATE FILE", + [0x10] = "TERMINAL PROFILE", + [0x12] = "ENVELOPE", + [0x14] = "FETCH", + [0x20] = "VERIFY PIN", + [0x24] = "CHANGE PIN", + [0x26] = "DISABLE PIN", + [0x28] = "ENABLE PIN", + [0x2C] = "UNBLOCK PIN", + [0x32] = "INCREASE", + [0x44] = "ACTIVATE FILE", + [0x70] = "MANAGE CHANNEL", + [0x73] = "MANAGE SECURE CHANNEL", + [0x75] = "TRANSACT DATA", + [0x88] = "AUTHENTICATE", + [0x89] = "AUTHENTICATE", + [0xA4] = "SELECT", + [0xAA] = "TERMINAL CAPABILITY", + [0xB0] = "READ BINARY", + [0xB2] = "READ RECORD", + [0xC0] = "GET RESPONSE", + [0xC2] = "ENVELOPE", + [0xCB] = "RETRIEVE DATA", + [0xD6] = "UPDATE BINARY", + [0xDB] = "SET DATA", + [0xDC] = "UPDATE RECORD", + [0xF2] = "STATUS", + [0xFA] = "SLEEP", +} + +-- ISO 7816 SW1 +local sw1_names = { + [0x90] = "OK", + [0x91] = "OK, proactive", + [0x9E] = "Response length", + [0x9F] = "Response length", + [0x61] = "Bytes available", + [0x62] = "Warning, unchanged", + [0x63] = "Warning, changed", + [0x64] = "Error, NV unchanged", + [0x65] = "Error, NV changed", + [0x67] = "Wrong length", + [0x68] = "CLA not supported", + [0x69] = "Command not allowed", + [0x6A] = "Wrong parameters", + [0x6B] = "Wrong P1/P2", + [0x6C] = "Wrong Le", + [0x6D] = "INS not supported", + [0x6E] = "CLA not supported", + [0x6F] = "Internal error", +} + +local msgtype = ProtoField.uint16("usb_simtrace.msgtype", "Command", base.HEX_DEC, control_commands) +local hf_msg_class = ProtoField.uint8("usb_simtrace.msg_class", "Message Class", base.HEX, msg_class_names) +local hf_msg_type = ProtoField.uint8("usb_simtrace.msg_type", "Message Type", base.HEX) + local seqnr = ProtoField.uint8("usb_simtrace.seqnr", "Sequence Number", base.DEC) local slotnr = ProtoField.uint8("usb_simtrace.slotnr", "Slot Number", base.DEC) local reserved = ProtoField.uint16("usb_simtrace.reserved", "reserved", base.HEX_DEC) -local payloadlen = ProtoField.uint16("usb_simtrace.length", "length", base.DEC) +local payloadlen = ProtoField.uint16("usb_simtrace.length", "Message Length", base.DEC) local payload = ProtoField.bytes("usb_simtrace.payload", "Data")
-local pb_and_rx = ProtoField.uint32("usb_simtrace.pb_and_rx", "pb_and_rx", base.HEX_DEC, NULL, 0x8) -local pb_and_tx = ProtoField.uint32("usb_simtrace.pb_and_tx", "pb_and_tx", base.HEX_DEC, NULL, 0x4) -local final = ProtoField.uint32("usb_simtrace.final", "final", base.HEX_DEC, NULL, 0x2) -local tpdu_hdr = ProtoField.uint32("usb_simtrace.tpdu_hdr", "tpdu_hdr", base.HEX_DEC, NULL, 0x1) -local rxtxdatalen = ProtoField.uint16("usb_simtrace.rxtxdatalen", "rx/tx data length", base.DEC) -local rxtxdata = ProtoField.bytes("usb_simtrace.rxtxdata", "rx/tx (data)") +local pb_and_rx = ProtoField.uint32("usb_simtrace.pb_and_rx", "pb_and_rx", base.HEX_DEC, NULL, 0x00000008) +local pb_and_tx = ProtoField.uint32("usb_simtrace.pb_and_tx", "pb_and_tx", base.HEX_DEC, NULL, 0x00000004) +local final = ProtoField.uint32("usb_simtrace.final", "Final", base.HEX_DEC, NULL, 0x00000002) +local tpdu_hdr = ProtoField.uint32("usb_simtrace.tpdu_hdr", "TPDU Header", base.HEX_DEC, NULL, 0x00000001) +local rxtxdatalen = ProtoField.uint16("usb_simtrace.rxtxdatalen", "Data Length", base.DEC) +local rxtxdata = ProtoField.bytes("usb_simtrace.rxtxdata", "TPDU Data")
-local hf_pts_len = ProtoField.uint8("usb_simtrace.pts_len", "PTS length", base.DEC) -local hf_pts_req = ProtoField.bytes("usb_simtrace.pts_req", "PTS request") -local hf_pts_resp = ProtoField.bytes("usb_simtrace.pts_resp", "PTS response") +local hf_tpdu_cla = ProtoField.uint8("usb_simtrace.tpdu.cla", "CLA", base.HEX) +local hf_tpdu_ins = ProtoField.uint8("usb_simtrace.tpdu.ins", "INS", base.HEX, ins_names) +local hf_tpdu_p1 = ProtoField.uint8("usb_simtrace.tpdu.p1", "P1", base.HEX) +local hf_tpdu_p2 = ProtoField.uint8("usb_simtrace.tpdu.p2", "P2", base.HEX) +local hf_tpdu_p3 = ProtoField.uint8("usb_simtrace.tpdu.p3", "P3", base.HEX) +local hf_tpdu_pb = ProtoField.uint8("usb_simtrace.tpdu.pb", "Procedure Byte", base.HEX) +local hf_tpdu_sw1 = ProtoField.uint8("usb_simtrace.tpdu.sw1", "SW1", base.HEX, sw1_names) +local hf_tpdu_sw2 = ProtoField.uint8("usb_simtrace.tpdu.sw2", "SW2", base.HEX)
-local hf_cemu_cfg_features = ProtoField.uint32("usb_simtrace.cemu_cfg.features.status_irq", "CardEm Features", base.HEX) -local hf_cemu_cfg_slot_mux_nr = ProtoField.uint32("usb_simtrace.cemu_cfg.features.slot_mux_nr", "CardEm Slot Mux Nr", base.DEC) -local hf_cemu_cfg_presence_polarity = ProtoField.uint8("usb_simtrace.cemu_cfg.features.presence_polarity", "Sim presence polarity", base.DEC) +local hf_pts_len = ProtoField.uint8("usb_simtrace.pts_len", "PTS Length", base.DEC) +local hf_pts_req = ProtoField.bytes("usb_simtrace.pts_req", "PTS Request") +local hf_pts_resp = ProtoField.bytes("usb_simtrace.pts_resp", "PTS Response") + +local hf_cemu_cfg_features = ProtoField.uint32("usb_simtrace.cemu_cfg.features", "CardEm Features", base.HEX) +local hf_cemu_cfg_slot_mux_nr = ProtoField.uint8("usb_simtrace.cemu_cfg.slot_mux_nr", "CardEm Slot Mux Nr", base.DEC) +local hf_cemu_cfg_presence_polarity = ProtoField.uint8("usb_simtrace.cemu_cfg.presence_polarity", "Sim Presence Polarity", base.HEX) +local hf_cemu_cfg_feat_status_irq = ProtoField.uint32("usb_simtrace.cemu_cfg.features.status_irq", "Status IRQ", base.HEX_DEC, NULL, 0x00000001)
local card_insert_types = { [0x00] = "not inserted", @@ -72,16 +149,22 @@ local CEMU_STATUS_F_CARD_INSERT = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_CARD_INSERT", "CARD_INSERT", base.HEX_DEC, NULL, 0x00000008) local CEMU_STATUS_F_RESET_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_RESET_ACTIVE", "RESET_ACTIVE", base.HEX_DEC, NULL, 0x00000010)
-local CEMU_CONFIG_PRES_POL_PRES_H = ProtoField.uint32("usb_simtrace.CEMU_CONFIG.PRES_POL_PRES_H", "PRESENCE_HIGH", base.HEX_DEC, NULL, 0x00000001) -local CEMU_CONFIG_PRES_POL_VALID = ProtoField.uint32("usb_simtrace.CEMU_CONFIG.PRES_POL_VALID", "PRESENCE_VALID", base.HEX_DEC, NULL, 0x00000002) +local hf_status_voltage = ProtoField.uint16("usb_simtrace.status.voltage_mv", "Voltage (mV)", base.DEC) +local hf_status_fi = ProtoField.uint8("usb_simtrace.status.fi", "F Index", base.DEC) +local hf_status_di = ProtoField.uint8("usb_simtrace.status.di", "D Index", base.DEC) +local hf_status_wi = ProtoField.uint8("usb_simtrace.status.wi", "Waiting Integer", base.DEC) +local hf_status_wt = ProtoField.uint32("usb_simtrace.status.waiting_time", "Waiting Time (ETU)", base.DEC) + +local CEMU_CONFIG_PRES_POL_PRES_H = ProtoField.uint8("usb_simtrace.CEMU_CONFIG.PRES_POL_PRES_H", "PRESENCE_HIGH", base.HEX_DEC, NULL, 0x01) +local CEMU_CONFIG_PRES_POL_VALID = ProtoField.uint8("usb_simtrace.CEMU_CONFIG.PRES_POL_VALID", "PRESENCE_VALID", base.HEX_DEC, NULL, 0x02)
local modem_reset_types = { [0x00] = "de-assert", [0x01] = "assert", [0x02] = "pulse" } -local modem_reset_status = ProtoField.uint8("usb_simtrace.modem.reset_type", "modem reset type", base.HEX, modem_reset_types, 0xf) -local modem_reset_len = ProtoField.uint8("usb_simtrace.modem.reset_len", "modem reset length (ms)", base.DEC) +local modem_reset_status = ProtoField.uint8("usb_simtrace.modem.reset_type", "modem reset type", base.HEX, modem_reset_types, 0x0f) +local modem_reset_len = ProtoField.uint16("usb_simtrace.modem.reset_len", "modem reset length (ms)", base.DEC)
local modem_sim_select_types = { [0x00] = "local", @@ -89,200 +172,478 @@ } local hf_modem_sim_select = ProtoField.uint8("usb_simtrace.modem.sim_select", "SIM card selection", base.DEC, modem_sim_select_types, 0xff)
+local hf_modem_status_supported = ProtoField.uint8("usb_simtrace.modem.status.supported", "Supported Status Bits", base.HEX) +local hf_modem_status_current = ProtoField.uint8("usb_simtrace.modem.status.current", "Current Status Bits", base.HEX) +local hf_modem_status_changed = ProtoField.uint8("usb_simtrace.modem.status.changed", "Changed Status Bits", base.HEX) +local hf_mdm_sts_wwan = ProtoField.uint8("usb_simtrace.modem.status.wwan_led", "WWAN LED", base.DEC, NULL, 0x01) +local hf_mdm_sts_card = ProtoField.uint8("usb_simtrace.modem.status.card_inserted", "Card Inserted", base.DEC, NULL, 0x02) + +local hf_error_severity = ProtoField.uint8("usb_simtrace.error.severity", "Severity", base.DEC) +local hf_error_subsystem = ProtoField.uint8("usb_simtrace.error.subsystem", "Subsystem", base.DEC) +local hf_error_code = ProtoField.uint16("usb_simtrace.error.code", "Error Code", base.HEX) +local hf_error_msg_len = ProtoField.uint8("usb_simtrace.error.msg_len", "Message Length", base.DEC) +local hf_error_msg = ProtoField.string("usb_simtrace.error.msg", "Error Message") + +local hf_bi_hw_manufacturer = ProtoField.string("usb_simtrace.board_info.hw.manufacturer", "HW Manufacturer") +local hf_bi_hw_model = ProtoField.string("usb_simtrace.board_info.hw.model", "HW Model") +local hf_bi_hw_version = ProtoField.string("usb_simtrace.board_info.hw.version", "HW Version") +local hf_bi_sw_provider = ProtoField.string("usb_simtrace.board_info.sw.provider", "SW Provider") +local hf_bi_sw_name = ProtoField.string("usb_simtrace.board_info.sw.name", "SW Name") +local hf_bi_sw_version = ProtoField.string("usb_simtrace.board_info.sw.version", "SW Version") +local hf_bi_sw_buildhost = ProtoField.string("usb_simtrace.board_info.sw.buildhost", "Build Host") +local hf_bi_sw_crc = ProtoField.uint32("usb_simtrace.board_info.sw.crc", "SW CRC", base.HEX) +local hf_bi_max_baud = ProtoField.uint32("usb_simtrace.board_info.max_baud_rate", "Max Baud Rate", base.DEC) +local hf_bi_cap_generic_bytes = ProtoField.uint8("usb_simtrace.board_info.cap_generic_bytes", "Generic Capability Bytes", base.DEC) +local hf_bi_cap_vendor_bytes = ProtoField.uint8("usb_simtrace.board_info.cap_vendor_bytes", "Vendor Capability Bytes", base.DEC) +local hf_bi_cap_data = ProtoField.bytes("usb_simtrace.board_info.cap_data", "Capability Data") + +local hf_atr_len = ProtoField.uint8("usb_simtrace.atr_len", "ATR Length", base.DEC) +local hf_atr_data = ProtoField.bytes("usb_simtrace.atr_data", "ATR Data") + +local hf_sniff_change_flags = ProtoField.uint32("usb_simtrace.sniff.change_flags", "Change Flags", base.HEX) +local hf_sniff_chg_card_insert = ProtoField.uint32("usb_simtrace.sniff.change.card_insert", "Card Insert", base.HEX_DEC, NULL, 0x00000001) +local hf_sniff_chg_card_eject = ProtoField.uint32("usb_simtrace.sniff.change.card_eject", "Card Eject", base.HEX_DEC, NULL, 0x00000002) +local hf_sniff_chg_reset_assert = ProtoField.uint32("usb_simtrace.sniff.change.reset_assert", "Reset Assert", base.HEX_DEC, NULL, 0x00000004) +local hf_sniff_chg_reset_deassert = ProtoField.uint32("usb_simtrace.sniff.change.reset_deassert", "Reset Deassert", base.HEX_DEC, NULL, 0x00000008) +local hf_sniff_chg_timeout_wt = ProtoField.uint32("usb_simtrace.sniff.change.timeout_wt", "Timeout WT", base.HEX_DEC, NULL, 0x00000010) + +local hf_sniff_fidi = ProtoField.uint8("usb_simtrace.sniff.fidi", "Fi/Di (TA1)", base.HEX) + +-- shared by SNIFF_ATR, SNIFF_PPS, SNIFF_TPDU +local hf_sniff_data_flags = ProtoField.uint32("usb_simtrace.sniff.data.flags", "Data Flags", base.HEX) +local hf_sniff_data_f_incomplete = ProtoField.uint32("usb_simtrace.sniff.data.flag.incomplete", "Incomplete", base.HEX_DEC, NULL, 0x00000020) +local hf_sniff_data_f_malformed = ProtoField.uint32("usb_simtrace.sniff.data.flag.malformed", "Malformed", base.HEX_DEC, NULL, 0x00000040) +local hf_sniff_data_f_checksum = ProtoField.uint32("usb_simtrace.sniff.data.flag.checksum_err", "Checksum Error", base.HEX_DEC, NULL, 0x00000080) +local hf_sniff_data_f_overrun = ProtoField.uint32("usb_simtrace.sniff.data.flag.overrun", "Overrun", base.HEX_DEC, NULL, 0x00000100) +local hf_sniff_data_f_framing = ProtoField.uint32("usb_simtrace.sniff.data.flag.framing_err", "Framing Error", base.HEX_DEC, NULL, 0x00000200) +local hf_sniff_data_f_parity = ProtoField.uint32("usb_simtrace.sniff.data.flag.parity_err", "Parity Error", base.HEX_DEC, NULL, 0x00000400) +local hf_sniff_data_len = ProtoField.uint16("usb_simtrace.sniff.data.length", "Data Length", base.DEC) +local hf_sniff_data = ProtoField.bytes("usb_simtrace.sniff.data.data", "Data") + + usb_simtrace_protocol.fields = { - msgtype, seqnr, slotnr, reserved, payloadlen, payload, + hf_msg_class, hf_msg_type, msgtype, seqnr, slotnr, reserved, payloadlen, payload, pb_and_rx, pb_and_tx, final, tpdu_hdr, rxtxdatalen, rxtxdata, + hf_tpdu_cla, hf_tpdu_ins, hf_tpdu_p1, hf_tpdu_p2, hf_tpdu_p3, hf_tpdu_pb, hf_tpdu_sw1, hf_tpdu_sw2, CEMU_STATUS_F_VCC_PRESENT, CEMU_STATUS_F_CLK_ACTIVE, CEMU_STATUS_F_RCEMU_ACTIVE, CEMU_STATUS_F_CARD_INSERT, CEMU_STATUS_F_RESET_ACTIVE, + hf_status_voltage, hf_status_fi, hf_status_di, hf_status_wi, hf_status_wt, CEMU_CONFIG_PRES_POL_PRES_H, CEMU_CONFIG_PRES_POL_VALID, modem_reset_status, modem_reset_len, hf_pts_len, hf_pts_req, hf_pts_resp, - hf_cemu_cfg_features, hf_cemu_cfg_slot_mux_nr, hf_cemu_cfg_presence_polarity, + hf_cemu_cfg_features, hf_cemu_cfg_feat_status_irq, hf_cemu_cfg_slot_mux_nr, hf_cemu_cfg_presence_polarity, hf_cemu_cardinsert, hf_modem_sim_select, + hf_modem_status_supported, hf_modem_status_current, hf_modem_status_changed, + hf_mdm_sts_wwan, hf_mdm_sts_card, + hf_error_severity, hf_error_subsystem, hf_error_code, hf_error_msg_len, hf_error_msg, + hf_bi_hw_manufacturer, hf_bi_hw_model, hf_bi_hw_version, + hf_bi_sw_provider, hf_bi_sw_name, hf_bi_sw_version, hf_bi_sw_buildhost, hf_bi_sw_crc, + hf_bi_max_baud, hf_bi_cap_generic_bytes, hf_bi_cap_vendor_bytes, hf_bi_cap_data, + hf_atr_len, hf_atr_data, + hf_sniff_change_flags, hf_sniff_chg_card_insert, hf_sniff_chg_card_eject, + hf_sniff_chg_reset_assert, hf_sniff_chg_reset_deassert, hf_sniff_chg_timeout_wt, + hf_sniff_fidi, + hf_sniff_data_flags, hf_sniff_data_f_incomplete, hf_sniff_data_f_malformed, + hf_sniff_data_f_checksum, hf_sniff_data_f_overrun, hf_sniff_data_f_framing, + hf_sniff_data_f_parity, hf_sniff_data_len, hf_sniff_data, }
-local is_hdr = Field.new("usb_simtrace.tpdu_hdr") -local is_pbrx = Field.new("usb_simtrace.pb_and_rx") -local is_pbtx = Field.new("usb_simtrace.pb_and_tx") -local is_final= Field.new("usb_simtrace.final") +-- unfortunately no easy dissection due to mixed in procedure bytes +-- that would need complicated reassembly of fragments, but this is enough to be useful
-function dissect_rxtx(payload_data,pinfo,tree) +function dissect_rxtx(payload_data, pinfo, tree, command) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "rx/tx data") + local flags = payload_data(0,4):le_uint() + local len = payload_data(4,2):le_uint()
- local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "rx/tx data") - local len = payload_data(4,2):le_uint(); - local cmd32 = payload_data(0,4):le_uint(); + subtree:add_le(pb_and_rx, payload_data(0,4)) + subtree:add_le(pb_and_tx, payload_data(0,4)) + subtree:add_le(final, payload_data(0,4)) + subtree:add_le(tpdu_hdr, payload_data(0,4))
- headerSubtree:add(pb_and_rx, cmd32) - headerSubtree:add(pb_and_tx, cmd32) - headerSubtree:add(final, cmd32) - headerSubtree:add(tpdu_hdr, cmd32) + subtree:add_le(rxtxdatalen, payload_data(4,2)) + subtree:add(rxtxdata, payload_data(6, len))
- headerSubtree:add(rxtxdatalen, len) - headerSubtree:add_le(rxtxdata, payload_data(6,len)) + local f_pbrx = bit.band(flags, 0x08) ~= 0 + local f_pbtx = bit.band(flags, 0x04) ~= 0 + local f_final = bit.band(flags, 0x02) ~= 0 + local f_hdr = bit.band(flags, 0x01) ~= 0
- local flagstr = " " - if is_pbrx().value == 1 then - flagstr = flagstr .. "R" - else - flagstr = flagstr .. "." + local flagstr = " " .. (f_pbrx and "R" or ".") .. (f_pbtx and "T" or ".") + .. (f_final and "F" or ".") .. (f_hdr and "H" or ".") + + local data_off = 6 + + if f_hdr and len >= 5 then + local hdr_tree = subtree:add(usb_simtrace_protocol, payload_data(data_off, 5), "TPDU Header") + hdr_tree:add(hf_tpdu_cla, payload_data(data_off, 1)) + hdr_tree:add(hf_tpdu_ins, payload_data(data_off + 1, 1)) + hdr_tree:add(hf_tpdu_p1, payload_data(data_off + 2, 1)) + hdr_tree:add(hf_tpdu_p2, payload_data(data_off + 3, 1)) + hdr_tree:add(hf_tpdu_p3, payload_data(data_off + 4, 1)) + + local ins = payload_data(data_off + 1, 1):uint() + local ins_name = ins_names[ins] or string.format("INS=%02X", ins) + pinfo.cols.info:append(string.format("%s %s P1=%02X P2=%02X P3=%02X", + flagstr, ins_name, + payload_data(data_off + 2, 1):uint(), + payload_data(data_off + 3, 1):uint(), + payload_data(data_off + 4, 1):uint())) + return end - if is_pbtx().value == 1 then - flagstr = flagstr .. "T" - else - flagstr = flagstr .. "." + + local pb_size = 0 + if (f_pbrx or f_pbtx) and len >= 1 then + subtree:add(hf_tpdu_pb, payload_data(data_off, 1)) + pb_size = 1 end - if is_final().value == 1 then - flagstr = flagstr .. "F" + + if f_final and command == 0x0101 and len >= (pb_size + 2) then + local sw1_off = data_off + len - 2 + subtree:add(hf_tpdu_sw1, payload_data(sw1_off, 1)) + subtree:add(hf_tpdu_sw2, payload_data(sw1_off + 1, 1)) + + local sw1 = payload_data(sw1_off, 1):uint() + local sw2 = payload_data(sw1_off + 1, 1):uint() + local sw_text = string.format("SW=%02X%02X", sw1, sw2) + local sw_name = sw1_names[sw1] + if sw_name then sw_text = sw_text .. " (" .. sw_name .. ")" end + + local resp_len = len - pb_size - 2 + if pb_size > 0 then + pinfo.cols.info:append(string.format("%s PB=%02X", flagstr, payload_data(data_off, 1):uint())) + else + pinfo.cols.info:append(flagstr) + end + if resp_len > 0 then + pinfo.cols.info:append(string.format(" [%d bytes]", resp_len)) + end + pinfo.cols.info:append(" " .. sw_text) else - flagstr = flagstr .. "." + if pb_size > 0 then + pinfo.cols.info:append(string.format("%s PB=%02X", flagstr, payload_data(data_off, 1):uint())) + else + pinfo.cols.info:append(flagstr) + end + local remaining = len - pb_size + if remaining > 0 then + pinfo.cols.info:append(" " .. payload_data(data_off + pb_size, remaining)) + end end - if is_hdr().value == 1 then - flagstr = flagstr .. "H" - else - flagstr = flagstr .. "." - end - flagstr = flagstr .. " " - pinfo.cols.info:append(flagstr .. payload_data(6,len)) - - -- ghetto dissection does not work due to mixed in procedure bytes - --if pinfo.visited == false then - -- Dissector.get("iso7816"):call(payload_data(6):tvb(), pinfo, tree) - --- local offs = 0 --- if (is_pbrx().value == 1 or is_pbtx().value == 1) and is_final().value == 0 then --- offs = 1 --- else --- offs = 0 --- end --- --- if is_hdr().value == 1 then --- Dissector.get("gsm_sim"):call(concatss:tvb(), pinfo, tree) --- concatss = payload_data(6):bytes() --- else --- concatss = concatss .. payload_data(6+offs):bytes() --- end - ---end - end
-function dissect_status(payload_data,pinfo,tree) +function dissect_status(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "status message")
- local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "status message") - local cmd32 = payload_data(0,4):le_uint(); + subtree:add_le(CEMU_STATUS_F_VCC_PRESENT, payload_data(0,4)) + subtree:add_le(CEMU_STATUS_F_CLK_ACTIVE, payload_data(0,4)) + subtree:add_le(CEMU_STATUS_F_RCEMU_ACTIVE, payload_data(0,4)) + subtree:add_le(CEMU_STATUS_F_CARD_INSERT, payload_data(0,4)) + subtree:add_le(CEMU_STATUS_F_RESET_ACTIVE, payload_data(0,4))
- headerSubtree:add(CEMU_STATUS_F_VCC_PRESENT, cmd32) - headerSubtree:add(CEMU_STATUS_F_CLK_ACTIVE, cmd32) - headerSubtree:add(CEMU_STATUS_F_RCEMU_ACTIVE, cmd32) - headerSubtree:add(CEMU_STATUS_F_CARD_INSERT, cmd32) - headerSubtree:add(CEMU_STATUS_F_RESET_ACTIVE, cmd32) + if payload_data:len() >= 6 then + subtree:add_le(hf_status_voltage, payload_data(4,2)) + end + if payload_data:len() >= 7 then + subtree:add(hf_status_fi, payload_data(6,1)) + end + if payload_data:len() >= 8 then + subtree:add(hf_status_di, payload_data(7,1)) + end + if payload_data:len() >= 9 then + subtree:add(hf_status_wi, payload_data(8,1)) + end + if payload_data:len() >= 13 then + subtree:add_le(hf_status_wt, payload_data(9,4)) + end
pinfo.cols.info:append(" VCC:" .. payload_data(0,1):bitfield(7, 1) .. " CLK:" .. payload_data(0,1):bitfield(6, 1) .. " RESET:" .. payload_data(0,1):bitfield(3, 1)) -end
-function dissect_atr(payload_data,pinfo,tree) - - local len = payload_data(0,1):le_uint() - Dissector.get("iso7816.atr"):call(payload_data(1):tvb(), pinfo, tree) -end - -function dissect_modem_reset(payload_data,pinfo,tree) - - local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "modem reset") - local cmd8 = payload_data(0,1):le_uint(); - - headerSubtree:add(modem_reset_status, cmd8) - pinfo.cols.info:append(" reset type:" .. modem_reset_types[cmd8]); - - if(cmd8 == 2) then - local duration = payload_data(1,2):le_uint() - headerSubtree:add(modem_reset_len, duration) - pinfo.cols.info:append(" duration:" .. duration .. "ms") + if payload_data:len() >= 6 then + local voltage = payload_data(4,2):le_uint() + if voltage > 0 then + pinfo.cols.info:append(" " .. voltage .. "mV") + end end + if payload_data:len() >= 9 then + pinfo.cols.info:append(" Fi=" .. payload_data(6,1):uint() .. " Di=" .. payload_data(7,1):uint() .. " Wi=" .. payload_data(8,1):uint()) + end +end
+function dissect_atr(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Set ATR") + local len = payload_data(0,1):le_uint()
+ subtree:add(hf_atr_len, payload_data(0,1)) + + if len > 0 and payload_data:len() > 1 then + subtree:add(hf_atr_data, payload_data(1, len)) + local ok, dissector = pcall(Dissector.get, "iso7816.atr") + if ok and dissector then + dissector:call(payload_data(1):tvb(), pinfo, tree) + end + pinfo.cols.info:append(" ATR:" .. payload_data(1, len)) + end +end + +function dissect_modem_reset(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "modem reset") + local cmd8 = payload_data(0,1):le_uint() + + subtree:add(modem_reset_status, payload_data(0,1)) + pinfo.cols.info:append(" reset type:" .. (modem_reset_types[cmd8] or "unknown")) + + if cmd8 == 2 and payload_data:len() >= 3 then + subtree:add_le(modem_reset_len, payload_data(1,2)) + local duration = payload_data(1,2):le_uint() + pinfo.cols.info:append(" duration:" .. duration .. "ms") + end end
function dissect_pts(payload_data, pinfo, tree) local subtree = tree:add(usb_simtrace_protocol, payload_data, "PTS") local pts_len = payload_data(0,1):le_uint() - local pts_req = payload_data(1, pts_len); - local pts_resp = payload_data(7, pts_len); + local pts_req = payload_data(1, pts_len) + local pts_resp = payload_data(7, pts_len)
- subtree:add(hf_pts_len, pts_len); - subtree:add(hf_pts_req, pts_req); - subtree:add(hf_pts_resp, pts_resp); + subtree:add(hf_pts_len, payload_data(0,1)) + subtree:add(hf_pts_req, pts_req) + subtree:add(hf_pts_resp, pts_resp)
- pinfo.cols.info:append(" Req: " .. pts_req .. ", Resp: " .. pts_resp); + pinfo.cols.info:append(" Req: " .. pts_req .. ", Resp: " .. pts_resp) end
function dissect_cemu_config(payload_data, pinfo, tree) local subtree = tree:add(usb_simtrace_protocol, payload_data, "Card Emu Config")
- subtree:add(hf_cemu_cfg_features, payload_data(0,4)); - if payload_data:len() >= 4 then - subtree:add(hf_cemu_cfg_slot_mux_nr, payload_data(4,1)); - end + subtree:add_le(hf_cemu_cfg_features, payload_data(0,4)) + subtree:add_le(hf_cemu_cfg_feat_status_irq, payload_data(0,4)) + if payload_data:len() >= 5 then - local pres = payload_data(5,1):le_uint(); - subtree:add(hf_cemu_cfg_presence_polarity, payload_data(5,1)); - headerSubtree:add(CEMU_CONFIG_PRES_POL_PRES_H, pres) - headerSubtree:add(CEMU_CONFIG_PRES_POL_VALID, pres) + subtree:add(hf_cemu_cfg_slot_mux_nr, payload_data(4,1)) + end + if payload_data:len() >= 6 then + subtree:add(hf_cemu_cfg_presence_polarity, payload_data(5,1)) + subtree:add(CEMU_CONFIG_PRES_POL_PRES_H, payload_data(5,1)) + subtree:add(CEMU_CONFIG_PRES_POL_VALID, payload_data(5,1)) end end
function dissect_modem_sim_sel(payload_data, pinfo, tree) local subtree = tree:add(usb_simtrace_protocol, payload_data, "Modem SIM Select") - local sim_select = payload_data(0,1):le_uint(); + local sim_select = payload_data(0,1):le_uint()
- subtree:add(hf_modem_sim_select, sim_select); - pinfo.cols.info:append(" " .. modem_sim_select_types[sim_select]); + subtree:add(hf_modem_sim_select, payload_data(0,1)) + pinfo.cols.info:append(" " .. (modem_sim_select_types[sim_select] or "unknown")) end
function dissect_cemu_cardinsert(payload_data, pinfo, tree) local subtree = tree:add(usb_simtrace_protocol, payload_data, "Card Insert") local cins_type = payload_data(0,1):le_uint()
- subtree:add(hf_cemu_cardinsert, cins_type); - pinfo.cols.info:append(" " .. card_insert_types[cins_type]); + subtree:add(hf_cemu_cardinsert, payload_data(0,1)) + pinfo.cols.info:append(" " .. (card_insert_types[cins_type] or "unknown")) end
+function dissect_error(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Error") + + subtree:add(hf_error_severity, payload_data(0,1)) + subtree:add(hf_error_subsystem, payload_data(1,1)) + subtree:add_le(hf_error_code, payload_data(2,2)) + + local severity = payload_data(0,1):uint() + local subsys = payload_data(1,1):uint() + local code = payload_data(2,2):le_uint() + + if payload_data:len() >= 5 then + local msg_len = payload_data(4,1):uint() + subtree:add(hf_error_msg_len, payload_data(4,1)) + if msg_len > 0 and payload_data:len() >= 5 + msg_len then + subtree:add(hf_error_msg, payload_data(5, msg_len)) + end + end + + pinfo.cols.info:append(string.format(" severity=%d subsys=%d code=0x%04X", severity, subsys, code)) +end + +function dissect_board_info(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Board Info") + + if payload_data:len() < 230 then + subtree:add(payload, payload_data) + return + end + + subtree:add(hf_bi_hw_manufacturer, payload_data(0, 32)) + subtree:add(hf_bi_hw_model, payload_data(32, 32)) + subtree:add(hf_bi_hw_version, payload_data(64, 32)) + subtree:add(hf_bi_sw_provider, payload_data(96, 32)) + subtree:add(hf_bi_sw_name, payload_data(128, 32)) + subtree:add(hf_bi_sw_version, payload_data(160, 32)) + subtree:add(hf_bi_sw_buildhost, payload_data(192, 32)) + subtree:add_le(hf_bi_sw_crc, payload_data(224, 4)) + subtree:add_le(hf_bi_max_baud, payload_data(228, 4)) + subtree:add(hf_bi_cap_generic_bytes, payload_data(232, 1)) + subtree:add(hf_bi_cap_vendor_bytes, payload_data(233, 1)) + + local cap_generic = payload_data(232,1):uint() + local cap_vendor = payload_data(233,1):uint() + local cap_total = cap_generic + cap_vendor + if cap_total > 0 and payload_data:len() >= 234 + cap_total then + subtree:add(hf_bi_cap_data, payload_data(234, cap_total)) + end + + local model = payload_data(32, 32):string() + local version = payload_data(160, 32):string() + pinfo.cols.info:append(" " .. model .. " " .. version) +end + +function dissect_modem_status(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Modem Status") + + subtree:add(hf_modem_status_supported, payload_data(0,1)) + subtree:add(hf_mdm_sts_wwan, payload_data(0,1)) + subtree:add(hf_mdm_sts_card, payload_data(0,1)) + + subtree:add(hf_modem_status_current, payload_data(1,1)) + subtree:add(hf_mdm_sts_wwan, payload_data(1,1)) + subtree:add(hf_mdm_sts_card, payload_data(1,1)) + + subtree:add(hf_modem_status_changed, payload_data(2,1)) + + local status = payload_data(1,1):uint() + local wwan = bit.band(status, 0x01) + local card = bit.rshift(bit.band(status, 0x02), 1) + pinfo.cols.info:append(string.format(" WWAN:%d CARD:%d", wwan, card)) +end + +function dissect_sniff_change(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Sniff Change") + local flags = payload_data(0,4):le_uint() + + subtree:add_le(hf_sniff_change_flags, payload_data(0,4)) + subtree:add_le(hf_sniff_chg_card_insert, payload_data(0,4)) + subtree:add_le(hf_sniff_chg_card_eject, payload_data(0,4)) + subtree:add_le(hf_sniff_chg_reset_assert, payload_data(0,4)) + subtree:add_le(hf_sniff_chg_reset_deassert, payload_data(0,4)) + subtree:add_le(hf_sniff_chg_timeout_wt, payload_data(0,4)) + + local parts = {} + if bit.band(flags, 0x01) ~= 0 then parts[#parts+1] = "INSERT" end + if bit.band(flags, 0x02) ~= 0 then parts[#parts+1] = "EJECT" end + if bit.band(flags, 0x04) ~= 0 then parts[#parts+1] = "RST_ASSERT" end + if bit.band(flags, 0x08) ~= 0 then parts[#parts+1] = "RST_DEASSERT" end + if bit.band(flags, 0x10) ~= 0 then parts[#parts+1] = "TIMEOUT_WT" end + pinfo.cols.info:append(" " .. table.concat(parts, ",")) +end + +function dissect_sniff_fidi(payload_data, pinfo, tree) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Sniff FiDi") + + subtree:add(hf_sniff_fidi, payload_data(0,1)) + pinfo.cols.info:append(string.format(" FiDi=0x%02X", payload_data(0,1):uint())) +end + +function dissect_sniff_data(payload_data, pinfo, tree, label) + local subtree = tree:add(usb_simtrace_protocol, payload_data, "Sniff " .. label) + local flags = payload_data(0,4):le_uint() + local len = payload_data(4,2):le_uint() + + subtree:add_le(hf_sniff_data_flags, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_incomplete, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_malformed, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_checksum, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_overrun, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_framing, payload_data(0,4)) + subtree:add_le(hf_sniff_data_f_parity, payload_data(0,4)) + subtree:add_le(hf_sniff_data_len, payload_data(4,2)) + + if len > 0 and payload_data:len() >= 6 + len then + subtree:add(hf_sniff_data, payload_data(6, len)) + pinfo.cols.info:append(" " .. payload_data(6, len)) + end + + if flags ~= 0 then + local parts = {} + if bit.band(flags, 0x020) ~= 0 then parts[#parts+1] = "INCOMPLETE" end + if bit.band(flags, 0x040) ~= 0 then parts[#parts+1] = "MALFORMED" end + if bit.band(flags, 0x080) ~= 0 then parts[#parts+1] = "CHECKSUM" end + if bit.band(flags, 0x100) ~= 0 then parts[#parts+1] = "OVERRUN" end + if bit.band(flags, 0x200) ~= 0 then parts[#parts+1] = "FRAMING" end + if bit.band(flags, 0x400) ~= 0 then parts[#parts+1] = "PARITY" end + if #parts > 0 then + pinfo.cols.info:append(" [" .. table.concat(parts, ",") .. "]") + end + end +end
function usb_simtrace_protocol.dissector(buffer, pinfo, tree) length = buffer:len() if length == 0 then return end + if length < 8 then return 0 end + + local msg_class = buffer(0,1):uint() + if msg_class > 3 then return 0 end
pinfo.cols.protocol = usb_simtrace_protocol.name
local subtree = tree:add(usb_simtrace_protocol, buffer(), "USB simtrace Data") local command = buffer(0,2):uint()
+ subtree:add(hf_msg_class, buffer(0,1)) + subtree:add(hf_msg_type, buffer(1,1)) subtree:add(msgtype, command):set_generated() subtree:add(seqnr, buffer(2,1)) subtree:add(slotnr, buffer(3,1)) + subtree:add_le(reserved, buffer(4,2)) subtree:add_le(payloadlen, buffer(6,2)) - pinfo.cols.info = string.format("Cmd 0x%04X : %s", command, control_commands[command]) - local payload_data = buffer(8,length-8) - if(command == 0x0101 or command == 0x0106) then - return dissect_rxtx(payload_data(),pinfo,subtree) - elseif(command == 0x0104) then - return dissect_status(payload_data(),pinfo,subtree) - elseif(command == 0x0102) then - return dissect_atr(payload_data(),pinfo,subtree) - elseif(command == 0x0105) then - return dissect_cemu_cardinsert(payload_data(),pinfo,subtree) - elseif(command == 0x0107) then - return dissect_pts(payload_data(),pinfo,subtree) - elseif(command == 0x0108) then - return dissect_cemu_config(payload_data(),pinfo,subtree) - elseif(command == 0x0201) then - return dissect_modem_reset(payload_data(),pinfo,subtree) - elseif(command == 0x0202) then - return dissect_modem_sim_sel(payload_data(),pinfo,subtree) + + local cmd_name = control_commands[command] + if cmd_name then + pinfo.cols.info = cmd_name + else + pinfo.cols.info = string.format("Unknown (0x%04X)", command) + end + + if length <= 8 then return end + local payload_data = buffer(8, length - 8) + + if command == 0x0101 or command == 0x0106 then + return dissect_rxtx(payload_data(), pinfo, subtree, command) + elseif command == 0x0104 then + return dissect_status(payload_data(), pinfo, subtree) + elseif command == 0x0102 then + return dissect_atr(payload_data(), pinfo, subtree) + elseif command == 0x0105 then + return dissect_cemu_cardinsert(payload_data(), pinfo, subtree) + elseif command == 0x0107 then + return dissect_pts(payload_data(), pinfo, subtree) + elseif command == 0x0108 then + return dissect_cemu_config(payload_data(), pinfo, subtree) + elseif command == 0x0201 then + return dissect_modem_reset(payload_data(), pinfo, subtree) + elseif command == 0x0202 then + return dissect_modem_sim_sel(payload_data(), pinfo, subtree) + elseif command == 0x0203 then + return dissect_modem_status(payload_data(), pinfo, subtree) + elseif command == 0x0000 then + return dissect_error(payload_data(), pinfo, subtree) + elseif command == 0x0001 then + return dissect_board_info(payload_data(), pinfo, subtree) + elseif command == 0x0300 then + return dissect_sniff_change(payload_data(), pinfo, subtree) + elseif command == 0x0301 then + return dissect_sniff_fidi(payload_data(), pinfo, subtree) + elseif command == 0x0302 then + return dissect_sniff_data(payload_data(), pinfo, subtree, "ATR") + elseif command == 0x0303 then + return dissect_sniff_data(payload_data(), pinfo, subtree, "PPS") + elseif command == 0x0304 then + return dissect_sniff_data(payload_data(), pinfo, subtree, "TPDU") else subtree:add(payload, payload_data) end - end