diff options
Diffstat (limited to 'epan/dissectors/packet-usb.c')
-rw-r--r-- | epan/dissectors/packet-usb.c | 1357 |
1 files changed, 957 insertions, 400 deletions
diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c index 1df618caa7..99e6ae6ca5 100644 --- a/epan/dissectors/packet-usb.c +++ b/epan/dissectors/packet-usb.c @@ -33,96 +33,104 @@ #include "packet-usbip.h" #include "packet-netmon.h" +/* dissector handles */ +static dissector_handle_t linux_usb_handle; +static dissector_handle_t linux_usb_mmapped_handle; +static dissector_handle_t win32_usb_handle; +static dissector_handle_t freebsd_usb_handle; +static dissector_handle_t darwin_usb_handle; +static dissector_handle_t netmon_usb_port_handle; + /* protocols and header fields */ -static int proto_usb = -1; -static int proto_usbport = -1; +static int proto_usb; +static int proto_usbport; /* USB pseudoheader fields, both FreeBSD and Linux */ -static int hf_usb_totlen = -1; -static int hf_usb_busunit = -1; -static int hf_usb_address = -1; -static int hf_usb_mode = -1; -static int hf_usb_freebsd_urb_type = -1; -static int hf_usb_freebsd_transfer_type = -1; -static int hf_usb_xferflags = -1; -static int hf_usb_xferflags_force_short_xfer = -1; -static int hf_usb_xferflags_short_xfer_ok = -1; -static int hf_usb_xferflags_short_frames_ok = -1; -static int hf_usb_xferflags_pipe_bof = -1; -static int hf_usb_xferflags_proxy_buffer = -1; -static int hf_usb_xferflags_ext_buffer = -1; -static int hf_usb_xferflags_manual_status = -1; -static int hf_usb_xferflags_no_pipe_ok = -1; -static int hf_usb_xferflags_stall_pipe = -1; -static int hf_usb_xferstatus = -1; -static int hf_usb_xferstatus_open = -1; -static int hf_usb_xferstatus_transferring = -1; -static int hf_usb_xferstatus_did_dma_delay = -1; -static int hf_usb_xferstatus_did_close = -1; -static int hf_usb_xferstatus_draining = -1; -static int hf_usb_xferstatus_started = -1; -static int hf_usb_xferstatus_bw_reclaimed = -1; -static int hf_usb_xferstatus_control_xfr = -1; -static int hf_usb_xferstatus_control_hdr = -1; -static int hf_usb_xferstatus_control_act = -1; -static int hf_usb_xferstatus_control_stall = -1; -static int hf_usb_xferstatus_short_frames_ok = -1; -static int hf_usb_xferstatus_short_xfer_ok = -1; -static int hf_usb_xferstatus_bdma_enable = -1; -static int hf_usb_xferstatus_bdma_no_post_sync = -1; -static int hf_usb_xferstatus_bdma_setup = -1; -static int hf_usb_xferstatus_isochronous_xfr = -1; -static int hf_usb_xferstatus_curr_dma_set = -1; -static int hf_usb_xferstatus_can_cancel_immed = -1; -static int hf_usb_xferstatus_doing_callback = -1; -static int hf_usb_error = -1; -static int hf_usb_interval = -1; -static int hf_usb_nframes = -1; -static int hf_usb_packet_size = -1; -static int hf_usb_packet_count = -1; -static int hf_usb_speed = -1; -static int hf_usb_frame_length = -1; -static int hf_usb_frame_flags = -1; -static int hf_usb_frame_flags_read = -1; -static int hf_usb_frame_flags_data_follows = -1; -static int hf_usb_frame_data = -1; -static int hf_usb_urb_id = -1; -static int hf_usb_linux_urb_type = -1; -static int hf_usb_linux_transfer_type = -1; -static int hf_usb_endpoint_address = -1; -static int hf_usb_endpoint_direction = -1; -static int hf_usb_endpoint_number = -1; -static int hf_usb_device_address = -1; -static int hf_usb_bus_id = -1; -static int hf_usb_setup_flag = -1; -static int hf_usb_data_flag = -1; -static int hf_usb_urb_ts_sec = -1; -static int hf_usb_urb_ts_usec = -1; -static int hf_usb_urb_status = -1; -static int hf_usb_urb_len = -1; -static int hf_usb_urb_data_len = -1; -static int hf_usb_urb_unused_setup_header = -1; -static int hf_usb_urb_interval = -1; -static int hf_usb_urb_start_frame = -1; -static int hf_usb_urb_copy_of_transfer_flags = -1; +static int hf_usb_totlen; +static int hf_usb_busunit; +static int hf_usb_address; +static int hf_usb_mode; +static int hf_usb_freebsd_urb_type; +static int hf_usb_freebsd_transfer_type; +static int hf_usb_xferflags; +static int hf_usb_xferflags_force_short_xfer; +static int hf_usb_xferflags_short_xfer_ok; +static int hf_usb_xferflags_short_frames_ok; +static int hf_usb_xferflags_pipe_bof; +static int hf_usb_xferflags_proxy_buffer; +static int hf_usb_xferflags_ext_buffer; +static int hf_usb_xferflags_manual_status; +static int hf_usb_xferflags_no_pipe_ok; +static int hf_usb_xferflags_stall_pipe; +static int hf_usb_xferstatus; +static int hf_usb_xferstatus_open; +static int hf_usb_xferstatus_transferring; +static int hf_usb_xferstatus_did_dma_delay; +static int hf_usb_xferstatus_did_close; +static int hf_usb_xferstatus_draining; +static int hf_usb_xferstatus_started; +static int hf_usb_xferstatus_bw_reclaimed; +static int hf_usb_xferstatus_control_xfr; +static int hf_usb_xferstatus_control_hdr; +static int hf_usb_xferstatus_control_act; +static int hf_usb_xferstatus_control_stall; +static int hf_usb_xferstatus_short_frames_ok; +static int hf_usb_xferstatus_short_xfer_ok; +static int hf_usb_xferstatus_bdma_enable; +static int hf_usb_xferstatus_bdma_no_post_sync; +static int hf_usb_xferstatus_bdma_setup; +static int hf_usb_xferstatus_isochronous_xfr; +static int hf_usb_xferstatus_curr_dma_set; +static int hf_usb_xferstatus_can_cancel_immed; +static int hf_usb_xferstatus_doing_callback; +static int hf_usb_error; +static int hf_usb_interval; +static int hf_usb_nframes; +static int hf_usb_packet_size; +static int hf_usb_packet_count; +static int hf_usb_speed; +static int hf_usb_frame_length; +static int hf_usb_frame_flags; +static int hf_usb_frame_flags_read; +static int hf_usb_frame_flags_data_follows; +static int hf_usb_frame_data; +static int hf_usb_urb_id; +static int hf_usb_linux_urb_type; +static int hf_usb_linux_transfer_type; +static int hf_usb_endpoint_address; +static int hf_usb_endpoint_direction; +static int hf_usb_endpoint_number; +static int hf_usb_device_address; +static int hf_usb_bus_id; +static int hf_usb_setup_flag; +static int hf_usb_data_flag; +static int hf_usb_urb_ts_sec; +static int hf_usb_urb_ts_usec; +static int hf_usb_urb_status; +static int hf_usb_urb_len; +static int hf_usb_urb_data_len; +static int hf_usb_urb_unused_setup_header; +static int hf_usb_urb_interval; +static int hf_usb_urb_start_frame; +static int hf_usb_urb_copy_of_transfer_flags; /* transfer_flags */ -static int hf_short_not_ok = -1; -static int hf_iso_asap = -1; -static int hf_no_transfer_dma_map = -1; -static int hf_no_fsbr = -1; -static int hf_zero_packet = -1; -static int hf_no_interrupt = -1; -static int hf_free_buffer = -1; -static int hf_dir_in = -1; -static int hf_dma_map_single = -1; -static int hf_dma_map_page = -1; -static int hf_dma_map_sg = -1; -static int hf_map_local = -1; -static int hf_setup_map_single = -1; -static int hf_setup_map_local = -1; -static int hf_dma_sg_combined = -1; -static int hf_aligned_temp_buffer = -1; +static int hf_short_not_ok; +static int hf_iso_asap; +static int hf_no_transfer_dma_map; +static int hf_no_fsbr; +static int hf_zero_packet; +static int hf_no_interrupt; +static int hf_free_buffer; +static int hf_dir_in; +static int hf_dma_map_single; +static int hf_dma_map_page; +static int hf_dma_map_sg; +static int hf_map_local; +static int hf_setup_map_single; +static int hf_setup_map_local; +static int hf_dma_sg_combined; +static int hf_aligned_temp_buffer; static int * const transfer_flags_fields[] = { &hf_short_not_ok, @@ -145,237 +153,260 @@ static int * const transfer_flags_fields[] = { }; /* Win32 USBPcap pseudoheader fields */ -static int hf_usb_win32_header_len = -1; -static int hf_usb_irp_id = -1; -static int hf_usb_usbd_status = -1; -static int hf_usb_function = -1; -static int hf_usb_info = -1; -static int hf_usb_usbpcap_info_reserved = -1; -static int hf_usb_usbpcap_info_direction = -1; -static int hf_usb_win32_device_address = -1; -static int hf_usb_win32_transfer_type = -1; +static int hf_usb_win32_header_len; +static int hf_usb_irp_id; +static int hf_usb_usbd_status; +static int hf_usb_function; +static int hf_usb_info; +static int hf_usb_usbpcap_info_reserved; +static int hf_usb_usbpcap_info_direction; +static int hf_usb_win32_device_address; +static int hf_usb_win32_transfer_type; /* hf_usb_bus_id, hf_usb_endpoint_address, hf_usb_endpoint_direction, * hf_usb_endpoint_number are common with * FreeBSD and Linux pseudoheaders */ -static int hf_usb_win32_data_len = -1; -static int hf_usb_win32_control_stage = -1; -static int hf_usb_win32_iso_start_frame = -1; -static int hf_usb_win32_iso_num_packets = -1; -static int hf_usb_win32_iso_error_count = -1; -static int hf_usb_win32_iso_offset = -1; -static int hf_usb_win32_iso_length = -1; -static int hf_usb_win32_iso_status = -1; - -static int hf_usb_request = -1; -static int hf_usb_request_unknown_class = -1; -static int hf_usb_value = -1; -static int hf_usb_index = -1; -static int hf_usb_length = -1; -/* static int hf_usb_data_len = -1; */ -static int hf_usb_capdata = -1; -static int hf_usb_device_wFeatureSelector = -1; -static int hf_usb_interface_wFeatureSelector = -1; -static int hf_usb_endpoint_wFeatureSelector = -1; -static int hf_usb_wInterface = -1; -static int hf_usb_wEndpoint = -1; -static int hf_usb_wStatus = -1; -static int hf_usb_wFrameNumber = -1; - -static int hf_usb_iso_error_count = -1; -static int hf_usb_iso_numdesc = -1; -static int hf_usb_iso_status = -1; -static int hf_usb_iso_off = -1; -static int hf_usb_iso_len = -1; -static int hf_usb_iso_actual_len = -1; -static int hf_usb_iso_pad = -1; -static int hf_usb_iso_data = -1; - -static int hf_usb_bmRequestType = -1; -static int hf_usb_control_response_generic = -1; -static int hf_usb_bmRequestType_direction = -1; -static int hf_usb_bmRequestType_type = -1; -static int hf_usb_bmRequestType_recipient = -1; -static int hf_usb_bDescriptorType = -1; -static int hf_usb_get_descriptor_resp_generic = -1; -static int hf_usb_descriptor_index = -1; -static int hf_usb_language_id = -1; -static int hf_usb_bLength = -1; -static int hf_usb_bcdUSB = -1; -static int hf_usb_bDeviceClass = -1; -static int hf_usb_bDeviceSubClass = -1; -static int hf_usb_bDeviceProtocol = -1; -static int hf_usb_bMaxPacketSize0 = -1; -static int hf_usb_idVendor = -1; -static int hf_usb_idProduct = -1; -static int hf_usb_bcdDevice = -1; -static int hf_usb_iManufacturer = -1; -static int hf_usb_iProduct = -1; -static int hf_usb_iSerialNumber = -1; -static int hf_usb_bNumConfigurations = -1; -static int hf_usb_wLANGID = -1; -static int hf_usb_bString = -1; -static int hf_usb_bInterfaceNumber = -1; -static int hf_usb_bAlternateSetting = -1; -static int hf_usb_bNumEndpoints = -1; -static int hf_usb_bInterfaceClass = -1; -static int hf_usb_bInterfaceSubClass = -1; -static int hf_usb_bInterfaceSubClass_audio = -1; -static int hf_usb_bInterfaceSubClass_cdc = -1; -static int hf_usb_bInterfaceSubClass_massstorage = -1; -static int hf_usb_bInterfaceSubClass_hid = -1; -static int hf_usb_bInterfaceSubClass_misc = -1; -static int hf_usb_bInterfaceSubClass_app = -1; -static int hf_usb_bInterfaceProtocol = -1; -static int hf_usb_bInterfaceProtocol_cdc = -1; -static int hf_usb_bInterfaceProtocol_massstorage = -1; -static int hf_usb_bInterfaceProtocol_cdc_data = -1; -static int hf_usb_bInterfaceProtocol_hid_boot = -1; -static int hf_usb_bInterfaceProtocol_app_dfu = -1; -static int hf_usb_bInterfaceProtocol_app_irda = -1; -static int hf_usb_bInterfaceProtocol_app_usb_test_and_measurement = -1; -static int hf_usb_iInterface = -1; -static int hf_usb_bEndpointAddress = -1; -static int hf_usb_bmAttributes = -1; -static int hf_usb_bEndpointAttributeTransfer = -1; -static int hf_usb_bEndpointAttributeSynchonisation = -1; -static int hf_usb_bEndpointAttributeBehaviour = -1; -static int hf_usb_wMaxPacketSize = -1; -static int hf_usb_wMaxPacketSize_size = -1; -static int hf_usb_wMaxPacketSize_slots = -1; -static int hf_usb_bInterval = -1; -static int hf_usb_bMaxBurst = -1; -static int hf_usb_audio_bRefresh = -1; -static int hf_usb_audio_bSynchAddress = -1; -static int hf_usb_bSSEndpointAttributeBulkMaxStreams = -1; -static int hf_usb_bSSEndpointAttributeIsoMult = -1; -static int hf_usb_wBytesPerInterval = -1; -static int hf_usb_wTotalLength = -1; -static int hf_usb_bNumInterfaces = -1; -static int hf_usb_bConfigurationValue = -1; -static int hf_usb_iConfiguration = -1; -static int hf_usb_bMaxPower = -1; -static int hf_usb_configuration_bmAttributes = -1; -static int hf_usb_configuration_legacy10buspowered = -1; -static int hf_usb_configuration_selfpowered = -1; -static int hf_usb_configuration_remotewakeup = -1; -static int hf_usb_bEndpointAddress_direction = -1; -static int hf_usb_bEndpointAddress_number = -1; -static int hf_usb_response_in = -1; -static int hf_usb_time = -1; -static int hf_usb_request_in = -1; -static int hf_usb_bFirstInterface = -1; -static int hf_usb_bInterfaceCount = -1; -static int hf_usb_bFunctionClass = -1; -static int hf_usb_bFunctionSubClass = -1; -static int hf_usb_bFunctionProtocol = -1; -static int hf_usb_iFunction = -1; -static int hf_usb_data_fragment = -1; -static int hf_usb_src = -1; -static int hf_usb_dst = -1; -static int hf_usb_addr = -1; +static int hf_usb_win32_data_len; +static int hf_usb_win32_control_stage; +static int hf_usb_win32_iso_start_frame; +static int hf_usb_win32_iso_num_packets; +static int hf_usb_win32_iso_error_count; +static int hf_usb_win32_iso_offset; +static int hf_usb_win32_iso_length; +static int hf_usb_win32_iso_status; + +static int hf_usb_request; +static int hf_usb_request_unknown_class; +static int hf_usb_value; +static int hf_usb_index; +static int hf_usb_length; +/* static int hf_usb_data_len; */ +static int hf_usb_capdata; +static int hf_usb_device_wFeatureSelector; +static int hf_usb_interface_wFeatureSelector; +static int hf_usb_endpoint_wFeatureSelector; +static int hf_usb_wInterface; +static int hf_usb_wEndpoint; +static int hf_usb_wStatus; +static int hf_usb_wFrameNumber; + +static int hf_usb_iso_error_count; +static int hf_usb_iso_numdesc; +static int hf_usb_iso_status; +static int hf_usb_iso_off; +static int hf_usb_iso_len; +static int hf_usb_iso_actual_len; +static int hf_usb_iso_pad; +static int hf_usb_iso_data; + +static int hf_usb_bmRequestType; +static int hf_usb_control_response_generic; +static int hf_usb_bmRequestType_direction; +static int hf_usb_bmRequestType_type; +static int hf_usb_bmRequestType_recipient; +static int hf_usb_bDescriptorType; +static int hf_usb_get_descriptor_resp_generic; +static int hf_usb_descriptor_index; +static int hf_usb_language_id; +static int hf_usb_bLength; +static int hf_usb_bcdUSB; +static int hf_usb_bDeviceClass; +static int hf_usb_bDeviceSubClass; +static int hf_usb_bDeviceProtocol; +static int hf_usb_bMaxPacketSize0; +static int hf_usb_idVendor; +static int hf_usb_idProduct; +static int hf_usb_bcdDevice; +static int hf_usb_iManufacturer; +static int hf_usb_iProduct; +static int hf_usb_iSerialNumber; +static int hf_usb_bNumConfigurations; +static int hf_usb_wLANGID; +static int hf_usb_bString; +static int hf_usb_bInterfaceNumber; +static int hf_usb_bAlternateSetting; +static int hf_usb_bNumEndpoints; +static int hf_usb_bInterfaceClass; +static int hf_usb_bInterfaceSubClass; +static int hf_usb_bInterfaceSubClass_audio; +static int hf_usb_bInterfaceSubClass_cdc; +static int hf_usb_bInterfaceSubClass_massstorage; +static int hf_usb_bInterfaceSubClass_hid; +static int hf_usb_bInterfaceSubClass_misc; +static int hf_usb_bInterfaceSubClass_app; +static int hf_usb_bInterfaceProtocol; +static int hf_usb_bInterfaceProtocol_cdc; +static int hf_usb_bInterfaceProtocol_massstorage; +static int hf_usb_bInterfaceProtocol_cdc_data; +static int hf_usb_bInterfaceProtocol_hid_boot; +static int hf_usb_bInterfaceProtocol_app_dfu; +static int hf_usb_bInterfaceProtocol_app_irda; +static int hf_usb_bInterfaceProtocol_app_usb_test_and_measurement; +static int hf_usb_iInterface; +static int hf_usb_bEndpointAddress; +static int hf_usb_bmAttributes; +static int hf_usb_bEndpointAttributeTransfer; +static int hf_usb_bEndpointAttributeSynchonisation; +static int hf_usb_bEndpointAttributeBehaviour; +static int hf_usb_wMaxPacketSize; +static int hf_usb_wMaxPacketSize_size; +static int hf_usb_wMaxPacketSize_slots; +static int hf_usb_bInterval; +static int hf_usb_bMaxBurst; +static int hf_usb_audio_bRefresh; +static int hf_usb_audio_bSynchAddress; +static int hf_usb_bSSEndpointAttributeBulkMaxStreams; +static int hf_usb_bSSEndpointAttributeIsoMult; +static int hf_usb_wBytesPerInterval; +static int hf_usb_wTotalLength; +static int hf_usb_bNumInterfaces; +static int hf_usb_bConfigurationValue; +static int hf_usb_iConfiguration; +static int hf_usb_bMaxPower; +static int hf_usb_configuration_bmAttributes; +static int hf_usb_configuration_legacy10buspowered; +static int hf_usb_configuration_selfpowered; +static int hf_usb_configuration_remotewakeup; +static int hf_usb_bEndpointAddress_direction; +static int hf_usb_bEndpointAddress_number; +static int hf_usb_response_in; +static int hf_usb_time; +static int hf_usb_request_in; +static int hf_usb_bFirstInterface; +static int hf_usb_bInterfaceCount; +static int hf_usb_bFunctionClass; +static int hf_usb_bFunctionSubClass; +static int hf_usb_bFunctionProtocol; +static int hf_usb_iFunction; +static int hf_usb_bNumDeviceCaps; +static int hf_usb_bDevCapabilityType; +static int hf_usb_usb20ext_bmAttributes; +static int hf_usb_usb20ext_LPM; +static int hf_usb_usb20ext_BESL_HIRD; +static int hf_usb_usb20ext_baseline_BESL_valid; +static int hf_usb_usb20ext_deep_BESL_valid; +static int hf_usb_usb20ext_baseline_BESL; +static int hf_usb_usb20ext_deep_BESL; +static int hf_usb_bReserved; +static int hf_usb_PlatformCapabilityUUID; +static int hf_usb_webusb_bcdVersion; +static int hf_usb_webusb_bVendorCode; +static int hf_usb_webusb_iLandingPage; +static int hf_usb_msos20_dwWindowsVersion; +static int hf_usb_msos20_wMSOSDescriptorSetTotalLength; +static int hf_usb_msos20_bMS_VendorCode; +static int hf_usb_msos20_bAltEnumCode; +static int hf_usb_data_fragment; +static int hf_usb_src; +static int hf_usb_dst; +static int hf_usb_addr; /* macOS */ -static int hf_usb_darwin_bcd_version = -1; -static int hf_usb_darwin_header_len = -1; -static int hf_usb_darwin_request_type = -1; -static int hf_usb_darwin_io_len = -1; -static int hf_usb_darwin_io_status = -1; -static int hf_usb_darwin_iso_num_packets = -1; -static int hf_usb_darwin_io_id = -1; -static int hf_usb_darwin_device_location = -1; -static int hf_usb_darwin_speed = -1; -static int hf_usb_darwin_device_address = -1; -static int hf_usb_darwin_endpoint_address = -1; -static int hf_usb_darwin_endpoint_type = -1; -static int hf_usb_darwin_iso_status = -1; -static int hf_usb_darwin_iso_frame_number = -1; -static int hf_usb_darwin_iso_timestamp = -1; +static int hf_usb_darwin_bcd_version; +static int hf_usb_darwin_header_len; +static int hf_usb_darwin_request_type; +static int hf_usb_darwin_io_len; +static int hf_usb_darwin_io_status; +static int hf_usb_darwin_iso_num_packets; +static int hf_usb_darwin_io_id; +static int hf_usb_darwin_device_location; +static int hf_usb_darwin_speed; +static int hf_usb_darwin_device_address; +static int hf_usb_darwin_endpoint_address; +static int hf_usb_darwin_endpoint_type; +static int hf_usb_darwin_iso_status; +static int hf_usb_darwin_iso_frame_number; +static int hf_usb_darwin_iso_timestamp; /* NetMon */ -static int hf_usbport_event_id = -1; -static int hf_usbport_device_object = -1; -static int hf_usbport_pci_bus = -1; -static int hf_usbport_pci_device = -1; -static int hf_usbport_pci_function = -1; -static int hf_usbport_pci_vendor_id = -1; -static int hf_usbport_pci_device_id = -1; -static int hf_usbport_port_path_depth = -1; -static int hf_usbport_port_path0 = -1; -static int hf_usbport_port_path1 = -1; -static int hf_usbport_port_path2 = -1; -static int hf_usbport_port_path3 = -1; -static int hf_usbport_port_path4 = -1; -static int hf_usbport_port_path5 = -1; -static int hf_usbport_device_handle = -1; -static int hf_usbport_device_speed = -1; -static int hf_usbport_endpoint = -1; -static int hf_usbport_pipehandle = -1; -static int hf_usbport_endpoint_desc_length = -1; -static int hf_usbport_endpoint_desc_type = -1; -static int hf_usbport_endpoint_address = -1; -static int hf_usbport_bm_attributes = -1; -static int hf_usbport_max_packet_size = -1; -static int hf_usbport_interval = -1; -static int hf_usbport_irp = -1; -static int hf_usbport_urb = -1; -static int hf_usbport_urb_transfer_data = -1; -static int hf_usbport_urb_header_length = -1; -static int hf_usbport_urb_header_function = -1; -static int hf_usbport_urb_header_status = -1; -static int hf_usbport_urb_header_usbddevice_handle = -1; -static int hf_usbport_urb_header_usbdflags = -1; -static int hf_usbport_urb_configuration_desc = -1; -static int hf_usbport_urb_configuration_handle = -1; -static int hf_usbport_urb_pipe_handle = -1; -static int hf_usbport_urb_xferflags = -1; -static int hf_usbport_urb_transfer_buffer_length = -1; -static int hf_usbport_urb_transfer_buffer = -1; -static int hf_usbport_urb_transfer_buffer_mdl = -1; -static int hf_usbport_urb_reserved_mbz = -1; -static int hf_usbport_urb_reserved_hcd = -1; -static int hf_usbport_urb_reserved = -1; -static int hf_usbport_keyword = -1; -static int hf_usbport_keyword_diagnostic = -1; -static int hf_usbport_keyword_power_diagnostics = -1; -static int hf_usbport_keyword_perf_diagnostics = -1; -static int hf_usbport_keyword_reserved1 = -1; - -static gint ett_usb_hdr = -1; -static gint ett_usb_setup_hdr = -1; -static gint ett_usb_isodesc = -1; -static gint ett_usb_win32_iso_packet = -1; -static gint ett_usb_endpoint = -1; -static gint ett_usb_setup_bmrequesttype = -1; -static gint ett_usb_usbpcap_info = -1; -static gint ett_descriptor_device = -1; -static gint ett_configuration_bmAttributes = -1; -static gint ett_configuration_bEndpointAddress = -1; -static gint ett_endpoint_bmAttributes = -1; -static gint ett_endpoint_wMaxPacketSize = -1; -static gint ett_usb_xferflags = -1; -static gint ett_usb_xferstatus = -1; -static gint ett_usb_frame = -1; -static gint ett_usb_frame_flags = -1; -static gint ett_usbport = -1; -static gint ett_usbport_host_controller = -1; -static gint ett_usbport_path = -1; -static gint ett_usbport_device = -1; -static gint ett_usbport_endpoint = -1; -static gint ett_usbport_endpoint_desc = -1; -static gint ett_usbport_urb = -1; -static gint ett_usbport_keyword = -1; -static gint ett_transfer_flags = -1; - -static expert_field ei_usb_undecoded = EI_INIT; -static expert_field ei_usb_bLength_even = EI_INIT; -static expert_field ei_usb_bLength_too_short = EI_INIT; -static expert_field ei_usb_desc_length_invalid = EI_INIT; -static expert_field ei_usb_invalid_setup = EI_INIT; -static expert_field ei_usb_ss_ep_companion_before_ep = EI_INIT; -static expert_field ei_usb_usbpcap_unknown_urb = EI_INIT; -static expert_field ei_usb_bad_length = EI_INIT; - -static expert_field ei_usbport_invalid_path_depth = EI_INIT; +static int hf_usbport_event_id; +static int hf_usbport_device_object; +static int hf_usbport_pci_bus; +static int hf_usbport_pci_device; +static int hf_usbport_pci_function; +static int hf_usbport_pci_vendor_id; +static int hf_usbport_pci_device_id; +static int hf_usbport_port_path_depth; +static int hf_usbport_port_path0; +static int hf_usbport_port_path1; +static int hf_usbport_port_path2; +static int hf_usbport_port_path3; +static int hf_usbport_port_path4; +static int hf_usbport_port_path5; +static int hf_usbport_device_handle; +static int hf_usbport_device_speed; +static int hf_usbport_endpoint; +static int hf_usbport_pipehandle; +static int hf_usbport_endpoint_desc_length; +static int hf_usbport_endpoint_desc_type; +static int hf_usbport_endpoint_address; +static int hf_usbport_bm_attributes; +static int hf_usbport_max_packet_size; +static int hf_usbport_interval; +static int hf_usbport_irp; +static int hf_usbport_urb; +static int hf_usbport_urb_transfer_data; +static int hf_usbport_urb_header_length; +static int hf_usbport_urb_header_function; +static int hf_usbport_urb_header_status; +static int hf_usbport_urb_header_usbddevice_handle; +static int hf_usbport_urb_header_usbdflags; +static int hf_usbport_urb_configuration_desc; +static int hf_usbport_urb_configuration_handle; +static int hf_usbport_urb_pipe_handle; +static int hf_usbport_urb_xferflags; +static int hf_usbport_urb_transfer_buffer_length; +static int hf_usbport_urb_transfer_buffer; +static int hf_usbport_urb_transfer_buffer_mdl; +static int hf_usbport_urb_reserved_mbz; +static int hf_usbport_urb_reserved_hcd; +static int hf_usbport_urb_reserved; +static int hf_usbport_keyword; +static int hf_usbport_keyword_diagnostic; +static int hf_usbport_keyword_power_diagnostics; +static int hf_usbport_keyword_perf_diagnostics; +static int hf_usbport_keyword_reserved1; + +static gint ett_usb_hdr; +static gint ett_usb_setup_hdr; +static gint ett_usb_isodesc; +static gint ett_usb_win32_iso_packet; +static gint ett_usb_endpoint; +static gint ett_usb_setup_bmrequesttype; +static gint ett_usb_usbpcap_info; +static gint ett_descriptor_device; +static gint ett_configuration_bmAttributes; +static gint ett_configuration_bEndpointAddress; +static gint ett_endpoint_bmAttributes; +static gint ett_endpoint_wMaxPacketSize; +static gint ett_usb_xferflags; +static gint ett_usb_xferstatus; +static gint ett_usb_frame; +static gint ett_usb_frame_flags; +static gint ett_usbport; +static gint ett_usbport_host_controller; +static gint ett_usbport_path; +static gint ett_usbport_device; +static gint ett_usbport_endpoint; +static gint ett_usbport_endpoint_desc; +static gint ett_usbport_urb; +static gint ett_usbport_keyword; +static gint ett_transfer_flags; +static gint ett_usb20ext_bmAttributes; + +static expert_field ei_usb_undecoded; +static expert_field ei_usb_bLength_even; +static expert_field ei_usb_bLength_too_short; +static expert_field ei_usb_desc_length_invalid; +static expert_field ei_usb_invalid_setup; +static expert_field ei_usb_ss_ep_companion_before_ep; +static expert_field ei_usb_usbpcap_unknown_urb; +static expert_field ei_usb_bad_length; +static expert_field ei_usb_invalid_max_packet_size; +static expert_field ei_usb_invalid_max_packet_size0; +static expert_field ei_usb_invalid_endpoint_type; +static expert_field ei_usb_unexpected_desc_type; + +static expert_field ei_usbport_invalid_path_depth; static int usb_address_type = -1; @@ -391,7 +422,7 @@ static int * const usb_usbpcap_info_fields[] = { NULL }; -static int usb_tap = -1; +static int usb_tap; static gboolean try_heuristics = TRUE; static dissector_table_t usb_bulk_dissector_table; @@ -438,6 +469,14 @@ typedef struct { guint8 setup_data[8]; } usbpcap_setup_data_t; +static const value_string usb_speed_vals[] = { + {USB_SPEED_UNKNOWN, "Unknown Speed"}, + {USB_SPEED_LOW, "Low-Speed"}, + {USB_SPEED_FULL, "Full-Speed"}, + {USB_SPEED_HIGH, "High-Speed"}, + {0, NULL} +}; + /* http://www.usb.org/developers/docs/USB_LANGIDs.pdf */ static const value_string usb_langid_vals[] = { {0x0000, "no language specified"}, @@ -653,6 +692,52 @@ static const value_string usb_protocols[] = { }; static value_string_ext usb_protocols_ext = VALUE_STRING_EXT_INIT(usb_protocols); +/* BOS Descriptor Device Capability Type Codes + https://www.usb.org/bos-descriptor-types +*/ +#define BOS_CAP_WIRELESS_USB 0x01 +#define BOS_CAP_USB_20_EXTENSION 0x02 +#define BOS_CAP_SUPERSPEED_USB 0x03 +#define BOS_CAP_CONTAINER_ID 0x04 +#define BOS_CAP_PLATFORM 0x05 +#define BOS_CAP_POWER_DELIVERY 0x06 +#define BOS_CAP_BATTERY_INFO 0x07 +#define BOS_CAP_PD_CONSUMER_PORT 0x08 +#define BOS_CAP_PD_PROVIDER_PORT 0x09 +#define BOS_CAP_SUPERSPEED_PLUS 0x0A +#define BOS_CAP_PRECISION_TIME_MEAS 0x0B +#define BOS_CAP_WIRELESS_USB_EXT 0x0C +#define BOS_CAP_BILLBOARD 0x0D +#define BOS_CAP_AUTHENTICATION 0x0E +#define BOS_CAP_BILLBOARD_EX 0x0F +#define BOS_CAP_CONFIGURATION_SUMMARY 0x10 +#define BOS_CAP_FWSTATUS 0x11 +#define BOS_CAP_USB3_GEN_T 0x13 +static const value_string usb_capability_vals[] = { + {BOS_CAP_WIRELESS_USB, "Wireless USB"}, + {BOS_CAP_USB_20_EXTENSION, "USB 2.0 Extension Descriptor"}, + {BOS_CAP_SUPERSPEED_USB, "SuperSpeed USB"}, + {BOS_CAP_CONTAINER_ID, "Container ID"}, + {BOS_CAP_PLATFORM, "Platform"}, + {BOS_CAP_POWER_DELIVERY, "Power Delivery Capability"}, + {BOS_CAP_BATTERY_INFO, "Battery Info Capability"}, + {BOS_CAP_PD_CONSUMER_PORT, "PD Consumer Port Capability"}, + {BOS_CAP_PD_PROVIDER_PORT, "PD Provider Port Capability"}, + {BOS_CAP_SUPERSPEED_PLUS, "SuperSpeed Plus"}, + {BOS_CAP_PRECISION_TIME_MEAS, "Precision Time Measurement"}, + {BOS_CAP_WIRELESS_USB_EXT, "Wireless USB Ext"}, + {BOS_CAP_BILLBOARD, "Billboard Capability"}, + {BOS_CAP_AUTHENTICATION, "Authentication Capability Descriptor"}, + {BOS_CAP_BILLBOARD_EX, "Billboard Ex capability"}, + {BOS_CAP_CONFIGURATION_SUMMARY, "Configuration Summary"}, + {BOS_CAP_FWSTATUS, "Firmware Status"}, + {0x12, "TBD (reserved for USB Audio 4.0)"}, + {BOS_CAP_USB3_GEN_T, "USB 3 Gen T Capability"}, + {0x14, "TBD (reserved for USB PD)"}, + {0, NULL} +}; +static value_string_ext usb_capability_vals_ext = VALUE_STRING_EXT_INIT(usb_capability_vals); + /* FreeBSD header */ /* Transfer mode */ @@ -880,6 +965,18 @@ static const value_string usb_endpoint_direction_vals[] = { {0, NULL} }; +static const range_string usb_setup_flag_rvals[] = { + {0, 0, "relevant"}, + {1, 255, "not relevant"}, + {0, 0, NULL} +}; + +static const range_string usb_data_flag_rvals[] = { + {0, 0, "present"}, + {1, 255, "not present"}, + {0, 0, NULL} +}; + extern value_string_ext ext_usb_vendors_vals; extern value_string_ext ext_usb_products_vals; extern value_string_ext ext_usb_audio_subclass_vals; @@ -1356,7 +1453,26 @@ static const value_string darwin_usb_status_vals[] = { {0xe00002da, "kIOReturnNoChannels"}, {0xe00002db, "kIOReturnNoSpace"}, + {0xe00002dd, "kIOReturnPortExists"}, + {0xe00002de, "kIOReturnCannotWire"}, + {0xe00002df, "kIOReturnNoInterrupt"}, + {0xe00002e0, "kIOReturnNoFrames"}, + {0xe00002e1, "kIOReturnMessageTooLarge"}, + {0xe00002e2, "kIOReturnNotPermitted"}, + {0xe00002e3, "kIOReturnNoPower"}, + {0xe00002e4, "kIOReturnNoMedia"}, + {0xe00002e5, "kIOReturnUnformattedMedia"}, + {0xe00002e6, "kIOReturnUnsupportedMode"}, + {0xe00002e7, "kIOReturnUnderrun"}, + {0xe00002e8, "kIOReturnOverrun"}, + {0xe00002e9, "kIOReturnDeviceError"}, + {0xe00002ea, "kIOReturnNoCompletion"}, {0xe00002eb, "kIOReturnAborted"}, + {0xe00002ec, "kIOReturnNoBandwidth"}, + {0xe00002ed, "kIOReturnNotResponding"}, + {0xe00002ee, "kIOReturnIsoTooOld"}, + {0xe00002ef, "kIOReturnIsoTooNew"}, + {0xe00002f0, "kIOReturnNotFound"}, {0, NULL} }; @@ -1616,8 +1732,8 @@ static int usb_addr_to_str(const address* addr, gchar *buf, int buf_len _U_) if(pletoh32(&addrp[0])==0xffffffff){ (void) g_strlcpy(buf, "host", buf_len); } else { - g_snprintf(buf, buf_len, "%d.%d.%d", pletoh16(&addrp[8]), - pletoh32(&addrp[0]), pletoh32(&addrp[4])); + snprintf(buf, buf_len, "%d.%d.%d", pletoh16(&addrp[8]), + pletoh32(&addrp[0]), pletoh32(&addrp[4]) & 0x0f); } return (int)(strlen(buf)+1); @@ -1642,7 +1758,7 @@ static int usb_addr_str_len(const address* addr _U_) static void usb_device_prompt(packet_info *pinfo, gchar* result) { - g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Bus ID %u \nDevice Address %u\nas ", + snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Bus ID %u \nDevice Address %u\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_BUS_ID)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_ADDRESS))); } @@ -1658,7 +1774,7 @@ usb_device_value(packet_info *pinfo) static void usb_product_prompt(packet_info *pinfo, gchar* result) { - g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Vendor ID 0x%04x \nProduct ID 0x%04x\nas ", + snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Vendor ID 0x%04x \nProduct ID 0x%04x\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_VENDOR_ID)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_PRODUCT_ID))); } @@ -1674,7 +1790,7 @@ usb_product_value(packet_info *pinfo) static void usb_protocol_prompt(packet_info *pinfo, gchar* result) { - g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Class ID 0x%04x \nSubclass ID 0x%04x\nProtocol 0x%04x\nas ", + snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Class ID 0x%04x \nSubclass ID 0x%04x\nProtocol 0x%04x\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_CLASS)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_SUBCLASS)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_PROTOCOL))); @@ -1754,6 +1870,7 @@ static void clear_usb_conv_tmp_data(usb_conv_info_t *usb_conv_info) usb_conv_info->is_request = FALSE; usb_conv_info->is_setup = FALSE; usb_conv_info->setup_requesttype = 0; + usb_conv_info->speed = USB_SPEED_UNKNOWN; /* when we parse the configuration, interface and endpoint descriptors, we store the current interface class in endpoint 0's @@ -1784,7 +1901,7 @@ get_usb_conversation(packet_info *pinfo, */ conversation = find_conversation(pinfo->num, src_addr, dst_addr, - conversation_pt_to_endpoint_type(pinfo->ptype), + conversation_pt_to_conversation_type(pinfo->ptype), src_endpoint, dst_endpoint, 0); if (conversation) { return conversation; @@ -1793,7 +1910,7 @@ get_usb_conversation(packet_info *pinfo, /* We don't yet have a conversation, so create one. */ conversation = conversation_new(pinfo->num, src_addr, dst_addr, - conversation_pt_to_endpoint_type(pinfo->ptype), + conversation_pt_to_conversation_type(pinfo->ptype), src_endpoint, dst_endpoint, 0); return conversation; } @@ -1838,7 +1955,7 @@ get_existing_usb_ep_conv_info(packet_info* pinfo, guint16 bus_id, guint16 device set_address(&dst, usb_address_type, USB_ADDR_LEN, (char *)dst_addr); conversation = find_conversation(pinfo->num, &src, &dst, - conversation_pt_to_endpoint_type(PT_USB), + conversation_pt_to_conversation_type(PT_USB), src_addr->endpoint, dst_addr->endpoint, 0); if (conversation) { usb_conv_info = (usb_conv_info_t *)conversation_get_proto_data(conversation, proto_usb); @@ -1863,17 +1980,19 @@ static const char* usb_conv_get_filter_type(conv_item_t* conv, conv_filter_type_ static ct_dissector_info_t usb_ct_dissector_info = {&usb_conv_get_filter_type}; static tap_packet_status -usb_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_) +usb_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pct; - add_conversation_table_data(hash, &pinfo->src, &pinfo->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &usb_ct_dissector_info, ENDPOINT_NONE); + hash->flags = flags; + + add_conversation_table_data(hash, &pinfo->src, &pinfo->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &usb_ct_dissector_info, CONVERSATION_NONE); return TAP_PACKET_REDRAW; } -static const char* usb_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter) +static const char* usb_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) { - if ((filter == CONV_FT_ANY_ADDRESS) && (host->myaddress.type == usb_address_type)) + if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == usb_address_type)) return "usb.addr"; return CONV_FILTER_INVALID; @@ -1885,18 +2004,19 @@ usb_col_filter_str(const address* addr _U_, gboolean is_src) return is_src ? "usb.src" : "usb.dst"; } -static hostlist_dissector_info_t usb_host_dissector_info = {&usb_host_get_filter_type}; +static et_dissector_info_t usb_endpoint_dissector_info = {&usb_endpoint_get_filter_type}; static tap_packet_status -usb_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_) +usb_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pit; + hash->flags = flags; /* Take two "add" passes per packet, adding for each direction, ensures that all packets are counted properly (even if address is sending to itself) - XXX - this could probably be done more efficiently inside hostlist_table */ - add_hostlist_table_data(hash, &pinfo->src, 0, TRUE, 1, pinfo->fd->pkt_len, &usb_host_dissector_info, ENDPOINT_NONE); - add_hostlist_table_data(hash, &pinfo->dst, 0, FALSE, 1, pinfo->fd->pkt_len, &usb_host_dissector_info, ENDPOINT_NONE); + XXX - this could probably be done more efficiently inside endpoint_table */ + add_endpoint_table_data(hash, &pinfo->src, 0, TRUE, 1, pinfo->fd->pkt_len, &usb_endpoint_dissector_info, ENDPOINT_NONE); + add_endpoint_table_data(hash, &pinfo->dst, 0, FALSE, 1, pinfo->fd->pkt_len, &usb_endpoint_dissector_info, ENDPOINT_NONE); return TAP_PACKET_REDRAW; } @@ -2016,14 +2136,39 @@ proto_item * dissect_usb_descriptor_header(proto_tree *tree, proto_tree_add_uint_format_value(tree, hf_usb_bDescriptorType, tvb, offset, 1, desc_type, "0x%02x (%s)", desc_type, - val_to_str_ext(desc_type, type_val_str, "unknown")); + val_to_str_ext_const(desc_type, type_val_str, "unknown")); return length_item; } +static void +dissect_max_packet_size0(packet_info *pinfo, proto_tree *tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info, gboolean other_speed) +{ + proto_item *item; + guint32 max_packet_size; + unsigned int sanitized_max_packet_size; + usb_speed_t speed = usb_conv_info->speed; + + item = proto_tree_add_item_ret_uint(tree, hf_usb_bMaxPacketSize0, tvb, offset, 1, ENC_LITTLE_ENDIAN, &max_packet_size); + if (other_speed) { + if (speed == USB_SPEED_FULL) + speed = USB_SPEED_HIGH; + else if (speed == USB_SPEED_HIGH) + speed = USB_SPEED_FULL; + } + sanitized_max_packet_size = sanitize_usb_max_packet_size(ENDPOINT_TYPE_CONTROL, speed, max_packet_size); + if (sanitized_max_packet_size != max_packet_size) { + expert_add_info_format(pinfo, item, &ei_usb_invalid_max_packet_size0, + "%s endpoint zero max packet size cannot be %u, using %d instead.", + try_val_to_str(speed, usb_speed_vals), max_packet_size, sanitized_max_packet_size); + } +} + /* 9.6.2 */ static int -dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, +dissect_usb_device_qualifier_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { @@ -2088,7 +2233,7 @@ dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *pare } /* bMaxPacketSize0 */ - proto_tree_add_item(tree, hf_usb_bMaxPacketSize0, tvb, offset, 1, ENC_LITTLE_ENDIAN); + dissect_max_packet_size0(pinfo, tree, tvb, offset, usb_conv_info, TRUE); offset += 1; /* bNumConfigurations */ @@ -2146,7 +2291,7 @@ dissect_usb_device_descriptor(packet_info *pinfo, proto_tree *parent_tree, offset += 1; /* bMaxPacketSize0 */ - proto_tree_add_item(tree, hf_usb_bMaxPacketSize0, tvb, offset, 1, ENC_LITTLE_ENDIAN); + dissect_max_packet_size0(pinfo, tree, tvb, offset, usb_conv_info, FALSE); offset += 1; /* if request was only for the first 8 bytes */ @@ -2472,23 +2617,98 @@ void dissect_usb_endpoint_address(proto_tree *tree, tvbuff_t *tvb, int offset) endpoint_item = proto_tree_add_item(tree, hf_usb_bEndpointAddress, tvb, offset, 1, ENC_LITTLE_ENDIAN); endpoint_tree = proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress); - endpoint = tvb_get_guint8(tvb, offset)&0x0f; + endpoint = tvb_get_guint8(tvb, offset); proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_item_append_text(endpoint_item, " %s", (tvb_get_guint8(tvb, offset)&0x80)?"IN":"OUT"); + proto_item_append_text(endpoint_item, " %s", (endpoint&0x80)?"IN":"OUT"); proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_number, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_item_append_text(endpoint_item, " Endpoint:%d", endpoint); + proto_item_append_text(endpoint_item, " Endpoint:%d", endpoint&0x0f); +} + +unsigned int +sanitize_usb_max_packet_size(guint8 ep_type, usb_speed_t speed, + unsigned int max_packet_size) +{ + unsigned int sanitized = max_packet_size; + switch (speed) { + case USB_SPEED_LOW: + switch (ep_type) { + case ENDPOINT_TYPE_CONTROL: + /* 8 is the only allowed value */ + sanitized = 8; + break; + case ENDPOINT_TYPE_INTERRUPT: + if (max_packet_size > 8) + sanitized = 8; + break; + default: + /* Not allowed */ + break; + } + break; + case USB_SPEED_FULL: + switch (ep_type) { + case ENDPOINT_TYPE_CONTROL: + case ENDPOINT_TYPE_BULK: + /* Allowed values are: 8, 16, 32 and 64 */ + if (max_packet_size > 32) + sanitized = 64; + else if (max_packet_size > 16) + sanitized = 32; + else if (max_packet_size > 8) + sanitized = 16; + else + sanitized = 8; + break; + case ENDPOINT_TYPE_INTERRUPT: + if (max_packet_size > 64) + sanitized = 64; + break; + case ENDPOINT_TYPE_ISOCHRONOUS: + if (max_packet_size > 1023) + sanitized = 1023; + break; + default: + break; + } + break; + case USB_SPEED_HIGH: + switch (ep_type) { + case ENDPOINT_TYPE_CONTROL: + /* 64 is the only allowed value */ + sanitized = 64; + break; + case ENDPOINT_TYPE_BULK: + /* 512 is the only allowed value */ + sanitized = 512; + break; + case ENDPOINT_TYPE_INTERRUPT: + case ENDPOINT_TYPE_ISOCHRONOUS: + if (max_packet_size > 1024) + sanitized = 1024; + break; + default: + break; + } + break; + case USB_SPEED_UNKNOWN: + default: + break; + } + + return sanitized; } int dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info, - guint8 *out_ep_type) + guint8 *out_ep_type, usb_speed_t speed) { proto_item *item; proto_tree *tree; proto_item *ep_attrib_item; proto_tree *ep_attrib_tree; + proto_item *ep_type_item; proto_item *ep_pktsize_item; proto_tree *ep_pktsize_tree; int old_offset = offset; @@ -2496,6 +2716,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, guint8 ep_type; guint8 len; guint32 max_packet_size; + unsigned int sanitized_max_packet_size; usb_trans_info_t *usb_trans_info = NULL; conversation_t *conversation = NULL; @@ -2508,7 +2729,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; - endpoint = tvb_get_guint8(tvb, offset)&0x0f; + endpoint = tvb_get_guint8(tvb, offset); dissect_usb_endpoint_address(tree, tvb, offset); offset += 1; @@ -2551,11 +2772,16 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, ep_attrib_item = proto_tree_add_item(tree, hf_usb_bmAttributes, tvb, offset, 1, ENC_LITTLE_ENDIAN); ep_attrib_tree = proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes); - proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeTransfer, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ep_type_item = proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeTransfer, tvb, offset, 1, ENC_LITTLE_ENDIAN); if (ep_type==USB_EP_ISOCHRONOUS) { proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeSynchonisation, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeBehaviour, tvb, offset, 1, ENC_LITTLE_ENDIAN); } + + /* At Low-Speed, only control and interrupt transfers are allowed */ + if ((speed == USB_SPEED_LOW) && !((ep_type == USB_EP_CONTROL) || (ep_type == USB_EP_INTERRUPT))) { + expert_add_info(pinfo, ep_type_item, &ei_usb_invalid_endpoint_type); + } offset += 1; /* wMaxPacketSize */ @@ -2565,6 +2791,14 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, proto_tree_add_item(ep_pktsize_tree, hf_usb_wMaxPacketSize_slots, tvb, offset, 2, ENC_LITTLE_ENDIAN); } proto_tree_add_item_ret_uint(ep_pktsize_tree, hf_usb_wMaxPacketSize_size, tvb, offset, 2, ENC_LITTLE_ENDIAN, &max_packet_size); + sanitized_max_packet_size = sanitize_usb_max_packet_size(ep_type, speed, max_packet_size); + if (sanitized_max_packet_size != max_packet_size) { + expert_add_info_format(pinfo, ep_pktsize_item, &ei_usb_invalid_max_packet_size, + "%s %s endpoint max packet size cannot be %u, using %d instead.", + try_val_to_str(speed, usb_speed_vals), try_val_to_str(ep_type, usb_bmAttributes_transfer_vals), + max_packet_size, sanitized_max_packet_size); + max_packet_size = sanitized_max_packet_size; + } offset+=2; if (conversation) { @@ -2757,7 +2991,7 @@ static const true_false_string tfs_remotewakeup = { static int dissect_usb_configuration_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, - usb_conv_info_t *usb_conv_info) + usb_conv_info_t *usb_conv_info, usb_speed_t speed) { proto_item *item; proto_tree *tree; @@ -2854,7 +3088,7 @@ dissect_usb_configuration_descriptor(packet_info *pinfo _U_, proto_tree *parent_ offset = dissect_usb_interface_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info); break; case USB_DT_ENDPOINT: - offset = dissect_usb_endpoint_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info, &last_ep_type); + offset = dissect_usb_endpoint_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info, &last_ep_type, speed); break; case USB_DT_INTERFACE_ASSOCIATION: offset = dissect_usb_interface_assn_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info); @@ -2879,6 +3113,194 @@ dissect_usb_configuration_descriptor(packet_info *pinfo _U_, proto_tree *parent_ return offset; } +/* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor */ +static int +dissect_webusb_platform_descriptor(packet_info *pinfo _U_, proto_tree *tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info _U_) +{ + proto_tree_add_item(tree, hf_usb_webusb_bcdVersion, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_usb_webusb_bVendorCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_usb_webusb_iLandingPage, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + return offset; +} + +/* Microsoft OS 2.0 Descriptors Specification */ +static int +dissect_msos20_platform_descriptor(packet_info *pinfo _U_, proto_tree *tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info _U_) +{ + proto_tree_add_item(tree, hf_usb_msos20_dwWindowsVersion, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_usb_msos20_wMSOSDescriptorSetTotalLength, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_usb_msos20_bMS_VendorCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_usb_msos20_bAltEnumCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + return offset; +} + +static struct { + e_guid_t uuid; + const gchar *text; + int (*dissect)(packet_info *pinfo, proto_tree *tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info); +} bos_platform_uuids[] = { + { {0x3408b638, 0x09a9, 0x47a0, {0x8b, 0xfd, 0xa0, 0x76, 0x88, 0x15, 0xb6, 0x65}}, + "WebUSB Platform Capability descriptor", + dissect_webusb_platform_descriptor }, + + { {0xd8dd60df, 0x4589, 0x4cc7, {0x9c, 0xd2, 0x65, 0x9d, 0x9e, 0x64, 0x8a, 0x9f}}, + "Microsoft OS 2.0 Platform Capability descriptor", + dissect_msos20_platform_descriptor }, +}; + +/* USB 3.2 Specification Table 9-13. Format of a Device Capability Descriptor */ +static int +dissect_usb_device_capability_descriptor(packet_info *pinfo, proto_tree *tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info) +{ + guint8 cap_type; + const gchar *cap_text; + e_guid_t uuid; + unsigned int i; + + proto_tree_add_item(tree, hf_usb_bDevCapabilityType, tvb, offset, 1, ENC_LITTLE_ENDIAN); + cap_type = tvb_get_guint8(tvb, offset); + offset += 1; + + cap_text = try_val_to_str_ext(cap_type, &usb_capability_vals_ext); + + if (cap_type == BOS_CAP_USB_20_EXTENSION) { + /* USB 2.0 ECN Errata for Link Power Management */ + static int * const usb20ext_fields[] = { + &hf_usb_usb20ext_LPM, + &hf_usb_usb20ext_BESL_HIRD, + &hf_usb_usb20ext_baseline_BESL_valid, + &hf_usb_usb20ext_deep_BESL_valid, + &hf_usb_usb20ext_baseline_BESL, + &hf_usb_usb20ext_deep_BESL, + NULL + }; + + proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_usb_usb20ext_bmAttributes, + ett_usb20ext_bmAttributes, usb20ext_fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND); + offset += 4; + } else if (cap_type == BOS_CAP_PLATFORM) { + proto_tree_add_item(tree, hf_usb_bReserved, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + tvb_get_letohguid(tvb, offset, &uuid); + proto_tree_add_guid(tree, hf_usb_PlatformCapabilityUUID, tvb, offset, 16, &uuid); + offset += 16; + + for (i = 0; i < array_length(bos_platform_uuids); i++) { + if (guid_cmp(&bos_platform_uuids[i].uuid, &uuid) == 0) { + offset = bos_platform_uuids[i].dissect(pinfo, tree, tvb, offset, usb_conv_info); + cap_text = bos_platform_uuids[i].text; + break; + } + } + } + + if (cap_text) { + proto_item_append_text(tree, ": %s", cap_text); + } + + return offset; +} + +/* USB 3.2 Specification 9.6.2 Binary Device Object Store (BOS) */ +static int +dissect_usb_bos_descriptor(packet_info *pinfo, proto_tree *parent_tree, + tvbuff_t *tvb, int offset, + usb_conv_info_t *usb_conv_info) +{ + proto_item *item; + proto_tree *tree; + int old_offset = offset; + guint16 total_len; + usb_trans_info_t *usb_trans_info; + + usb_trans_info = usb_conv_info->usb_trans_info; + + tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "BOS DESCRIPTOR"); + + dissect_usb_descriptor_header(tree, tvb, offset, NULL); + offset += 2; + + /* wTotalLength */ + proto_tree_add_item(tree, hf_usb_wTotalLength, tvb, offset, 2, ENC_LITTLE_ENDIAN); + total_len = tvb_get_letohs(tvb, offset); + offset += 2; + + proto_tree_add_item(tree, hf_usb_bNumDeviceCaps, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + if (offset - old_offset >= usb_trans_info->setup.wLength) { + /* Do not report the most common case where host finds out about + * wTotalLength by requesting just BOS descriptor as Malformed Packet. + * TODO: Generic handling of "host requested too few bytes" (which is + * perfectly fine, but complicates dissection) because host is allowed + * to request any number of bytes. + */ + return offset; + } + + /* Dissect capabilities */ + while (total_len > (offset - old_offset)) { + proto_item *desc_item; + int prev_offset = offset; + guint8 desc_len, desc_type; + + tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &desc_item, "DEVICE CAPABILITY DESCRIPTOR"); + + item = proto_tree_add_item(tree, hf_usb_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN); + desc_len = tvb_get_guint8(tvb, offset); + offset += 1; + if (desc_len < 3) { + expert_add_info_format(pinfo, item, &ei_usb_bLength_too_short, "Invalid Length (must be 3 or larger)"); + break; + } + + item = proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN); + desc_type = tvb_get_guint8(tvb, offset); + offset += 1; + if (desc_type == USB_DT_DEVICE_CAPABILITY) { + tvbuff_t *desc_tvb = tvb_new_subset_length(tvb, offset, desc_len - 2); + offset += dissect_usb_device_capability_descriptor(pinfo, tree, desc_tvb, 0, usb_conv_info); + } else { + expert_add_info(pinfo, item, &ei_usb_unexpected_desc_type); + /* Already reported unexpected type, do not mark rest as undecoded */ + offset = prev_offset + desc_len; + } + + if (offset < prev_offset + desc_len) { + proto_tree_add_expert(tree, pinfo, &ei_usb_undecoded, tvb, offset, prev_offset + desc_len - offset); + offset = prev_offset + desc_len; + } + proto_item_set_len(item, offset - prev_offset); + } + + proto_item_set_len(item, offset - old_offset); + + return offset; +} + /* 9.4.3 */ static int dissect_usb_setup_get_descriptor_request(packet_info *pinfo, proto_tree *tree, @@ -2921,8 +3343,10 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, usb_conv_info_t *usb_conv_info) { usb_trans_info_t *usb_trans_info; + usb_speed_t speed; usb_trans_info = usb_conv_info->usb_trans_info; + speed = usb_conv_info->speed; col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_ext(usb_trans_info->u.get_descriptor.type, &std_descriptor_type_vals_ext, "Unknown type %u")); @@ -2936,8 +3360,15 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, case USB_DT_DEVICE: offset = dissect_usb_device_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; + case USB_DT_OTHER_SPEED_CONFIG: + /* USB 2.0 Specification: 9.2.6.6 Speed Dependent Descriptors */ + if (speed == USB_SPEED_FULL) + speed = USB_SPEED_HIGH; + else if (speed == USB_SPEED_HIGH) + speed = USB_SPEED_FULL; + /* fall-through */ case USB_DT_CONFIG: - offset = dissect_usb_configuration_descriptor(pinfo, tree, tvb, offset, usb_conv_info); + offset = dissect_usb_configuration_descriptor(pinfo, tree, tvb, offset, usb_conv_info, speed); break; case USB_DT_STRING: offset = dissect_usb_string_descriptor(pinfo, tree, tvb, offset, usb_conv_info); @@ -2945,6 +3376,9 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, case USB_DT_DEVICE_QUALIFIER: offset = dissect_usb_device_qualifier_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; + case USB_DT_BOS: + offset = dissect_usb_bos_descriptor(pinfo, tree, tvb, offset, usb_conv_info); + break; default: /* XXX dissect the descriptor coming back from the device */ { @@ -3521,6 +3955,7 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin guint32 k_frame_number; guint32 k_device_address; guint32 k_bus_id; + usb_conv_info_t *old_conv_info = usb_conv_info; usb_trans_info_t *usb_trans_info; heur_dtbl_entry_t *hdtbl_entry; heur_dissector_list_t heur_subdissector_list = NULL; @@ -3532,6 +3967,7 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin /* if we select the next dissector based on a class, this is the (device or interface) class we're using */ guint32 usb_class; + guint32 protocol; guint8 transfer_type; gboolean use_setup_tree = FALSE; @@ -3630,6 +4066,7 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin usb_conv_info = get_usb_iface_conv_info(pinfo, interface_num); usb_conv_info->usb_trans_info = usb_trans_info; + usb_conv_info->endpoint = NO_ENDPOINT8; } else if (ctrl_recip == RQT_SETUP_RECIPIENT_ENDPOINT) { address endpoint_addr; @@ -3640,7 +4077,7 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin heur_subdissector_list = heur_control_subdissector_list; usb_dissector_table = usb_control_dissector_table; - endpoint = usb_trans_info->setup.wIndex & 0x0f; + endpoint = usb_trans_info->setup.wIndex & 0xff; if (usb_conv_info->is_request) { usb_address_t *dst_addr = wmem_new0(pinfo->pool, usb_address_t); @@ -3674,6 +4111,15 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin usb_dissector_table = usb_control_dissector_table; } + if (old_conv_info != usb_conv_info) { + /* Preserve URB specific information */ + usb_conv_info->transfer_type = old_conv_info->transfer_type; + usb_conv_info->is_setup = old_conv_info->is_setup; + usb_conv_info->is_request = old_conv_info->is_request; + usb_conv_info->setup_requesttype = old_conv_info->setup_requesttype; + usb_conv_info->speed = old_conv_info->speed; + } + usb_tap_queue_packet(pinfo, urb_type, usb_conv_info); sub_item = proto_tree_add_uint(urb_tree, hf_usb_bInterfaceClass, next_tvb, 0, 0, usb_conv_info->interfaceClass); proto_item_set_generated(sub_item); @@ -3683,6 +4129,15 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin break; } + /* try "usb.protocol" on interface level */ + protocol = (usb_conv_info->interfaceClass & 0xFF) << 16 | + (usb_conv_info->interfaceSubclass & 0xFF) << 8 | + (usb_conv_info->interfaceProtocol & 0xFF); + ret = dissector_try_uint_new(protocol_to_dissector, protocol, + next_tvb, pinfo, tree, TRUE, usb_conv_info); + if (ret) + return tvb_captured_length(next_tvb); + if (try_heuristics && heur_subdissector_list) { ret = dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, use_setup_tree ? setup_tree : tree, &hdtbl_entry, usb_conv_info); @@ -3705,6 +4160,15 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin next_tvb, pinfo, use_setup_tree ? setup_tree : tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); + + /* try protocol specific dissector if there is one */ + usb_class = USB_PROTOCOL_KEY(usb_conv_info->interfaceClass, + usb_conv_info->interfaceSubclass, + usb_conv_info->interfaceProtocol); + ret = dissector_try_uint_new(usb_dissector_table, usb_class, + next_tvb, pinfo, use_setup_tree ? setup_tree : tree, TRUE, usb_conv_info); + if (ret) + return tvb_captured_length(next_tvb); } return 0; @@ -3876,7 +4340,7 @@ dissect_usb_setup_request(packet_info *pinfo, proto_tree *tree, if (tvb_captured_length_remaining(tvb, offset) > 0) { next_tvb = tvb_new_composite(); - tvb_composite_append(next_tvb, tvb_new_subset_length_caplen(tvb, setup_offset, 7, 7)); + tvb_composite_append(next_tvb, tvb_new_subset_length(tvb, setup_offset, 7)); data_tvb = tvb_new_subset_remaining(tvb, offset); tvb_composite_append(next_tvb, data_tvb); @@ -3888,7 +4352,7 @@ dissect_usb_setup_request(packet_info *pinfo, proto_tree *tree, tvb_captured_length(next_tvb)); add_new_data_source(pinfo, next_tvb, "USB Control"); } else { - next_tvb = tvb_new_subset_length_caplen(tvb, setup_offset, 7, 7); + next_tvb = tvb_new_subset_length(tvb, setup_offset, 7); } /* at this point, offset contains the number of bytes that we @@ -3932,7 +4396,7 @@ dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t guint8 endpoint_byte; guint8 transfer_type_and_direction; guint8 urb_type; - guint8 flag[2]; + guint32 flag; guint32 bus_id; *urb_id = tvb_get_guint64(tvb, 0, ENC_HOST_ENDIAN); @@ -3969,27 +4433,16 @@ dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t * sizeof(struct usb_device_setup_hdr) bytes. The content of these * bytes only have meaning in case setup_flag == 0. */ - flag[0] = tvb_get_guint8(tvb, 14); - flag[1] = '\0'; - if (flag[0] == 0) { + proto_tree_add_item_ret_uint(tree, hf_usb_setup_flag, tvb, 14, 1, ENC_NA, &flag); + if (flag == 0) { usb_conv_info->is_setup = TRUE; - proto_tree_add_string(tree, hf_usb_setup_flag, tvb, 14, 1, "relevant (0)"); if (usb_conv_info->transfer_type!=URB_CONTROL) proto_tree_add_expert(tree, pinfo, &ei_usb_invalid_setup, tvb, 14, 1); } else { usb_conv_info->is_setup = FALSE; - proto_tree_add_string_format_value(tree, hf_usb_setup_flag, tvb, - 14, 1, flag, "not relevant ('%c')", g_ascii_isprint(flag[0]) ? flag[0]: '.'); } - flag[0] = tvb_get_guint8(tvb, 15); - flag[1] = '\0'; - if (flag[0] == 0) { - proto_tree_add_string(tree, hf_usb_data_flag, tvb, 15, 1, "present (0)"); - } else { - proto_tree_add_string_format_value(tree, hf_usb_data_flag, tvb, - 15, 1, flag, "not present ('%c')", g_ascii_isprint(flag[0]) ? flag[0] : '.'); - } + proto_tree_add_item(tree, hf_usb_data_flag, tvb, 15, 1, ENC_NA); proto_tree_add_item(tree, hf_usb_urb_ts_sec, tvb, 16, 8, ENC_HOST_ENDIAN); proto_tree_add_item(tree, hf_usb_urb_ts_usec, tvb, 24, 4, ENC_HOST_ENDIAN); @@ -4562,7 +5015,7 @@ dissect_darwin_usb_iso_transfer(packet_info *pinfo _U_, proto_tree *tree, usb_he } iso_desc_ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, - 20, "Frame %u [%s]", i, val_to_str_ext(status, &usb_darwin_status_vals_ext, "Error %d")); + 20, "Frame %u", i); iso_desc_tree = proto_item_add_subtree(iso_desc_ti, ett_usb_isodesc); @@ -4572,7 +5025,9 @@ dissect_darwin_usb_iso_transfer(packet_info *pinfo _U_, proto_tree *tree, usb_he if (usb_conv_info->is_request == FALSE) { proto_tree_add_item(iso_desc_tree, hf_usb_darwin_iso_timestamp, tvb, offset + 20, 8, ENC_LITTLE_ENDIAN); - proto_tree_add_item(iso_desc_tree, hf_usb_darwin_iso_status, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item_ret_uint(iso_desc_tree, hf_usb_darwin_iso_status, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN, &status); + + proto_item_append_text(iso_desc_ti, " [%s]", val_to_str_ext(status, &usb_darwin_status_vals_ext, "Error %d")); /* Data */ if (frame_length > len) { @@ -5028,7 +5483,7 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: urb_type = tvb_get_guint8(tvb, 8); - endpoint = tvb_get_guint8(tvb, 10) & 0x7F; + endpoint = tvb_get_guint8(tvb, 10); device_address = (guint16)tvb_get_guint8(tvb, 11); bus_id = tvb_get_letohs(tvb, 12); break; @@ -5042,7 +5497,6 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, /* USBPcap before 1.3.0.0 DATA OUT packet (the info at offset 16 is wrong) */ urb_type = URB_SUBMIT; } - endpoint &= 0x7F; /* Clear the direction flag */ bus_id = tvb_get_letohs(tvb, 17); break; @@ -5052,6 +5506,10 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, device_address = mausb_ep_handle_dev_addr(ma_header->handle); endpoint = mausb_ep_handle_ep_num(ma_header->handle); bus_id = mausb_ep_handle_bus_num(ma_header->handle); + if (mausb_ep_handle_ep_d(ma_header->handle)) { + /* IN endpoint */ + endpoint |= 0x80; + } break; case USB_HEADER_USBIP: @@ -5060,13 +5518,17 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, device_address = ip_header->devid; bus_id = ip_header->busid; endpoint = ip_header->ep; + if (ip_header->dir == 1) { + /* IN endpoint */ + endpoint |= 0x80; + } break; case USB_HEADER_DARWIN: - urb_type = tvb_get_guint8(tvb, 1); - endpoint = tvb_get_guint8(tvb, 30) & 0x7F; + urb_type = tvb_get_guint8(tvb, 3) ? URB_COMPLETE : URB_SUBMIT; + endpoint = tvb_get_guint8(tvb, 30); device_address = (guint16)tvb_get_guint8(tvb, 29); - location = tvb_get_letohl(tvb, 23); + location = tvb_get_letohl(tvb, 24); bus_id = location >> 24; break; @@ -5086,6 +5548,13 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, urb_tree_ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, -1, "USB URB"); tree = proto_item_add_subtree(urb_tree_ti, ett_usb_hdr); + if (endpoint == 0x80) { + /* Control endpoint is only bidirectional endpoint, use 0 to look up + * correct conversation. + */ + endpoint = 0; + } + usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, (urb_type == URB_SUBMIT)); @@ -5118,7 +5587,7 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, case USB_HEADER_USBIP: iso_numdesc = tvb_get_ntohl(tvb, 0x20); - usb_conv_info->transfer_type = endpoint == 0 ? URB_CONTROL : (iso_numdesc > 0 ? URB_ISOCHRONOUS : URB_UNKNOWN); + usb_conv_info->transfer_type = endpoint == 0 ? URB_CONTROL : (iso_numdesc != 0xffffffff ? URB_ISOCHRONOUS : URB_UNKNOWN); usb_conv_info->direction = ip_header->dir == USBIP_DIR_OUT ? P2P_DIR_SENT : P2P_DIR_RECV; usb_conv_info->is_setup = endpoint == 0 ? (tvb_get_ntoh64(tvb, 0x28) != G_GUINT64_CONSTANT(0)) : FALSE; usb_conv_info->is_request = (urb_type==URB_SUBMIT); @@ -5144,6 +5613,7 @@ dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, usb_conv_info->direction = pseudo_urb->from_host ? P2P_DIR_SENT : P2P_DIR_RECV; usb_conv_info->is_setup = pseudo_urb->from_host && (pseudo_urb->transfer_type == URB_CONTROL); usb_conv_info->is_request = pseudo_urb->from_host; + usb_conv_info->speed = pseudo_urb->speed; usb_id = 0; break; @@ -5425,7 +5895,7 @@ proto_register_usb(void) NULL, HFILL }}, { &hf_usb_mode, - { "Mode of transfer", "usb.address", + { "Mode of transfer", "usb.transfer_mode", FT_UINT8, BASE_DEC, VALS(usb_freebsd_transfer_mode_vals), 0x0, NULL, HFILL }}, @@ -5681,7 +6151,7 @@ proto_register_usb(void) { &hf_usb_device_address, { "Device", "usb.device_address", - FT_UINT8, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, "USB device address", HFILL }}, { &hf_usb_bus_id, @@ -5691,12 +6161,12 @@ proto_register_usb(void) { &hf_usb_setup_flag, { "Device setup request", "usb.setup_flag", - FT_STRING, BASE_NONE, NULL, 0x0, + FT_CHAR, BASE_HEX|BASE_RANGE_STRING, RVALS(usb_setup_flag_rvals), 0x0, "USB device setup request is relevant (0) or not", HFILL }}, { &hf_usb_data_flag, { "Data", "usb.data_flag", - FT_STRING, BASE_NONE, NULL, 0x0, + FT_CHAR, BASE_HEX|BASE_RANGE_STRING, RVALS(usb_data_flag_rvals), 0x0, "USB data is present (0) or not", HFILL }}, { &hf_usb_urb_ts_sec, @@ -5860,7 +6330,7 @@ proto_register_usb(void) { &hf_usb_win32_data_len, { "Packet Data Length", "usb.data_len", - FT_UINT16, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_control_stage, @@ -6049,12 +6519,12 @@ proto_register_usb(void) /* --------------------------------- */ { &hf_usb_iso_error_count, /* host endian byte order */ { "ISO error count", "usb.iso.error_count", - FT_UINT16, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iso_numdesc, { "Number of ISO descriptors", "usb.iso.numdesc", - FT_UINT16, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, /* fields of struct mon_bin_isodesc from linux/drivers/usb/mon/mon_bin.c */ @@ -6349,7 +6819,7 @@ proto_register_usb(void) { &hf_usb_wMaxPacketSize_size, { "Maximum Packet Size", "usb.wMaxPacketSize.size", - FT_UINT16, BASE_DEC, NULL, 0x3FF, + FT_UINT16, BASE_DEC, NULL, 0x03FF, NULL, HFILL }}, { &hf_usb_wMaxPacketSize_slots, @@ -6484,23 +6954,113 @@ proto_register_usb(void) "usb.iFunction", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_usb_bNumDeviceCaps, + { "bNumDeviceCaps", "usb.bNumDeviceCaps", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_bDevCapabilityType, + { "bDevCapabilityType", "usb.bDevCapabilityType", + FT_UINT8, BASE_HEX|BASE_EXT_STRING, &usb_capability_vals_ext, 0x0, + NULL, HFILL }}, + + { &hf_usb_usb20ext_bmAttributes, + { "bmAttributes", "usb.usb20ext.bmAttributes", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_usb20ext_LPM, + { "LPM", "usb.usb20ext.bmAttributes.LPM", + FT_BOOLEAN, 32, NULL, 0x00000002, + NULL, HFILL }}, + + { &hf_usb_usb20ext_BESL_HIRD, + { "BESL & Alternate HIRD", "usb.usb20ext.bmAttributes.BESL", + FT_BOOLEAN, 32, NULL, 0x00000004, + NULL, HFILL }}, + + { &hf_usb_usb20ext_baseline_BESL_valid, + { "Baseline BESL valid", "usb.usb20ext.bmAttributes.baseline_BESL_valid", + FT_BOOLEAN, 32, NULL, 0x00000008, + NULL, HFILL }}, + + { &hf_usb_usb20ext_deep_BESL_valid, + { "Deep BESL valid", "usb.usb20ext.bmAttributes.deep_BESL_valid", + FT_BOOLEAN, 32, NULL, 0x00000010, + NULL, HFILL }}, + + { &hf_usb_usb20ext_baseline_BESL, + { "Recommended Baseline BESL", "usb.usb20ext.bmAttributes.baseline_BESL", + FT_UINT32, BASE_CUSTOM, CF_FUNC(usb_lpm_besl_str), 0x00000F00, + NULL, HFILL }}, + + { &hf_usb_usb20ext_deep_BESL, + { "Recommended Deep BESL", "usb.usb20ext.bmAttributes.deep_BESL", + FT_UINT32, BASE_CUSTOM, CF_FUNC(usb_lpm_besl_str), 0x0000F000, + NULL, HFILL }}, + + { &hf_usb_bReserved, + { "bReserved", "usb.bReserved", + FT_UINT8, BASE_DEC, NULL, 0x0, + "This field is reserved and shall be set to zero", HFILL }}, + + { &hf_usb_PlatformCapabilityUUID, + { "PlatformCapabilityUUID", "usb.PlatformCapabilityUUID", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_webusb_bcdVersion, + { "bcdVersion", "usb.webusb.bcdVersion", + FT_UINT16, BASE_HEX, NULL, 0x0, + "WebUSB descriptor version", HFILL }}, + + { &hf_usb_webusb_bVendorCode, + { "bVendorCode", "usb.webusb.bVendorCode", + FT_UINT8, BASE_DEC, NULL, 0x0, + "bRequest value for WebUSB", HFILL }}, + + { &hf_usb_webusb_iLandingPage, + { "iLandingPage", "usb.webusb.iLandingPage", + FT_UINT8, BASE_DEC, NULL, 0x0, + "URL for landing page", HFILL }}, + + { &hf_usb_msos20_dwWindowsVersion, + { "dwWindowsVersion", "usb.msos20.dwWindowsVersion", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_msos20_wMSOSDescriptorSetTotalLength, + { "wMSOSDescriptorSetTotalLength", "usb.msos20.wMSOSDescriptorSetTotalLength", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_msos20_bMS_VendorCode, + { "bMS_VendorCode", "usb.msos20.bMS_VendorCode", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_usb_msos20_bAltEnumCode, + { "bAltEnumCode", "usb.msos20.bAltEnumCode", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_usb_data_fragment, { "Data Fragment", "usb.data_fragment", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_src, { "Source", "usb.src", - FT_STRING, STR_ASCII, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_usb_dst, { "Destination", "usb.dst", - FT_STRING, STR_ASCII, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_usb_addr, { "Source or Destination", "usb.addr", - FT_STRING, STR_ASCII, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } } }; @@ -6653,7 +7213,7 @@ proto_register_usb(void) }, { &hf_usbport_urb_header_status, { "URB Header Status", "usbport.urb_header_status", - FT_UINT16, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_usbddevice_handle, @@ -6761,6 +7321,7 @@ proto_register_usb(void) &ett_endpoint_bmAttributes, &ett_endpoint_wMaxPacketSize, &ett_transfer_flags, + &ett_usb20ext_bmAttributes, }; static gint *usbport_subtrees[] = { @@ -6783,6 +7344,10 @@ proto_register_usb(void) { &ei_usb_ss_ep_companion_before_ep, { "usb.bmAttributes.invalid_order", PI_MALFORMED, PI_ERROR, "SuperSpeed Endpoint Companion must come after Endpoint Descriptor", EXPFILL }}, { &ei_usb_usbpcap_unknown_urb, { "usb.usbpcap.unknown_urb", PI_MALFORMED, PI_ERROR, "USBPcap did not recognize URB Function code (report to desowin.org/USBPcap)", EXPFILL }}, { &ei_usb_bad_length, { "usb.bad_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }}, + { &ei_usb_invalid_max_packet_size, { "usb.wMaxPacketSize.invalid", PI_PROTOCOL, PI_WARN, "Invalid Max Packet Size", EXPFILL }}, + { &ei_usb_invalid_max_packet_size0, { "usb.bMaxPacketSize0.invalid", PI_PROTOCOL, PI_WARN, "Invalid Max Packet Size", EXPFILL }}, + { &ei_usb_invalid_endpoint_type, { "usb.bmAttributes.transfer.invalid", PI_PROTOCOL, PI_WARN, "Transfer type not allowed at Low-Speed", EXPFILL }}, + { &ei_usb_unexpected_desc_type, { "usb.bDescriptorType.unexpected", PI_MALFORMED, PI_ERROR, "Unexpected descriptor type", EXPFILL }}, }; static ei_register_info ei_usbport[] = { { &ei_usbport_invalid_path_depth, { "usbport.path_depth.invalid", PI_PROTOCOL, PI_WARN, "Invalid path depth", EXPFILL }}, @@ -6811,14 +7376,14 @@ proto_register_usb(void) product_to_dissector = register_dissector_table("usb.product", "USB product", proto_usb, FT_UINT32, BASE_HEX); usb_bulk_dissector_table = register_dissector_table("usb.bulk", - "USB bulk endpoint", proto_usb, FT_UINT8, BASE_DEC); - heur_bulk_subdissector_list = register_heur_dissector_list("usb.bulk", proto_usb); + "USB bulk endpoint", proto_usb, FT_UINT32, BASE_HEX); + heur_bulk_subdissector_list = register_heur_dissector_list_with_description("usb.bulk", "USB bulk fallback", proto_usb); usb_control_dissector_table = register_dissector_table("usb.control", - "USB control endpoint", proto_usb, FT_UINT8, BASE_DEC); - heur_control_subdissector_list = register_heur_dissector_list("usb.control", proto_usb); + "USB control endpoint", proto_usb, FT_UINT32, BASE_HEX); + heur_control_subdissector_list = register_heur_dissector_list_with_description("usb.control", "USB control fallback", proto_usb); usb_interrupt_dissector_table = register_dissector_table("usb.interrupt", - "USB interrupt endpoint", proto_usb, FT_UINT8, BASE_DEC); - heur_interrupt_subdissector_list = register_heur_dissector_list("usb.interrupt", proto_usb); + "USB interrupt endpoint", proto_usb, FT_UINT32, BASE_HEX); + heur_interrupt_subdissector_list = register_heur_dissector_list_with_description("usb.interrupt", "USB interrupt fallback", proto_usb); usb_descriptor_dissector_table = register_dissector_table("usb.descriptor", "USB descriptor", proto_usb, FT_UINT8, BASE_DEC); @@ -6835,38 +7400,30 @@ proto_register_usb(void) register_decode_as(&usb_product_da); register_decode_as(&usb_device_da); + linux_usb_handle = register_dissector("usb_linux", dissect_linux_usb, proto_usb); + linux_usb_mmapped_handle = register_dissector("usb_linux_mmapped", dissect_linux_usb_mmapped, proto_usb); + win32_usb_handle = register_dissector("usb_win32", dissect_win32_usb, proto_usb); + freebsd_usb_handle = register_dissector("usb_freebsd", dissect_freebsd_usb, proto_usb); + darwin_usb_handle = register_dissector("usb_darwin", dissect_darwin_usb, proto_usb); + netmon_usb_port_handle = register_dissector("usb_netmon", dissect_netmon_usb_port, proto_usbport); + usb_address_type = address_type_dissector_register("AT_USB", "USB Address", usb_addr_to_str, usb_addr_str_len, NULL, usb_col_filter_str, NULL, NULL, NULL); - register_conversation_table(proto_usb, TRUE, usb_conversation_packet, usb_hostlist_packet); + register_conversation_table(proto_usb, TRUE, usb_conversation_packet, usb_endpoint_packet); } void proto_reg_handoff_usb(void) { - dissector_handle_t linux_usb_handle; - dissector_handle_t linux_usb_mmapped_handle; - dissector_handle_t win32_usb_handle; - dissector_handle_t freebsd_usb_handle; - dissector_handle_t darwin_usb_handle; - dissector_handle_t netmon_usb_port_handle; static guid_key usb_port_key = {{ 0xc88a4ef5, 0xd048, 0x4013, { 0x94, 0x08, 0xe0, 0x4b, 0x7d, 0xb2, 0x81, 0x4a }}, 0 }; - linux_usb_handle = create_dissector_handle(dissect_linux_usb, proto_usb); - linux_usb_mmapped_handle = create_dissector_handle(dissect_linux_usb_mmapped, - proto_usb); - win32_usb_handle = create_dissector_handle(dissect_win32_usb, proto_usb); - freebsd_usb_handle = create_dissector_handle(dissect_freebsd_usb, proto_usb); - darwin_usb_handle = create_dissector_handle(dissect_darwin_usb, proto_usb); - dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_LINUX, linux_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_LINUX_MMAPPED, linux_usb_mmapped_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USBPCAP, win32_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_FREEBSD, freebsd_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_DARWIN, darwin_usb_handle); - netmon_usb_port_handle = create_dissector_handle( dissect_netmon_usb_port, proto_usbport); dissector_add_guid( "netmon.provider_id", &usb_port_key, netmon_usb_port_handle); - } /* |