Skip to content

Commit

Permalink
Implement pcap based USB replay
Browse files Browse the repository at this point in the history
The ioctl-tree based replay is mostly useful for protocols that are
fundamentally state-less. With state-full protocols, the ioctl-tree may
randomly jump around, cause confusing situations and gets the order
wrong during recording.

The pcap based replay is also able to play-back control transfers adding
this feature to umockdev, even if outside of the original ioctl-tree
implementation.

Note that umockdev does not support creating a recording. Recordings
should be done using a separate tool such as wireshark.

Closes: martinpitt#82, martinpitt#117
  • Loading branch information
Benjamin Berg authored and martinpitt committed Jun 15, 2021
1 parent fc722e4 commit 86d4809
Show file tree
Hide file tree
Showing 10 changed files with 954 additions and 3 deletions.
Binary file added devices/input/usbkbd.pcap.pcapng
Binary file not shown.
223 changes: 223 additions & 0 deletions devices/input/usbkbd.pcap.umockdev
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-3
N: bus/usb/001/011=1201100100000008D904031610030102000109023B00020100A032090400000103010100092110010001223E000705810308000A0904010001030000000921100100012265000705820308000A
E: DEVNAME=/dev/bus/usb/001/011
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=4d9/1603/310
E: TYPE=0/0/0
E: BUSNUM=001
E: DEVNUM=011
E: MAJOR=189
E: MINOR=10
E: SUBSYSTEM=usb
E: ID_VENDOR_ENC=\x20
E: ID_VENDOR_ID=04d9
E: ID_MODEL=USB_Keyboard
E: ID_MODEL_ENC=USB\x20Keyboard
E: ID_MODEL_ID=1603
E: ID_REVISION=0310
E: ID_SERIAL=_USB_Keyboard
E: ID_BUS=usb
E: ID_USB_INTERFACES=:030101:030000:
E: ID_VENDOR_FROM_DATABASE=Holtek Semiconductor, Inc.
E: ID_MODEL_FROM_DATABASE=Keyboard
E: ID_PATH=pci-0000:00:14.0-usb-0:3
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_3
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=00
A: bDeviceProtocol=00
A: bDeviceSubClass=00
A: bMaxPacketSize0=8
A: bMaxPower=100mA
A: bNumConfigurations=1
A: bNumInterfaces= 2
A: bcdDevice=0310
A: bmAttributes=a0
A: busnum=1
A: configuration=
H: descriptors=1201100100000008D904031610030102000109023B00020100A032090400000103010100092110010001223E000705810308000A0904010001030000000921100100012265000705820308000A
A: dev=189:10
A: devnum=11
A: devpath=3
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:20
A: idProduct=1603
A: idVendor=04d9
A: ltm_capable=no
A: manufacturer=
A: maxchild=0
L: port=../1-0:1.0/usb1-port3
A: power/active_duration=95563
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=95563
A: power/control=on
A: power/level=on
A: power/persist=1
A: power/runtime_active_time=95316
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=0
A: power/wakeup_count=0
A: power/wakeup_expire_count=0
A: power/wakeup_last_time_ms=0
A: power/wakeup_max_time_ms=0
A: power/wakeup_total_time_ms=0
A: product=USB Keyboard
A: quirks=0x0
A: removable=removable
A: rx_lanes=1
A: speed=1.5
A: tx_lanes=1
A: urbnum=30
A: version= 1.10

P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/512
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.12.6-300.fc34.x86_64_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.12.6-300.fc34.x86_64\x20xhci-hcd
E: ID_VENDOR_ID=1d6b
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002
E: ID_REVISION=0512
E: ID_SERIAL=Linux_5.12.6-300.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=1
A: authorized_default=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0512
A: bmAttributes=e0
A: busnum=1
A: configuration=
H: descriptors=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0
A: devnum=1
A: devpath=0
L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d
A: idProduct=0002
A: idVendor=1d6b
A: interface_authorized_default=1
A: ltm_capable=no
A: manufacturer=Linux 5.12.6-300.fc34.x86_64 xhci-hcd
A: maxchild=12
A: power/active_duration=95119218
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=95225105
A: power/control=auto
A: power/level=auto
A: power/runtime_active_time=95129156
A: power/runtime_status=active
A: power/runtime_suspended_time=88458
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=xHCI Host Controller
A: quirks=0x0
A: removable=unknown
A: rx_lanes=1
A: serial=0000:00:14.0
A: speed=480
A: tx_lanes=1
A: urbnum=1103
A: version= 2.00

