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:
Guy Harris 2007-01-30 20:07:55 +00:00
parent 7317125c33
commit 9633ac8fee
3 changed files with 421 additions and 300 deletions

View File

@ -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 /* packet-usb.c
* *
* $Id$ * $Id$
* *
* usb basic dissector * USB basic dissector
* By Paolo Abeni <paolo.abeni@email.com> * By Paolo Abeni <paolo.abeni@email.it>
* Ronnie Sahlberg 2006 * Ronnie Sahlberg 2006
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -43,9 +38,13 @@
/* protocols and header fields */ /* protocols and header fields */
static int proto_usb = -1; 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_urb_type = -1;
static int hf_usb_device_address = -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_endpoint_number = -1;
static int hf_usb_src_endpoint_number = -1; static int hf_usb_src_endpoint_number = -1;
static int hf_usb_dst_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_bulk_dissector_table;
static dissector_table_t usb_control_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[] = { static const value_string usb_langid_vals[] = {
{0x0000, "no language specified"}, {0x0000, "no language specified"},
{0x0409, "English (United States)"}, {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[] = { static const value_string usb_urb_type_vals[] = {
{URB_CONTROL_INPUT, "URB_CONTROL_INPUT"}, {URB_SUBMIT, "URB_SUBMIT"},
{URB_CONTROL_OUTPUT,"URB_CONTROL_OUTPUT"}, {URB_COMPLETE,"URB_COMPLETE"},
{URB_ISOCHRONOUS_INPUT,"URB_ISOCHRONOUS_INPUT"}, {URB_ERROR,"URB_ERROR"},
{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"},
{0, NULL} {0, NULL}
}; };
@ -295,7 +267,7 @@ dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *pare
if(parent_tree){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE QUALIFIER DESCRIPTOR"); 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 */ /* bLength */
@ -350,7 +322,7 @@ dissect_usb_device_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, t
if(parent_tree){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE DESCRIPTOR"); 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 */ /* bLength */
@ -427,7 +399,7 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, t
if(parent_tree){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "STRING DESCRIPTOR"); 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 */ /* bLength */
@ -473,7 +445,7 @@ dissect_usb_interface_descriptor(packet_info *pinfo, proto_tree *parent_tree, tv
if(parent_tree){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "INTERFACE DESCRIPTOR"); 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 */ /* bLength */
@ -546,7 +518,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvb
if(parent_tree){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "ENDPOINT DESCRIPTOR"); 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 */ /* bLength */
@ -560,7 +532,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvb
/* bEndpointAddress */ /* bEndpointAddress */
if(tree){ if(tree){
endpoint_item=proto_tree_add_item(tree, hf_usb_bEndpointAddress, tvb, offset, 1, TRUE); 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; endpoint=tvb_get_guint8(tvb, offset)&0x0f;
proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_direction, tvb, offset, 1, TRUE); 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){ if(parent_tree){
item=proto_tree_add_text(parent_tree, tvb, offset, 0, "CONFIGURATION DESCRIPTOR"); 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 */ /* bLength */
@ -729,7 +701,7 @@ dissect_usb_setup_get_descriptor(packet_info *pinfo, proto_tree *tree, tvbuff_t
{ {
if(is_request){ if(is_request){
/* descriptor type */ /* 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); usb_trans_info->u.get_descriptor.type=tvb_get_guint8(tvb, offset);
offset++; offset++;
if (check_col(pinfo->cinfo, COL_INFO)) { 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 */ /* 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); usb_trans_info->u.get_descriptor.index=tvb_get_guint8(tvb, offset);
offset++; offset++;
/* language id */ /* 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; offset+=2;
/* length */ /* 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; offset += 2;
} else { } else {
if (check_col(pinfo->cinfo, COL_INFO)) { if (check_col(pinfo->cinfo, COL_INFO)) {
@ -810,11 +782,15 @@ static const true_false_string tfs_bmrequesttype_direction = {
"Device-to-host", "Device-to-host",
"Host-to-device" "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[] = { static const value_string bmrequesttype_type_vals[] = {
{0, "Standard"}, {RQT_SETUP_TYPE_STANDARD, "Standard"},
{1, "Class"}, {RQT_SETUP_TYPE_CLASS, "Class"},
{2, "Vendor"}, {RQT_SETUP_TYPE_VENDOR, "Vendor"},
{3, "Reserved"},
{0, NULL} {0, NULL}
}; };
static const value_string bmrequesttype_recipient_vals[] = { static const value_string bmrequesttype_recipient_vals[] = {
@ -826,16 +802,20 @@ static const value_string bmrequesttype_recipient_vals[] = {
}; };
static int 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_item *item=NULL;
proto_tree *tree=NULL; proto_tree *tree=NULL;
guint8 bmRequestType;
if(parent_tree){ if(parent_tree){
item=proto_tree_add_item(parent_tree, hf_usb_bmRequestType, tvb, offset, 1, TRUE); item=proto_tree_add_item(parent_tree, hf_usb_bmRequestType, tvb, offset, 1, TRUE);
tree = proto_item_add_subtree(item, ett_usb_setup_bmrequesttype); 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_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_type, tvb, offset, 1, TRUE);
proto_tree_add_item(tree, hf_usb_bmRequestType_recipient, 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 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 offset = 0;
int type, endpoint; int type, endpoint;
gboolean setup; guint8 setup_flag;
proto_tree *tree = NULL; proto_tree *tree = NULL;
guint32 src_device, dst_device, tmp_addr; guint32 src_device, dst_device, tmp_addr;
static usb_address_t src_addr, dst_addr; /* has to be static due to SET_ADDRESS */ 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*/ /* add usb hdr*/
if (parent) { if (parent) {
proto_item *ti = NULL; 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); tree = proto_item_add_subtree(ti, usb_hdr);
} }
proto_tree_add_uint64(tree, hf_usb_urb_id, tvb, 0, 0,
type = tvb_get_ntohl(tvb, offset); pinfo->pseudo_header->linux_usb.id);
proto_tree_add_item(tree, hf_usb_urb_type, tvb, offset, 4, FALSE);
offset += 4; 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)) { if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", 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); endpoint=pinfo->pseudo_header->linux_usb.endpoint_number;
tmp_addr=tvb_get_ntohl(tvb, offset); proto_tree_add_uint(tree, hf_usb_endpoint_number, tvb, 0, 0, endpoint);
offset += 4;
proto_tree_add_item(tree, hf_usb_endpoint_number, tvb, offset, 4, FALSE); tmp_addr=pinfo->pseudo_header->linux_usb.device_address;
endpoint=tvb_get_ntohl(tvb, offset); proto_tree_add_uint(tree, hf_usb_device_address, tvb, 0, 0, tmp_addr);
offset += 4;
/* check for setup hdr presence */ proto_tree_add_uint(tree, hf_usb_bus_id, tvb, 0, 0,
proto_tree_add_item(tree, hf_usb_setup, tvb, offset, 4, FALSE); pinfo->pseudo_header->linux_usb.bus_id);
setup = tvb_get_ntohl(tvb, offset);
offset += 4;
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 */ /* set up addresses and ports */
switch(type){ is_request = endpoint & URB_TRANSFER_IN;
case URB_BULK_INPUT: if (is_request){
/* Bulk input are responses if they contain payload data and src_addr.device = src_device = htolel(tmp_addr);
* requests otherwise. src_addr.endpoint = src_endpoint = htolel(endpoint);
*/ dst_addr.device = dst_device = 0xffffffff;
if(tvb_length_remaining(tvb, offset)>0){ dst_addr.endpoint = dst_endpoint = NO_ENDPOINT;
src_device=tmp_addr; } else {
src_endpoint=endpoint; src_addr.device = src_device = 0xffffffff;
dst_device=0xffffffff; src_addr.endpoint = src_endpoint = NO_ENDPOINT;
dst_endpoint=NO_ENDPOINT; dst_addr.device = src_device = htolel(tmp_addr);
is_request=FALSE; dst_addr.endpoint = src_endpoint = htolel(endpoint);
} 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;
} }
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->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->src, AT_USB, USB_ADDR_LEN, (char *)&src_addr);
SET_ADDRESS(&pinfo->net_dst, AT_USB, USB_ADDR_LEN, (char *)&dst_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->srcport=src_endpoint;
pinfo->destport=dst_endpoint; pinfo->destport=dst_endpoint;
conversation=get_usb_conversation(pinfo, pinfo->srcport, pinfo->destport); conversation=get_usb_conversation(pinfo, pinfo->srcport, pinfo->destport);
usb_conv_info=get_usb_conv_info(conversation); 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; pinfo->usb_conv_info=usb_conv_info;
/* request/response matching so we can keep track of transaction specific /* request/response matching so we can keep track of transaction specific
* data. * data.
*/ */
@ -1023,7 +941,7 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
switch(type){ switch(type){
case URB_BULK_INPUT: case URB_BULK:
{ {
proto_item *item; proto_item *item;
@ -1033,107 +951,96 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
tvbuff_t *next_tvb; tvbuff_t *next_tvb;
pinfo->usb_conv_info=usb_conv_info; 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)){ if(dissector_try_port(usb_bulk_dissector_table, usb_conv_info->class, next_tvb, pinfo, parent)){
return; return;
} }
} }
} }
break; break;
case URB_BULK_OUTPUT: case URB_CONTROL:
{
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:
{ {
const usb_setup_dissector_table_t *tmp; const usb_setup_dissector_table_t *tmp;
usb_setup_dissector dissector; usb_setup_dissector dissector;
proto_item *ti = NULL; proto_item *ti = NULL;
proto_tree *setup_tree = NULL; proto_tree *setup_tree = NULL;
int type;
ti=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->class); ti=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->class);
PROTO_ITEM_SET_GENERATED(ti); PROTO_ITEM_SET_GENERATED(ti);
if(is_request){ if(is_request){
tvbuff_t *next_tvb; if (setup_flag == 0) {
tvbuff_t *next_tvb;
/* this is a request */ /* this is a request */
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_request_t), "URB setup"); 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); setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
usb_trans_info->requesttype=tvb_get_guint8(tvb, offset); usb_trans_info->requesttype=tvb_get_guint8(tvb, offset);
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset); offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset, &type);
/* read the request code and spawn off to a class specific /* read the request code and spawn off to a class specific
* dissector if found * dissector if found
*/ */
usb_trans_info->request=tvb_get_guint8(tvb, offset); usb_trans_info->request=tvb_get_guint8(tvb, offset);
/* Try to find a class specific dissector */ switch (type) {
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;
}
/* case RQT_SETUP_TYPE_STANDARD:
* This was a standard request which is managed by this dissector /*
*/ * This is a standard request which is managed by this
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE); * dissector
offset += 1; */
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
offset += 1;
if (check_col(pinfo->cinfo, COL_INFO)) { if (check_col(pinfo->cinfo, COL_INFO)) {
col_clear(pinfo->cinfo, COL_INFO); col_clear(pinfo->cinfo, COL_INFO);
col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request", col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request",
val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x")); val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x"));
} }
dissector=NULL; dissector=NULL;
for(tmp=setup_dissectors;tmp->dissector;tmp++){ for(tmp=setup_dissectors;tmp->dissector;tmp++){
if(tmp->request==usb_trans_info->request){ if(tmp->request==usb_trans_info->request){
dissector=tmp->dissector; 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; break;
} }
}
if(dissector){
dissector(pinfo, setup_tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
offset+=6;
} else { } else {
proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, FALSE); offset += 8;
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;
} }
} else { } else {
tvbuff_t *next_tvb; tvbuff_t *next_tvb;
/* this is a response */ /* this is a response */
if(usb_conv_info->usb_trans_info){ 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 */ /* 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)){ if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){
return; 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")); 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){ if(dissector){
dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info->usb_trans_info, usb_conv_info); dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info->usb_trans_info, usb_conv_info);
} }
} else { } else {
/* no matching request available */ /* no matching request available */
;
} }
} }
return;
} }
break; break;
default: default:
/* dont know */ /* 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;
} }
proto_tree_add_item(tree, hf_usb_data, tvb, offset, -1, FALSE);
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);
} }
void void
proto_register_usb(void) proto_register_usb(void)
{ {
static hf_register_info hf[] = { 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, { &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, VALS(usb_urb_type_vals), 0x0,
"URB type", HFILL }}, "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, { &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 }}, "USB device address", HFILL }},
{ &hf_usb_setup, { &hf_usb_data_flag,
{ "Setup", "usb.setup", FT_UINT32, BASE_DEC, NULL, 0x0, { "Data flag", "usb.data_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
"USB setup", HFILL }}, "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, { &hf_usb_endpoint_number,
{ "Endpoint", "usb.endpoint_number", FT_UINT32, BASE_HEX, NULL, 0x0, { "Endpoint", "usb.endpoint_number", FT_UINT8, BASE_HEX, NULL, 0x0,
"usb endpoint number", HFILL }}, "USB endpoint number", HFILL }},
{ &hf_usb_src_endpoint_number, { &hf_usb_src_endpoint_number,
{ "Src Endpoint", "usb.src.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0, { "Src Endpoint", "usb.src.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
"src usb endpoint number", HFILL }}, "Source USB endpoint number", HFILL }},
{ &hf_usb_dst_endpoint_number, { &hf_usb_dst_endpoint_number,
{ "Dst Endpoint", "usb.dst.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0, { "Dst Endpoint", "usb.dst.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
"dst usb endpoint number", HFILL }}, "Destination USB endpoint number", HFILL }},
{ &hf_usb_bmRequestType, { &hf_usb_bmRequestType,
{ "bmRequestType", "usb.bmRequestType", FT_UINT8, BASE_HEX, NULL, 0x0, { "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_field_array(proto_usb, hf, array_length(hf));
proto_register_subtree_array(usb_subtrees, array_length(usb_subtrees)); 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_dissector_table = register_dissector_table("usb.bulk",
"USB bulk endpoint", FT_UINT8, BASE_DEC); "USB bulk endpoint", FT_UINT8, BASE_DEC);
@ -1457,8 +1389,9 @@ proto_register_usb(void)
void void
proto_reg_handoff_usb(void) proto_reg_handoff_usb(void)
{ {
dissector_handle_t usb_handle; dissector_handle_t linux_usb_handle;
usb_handle = create_dissector_handle(dissect_usb, proto_usb);
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);
} }

View File

@ -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); union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh, static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh,
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); 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, static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length,
int *err); int *err);
static void libpcap_close(wtap *wth); static void libpcap_close(wtap *wth);
@ -416,6 +418,8 @@ static const struct {
{ 187, WTAP_ENCAP_BLUETOOTH_H4 }, { 187, WTAP_ENCAP_BLUETOOTH_H4 },
/* IEEE 802.16 MAC Common Part Sublayer */ /* IEEE 802.16 MAC Common Part Sublayer */
{ 188, WTAP_ENCAP_IEEE802_16_MAC_CPS }, { 188, WTAP_ENCAP_IEEE802_16_MAC_CPS },
/* USB packets with Linux-specified header */
{ 189, WTAP_ENCAP_USB_LINUX },
/* /*
* To repeat: * To repeat:
@ -640,7 +644,6 @@ int libpcap_open(wtap *wth, int *err, gchar **err_info)
gboolean aix; gboolean aix;
int file_encap; int file_encap;
/* Read in the number that should be at the start of a "libpcap" file */ /* Read in the number that should be at the start of a "libpcap" file */
errno = WTAP_ERR_CANT_READ; errno = WTAP_ERR_CANT_READ;
bytes_read = file_read(&magic, 1, sizeof magic, wth->fh); 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); packet_size -= sizeof (struct irda_sll_hdr);
wth->data_offset += sizeof (struct irda_sll_hdr); wth->data_offset += sizeof (struct irda_sll_hdr);
break; break;
case WTAP_ENCAP_MTP2_WITH_PHDR: case WTAP_ENCAP_MTP2_WITH_PHDR:
if (packet_size < sizeof (struct mtp2_hdr)) { 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); packet_size -= sizeof (struct lapd_sll_hdr);
wth->data_offset += sizeof (struct lapd_sll_hdr); wth->data_offset += sizeof (struct lapd_sll_hdr);
break; 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); buffer_assure_space(wth->frame_buffer, packet_size);
@ -1455,6 +1482,7 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
return FALSE; return FALSE;
} }
break; break;
case WTAP_ENCAP_MTP2_WITH_PHDR: case WTAP_ENCAP_MTP2_WITH_PHDR:
if (!libpcap_read_mtp2_pseudoheader(wth->random_fh, pseudo_header, if (!libpcap_read_mtp2_pseudoheader(wth->random_fh, pseudo_header,
err, err_info)) { err, err_info)) {
@ -1470,6 +1498,12 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
return FALSE; return FALSE;
} }
break; 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); 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 static gboolean
libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err) 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 * the VCI; read them and generate the pseudo-header from
* them. * them.
*/ */
if (linktype == WTAP_ENCAP_ATM_PDUS) { switch (linktype) {
case WTAP_ENCAP_ATM_PDUS:
if (whdr->caplen < sizeof (struct sunatm_hdr)) { if (whdr->caplen < sizeof (struct sunatm_hdr)) {
/* /*
* Uh-oh, the packet isn't big enough to even * 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) if (pseudo_header->atm.type == TRAF_LANE)
atm_guess_lane_type(pd, whdr->caplen, pseudo_header); atm_guess_lane_type(pd, whdr->caplen, pseudo_header);
} break;
else if (linktype == WTAP_ENCAP_IRDA) {
case WTAP_ENCAP_IRDA:
if (whdr->caplen < sizeof (struct irda_sll_hdr)) { if (whdr->caplen < sizeof (struct irda_sll_hdr)) {
/* /*
* Uh-oh, the packet isn't big enough to even * 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->len -= sizeof (struct irda_sll_hdr);
whdr->caplen -= sizeof (struct irda_sll_hdr); whdr->caplen -= sizeof (struct irda_sll_hdr);
pd += sizeof (struct irda_sll_hdr); pd += sizeof (struct irda_sll_hdr);
} break;
else if (linktype == WTAP_ENCAP_MTP2_WITH_PHDR) {
case WTAP_ENCAP_MTP2_WITH_PHDR:
if (whdr->caplen < sizeof (struct mtp2_hdr)) { if (whdr->caplen < sizeof (struct mtp2_hdr)) {
/* /*
* Uh-oh, the packet isn't big enough to even * 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->len -= sizeof (struct mtp2_hdr);
whdr->caplen -= sizeof (struct mtp2_hdr); whdr->caplen -= sizeof (struct mtp2_hdr);
pd += sizeof (struct mtp2_hdr); pd += sizeof (struct mtp2_hdr);
} break;
else if (linktype == WTAP_ENCAP_LINUX_LAPD) {
case WTAP_ENCAP_LINUX_LAPD:
if (whdr->caplen < sizeof (struct lapd_sll_hdr)) { if (whdr->caplen < sizeof (struct lapd_sll_hdr)) {
/* /*
* Uh-oh, the packet isn't big enough to even * 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->len -= sizeof (struct lapd_sll_hdr);
whdr->caplen -= sizeof (struct lapd_sll_hdr); whdr->caplen -= sizeof (struct lapd_sll_hdr);
pd += 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; return pd;
} }
@ -2178,14 +2270,32 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
struct mtp2_hdr mtp2_hdr; struct mtp2_hdr mtp2_hdr;
int hdrsize; int hdrsize;
if (wdh->encap == WTAP_ENCAP_ATM_PDUS) switch (wdh->encap) {
case WTAP_ENCAP_ATM_PDUS:
hdrsize = sizeof (struct sunatm_hdr); hdrsize = sizeof (struct sunatm_hdr);
else if (wdh->encap == WTAP_ENCAP_IRDA) break;
case WTAP_ENCAP_IRDA:
hdrsize = sizeof (struct irda_sll_hdr); 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); hdrsize = sizeof (struct lapd_sll_hdr);
else break;
case WTAP_ENCAP_USB_LINUX:
hdrsize = sizeof (struct linux_usb_phdr);
break;
default:
hdrsize = 0; hdrsize = 0;
break;
}
rec_hdr.hdr.ts_sec = phdr->ts.secs; rec_hdr.hdr.ts_sec = phdr->ts.secs;
if(wdh->tsprecision == WTAP_FILE_TSPREC_NSEC) { if(wdh->tsprecision == WTAP_FILE_TSPREC_NSEC) {
@ -2265,7 +2375,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
} }
wdh->bytes_dumped += hdr_size; wdh->bytes_dumped += hdr_size;
if (wdh->encap == WTAP_ENCAP_ATM_PDUS) { switch (wdh->encap) {
case WTAP_ENCAP_ATM_PDUS:
/* /*
* Write the ATM header. * Write the ATM header.
*/ */
@ -2309,8 +2421,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return FALSE; return FALSE;
} }
wdh->bytes_dumped += sizeof atm_hdr; wdh->bytes_dumped += sizeof atm_hdr;
} break;
else if (wdh->encap == WTAP_ENCAP_IRDA) {
case WTAP_ENCAP_IRDA:
/* /*
* Write the IrDA header. * Write the IrDA header.
*/ */
@ -2326,8 +2439,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return FALSE; return FALSE;
} }
wdh->bytes_dumped += sizeof(irda_hdr); wdh->bytes_dumped += sizeof(irda_hdr);
} break;
else if (wdh->encap == WTAP_ENCAP_MTP2_WITH_PHDR) {
case WTAP_ENCAP_MTP2_WITH_PHDR:
/* /*
* Write the MTP2 header. * Write the MTP2 header.
*/ */
@ -2344,8 +2458,9 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return FALSE; return FALSE;
} }
wdh->bytes_dumped += sizeof(mtp2_hdr); wdh->bytes_dumped += sizeof(mtp2_hdr);
} break;
else if (wdh->encap == WTAP_ENCAP_LINUX_LAPD) {
case WTAP_ENCAP_LINUX_LAPD:
/* /*
* Write the LAPD header. * Write the LAPD header.
*/ */
@ -2362,6 +2477,26 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return FALSE; return FALSE;
} }
wdh->bytes_dumped += sizeof(lapd_hdr); 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); nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen);

