]> The Tcpdump Group git mirrors - libpcap/commitdiff
Probe CONFIGURATION descriptor of connected USB devices 895/head
authorTomasz Moń <[email protected]>
Wed, 25 Dec 2019 13:17:12 +0000 (14:17 +0100)
committerTomasz Moń <[email protected]>
Thu, 26 Dec 2019 08:26:45 +0000 (09:26 +0100)
The DEVICE descriptor alone is not enough for full fledged USB class
(eg. Communications, Audio) dissection. Read CONFIGURATION descriptor
twice. First time just with the mandatory 9 bytes, and then using the
wTotalLength to get full CONFIGURATION. Do not attempt requesting full
65535 bytes as many devices do not return the descriptor in such case.

While the DEVICE and CONFIGURATION descriptors are not allowing full
dissection for all cases (eg. HID devices need also report descriptors)
knowing the CONFIGURATION descriptor makes the dissection possible in
many cases.

pcap-usb-linux.c

index d6e368ddb6454d6d4f15a9534112846238f1199f..4debdee1dc8280430d4f58d5d7a4c7ee0c66ca5b 100644 (file)
@@ -489,8 +489,10 @@ int usb_mmap(pcap_t* handle)
 #define USB_REQ_GET_DESCRIPTOR 6
 
 #define USB_DT_DEVICE          1
+#define USB_DT_CONFIG          2
 
 #define USB_DEVICE_DESCRIPTOR_SIZE     18
+#define USB_CONFIG_DESCRIPTOR_SIZE     9
 
 /* probe the descriptors of the devices attached to the bus */
 /* the descriptors will end up in the captured packet stream */
@@ -504,7 +506,8 @@ probe_devices(int bus)
        int ret = 0;
        char busdevpath[sizeof("/dev/bus/usb/000/") + NAME_MAX];
        DIR* dir;
-       char descriptor[USB_DEVICE_DESCRIPTOR_SIZE];
+       uint8_t descriptor[USB_DEVICE_DESCRIPTOR_SIZE];
+       uint8_t configdesc[USB_CONFIG_DESCRIPTOR_SIZE];
 
        /* scan usb bus directories for device nodes */
        snprintf(busdevpath, sizeof(busdevpath), "/dev/bus/usb/%03d", bus);
@@ -547,6 +550,30 @@ probe_devices(int bus)
 
                ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
 
+               /* Request CONFIGURATION descriptor alone to know wTotalLength */
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+               ctrl.wValue = USB_DT_CONFIG << 8;
+               ctrl.wLength = sizeof(configdesc);
+#else
+               ctrl.value = USB_DT_CONFIG << 8;
+               ctrl.length = sizeof(configdesc);
+#endif
+               ctrl.data = configdesc;
+               ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+               if (ret >= 0) {
+                       uint16_t wtotallength;
+                       wtotallength = (configdesc[2]) | (configdesc[3] << 8);
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+                       ctrl.wLength = wtotallength;
+#else
+                       ctrl.length = wtotallength;
+#endif
+                       ctrl.data = malloc(wtotallength);
+                       if (ctrl.data) {
+                               ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+                               free(ctrl.data);
+                       }
+               }
                close(fd);
        }
        closedir(dir);