P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: PCI_CLASS=C0330
E: PCI_ID=8086:9DED
E: PCI_SUBSYS_ID=17AA:2292
E: PCI_SLOT_NAME=0000:00:14.0
E: MODALIAS=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
E: SUBSYSTEM=pci
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
A: ari_enabled=0
A: broken_parity_status=0
A: class=0x0c0330
H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000
A: consistent_dma_mask_bits=64
A: d3cold_allowed=1
A: dbc=disabled
A: device=0x9ded
A: dma_mask_bits=64
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)
A: enable=1
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c
A: irq=128
A: local_cpulist=0-7
A: local_cpus=ff
A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
A: msi_bus=1
A: msi_irqs/128=msi
A: numa_node=-1
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 7 12 2112 12\nxHCI ring segments 20 50 4096 50\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 6 32 128 1\nbuffer-32 0 0 32 0
A: power/control=auto
A: power/runtime_active_time=95130693
A: power/runtime_status=active
A: power/runtime_suspended_time=87799
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=2
A: power/wakeup_count=0
A: power/wakeup_expire_count=2
A: power/wakeup_last_time_ms=95131060
A: power/wakeup_max_time_ms=115
A: power/wakeup_total_time_ms=229
A: power_state=D0
A: resource=0x00000000ea220000 0x00000000ea22ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0x11
A: subsystem_device=0x2292
A: subsystem_vendor=0x17aa
A: vendor=0x8086

9 changes: 7 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ gobject = dependency('gobject-2.0', version: '>= 2.32.0')
gio = dependency('gio-2.0', version: '>= 2.32.0')
gio_unix = dependency('gio-unix-2.0', version: '>= 2.32.0')
libudev = dependency('libudev')
libpcap = dependency('libpcap')
gudev = dependency('gudev-1.0', required: false)
python = find_program('python3', 'python', required: false)

Expand Down Expand Up @@ -102,21 +103,23 @@ umockdev_utils_lib = static_library('umockdev-utils',
umockdev_lib = shared_library('umockdev',
['src/umockdev.vala',
'src/umockdev-ioctl.vala',
'src/umockdev-pcap.vala',
'src/uevent_sender.vapi',
'src/uevent_sender.c',
'src/ioctl_tree.vapi',
'src/ioctl_tree.c',
'src/debug.c'],
vala_vapi: 'umockdev-1.0.vapi',
vala_gir: 'UMockdev-1.0.gir',
dependencies: [glib, gobject, gio, gio_unix, vapi_posix, vapi_linux, vapi_linux_fixes, vala_libudev, vala_libutil, vapi_ioctl],
dependencies: [glib, gobject, gio, gio_unix, vapi_posix, vapi_linux, vapi_linux_fixes, vala_libudev, vala_libutil, vapi_ioctl, libpcap],
link_with: [umockdev_utils_lib],
link_depends: ['src/umockdev.map'],
link_args: [
'-Wl,-export-dynamic',
'-Wl,--no-undefined',
'-Wl,--version-script,@0@/umockdev.map'.format(srcdir),
],
vala_args: [ '--vapidir=@0@/src'.format(meson.current_source_dir()) ],
include_directories: include_directories('src'),
version: lib_version,
install: true,
Expand Down Expand Up @@ -160,11 +163,13 @@ umockdev_run_exe = executable('umockdev-run',
umockdev_record_exe = executable('umockdev-record',
['src/umockdev-record.vala',
'src/umockdev-ioctl.vala',
'src/umockdev-pcap.vala',
'src/ioctl_tree.vapi',
'src/ioctl_tree.c',
'src/debug.c'],
dependencies: [glib, gobject, gio_unix, vapi_posix, vapi_config, vapi_ioctl],
dependencies: [glib, gobject, gio_unix, vapi_posix, vapi_config, vapi_ioctl, libpcap],
link_with: [umockdev_utils_lib],
vala_args: [ '--vapidir=@0@/src'.format(meson.current_source_dir()) ],
include_directories: include_directories('src'),
install: true)

Expand Down
31 changes: 31 additions & 0 deletions src/ioctl.vapi
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,39 @@ namespace Ioctl {
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_REAPURBNDELAY;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_DISCARDURB;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_GET_CAPABILITIES;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_RELEASEINTERFACE;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_CLEAR_HALT;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_RESET;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int USBDEVFS_RESETEP;
[CCode (cheader_filename = "sys/ioctl.h")]
public const int TIOCSBRK;

[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_ZERO_PACKET;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_BULK_CONTINUATION;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_NO_PACKET_SIZE_LIM;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_BULK_SCATTER_GATHER;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_REAP_AFTER_DISCONNECT;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_MMAP;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_DROP_PRIVILEGES;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_CONNINFO_EX;
[CCode (cheader_filename = "linux/usbdevice_fs.h")]
public const int USBDEVFS_CAP_SUSPEND;

[CCode (cheader_filename = "asm-generic/ioctl.h")]
public const int _IOC_SIZEBITS;
[CCode (cheader_filename = "asm-generic/ioctl.h")]
Expand Down
Loading

0 comments on commit 86d4809

Please sign in to comment.