View File

@ -182,16 +182,17 @@ extern "C" {
#define WTAP_ENCAP_JUNIPER_FRELAY 85 #define WTAP_ENCAP_JUNIPER_FRELAY 85
#define WTAP_ENCAP_JUNIPER_CHDLC 86 #define WTAP_ENCAP_JUNIPER_CHDLC 86
#define WTAP_ENCAP_JUNIPER_GGSN 87 #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_CATAPULT_DCT2000 89
#define WTAP_ENCAP_BER 90 #define WTAP_ENCAP_BER 90
#define WTAP_ENCAP_JUNIPER_VP 91 #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_IEEE802_16_MAC_CPS 93
#define WTAP_ENCAP_NETTL_RAW_TELNET 94 #define WTAP_ENCAP_NETTL_RAW_TELNET 94
#define WTAP_ENCAP_USB_LINUX 95
/* last WTAP_ENCAP_ value + 1 */ /* 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. /* File types that can be read by wiretap.
We support writing some many of these file types, too, so we 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_DS1 0x00100008
#define K12_PORT_ATMPVC 0x01020000 #define K12_PORT_ATMPVC 0x01020000
struct lapd_phdr {
guint16 pkttype; /* packet type */
guint8 we_network;
};
struct wtap; struct wtap;
struct catapult_dct2000_phdr struct catapult_dct2000_phdr
{ {
@ -539,11 +545,58 @@ struct catapult_dct2000_phdr
struct wtap *wth; struct wtap *wth;
}; };
struct lapd_phdr { /*
guint16 pkttype; /* packet type */ * possible event type
guint8 we_network; */
#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 { union wtap_pseudo_header {
struct eth_phdr eth; struct eth_phdr eth;
struct x25_phdr x25; struct x25_phdr x25;
@ -559,6 +612,7 @@ union wtap_pseudo_header {
struct k12_phdr k12; struct k12_phdr k12;
struct lapd_phdr lapd; struct lapd_phdr lapd;
struct catapult_dct2000_phdr dct2000; struct catapult_dct2000_phdr dct2000;
struct linux_usb_phdr linux_usb;
}; };
struct wtap_nstime { struct wtap_nstime {
@ -566,7 +620,6 @@ struct wtap_nstime {
int nsecs; int nsecs;
}; };
struct wtap_pkthdr { struct wtap_pkthdr {
struct wtap_nstime ts; struct wtap_nstime ts;
guint32 caplen; guint32 caplen;