From Paolo Abeni: update to support the new DLT_USB_LINUX format header.
Modified to support the header as a pseudo_header rather than as part of the packet data. Fixed some calls that fetch data from the USB packet to fetch it in little-endian byte order. Got rid of redundant code to get conversation-specific data (the get_usb_conv_info() call already does that). For control packets, only parse the setup information if setup_flag is 0. Don't interpret a control packet as a standard request unless the setup type is "Standard". svn path=/trunk/; revision=20632
This commit is contained in:
parent
7317125c33
commit
9633ac8fee
|
@ -1,14 +1,9 @@
|
|||
/* Man this is suboptimal.
|
||||
* The USB Header and the setup data are BIG ENDIAN
|
||||
* but all the real usb data is LITTLE ENDIAN.
|
||||
*/
|
||||
|
||||
/* packet-usb.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* usb basic dissector
|
||||
* By Paolo Abeni <paolo.abeni@email.com>
|
||||
* USB basic dissector
|
||||
* By Paolo Abeni <paolo.abeni@email.it>
|
||||
* Ronnie Sahlberg 2006
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -43,9 +38,13 @@
|
|||
|
||||
/* protocols and header fields */
|
||||
static int proto_usb = -1;
|
||||
static int hf_usb_urb_id = -1;
|
||||
static int hf_usb_bus_id = -1;
|
||||
static int hf_usb_transfer_type = -1;
|
||||
static int hf_usb_urb_type = -1;
|
||||
static int hf_usb_device_address = -1;
|
||||
static int hf_usb_setup = -1;
|
||||
static int hf_usb_data_flag = -1;
|
||||
static int hf_usb_setup_flag = -1;
|
||||
static int hf_usb_endpoint_number = -1;
|
||||
static int hf_usb_src_endpoint_number = -1;
|
||||
static int hf_usb_dst_endpoint_number = -1;
|
||||
|
@ -114,35 +113,6 @@ static gint ett_endpoint_bmAttributes = -1;
|
|||
static dissector_table_t usb_bulk_dissector_table;
|
||||
static dissector_table_t usb_control_dissector_table;
|
||||
|
||||
|
||||
typedef enum {
|
||||
URB_CONTROL_INPUT,
|
||||
URB_CONTROL_OUTPUT,
|
||||
URB_ISOCHRONOUS_INPUT,
|
||||
URB_ISOCHRONOUS_OUTPUT,
|
||||
URB_INTERRUPT_INPUT,
|
||||
URB_INTERRUPT_OUTPUT,
|
||||
URB_BULK_INPUT,
|
||||
URB_BULK_OUTPUT,
|
||||
URB_UNKNOWN
|
||||
} urb_type_t;
|
||||
|
||||
typedef struct usb_header {
|
||||
guint32 urb_type;
|
||||
guint32 device_address;
|
||||
guint32 endpoint_number;
|
||||
guint32 setup_packet;
|
||||
} usb_header_t;
|
||||
|
||||
typedef struct usb_request {
|
||||
guint8 bmRequestType;
|
||||
guint8 bRequest;
|
||||
guint16 wValue;
|
||||
guint16 wIndex;
|
||||
guint16 wLength;
|
||||
} usb_request_t;
|
||||
|
||||
|
||||
static const value_string usb_langid_vals[] = {
|
||||
{0x0000, "no language specified"},
|
||||
{0x0409, "English (United States)"},
|
||||
|
@ -172,16 +142,18 @@ static const value_string usb_interfaceclass_vals[] = {
|
|||
};
|
||||
|
||||
|
||||
static const value_string usb_transfer_type_vals[] = {
|
||||
{URB_CONTROL, "URB_CONTROL"},
|
||||
{URB_ISOCHRONOUS,"URB_ISOCHRONOUS"},
|
||||
{URB_INTERRUPT,"URB_INTERRUPT"},
|
||||
{URB_BULK,"URB_BULK"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const value_string usb_urb_type_vals[] = {
|
||||
{URB_CONTROL_INPUT, "URB_CONTROL_INPUT"},
|
||||
{URB_CONTROL_OUTPUT,"URB_CONTROL_OUTPUT"},
|
||||
{URB_ISOCHRONOUS_INPUT,"URB_ISOCHRONOUS_INPUT"},
|
||||
{URB_ISOCHRONOUS_OUTPUT,"URB_ISOCHRONOUS_OUTPUT"},
|
||||
{URB_INTERRUPT_INPUT,"URB_INTERRUPT_INPUT"},
|
||||
{URB_INTERRUPT_OUTPUT,"URB_INTERRUPT_OUTPUT"},
|
||||
{URB_BULK_INPUT,"URB_BULK_INPUT"},
|
||||
{URB_BULK_OUTPUT,"URB_BULK_OUTPUT"},
|
||||
{URB_UNKNOWN, "URB_UNKNOWN"},
|
||||
{URB_SUBMIT, "URB_SUBMIT"},
|
||||
{URB_COMPLETE,"URB_COMPLETE"},
|
||||
{URB_ERROR,"URB_ERROR"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
@ -295,7 +267,7 @@ dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *pare
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE QUALIFIER DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -350,7 +322,7 @@ dissect_usb_device_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, t
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -427,7 +399,7 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, t
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "STRING DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -473,7 +445,7 @@ dissect_usb_interface_descriptor(packet_info *pinfo, proto_tree *parent_tree, tv
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "INTERFACE DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -546,7 +518,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvb
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "ENDPOINT DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -560,7 +532,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvb
|
|||
/* bEndpointAddress */
|
||||
if(tree){
|
||||
endpoint_item=proto_tree_add_item(tree, hf_usb_bEndpointAddress, tvb, offset, 1, TRUE);
|
||||
endpoint_tree=proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress);
|
||||
endpoint_tree=proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress);
|
||||
}
|
||||
endpoint=tvb_get_guint8(tvb, offset)&0x0f;
|
||||
proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_direction, tvb, offset, 1, TRUE);
|
||||
|
@ -644,7 +616,7 @@ dissect_usb_configuration_descriptor(packet_info *pinfo _U_, proto_tree *parent_
|
|||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "CONFIGURATION DESCRIPTOR");
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
tree=proto_item_add_subtree(item, ett_descriptor_device);
|
||||
}
|
||||
|
||||
/* bLength */
|
||||
|
@ -729,7 +701,7 @@ dissect_usb_setup_get_descriptor(packet_info *pinfo, proto_tree *tree, tvbuff_t
|
|||
{
|
||||
if(is_request){
|
||||
/* descriptor type */
|
||||
proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset, 1, FALSE);
|
||||
proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset, 1, TRUE);
|
||||
usb_trans_info->u.get_descriptor.type=tvb_get_guint8(tvb, offset);
|
||||
offset++;
|
||||
if (check_col(pinfo->cinfo, COL_INFO)) {
|
||||
|
@ -738,16 +710,16 @@ dissect_usb_setup_get_descriptor(packet_info *pinfo, proto_tree *tree, tvbuff_t
|
|||
}
|
||||
|
||||
/* descriptor index */
|
||||
proto_tree_add_item(tree, hf_usb_descriptor_index, tvb, offset, 1, FALSE);
|
||||
proto_tree_add_item(tree, hf_usb_descriptor_index, tvb, offset, 1, TRUE);
|
||||
usb_trans_info->u.get_descriptor.index=tvb_get_guint8(tvb, offset);
|
||||
offset++;
|
||||
|
||||
/* language id */
|
||||
proto_tree_add_item(tree, hf_usb_language_id, tvb, offset, 2, FALSE);
|
||||
proto_tree_add_item(tree, hf_usb_language_id, tvb, offset, 2, TRUE);
|
||||
offset+=2;
|
||||
|
||||
/* length */
|
||||
proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, FALSE);
|
||||
proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
} else {
|
||||
if (check_col(pinfo->cinfo, COL_INFO)) {
|
||||
|
@ -810,11 +782,15 @@ static const true_false_string tfs_bmrequesttype_direction = {
|
|||
"Device-to-host",
|
||||
"Host-to-device"
|
||||
};
|
||||
|
||||
#define RQT_SETUP_TYPE_STANDARD 0
|
||||
#define RQT_SETUP_TYPE_CLASS 1
|
||||
#define RQT_SETUP_TYPE_VENDOR 2
|
||||
|
||||
static const value_string bmrequesttype_type_vals[] = {
|
||||
{0, "Standard"},
|
||||
{1, "Class"},
|
||||
{2, "Vendor"},
|
||||
{3, "Reserved"},
|
||||
{RQT_SETUP_TYPE_STANDARD, "Standard"},
|
||||
{RQT_SETUP_TYPE_CLASS, "Class"},
|
||||
{RQT_SETUP_TYPE_VENDOR, "Vendor"},
|
||||
{0, NULL}
|
||||
};
|
||||
static const value_string bmrequesttype_recipient_vals[] = {
|
||||
|
@ -826,16 +802,20 @@ static const value_string bmrequesttype_recipient_vals[] = {
|
|||
};
|
||||
|
||||
static int
|
||||
dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
|
||||
dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset,
|
||||
int *type)
|
||||
{
|
||||
proto_item *item=NULL;
|
||||
proto_tree *tree=NULL;
|
||||
guint8 bmRequestType;
|
||||
|
||||
if(parent_tree){
|
||||
item=proto_tree_add_item(parent_tree, hf_usb_bmRequestType, tvb, offset, 1, TRUE);
|
||||
tree = proto_item_add_subtree(item, ett_usb_setup_bmrequesttype);
|
||||
}
|
||||
|
||||
bmRequestType = tvb_get_guint8(tvb, offset);
|
||||
*type = (bmRequestType >> 5) & 0x03;
|
||||
proto_tree_add_item(tree, hf_usb_bmRequestType_direction, tvb, offset, 1, TRUE);
|
||||
proto_tree_add_item(tree, hf_usb_bmRequestType_type, tvb, offset, 1, TRUE);
|
||||
proto_tree_add_item(tree, hf_usb_bmRequestType_recipient, tvb, offset, 1, TRUE);
|
||||
|
@ -849,11 +829,11 @@ dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
|
|||
|
||||
|
||||
static void
|
||||
dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
||||
dissect_linux_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
||||
{
|
||||
int offset = 0;
|
||||
int type, endpoint;
|
||||
gboolean setup;
|
||||
guint8 setup_flag;
|
||||
proto_tree *tree = NULL;
|
||||
guint32 src_device, dst_device, tmp_addr;
|
||||
static usb_address_t src_addr, dst_addr; /* has to be static due to SET_ADDRESS */
|
||||
|
@ -869,102 +849,53 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
|||
/* add usb hdr*/
|
||||
if (parent) {
|
||||
proto_item *ti = NULL;
|
||||
ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, sizeof(usb_header_t), "USB URB");
|
||||
ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, sizeof(struct usb_request_hdr), "USB URB");
|
||||
|
||||
tree = proto_item_add_subtree(ti, usb_hdr);
|
||||
}
|
||||
|
||||
|
||||
type = tvb_get_ntohl(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_usb_urb_type, tvb, offset, 4, FALSE);
|
||||
offset += 4;
|
||||
proto_tree_add_uint64(tree, hf_usb_urb_id, tvb, 0, 0,
|
||||
pinfo->pseudo_header->linux_usb.id);
|
||||
|
||||
proto_tree_add_uint(tree, hf_usb_urb_type, tvb, 0, 0,
|
||||
pinfo->pseudo_header->linux_usb.event_type);
|
||||
|
||||
type = pinfo->pseudo_header->linux_usb.transfer_type;
|
||||
proto_tree_add_uint(tree, hf_usb_transfer_type, tvb, 0, 0, type);
|
||||
if (check_col(pinfo->cinfo, COL_INFO)) {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
|
||||
val_to_str(type, usb_urb_type_vals, "Unknown type %x"));
|
||||
val_to_str(type, usb_transfer_type_vals, "Unknown type %x"));
|
||||
}
|
||||
|
||||
proto_tree_add_item(tree, hf_usb_device_address, tvb, offset, 4, FALSE);
|
||||
tmp_addr=tvb_get_ntohl(tvb, offset);
|
||||
offset += 4;
|
||||
endpoint=pinfo->pseudo_header->linux_usb.endpoint_number;
|
||||
proto_tree_add_uint(tree, hf_usb_endpoint_number, tvb, 0, 0, endpoint);
|
||||
|
||||
proto_tree_add_item(tree, hf_usb_endpoint_number, tvb, offset, 4, FALSE);
|
||||
endpoint=tvb_get_ntohl(tvb, offset);
|
||||
offset += 4;
|
||||
tmp_addr=pinfo->pseudo_header->linux_usb.device_address;
|
||||
proto_tree_add_uint(tree, hf_usb_device_address, tvb, 0, 0, tmp_addr);
|
||||
|
||||
/* check for setup hdr presence */
|
||||
proto_tree_add_item(tree, hf_usb_setup, tvb, offset, 4, FALSE);
|
||||
setup = tvb_get_ntohl(tvb, offset);
|
||||
offset += 4;
|
||||
proto_tree_add_uint(tree, hf_usb_bus_id, tvb, 0, 0,
|
||||
pinfo->pseudo_header->linux_usb.bus_id);
|
||||
|
||||
setup_flag = pinfo->pseudo_header->linux_usb.setup_flag;
|
||||
proto_tree_add_uint(tree, hf_usb_setup_flag, tvb, 0, 0, setup_flag);
|
||||
|
||||
proto_tree_add_uint(tree, hf_usb_data_flag, tvb, 0, 0,
|
||||
pinfo->pseudo_header->linux_usb.data_flag);
|
||||
|
||||
/* set up addresses and ports */
|
||||
switch(type){
|
||||
case URB_BULK_INPUT:
|
||||
/* Bulk input are responses if they contain payload data and
|
||||
* requests otherwise.
|
||||
*/
|
||||
if(tvb_length_remaining(tvb, offset)>0){
|
||||
src_device=tmp_addr;
|
||||
src_endpoint=endpoint;
|
||||
dst_device=0xffffffff;
|
||||
dst_endpoint=NO_ENDPOINT;
|
||||
is_request=FALSE;
|
||||
} else {
|
||||
src_device=0xffffffff;
|
||||
src_endpoint=NO_ENDPOINT;
|
||||
dst_device=tmp_addr;
|
||||
dst_endpoint=endpoint;
|
||||
is_request=TRUE;
|
||||
}
|
||||
break;
|
||||
case URB_BULK_OUTPUT:
|
||||
/* Bulk output are requests if they contain payload data and
|
||||
* responses otherwise.
|
||||
*/
|
||||
if(tvb_length_remaining(tvb, offset)>0){
|
||||
src_device=0xffffffff;
|
||||
src_endpoint=NO_ENDPOINT;
|
||||
dst_device=tmp_addr;
|
||||
dst_endpoint=endpoint;
|
||||
is_request=TRUE;
|
||||
} else {
|
||||
src_device=tmp_addr;
|
||||
src_endpoint=endpoint;
|
||||
dst_device=0xffffffff;
|
||||
dst_endpoint=NO_ENDPOINT;
|
||||
is_request=FALSE;
|
||||
}
|
||||
break;
|
||||
case URB_CONTROL_INPUT:
|
||||
/* CONTROL INPUT packets are requests if they contain a "setup"
|
||||
* blob and responses othervise
|
||||
*/
|
||||
if(setup){
|
||||
src_device=0xffffffff;
|
||||
src_endpoint=NO_ENDPOINT;
|
||||
dst_device=tmp_addr;
|
||||
dst_endpoint=endpoint;
|
||||
is_request=TRUE;
|
||||
} else {
|
||||
src_device=tmp_addr;
|
||||
src_endpoint=endpoint;
|
||||
dst_device=0xffffffff;
|
||||
dst_endpoint=NO_ENDPOINT;
|
||||
is_request=FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* dont know */
|
||||
src_device=0xffffffff;
|
||||
dst_device=0xffffffff;
|
||||
src_endpoint=NO_ENDPOINT;
|
||||
dst_endpoint=NO_ENDPOINT;
|
||||
is_request=FALSE;
|
||||
is_request = endpoint & URB_TRANSFER_IN;
|
||||
if (is_request){
|
||||
src_addr.device = src_device = htolel(tmp_addr);
|
||||
src_addr.endpoint = src_endpoint = htolel(endpoint);
|
||||
dst_addr.device = dst_device = 0xffffffff;
|
||||
dst_addr.endpoint = dst_endpoint = NO_ENDPOINT;
|
||||
} else {
|
||||
src_addr.device = src_device = 0xffffffff;
|
||||
src_addr.endpoint = src_endpoint = NO_ENDPOINT;
|
||||
dst_addr.device = src_device = htolel(tmp_addr);
|
||||
dst_addr.endpoint = src_endpoint = htolel(endpoint);
|
||||
}
|
||||
src_addr.device = src_device;
|
||||
src_addr.endpoint = src_endpoint;
|
||||
dst_addr.device = dst_device;
|
||||
dst_addr.endpoint = dst_endpoint;
|
||||
|
||||
SET_ADDRESS(&pinfo->net_src, AT_USB, USB_ADDR_LEN, (char *)&src_addr);
|
||||
SET_ADDRESS(&pinfo->src, AT_USB, USB_ADDR_LEN, (char *)&src_addr);
|
||||
SET_ADDRESS(&pinfo->net_dst, AT_USB, USB_ADDR_LEN, (char *)&dst_addr);
|
||||
|
@ -973,25 +904,12 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
|||
pinfo->srcport=src_endpoint;
|
||||
pinfo->destport=dst_endpoint;
|
||||
|
||||
|
||||
conversation=get_usb_conversation(pinfo, pinfo->srcport, pinfo->destport);
|
||||
|
||||
usb_conv_info=get_usb_conv_info(conversation);
|
||||
|
||||
/* do we have conversation specific data ? */
|
||||
usb_conv_info = conversation_get_proto_data(conversation, proto_usb);
|
||||
if(!usb_conv_info){
|
||||
/* no not yet so create some */
|
||||
usb_conv_info = se_alloc(sizeof(usb_conv_info_t));
|
||||
usb_conv_info->class=IF_CLASS_UNKNOWN;
|
||||
usb_conv_info->transactions=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "usb transactions");
|
||||
usb_conv_info->masstorage=NULL;
|
||||
|
||||
conversation_add_proto_data(conversation, proto_usb, usb_conv_info);
|
||||
}
|
||||
pinfo->usb_conv_info=usb_conv_info;
|
||||
|
||||
|
||||
/* request/response matching so we can keep track of transaction specific
|
||||
* data.
|
||||
*/
|
||||
|
@ -1023,7 +941,7 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
|||
|
||||
|
||||
switch(type){
|
||||
case URB_BULK_INPUT:
|
||||
case URB_BULK:
|
||||
{
|
||||
proto_item *item;
|
||||
|
||||
|
@ -1033,107 +951,96 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
|||
tvbuff_t *next_tvb;
|
||||
|
||||
pinfo->usb_conv_info=usb_conv_info;
|
||||
next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
|
||||
next_tvb=tvb_new_subset(tvb, offset, -1, -1);
|
||||
if(dissector_try_port(usb_bulk_dissector_table, usb_conv_info->class, next_tvb, pinfo, parent)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case URB_BULK_OUTPUT:
|
||||
{
|
||||
proto_item *item;
|
||||
|
||||
item=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->class);
|
||||
PROTO_ITEM_SET_GENERATED(item);
|
||||
if(tvb_length_remaining(tvb, offset)){
|
||||
tvbuff_t *next_tvb;
|
||||
|
||||
pinfo->usb_conv_info=usb_conv_info;
|
||||
next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
|
||||
if(dissector_try_port(usb_bulk_dissector_table, usb_conv_info->class, next_tvb, pinfo, parent)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case URB_CONTROL_INPUT:
|
||||
case URB_CONTROL:
|
||||
{
|
||||
const usb_setup_dissector_table_t *tmp;
|
||||
usb_setup_dissector dissector;
|
||||
proto_item *ti = NULL;
|
||||
proto_tree *setup_tree = NULL;
|
||||
int type;
|
||||
|
||||
ti=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->class);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
|
||||
if(is_request){
|
||||
tvbuff_t *next_tvb;
|
||||
if (setup_flag == 0) {
|
||||
tvbuff_t *next_tvb;
|
||||
|
||||
/* this is a request */
|
||||
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_request_t), "URB setup");
|
||||
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
|
||||
usb_trans_info->requesttype=tvb_get_guint8(tvb, offset);
|
||||
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset);
|
||||
/* this is a request */
|
||||
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_request_hdr), "URB setup");
|
||||
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
|
||||
usb_trans_info->requesttype=tvb_get_guint8(tvb, offset);
|
||||
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset, &type);
|
||||
|
||||
|
||||
/* read the request code and spawn off to a class specific
|
||||
* dissector if found
|
||||
*/
|
||||
usb_trans_info->request=tvb_get_guint8(tvb, offset);
|
||||
/* read the request code and spawn off to a class specific
|
||||
* dissector if found
|
||||
*/
|
||||
usb_trans_info->request=tvb_get_guint8(tvb, offset);
|
||||
|
||||
/* Try to find a class specific dissector */
|
||||
next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
|
||||
if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
|
||||
/*
|
||||
* This was a standard request which is managed by this dissector
|
||||
*/
|
||||
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
|
||||
offset += 1;
|
||||
case RQT_SETUP_TYPE_STANDARD:
|
||||
/*
|
||||
* This is a standard request which is managed by this
|
||||
* dissector
|
||||
*/
|
||||
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
|
||||
offset += 1;
|
||||
|
||||
if (check_col(pinfo->cinfo, COL_INFO)) {
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request",
|
||||
val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x"));
|
||||
}
|
||||
if (check_col(pinfo->cinfo, COL_INFO)) {
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request",
|
||||
val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x"));
|
||||
}
|
||||
|
||||
dissector=NULL;
|
||||
for(tmp=setup_dissectors;tmp->dissector;tmp++){
|
||||
if(tmp->request==usb_trans_info->request){
|
||||
dissector=tmp->dissector;
|
||||
dissector=NULL;
|
||||
for(tmp=setup_dissectors;tmp->dissector;tmp++){
|
||||
if(tmp->request==usb_trans_info->request){
|
||||
dissector=tmp->dissector;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dissector){
|
||||
dissector(pinfo, setup_tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
|
||||
offset+=6;
|
||||
} else {
|
||||
proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(setup_tree, hf_usb_index, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(setup_tree, hf_usb_length, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case RQT_SETUP_TYPE_CLASS:
|
||||
/* Try to find a class specific dissector */
|
||||
next_tvb=tvb_new_subset(tvb, offset, -1, -1);
|
||||
if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){
|
||||
return;
|
||||
/* XXX - dump as hex */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dissector){
|
||||
dissector(pinfo, setup_tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
|
||||
offset+=6;
|
||||
} else {
|
||||
proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(setup_tree, hf_usb_index, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(setup_tree, hf_usb_length, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
offset += 8;
|
||||
}
|
||||
} else {
|
||||
tvbuff_t *next_tvb;
|
||||
|
||||
/* this is a response */
|
||||
if(usb_conv_info->usb_trans_info){
|
||||
dissector=NULL;
|
||||
for(tmp=setup_dissectors;tmp->dissector;tmp++){
|
||||
if(tmp->request==usb_conv_info->usb_trans_info->request){
|
||||
dissector=tmp->dissector;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find a class specific dissector */
|
||||
next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
|
||||
next_tvb=tvb_new_subset(tvb, offset, -1, -1);
|
||||
if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){
|
||||
return;
|
||||
}
|
||||
|
@ -1144,79 +1051,106 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
|
|||
val_to_str(usb_conv_info->usb_trans_info->request, setup_request_names_vals, "Unknown type %x"));
|
||||
}
|
||||
|
||||
dissector=NULL;
|
||||
for(tmp=setup_dissectors;tmp->dissector;tmp++){
|
||||
if(tmp->request==usb_conv_info->usb_trans_info->request){
|
||||
dissector=tmp->dissector;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dissector){
|
||||
dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info->usb_trans_info, usb_conv_info);
|
||||
}
|
||||
} else {
|
||||
/* no matching request available */
|
||||
;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* dont know */
|
||||
;
|
||||
if (setup_flag == 0) {
|
||||
proto_item *ti = NULL;
|
||||
proto_tree *setup_tree = NULL;
|
||||
guint8 requesttype, request;
|
||||
int type;
|
||||
|
||||
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_request_hdr), "URB setup");
|
||||
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
|
||||
|
||||
|
||||
requesttype=tvb_get_guint8(tvb, offset);
|
||||
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset, &type);
|
||||
|
||||
request=tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, TRUE);
|
||||
offset += 2;
|
||||
} else {
|
||||
offset += 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (setup) {
|
||||
proto_item *ti = NULL;
|
||||
proto_tree *setup_tree = NULL;
|
||||
guint8 requesttype, request;
|
||||
|
||||
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_request_t), "URB setup");
|
||||
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
|
||||
|
||||
|
||||
requesttype=tvb_get_guint8(tvb, offset);
|
||||
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset);
|
||||
|
||||
request=tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, FALSE);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, FALSE);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
proto_tree_add_item(tree, hf_usb_data, tvb,
|
||||
offset, tvb_length_remaining(tvb, offset), FALSE);
|
||||
proto_tree_add_item(tree, hf_usb_data, tvb, offset, -1, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_usb(void)
|
||||
{
|
||||
static hf_register_info hf[] = {
|
||||
|
||||
|
||||
{ &hf_usb_urb_id,
|
||||
{ "URB id", "usb.urb_id", FT_UINT64, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
"URB id", HFILL }},
|
||||
|
||||
{ &hf_usb_bus_id,
|
||||
{ "URB bus id", "usb.bus_id", FT_UINT16, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
"URB bus id", HFILL }},
|
||||
|
||||
{ &hf_usb_urb_type,
|
||||
{ "URB type", "usb.urb_type", FT_UINT32, BASE_DEC,
|
||||
{ "URB type", "usb.urb_type", FT_UINT8, BASE_DEC,
|
||||
VALS(usb_urb_type_vals), 0x0,
|
||||
"URB type", HFILL }},
|
||||
|
||||
{ &hf_usb_transfer_type,
|
||||
{ "URB transfer type", "usb.transfer_type", FT_UINT8, BASE_DEC,
|
||||
VALS(usb_transfer_type_vals), 0x0,
|
||||
"URB transfer type", HFILL }},
|
||||
|
||||
{ &hf_usb_device_address,
|
||||
{ "Device", "usb.device_address", FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
{ "Device", "usb.device_address", FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
"USB device address", HFILL }},
|
||||
|
||||
{ &hf_usb_setup,
|
||||
{ "Setup", "usb.setup", FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
"USB setup", HFILL }},
|
||||
{ &hf_usb_data_flag,
|
||||
{ "Data flag", "usb.data_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
"USB data flag", HFILL }},
|
||||
|
||||
{ &hf_usb_setup_flag,
|
||||
{ "Setup flag", "usb.setup_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
"USB setup flag", HFILL }},
|
||||
|
||||
{ &hf_usb_endpoint_number,
|
||||
{ "Endpoint", "usb.endpoint_number", FT_UINT32, BASE_HEX, NULL, 0x0,
|
||||
"usb endpoint number", HFILL }},
|
||||
{ "Endpoint", "usb.endpoint_number", FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"USB endpoint number", HFILL }},
|
||||
|
||||
{ &hf_usb_src_endpoint_number,
|
||||
{ "Src Endpoint", "usb.src.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0,
|
||||
"src usb endpoint number", HFILL }},
|
||||
{ "Src Endpoint", "usb.src.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"Source USB endpoint number", HFILL }},
|
||||
|
||||
{ &hf_usb_dst_endpoint_number,
|
||||
{ "Dst Endpoint", "usb.dst.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0,
|
||||
"dst usb endpoint number", HFILL }},
|
||||
{ "Dst Endpoint", "usb.dst.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"Destination USB endpoint number", HFILL }},
|
||||
|
||||
{ &hf_usb_bmRequestType,
|
||||
{ "bmRequestType", "usb.bmRequestType", FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
|
@ -1444,8 +1378,6 @@ proto_register_usb(void)
|
|||
proto_register_field_array(proto_usb, hf, array_length(hf));
|
||||
proto_register_subtree_array(usb_subtrees, array_length(usb_subtrees));
|
||||
|
||||
register_dissector("usb", dissect_usb, proto_usb);
|
||||
|
||||
usb_bulk_dissector_table = register_dissector_table("usb.bulk",
|
||||
"USB bulk endpoint", FT_UINT8, BASE_DEC);
|
||||
|
||||
|
@ -1457,8 +1389,9 @@ proto_register_usb(void)
|
|||
void
|
||||
proto_reg_handoff_usb(void)
|
||||
{
|
||||
dissector_handle_t usb_handle;
|
||||
usb_handle = create_dissector_handle(dissect_usb, proto_usb);
|
||||
dissector_handle_t linux_usb_handle;
|
||||
|
||||
dissector_add("wtap_encap", WTAP_ENCAP_USB, usb_handle);
|
||||
linux_usb_handle = create_dissector_handle(dissect_linux_usb, proto_usb);
|
||||
|
||||
dissector_add("wtap_encap", WTAP_ENCAP_USB_LINUX, linux_usb_handle);
|
||||
}
|
||||
|
|
|
@ -138,6 +138,8 @@ static gboolean libpcap_get_lapd_pseudoheader(const struct lapd_sll_hdr *lapd_ph
|
|||
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
|
||||
static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh,
|
||||
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
|
||||
static gboolean libpcap_read_linux_usb_pseudoheader(wtap *wth, FILE_T fh,
|
||||
union wtap_pseudo_header *pseudo_header, int *err);
|
||||
static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length,
|
||||
int *err);
|
||||
static void libpcap_close(wtap *wth);
|
||||
|
@ -416,6 +418,8 @@ static const struct {
|
|||
{ 187, WTAP_ENCAP_BLUETOOTH_H4 },
|
||||
/* IEEE 802.16 MAC Common Part Sublayer */
|
||||
{ 188, WTAP_ENCAP_IEEE802_16_MAC_CPS },
|
||||
/* USB packets with Linux-specified header */
|
||||
{ 189, WTAP_ENCAP_USB_LINUX },
|
||||
|
||||
/*
|
||||
* To repeat:
|
||||
|
@ -640,7 +644,6 @@ int libpcap_open(wtap *wth, int *err, gchar **err_info)
|
|||
gboolean aix;
|
||||
int file_encap;
|
||||
|
||||
|
||||
/* Read in the number that should be at the start of a "libpcap" file */
|
||||
errno = WTAP_ERR_CANT_READ;
|
||||
bytes_read = file_read(&magic, 1, sizeof magic, wth->fh);
|
||||
|
@ -1307,6 +1310,7 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
|
|||
packet_size -= sizeof (struct irda_sll_hdr);
|
||||
wth->data_offset += sizeof (struct irda_sll_hdr);
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_MTP2_WITH_PHDR:
|
||||
if (packet_size < sizeof (struct mtp2_hdr)) {
|
||||
/*
|
||||
|
@ -1352,6 +1356,29 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
|
|||
packet_size -= sizeof (struct lapd_sll_hdr);
|
||||
wth->data_offset += sizeof (struct lapd_sll_hdr);
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_USB_LINUX:
|
||||
if (packet_size < sizeof (struct linux_usb_phdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
* have a pseudo-header.
|
||||
*/
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup_printf("libpcap: Linux USB file has a %u-byte packet, too small to have even a LAPD pseudo-header\n",
|
||||
packet_size);
|
||||
return FALSE;
|
||||
}
|
||||
if (!libpcap_read_linux_usb_pseudoheader(wth, wth->fh,
|
||||
&wth->pseudo_header, err))
|
||||
return FALSE; /* Read error */
|
||||
|
||||
/*
|
||||
* Don't count the pseudo-header as part of the packet.
|
||||
*/
|
||||
orig_size -= sizeof (struct linux_usb_phdr);
|
||||
packet_size -= sizeof (struct linux_usb_phdr);
|
||||
wth->data_offset += sizeof (struct linux_usb_phdr);
|
||||
break;
|
||||
}
|
||||
|
||||
buffer_assure_space(wth->frame_buffer, packet_size);
|
||||
|
@ -1455,6 +1482,7 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_MTP2_WITH_PHDR:
|
||||
if (!libpcap_read_mtp2_pseudoheader(wth->random_fh, pseudo_header,
|
||||
err, err_info)) {
|
||||
|
@ -1470,6 +1498,12 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_USB_LINUX:
|
||||
if (!libpcap_read_linux_usb_pseudoheader(wth, wth->random_fh,
|
||||
pseudo_header, err))
|
||||
return FALSE; /* Read error */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1855,6 +1889,38 @@ libpcap_read_lapd_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_heade
|
|||
err_info);
|
||||
}
|
||||
|
||||
static void
|
||||
libpcap_swap_linux_usb_pseudoheader(struct linux_usb_phdr *phdr)
|
||||
{
|
||||
phdr->id = GUINT64_SWAP_LE_BE(phdr->id);
|
||||
phdr->bus_id = GUINT16_SWAP_LE_BE(phdr->bus_id);
|
||||
phdr->ts_sec = GUINT64_SWAP_LE_BE(phdr->ts_sec);
|
||||
phdr->ts_usec = GUINT32_SWAP_LE_BE(phdr->ts_usec);
|
||||
phdr->status = GUINT32_SWAP_LE_BE(phdr->status);
|
||||
phdr->urb_len = GUINT32_SWAP_LE_BE(phdr->urb_len);
|
||||
phdr->data_len = GUINT32_SWAP_LE_BE(phdr->data_len);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
libpcap_read_linux_usb_pseudoheader(wtap *wth, FILE_T fh,
|
||||
union wtap_pseudo_header *pseudo_header, int *err)
|
||||
{
|
||||
int bytes_read;
|
||||
|
||||
errno = WTAP_ERR_CANT_READ;
|
||||
bytes_read = file_read(&pseudo_header->linux_usb, 1,
|
||||
sizeof (struct linux_usb_phdr), fh);
|
||||
if (bytes_read != sizeof (struct linux_usb_phdr)) {
|
||||
*err = file_error(fh);
|
||||
if (*err == 0)
|
||||
*err = WTAP_ERR_SHORT_READ;
|
||||
return FALSE;
|
||||
}
|
||||
if (wth->capture.pcap->byte_swapped)
|
||||
libpcap_swap_linux_usb_pseudoheader(&pseudo_header->linux_usb);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
|
||||
{
|
||||
|
@ -1969,7 +2035,9 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr,
|
|||
* the VCI; read them and generate the pseudo-header from
|
||||
* them.
|
||||
*/
|
||||
if (linktype == WTAP_ENCAP_ATM_PDUS) {
|
||||
switch (linktype) {
|
||||
|
||||
case WTAP_ENCAP_ATM_PDUS:
|
||||
if (whdr->caplen < sizeof (struct sunatm_hdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
|
@ -1996,8 +2064,9 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr,
|
|||
*/
|
||||
if (pseudo_header->atm.type == TRAF_LANE)
|
||||
atm_guess_lane_type(pd, whdr->caplen, pseudo_header);
|
||||
}
|
||||
else if (linktype == WTAP_ENCAP_IRDA) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_IRDA:
|
||||
if (whdr->caplen < sizeof (struct irda_sll_hdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
|
@ -2018,8 +2087,9 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr,
|
|||
whdr->len -= sizeof (struct irda_sll_hdr);
|
||||
whdr->caplen -= sizeof (struct irda_sll_hdr);
|
||||
pd += sizeof (struct irda_sll_hdr);
|
||||
}
|
||||
else if (linktype == WTAP_ENCAP_MTP2_WITH_PHDR) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_MTP2_WITH_PHDR:
|
||||
if (whdr->caplen < sizeof (struct mtp2_hdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
|
@ -2039,8 +2109,9 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr,
|
|||
whdr->len -= sizeof (struct mtp2_hdr);
|
||||
whdr->caplen -= sizeof (struct mtp2_hdr);
|
||||
pd += sizeof (struct mtp2_hdr);
|
||||
}
|
||||
else if (linktype == WTAP_ENCAP_LINUX_LAPD) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_LINUX_LAPD:
|
||||
if (whdr->caplen < sizeof (struct lapd_sll_hdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
|
@ -2061,6 +2132,27 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr,
|
|||
whdr->len -= sizeof (struct lapd_sll_hdr);
|
||||
whdr->caplen -= sizeof (struct lapd_sll_hdr);
|
||||
pd += sizeof (struct lapd_sll_hdr);
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_USB_LINUX:
|
||||
if (whdr->caplen < sizeof (struct linux_usb_phdr)) {
|
||||
/*
|
||||
* Uh-oh, the packet isn't big enough to even
|
||||
* have a pseudo-header.
|
||||
*/
|
||||
g_message("libpcap: Linux USB file has a %u-byte packet, too small to have even a LAPD pseudo-header\n",
|
||||
whdr->caplen);
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't count the pseudo-header as part of the packet.
|
||||
*/
|
||||
whdr->len -= sizeof (struct linux_usb_phdr);
|
||||
whdr->caplen -= sizeof (struct linux_usb_phdr);
|
||||
pd += sizeof (struct linux_usb_phdr);
|
||||
break;
|
||||
}
|
||||
return pd;
|
||||
}
|
||||
|
@ -2178,14 +2270,32 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
struct mtp2_hdr mtp2_hdr;
|
||||
int hdrsize;
|
||||
|
||||
if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
|
||||
switch (wdh->encap) {
|
||||
|
||||
case WTAP_ENCAP_ATM_PDUS:
|
||||
hdrsize = sizeof (struct sunatm_hdr);
|
||||
else if (wdh->encap == WTAP_ENCAP_IRDA)
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_IRDA:
|
||||
hdrsize = sizeof (struct irda_sll_hdr);
|
||||
else if (wdh->encap == WTAP_ENCAP_LINUX_LAPD)
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_MTP2_WITH_PHDR:
|
||||
hdrsize = sizeof (struct mtp2_hdr);
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_LINUX_LAPD:
|
||||
hdrsize = sizeof (struct lapd_sll_hdr);
|
||||
else
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_USB_LINUX:
|
||||
hdrsize = sizeof (struct linux_usb_phdr);
|
||||
break;
|
||||
|
||||
default:
|
||||
hdrsize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rec_hdr.hdr.ts_sec = phdr->ts.secs;
|
||||
if(wdh->tsprecision == WTAP_FILE_TSPREC_NSEC) {
|
||||
|
@ -2265,7 +2375,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
}
|
||||
wdh->bytes_dumped += hdr_size;
|
||||
|
||||
if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
|
||||
switch (wdh->encap) {
|
||||
|
||||
case WTAP_ENCAP_ATM_PDUS:
|
||||
/*
|
||||
* Write the ATM header.
|
||||
*/
|
||||
|
@ -2309,8 +2421,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
return FALSE;
|
||||
}
|
||||
wdh->bytes_dumped += sizeof atm_hdr;
|
||||
}
|
||||
else if (wdh->encap == WTAP_ENCAP_IRDA) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_IRDA:
|
||||
/*
|
||||
* Write the IrDA header.
|
||||
*/
|
||||
|
@ -2326,8 +2439,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
return FALSE;
|
||||
}
|
||||
wdh->bytes_dumped += sizeof(irda_hdr);
|
||||
}
|
||||
else if (wdh->encap == WTAP_ENCAP_MTP2_WITH_PHDR) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_MTP2_WITH_PHDR:
|
||||
/*
|
||||
* Write the MTP2 header.
|
||||
*/
|
||||
|
@ -2344,8 +2458,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
return FALSE;
|
||||
}
|
||||
wdh->bytes_dumped += sizeof(mtp2_hdr);
|
||||
}
|
||||
else if (wdh->encap == WTAP_ENCAP_LINUX_LAPD) {
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_LINUX_LAPD:
|
||||
/*
|
||||
* Write the LAPD header.
|
||||
*/
|
||||
|
@ -2362,6 +2477,26 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
|
|||
return FALSE;
|
||||
}
|
||||
wdh->bytes_dumped += sizeof(lapd_hdr);
|
||||
break;
|
||||
|
||||
case WTAP_ENCAP_USB_LINUX:
|
||||
/*
|
||||
* Write out the pseudo-header; it has the same format
|
||||
* as the Linux USB header, and that header is supposed
|
||||
* to be written in the host byte order of the machine
|
||||
* writing the file.
|
||||
*/
|
||||
nwritten = fwrite(&pseudo_header->linux_usb, 1,
|
||||
sizeof(pseudo_header->linux_usb), wdh->fh);
|
||||
if (nwritten != sizeof(pseudo_header->linux_usb)) {
|
||||
if (nwritten == 0 && ferror(wdh->fh))
|
||||
*err = errno;
|
||||
else
|
||||
*err = WTAP_ERR_SHORT_WRITE;
|
||||
return FALSE;
|
||||
}
|
||||
wdh->bytes_dumped += sizeof(lapd_hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen);
|
||||
|
|
|
@ -182,16 +182,17 @@ extern "C" {
|
|||
#define WTAP_ENCAP_JUNIPER_FRELAY 85
|
||||
#define WTAP_ENCAP_JUNIPER_CHDLC 86
|
||||
#define WTAP_ENCAP_JUNIPER_GGSN 87
|
||||
#define WTAP_ENCAP_LINUX_LAPD 88
|
||||
#define WTAP_ENCAP_LINUX_LAPD 88
|
||||
#define WTAP_ENCAP_CATAPULT_DCT2000 89
|
||||
#define WTAP_ENCAP_BER 90
|
||||
#define WTAP_ENCAP_JUNIPER_VP 91
|
||||
#define WTAP_ENCAP_USB 92
|
||||
#define WTAP_ENCAP_USB 92
|
||||
#define WTAP_ENCAP_IEEE802_16_MAC_CPS 93
|
||||
#define WTAP_ENCAP_NETTL_RAW_TELNET 94
|
||||
#define WTAP_ENCAP_USB_LINUX 95
|
||||
|
||||
/* last WTAP_ENCAP_ value + 1 */
|
||||
#define WTAP_NUM_ENCAP_TYPES 95
|
||||
#define WTAP_NUM_ENCAP_TYPES 96
|
||||
|
||||
/* File types that can be read by wiretap.
|
||||
We support writing some many of these file types, too, so we
|
||||
|
@ -526,6 +527,11 @@ struct k12_phdr {
|
|||
#define K12_PORT_DS1 0x00100008
|
||||
#define K12_PORT_ATMPVC 0x01020000
|
||||
|
||||
struct lapd_phdr {
|
||||
guint16 pkttype; /* packet type */
|
||||
guint8 we_network;
|
||||
};
|
||||
|
||||
struct wtap;
|
||||
struct catapult_dct2000_phdr
|
||||
{
|
||||
|
@ -539,11 +545,58 @@ struct catapult_dct2000_phdr
|
|||
struct wtap *wth;
|
||||
};
|
||||
|
||||
struct lapd_phdr {
|
||||
guint16 pkttype; /* packet type */
|
||||
guint8 we_network;
|
||||
/*
|
||||
* possible event type
|
||||
*/
|
||||
#define URB_SUBMIT 'S'
|
||||
#define URB_COMPLETE 'C'
|
||||
#define URB_ERROR 'E'
|
||||
|
||||
/*
|
||||
* possible transfer mode
|
||||
*/
|
||||
#define URB_ISOCHRONOUS 0x0
|
||||
#define URB_INTERRUPT 0x1
|
||||
#define URB_CONTROL 0x2
|
||||
#define URB_BULK 0x3
|
||||
|
||||
#define URB_TRANSFER_IN 0x80 /* to host */
|
||||
|
||||
/*
|
||||
* USB setup header as defined in USB specification
|
||||
*/
|
||||
struct usb_request_hdr {
|
||||
gint8 bmRequestType;
|
||||
guint8 bRequest;
|
||||
guint16 wValue;
|
||||
guint16 wIndex;
|
||||
guint16 wLength;
|
||||
};
|
||||
|
||||
/*
|
||||
* Header prepended by Linux kernel to each USB event.
|
||||
* Followed by a struct usb_request_hdr, although that header is valid
|
||||
* only if setup_flag is 0.
|
||||
* (Setup flag is '-', 'D', 'Z', or 0. Data flag is '<', '>', 'Z', or 0.)
|
||||
*
|
||||
* We present this as a pseudo-header; the values are in host byte order.
|
||||
*/
|
||||
struct linux_usb_phdr {
|
||||
guint64 id; /* urb id, to link submission and completion events*/
|
||||
guint8 event_type; /* Submit ('S'), Completed ('C'), Error ('E') */
|
||||
guint8 transfer_type; /* ISO (0), Intr, Control, Bulk (3) */
|
||||
guint8 endpoint_number; /* Endpoint number (0-15) and transfer direction */
|
||||
guint8 device_address; /* 0-127 */
|
||||
guint16 bus_id;
|
||||
gint8 setup_flag; /*if !=0 the urb setup header is not present*/
|
||||
gint8 data_flag; /*if !=0 no urb data is present*/
|
||||
gint64 ts_sec;
|
||||
gint32 ts_usec;
|
||||
gint32 status;
|
||||
guint32 urb_len; /* whole len of urb this event refers to */
|
||||
guint32 data_len; /* amount of urb data really present in this event*/
|
||||
};
|
||||
|
||||
union wtap_pseudo_header {
|
||||
struct eth_phdr eth;
|
||||
struct x25_phdr x25;
|
||||
|
@ -559,6 +612,7 @@ union wtap_pseudo_header {
|
|||
struct k12_phdr k12;
|
||||
struct lapd_phdr lapd;
|
||||
struct catapult_dct2000_phdr dct2000;
|
||||
struct linux_usb_phdr linux_usb;
|
||||
};
|
||||
|
||||
struct wtap_nstime {
|
||||
|
@ -566,7 +620,6 @@ struct wtap_nstime {
|
|||
int nsecs;
|
||||
};
|
||||
|
||||
|
||||
struct wtap_pkthdr {
|
||||
struct wtap_nstime ts;
|
||||
guint32 caplen;
|
||||
|
|
Loading…
Reference in New Issue