diff options
author | Guy Harris <guy@alum.mit.edu> | 2010-04-21 20:51:22 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2010-04-21 20:51:22 +0000 |
commit | 21a210b77763224e0ac15611842cf7203d07fa08 (patch) | |
tree | 8bcb5aa12a0e02936ac8737faf20ddbae72d0998 /wiretap | |
parent | c1729024c520afc5c8824abc04b3a3cc9eacb716 (diff) |
From Chris Maynard:
Support PPP-over-USB.
Don't remove the USB pseudo-header from the packet data for
Linux USB packets, just byte-swap it if necessary and have the
USB dissector fetch the pseudo-header from the raw packet data.
Update USB language ID values.
svn path=/trunk/; revision=32534
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/libpcap.c | 11 | ||||
-rw-r--r-- | wiretap/pcap-common.c | 123 | ||||
-rw-r--r-- | wiretap/pcap-common.h | 6 | ||||
-rw-r--r-- | wiretap/pcapng.c | 7 | ||||
-rw-r--r-- | wiretap/wtap-int.h | 18 | ||||
-rw-r--r-- | wiretap/wtap.h | 11 |
6 files changed, 92 insertions, 84 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index 6a0d9aaecc..117409c25a 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -643,8 +643,8 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info, libpcap = (libpcap_t *)wth->priv; phdr_len = pcap_process_pseudo_header(wth->fh, wth->file_type, - wth->file_encap, libpcap->byte_swapped, packet_size, - TRUE, &wth->phdr, &wth->pseudo_header, err, err_info); + wth->file_encap, packet_size, TRUE, &wth->phdr, + &wth->pseudo_header, err, err_info); if (phdr_len < 0) return FALSE; /* error */ @@ -698,6 +698,8 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info, } } + pcap_read_post_process(wth->file_encap, wth->phdr.caplen, + libpcap->byte_swapped, buffer_start_ptr(wth->frame_buffer)); return TRUE; } @@ -714,8 +716,7 @@ libpcap_seek_read(wtap *wth, gint64 seek_off, libpcap = (libpcap_t *)wth->priv; phdr_len = pcap_process_pseudo_header(wth->random_fh, wth->file_type, - wth->file_encap, libpcap->byte_swapped, length, - FALSE, NULL, pseudo_header, err, err_info); + wth->file_encap, length, FALSE, NULL, pseudo_header, err, err_info); if (phdr_len < 0) return FALSE; /* error */ @@ -746,6 +747,8 @@ libpcap_seek_read(wtap *wth, gint64 seek_off, atm_guess_lane_type(pd, length, pseudo_header); } } + pcap_read_post_process(wth->file_encap, length, + libpcap->byte_swapped, pd); return TRUE; } diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c index d404859ca8..7344543b72 100644 --- a/wiretap/pcap-common.c +++ b/wiretap/pcap-common.c @@ -924,33 +924,44 @@ pcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, return TRUE; } -static gboolean -pcap_read_linux_usb_pseudoheader(FILE_T fh, - union wtap_pseudo_header *pseudo_header, gboolean byte_swapped, int *err) -{ - int bytes_read; +/* + * Offset of the *end* of a field within a particular structure. + */ +#define END_OFFSETOF(basep, fieldp) \ + (((char *)(void *)(fieldp)) - ((char *)(void *)(basep)) + \ + sizeof(*fieldp)) - 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; - } +static void +pcap_process_linux_usb_pseudoheader(guint packet_size, gboolean byte_swapped, + guint8 *pd) +{ + struct linux_usb_phdr *phdr; if (byte_swapped) { - pseudo_header->linux_usb.id = GUINT64_SWAP_LE_BE(pseudo_header->linux_usb.id); - pseudo_header->linux_usb.bus_id = GUINT16_SWAP_LE_BE(pseudo_header->linux_usb.bus_id); - pseudo_header->linux_usb.ts_sec = GUINT64_SWAP_LE_BE(pseudo_header->linux_usb.ts_sec); - pseudo_header->linux_usb.ts_usec = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.ts_usec); - pseudo_header->linux_usb.status = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.status); - pseudo_header->linux_usb.urb_len = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.urb_len); - pseudo_header->linux_usb.data_len = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.data_len); + phdr = (struct linux_usb_phdr *)pd; + + if (packet_size < END_OFFSETOF(phdr, &phdr->id)) + return; + PBSWAP64((guint8 *)&phdr->id); + if (packet_size < END_OFFSETOF(phdr, &phdr->bus_id)) + return; + PBSWAP16((guint8 *)&phdr->bus_id); + if (packet_size < END_OFFSETOF(phdr, &phdr->ts_sec)) + return; + PBSWAP64((guint8 *)&phdr->ts_sec); + if (packet_size < END_OFFSETOF(phdr, &phdr->ts_usec)) + return; + PBSWAP32((guint8 *)&phdr->ts_usec); + if (packet_size < END_OFFSETOF(phdr, &phdr->status)) + return; + PBSWAP32((guint8 *)&phdr->status); + if (packet_size < END_OFFSETOF(phdr, &phdr->urb_len)) + return; + PBSWAP32((guint8 *)&phdr->urb_len); + if (packet_size < END_OFFSETOF(phdr, &phdr->data_len)) + return; + PBSWAP32((guint8 *)&phdr->data_len); } - - return TRUE; } static gboolean @@ -1144,8 +1155,8 @@ pcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, i } int -pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, gboolean bytes_swapped, guint packet_size, - gboolean check_packet_size, struct wtap_pkthdr *phdr, +pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, + guint packet_size, gboolean check_packet_size, struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info) { int phdr_len = 0; @@ -1289,26 +1300,6 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, gboolean by phdr_len = SITA_HDR_LEN; break; - case WTAP_ENCAP_USB_LINUX: - case WTAP_ENCAP_USB_LINUX_MMAPPED: - if (check_packet_size && - 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("pcap: Linux USB file has a %u-byte packet, too small to have even a Linux USB pseudo-header", - packet_size); - return -1; - } - if (!pcap_read_linux_usb_pseudoheader(fh, - pseudo_header, bytes_swapped, err)) - return -1; /* Read error */ - - phdr_len = (int)sizeof (struct linux_usb_phdr); - break; - case WTAP_ENCAP_BLUETOOTH_H4: /* We don't have pseudoheader, so just pretend we received everything. */ pseudo_header->p2p.sent = FALSE; @@ -1412,6 +1403,23 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, gboolean by return phdr_len; } +void +pcap_read_post_process(int wtap_encap, guint packet_size, + gboolean bytes_swapped, guchar *pd) +{ + switch (wtap_encap) { + + case WTAP_ENCAP_USB_LINUX: + case WTAP_ENCAP_USB_LINUX_MMAPPED: + pcap_process_linux_usb_pseudoheader(packet_size, + bytes_swapped, pd); + break; + + default: + break; + } +} + int pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header) { @@ -1439,11 +1447,6 @@ pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header) hdrsize = SITA_HDR_LEN; break; - case WTAP_ENCAP_USB_LINUX: - case WTAP_ENCAP_USB_LINUX_MMAPPED: - hdrsize = (int)sizeof (struct linux_usb_phdr); - break; - case WTAP_ENCAP_ERF: hdrsize = (int)sizeof (struct erf_phdr); if (pseudo_header->erf.phdr.type & 0x80) @@ -1636,26 +1639,6 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse wdh->bytes_dumped += sizeof(sita_hdr); break; - case WTAP_ENCAP_USB_LINUX: - case WTAP_ENCAP_USB_LINUX_MMAPPED: - /* - * 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; - case WTAP_ENCAP_ERF: /* * Write the ERF header. diff --git a/wiretap/pcap-common.h b/wiretap/pcap-common.h index 60762abe77..9477ad0ae4 100644 --- a/wiretap/pcap-common.h +++ b/wiretap/pcap-common.h @@ -25,10 +25,12 @@ */ extern int pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, - gboolean byte_swapped, guint packet_size, - gboolean check_packet_size, struct wtap_pkthdr *phdr, + guint packet_size, gboolean check_packet_size, struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); +extern void pcap_read_post_process(int wtap_encap, guint packet_size, + gboolean bytes_swapped, guchar *pd); + extern int pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header); diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index fb793fea10..5c0a4e4caa 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -829,7 +829,6 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta pseudo_header_len = pcap_process_pseudo_header(fh, WTAP_FILE_PCAPNG, wtap_encap, - pn->byte_swapped, wblock->data.packet.cap_len, TRUE, wblock->packet_header, @@ -935,6 +934,9 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta } } + pcap_read_post_process(wtap_encap, + (int) (wblock->data.packet.cap_len - pseudo_header_len), + pn->byte_swapped, (guchar *) (wblock->frame_buffer)); return block_read; } @@ -987,7 +989,6 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t * pseudo_header_len = pcap_process_pseudo_header(fh, WTAP_FILE_PCAPNG, encap, - pn->byte_swapped, wblock->data.simple_packet.cap_len, TRUE, wblock->packet_header, @@ -1035,6 +1036,8 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t * block_read += 4 - (wblock->data.simple_packet.cap_len % 4); } + pcap_read_post_process(encap, (int) wblock->data.simple_packet.cap_len, + pn->byte_swapped, (guchar *) (wblock->frame_buffer)); return block_read; } diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h index c85c26af15..1967457cf9 100644 --- a/wiretap/wtap-int.h +++ b/wiretap/wtap-int.h @@ -122,9 +122,25 @@ extern gint wtap_num_file_types; ((((x)&0xFF00)>>8) | \ (((x)&0x00FF)<<8)) -/* Macros to byte-swap possibly-unaligned 32-bit and 16-bit quantities; +/* Macros to byte-swap possibly-unaligned 64-bit, 32-bit and 16-bit quantities; * they take a pointer to the quantity, and byte-swap it in place. */ +#define PBSWAP64(p) \ + { \ + guint8 tmp; \ + tmp = (p)[7]; \ + (p)[7] = (p)[0]; \ + (p)[0] = tmp; \ + tmp = (p)[6]; \ + (p)[6] = (p)[1]; \ + (p)[1] = tmp; \ + tmp = (p)[5]; \ + (p)[5] = (p)[2]; \ + (p)[2] = tmp; \ + tmp = (p)[4]; \ + (p)[4] = (p)[3]; \ + (p)[3] = tmp; \ + } #define PBSWAP32(p) \ { \ guint8 tmp; \ diff --git a/wiretap/wtap.h b/wiretap/wtap.h index c7757b0e68..6e89159389 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -633,6 +633,7 @@ struct catapult_dct2000_phdr /* * USB setup header as defined in USB specification * See usb_20.pdf, Chapter 9.3 'USB Device Requests' for details. + * http://www.usb.org/developers/docs/usb_20_122909-2.zip */ struct usb_device_setup_hdr { gint8 bmRequestType; @@ -658,7 +659,7 @@ struct linux_usb_phdr { guint8 endpoint_number; /* Endpoint number (0-15) and transfer direction */ guint8 device_address; /* 0-127 */ guint16 bus_id; - gint8 setup_flag; /* 0, if the urb setup header is present */ + gint8 setup_flag; /* 0, if the urb setup header is meaningful */ gint8 data_flag; /* 0, if urb data is present */ gint64 ts_sec; gint32 ts_usec; @@ -837,12 +838,11 @@ union wtap_pseudo_header { struct cosine_phdr cosine; struct irda_phdr irda; struct nettl_phdr nettl; - struct mtp2_phdr mtp2; + struct mtp2_phdr mtp2; struct k12_phdr k12; struct lapd_phdr lapd; struct catapult_dct2000_phdr dct2000; - struct linux_usb_phdr linux_usb; - struct erf_mc_phdr erf; + struct erf_mc_phdr erf; struct sita_phdr sita; struct bthci_phdr bthci; struct l1event_phdr l1event; @@ -863,7 +863,6 @@ struct wtap_pkthdr { int pkt_encap; }; -struct wtap; struct Buffer; struct wtap_dumper; @@ -1025,6 +1024,8 @@ int wtap_register_encap_type(char* name, char* short_name); /* We're trying to open the standard input for random access */ #define WTAP_ERR_COMPRESSION_NOT_SUPPORTED -19 /* The filetype doesn't support output compression */ +#define WTAP_ERR_CANT_SEEK -20 + /* An attempt to seek failed, reason unknown */ /* Errors from zlib; zlib error Z_xxx turns into Wiretap error WTAP_ERR_ZLIB + Z_xxx. |