aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2007-01-30 20:07:55 +0000
committerGuy Harris <guy@alum.mit.edu>2007-01-30 20:07:55 +0000
commit9633ac8fee55a3779612d0416051d57540e28014 (patch)
tree41a3f2a24ac00657ade8e7ac495ff711ddd5d3f9 /wiretap
parent7317125c334a6918981851736b197d00a4b65774 (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.c173
-rw-r--r--wiretap/wtap.h67
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;