diff options
author | Guy Harris <guy@alum.mit.edu> | 2007-01-30 20:07:55 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2007-01-30 20:07:55 +0000 |
commit | 9633ac8fee55a3779612d0416051d57540e28014 (patch) | |
tree | 41a3f2a24ac00657ade8e7ac495ff711ddd5d3f9 /wiretap | |
parent | 7317125c334a6918981851736b197d00a4b65774 (diff) |
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
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/libpcap.c | 173 | ||||
-rw-r--r-- | wiretap/wtap.h | 67 |
2 files changed, 214 insertions, 26 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index d348ee27e5..66ab588338 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -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); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 9f7053dd58..4b612863a2 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -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; |