aboutsummaryrefslogtreecommitdiff
path: root/decode/wmc.py
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-12-30 20:36:01 -0600
committerDan Williams <dcbw@redhat.com>2011-12-30 20:42:51 -0600
commitc9d0dea5b09f2b6ad3b6f199a32a5c282d3716bc (patch)
tree0e549f587e3437d2737127a0d317a7a853ec94c0 /decode/wmc.py
parenta2b578d755e51f820bbe015431ef02266454e66b (diff)
decode: add some python tools to decode SniffUSB dumps
decode.py will read SniffUSB logs of communication with QMUX or WMC speaking devices. It will dump the packets in both hex and ASCII. If you know something about the device then you can tell it to decode the packets. For example, we know the Pantech UML290's WMC port speaks WMC using Bulk Transfers, so we can: decode.py --transfer=wmc <path to sniffusb logs> or we know the UML290's "rmnet" port speaks raw IP in the Bulk Transfers and QMUX in the Control Transfers, so: decode.py --control=qmux <path to sniffusb logs> qmiprotgen.py takes a path to an Entities.txt file and dumps out the protocol entities and services in Python code which is used by qmux.py. xml2ascii.py and analyze.py dump out UsbSnoopy XML logs but these are not as usable as the SniffUSB logs (they do not provide good direction information). http://www.wingmanteam.com/usbsnoopy/ http://www.pcausa.com/Utilities/UsbSnoop/
Diffstat (limited to 'decode/wmc.py')
-rw-r--r--decode/wmc.py211
1 files changed, 211 insertions, 0 deletions
diff --git a/decode/wmc.py b/decode/wmc.py
new file mode 100644
index 00000000..cf7d9a91
--- /dev/null
+++ b/decode/wmc.py
@@ -0,0 +1,211 @@
+#!/usr/bin/python
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details:
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+
+import binascii
+import struct
+import defs
+
+def unpack(data, direction):
+ # unpack the data
+ if direction == defs.TO_MODEM:
+ if data[:14] == "41542a574d433d":
+ # remove the AT*WMC= bits, and the newline and CRC at the end
+ data = data[14:]
+ if data[len(data) - 2:] == "0d":
+ data = data[:len(data) - 6]
+ elif direction == defs.TO_HOST:
+ if data[len(data) - 2:] == "7e":
+ # remove HDLC terminator and CRC
+ data = data[:len(data) - 6]
+ else:
+ raise ValueError("No data direction")
+
+ data = binascii.unhexlify(data)
+
+ # PPP-unescape it
+ escape = False
+ new_data = ""
+ for i in data:
+ if ord(i) == 0x7D:
+ escape = True
+ elif escape == True:
+ new_data += chr(ord(i) ^ 0x20)
+ escape = False
+ else:
+ new_data += i
+
+ return new_data
+
+def show_data(data, prefix):
+ line = ""
+ for i in data:
+ line += " %02x" % ord(i)
+ print prefix + " Data: %s" % line
+
+def show_device_info(data, prefix, direction):
+ if direction != defs.TO_HOST:
+ return
+
+ fmt = "<"
+ fmt = fmt + "27s" # unknown1
+ fmt = fmt + "64s" # manf
+ fmt = fmt + "64s" # model
+ fmt = fmt + "64s" # fwrev
+ fmt = fmt + "64s" # hwrev
+ fmt = fmt + "64s" # unknown2
+ fmt = fmt + "64s" # unknown3
+ fmt = fmt + "10s" # min
+ fmt = fmt + "12s" # unknown4
+ fmt = fmt + "H" # home_sid
+ fmt = fmt + "6s" # unknown5
+ fmt = fmt + "H" # eri_ver?
+ fmt = fmt + "3s" # unknown6
+ fmt = fmt + "64s" # unknown7
+ fmt = fmt + "20s" # meid
+ fmt = fmt + "22s" # imei
+ fmt = fmt + "16s" # unknown9
+ fmt = fmt + "22s" # iccid
+ fmt = fmt + "4s" # unknown10
+ fmt = fmt + "16s" # MCC
+ fmt = fmt + "16s" # MNC
+ fmt = fmt + "4s" # unknown11
+ fmt = fmt + "4s" # unknown12
+ fmt = fmt + "4s" # unknown13
+ fmt = fmt + "1s"
+
+ expected = struct.calcsize(fmt)
+ if len(data) != expected:
+ raise ValueError("Unexpected Info command response len (got %d expected %d)" % (len(data), expected))
+ (u1, manf, model, fwrev, hwrev, u2, u3, cdmamin, u4, homesid, u5, eriver, \
+ u6, u7, meid, imei, u9, iccid, u10, mcc, mnc, u11, u12, u13, u14) = struct.unpack(fmt, data)
+
+ print prefix + " Manf: %s" % manf
+ print prefix + " Model: %s" % model
+ print prefix + " FW Rev: %s" % fwrev
+ print prefix + " HW Rev: %s" % hwrev
+ print prefix + " MIN: %s" % cdmamin
+ print prefix + " Home SID: %d" % homesid
+ print prefix + " ERI Ver: %d" % eriver
+ print prefix + " MEID: %s" % meid
+ print prefix + " IMEI: %s" % imei
+ print prefix + " Unk9: %s" % u9
+ print prefix + " ICCID: %s" % iccid
+ print prefix + " MCC: %s" % mcc
+ print prefix + " MNC: %s" % mnc
+
+def show_ip_info(data, prefix, direction):
+ if direction != defs.TO_HOST:
+ return
+
+ fmt = "<"
+ fmt = fmt + "I" # rx_bytes
+ fmt = fmt + "I" # tx_bytes
+ fmt = fmt + "8s" # unknown3
+ fmt = fmt + "B" # unknown4
+ fmt = fmt + "7s" # unknown7
+ fmt = fmt + "16s" # ip4_address
+ fmt = fmt + "8s" # netmask?
+ fmt = fmt + "40s" # ip6_address
+
+ expected = struct.calcsize(fmt)
+ if len(data) != expected:
+ raise ValueError("Unexpected IP Info command response len (got %d expected %d)" % (len(data), expected))
+ (rxb, txb, u3, u4, u7, ip4addr, netmask, ip6addr) = struct.unpack(fmt, data)
+
+ print prefix + " RX Bytes: %d" % rxb
+ print prefix + " TX Bytes: %d" % txb
+ print prefix + " IP4 Addr: %s" % ip4addr
+ print prefix + " IP6 Addr: %s" % ip6addr
+
+def get_signal(item):
+ if item == 0x7D:
+ return (item * -1, "(NO SIGNAL)")
+ else:
+ return (item * -1, "")
+
+def show_status(data, prefix, direction):
+ if direction != defs.TO_HOST:
+ return
+
+ fmt = "<"
+ fmt = fmt + "B" # unknown1
+ fmt = fmt + "3s" # unknown2
+ fmt = fmt + "B" # unknown3
+ fmt = fmt + "B" # unknown4
+ fmt = fmt + "10s" # magic
+ fmt = fmt + "H" # counter1
+ fmt = fmt + "H" # counter2
+ fmt = fmt + "B" # unknown5
+ fmt = fmt + "3s" # unknown6
+ fmt = fmt + "B" # cdma1x_dbm
+ fmt = fmt + "3s" # unknown7
+ fmt = fmt + "16s" # cdma_opname
+ fmt = fmt + "18s" # unknown8
+ fmt = fmt + "B" # hdr_dbm
+ fmt = fmt + "3s" # unknown9
+ fmt = fmt + "B" # unknown10
+ fmt = fmt + "3s" # unknown11
+ fmt = fmt + "B" # unknown12
+ fmt = fmt + "8s" # lte_opname
+ fmt = fmt + "60s" # unknown13
+ fmt = fmt + "B" # lte_dbm
+ fmt = fmt + "3s" # unknown14
+ fmt = fmt + "4s" # unknown15
+
+ expected = struct.calcsize(fmt)
+ if len(data) != expected:
+ raise ValueError("Unexpected Status command response len (got %d expected %d)" % (len(data), expected))
+ (u1, u2, u3, u4, magic, counter1, counter2, u5, u6, cdma_dbm, u7, cdma_opname, \
+ u8, hdr_dbm, u9, u10, u11, u12, lte_opname, u13, lte_dbm, u14, u15) = struct.unpack(fmt, data)
+
+ print prefix + " Counter1: %s" % counter1
+ print prefix + " Counter2: %s" % counter2
+ print prefix + " CDMA dBm: %d dBm %s" % get_signal(cdma_dbm)
+ print prefix + " CDMA Op: %s" % cdma_opname
+ print prefix + " HDR dBm: %d dBm %s" % get_signal(hdr_dbm)
+ print prefix + " LTE Op: %s" % lte_opname
+ print prefix + " LTE dBm: %d dBm %s" % get_signal(lte_dbm)
+
+def show_init(data, prefix, direction):
+ show_data(data, prefix)
+
+def show_bearer_info(data, prefix, direction):
+ pass
+
+cmds = { 0x06: ("DEVICE_INFO", show_device_info),
+ 0x0A: ("IP_INFO", show_ip_info),
+ 0x0B: ("STATUS", show_status),
+ 0x0D: ("INIT", show_init),
+ 0x4D: ("EPS_BEARER_INFO", show_bearer_info)
+ }
+
+def show(data, prefix, direction):
+ data = data[1:] # skip 0xC8 header
+ cmdno = ord(data[:1])
+ try:
+ cmdinfo = cmds[cmdno]
+ except KeyError:
+ return
+ data = data[1:] # skip cmdno
+
+ print prefix + "WMC Packet:"
+ print prefix + " Cmd: 0x%02x (%s)" % (cmdno, cmdinfo[0])
+ cmdinfo[1](data, prefix, direction)
+ print ""
+
+def get_funcs():
+ return (unpack, show)
+