aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorMichael Tüxen <tuexen@fh-muenster.de>2009-06-27 11:39:47 +0000
committerMichael Tüxen <tuexen@fh-muenster.de>2009-06-27 11:39:47 +0000
commit267df8e183e9ed9e56750b4674cc38afd8a7efc3 (patch)
tree56251fa022928d24f19cd71dbcdb327e83251ac5 /wiretap
parente4fea1939cd608cc09eff9406a2225a227ea30c3 (diff)
This commit
* adds an encap argument to pcap_process_pseudo_header. * adds support for reading pseudo headers. It fixes Bug 3560. Thanks to Tyson Key for reporting the bug and providing trace files. This fix will be scheduled for inclusion in Wireshark 1.2.1 and higher. svn path=/trunk/; revision=28857
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/libpcap.c4
-rw-r--r--wiretap/pcap-common.c4
-rw-r--r--wiretap/pcap-common.h2
-rw-r--r--wiretap/pcapng.c152
4 files changed, 113 insertions, 49 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c
index beee98f4fd..31e8e712fd 100644
--- a/wiretap/libpcap.c
+++ b/wiretap/libpcap.c
@@ -636,7 +636,7 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
*data_offset = wth->data_offset;
- phdr_len = pcap_process_pseudo_header(wth, wth->fh, packet_size,
+ phdr_len = pcap_process_pseudo_header(wth, wth->file_encap, wth->fh, packet_size,
TRUE, &wth->phdr, &wth->pseudo_header, err, err_info);
if (phdr_len < 0)
return FALSE; /* error */
@@ -704,7 +704,7 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
- phdr_len = pcap_process_pseudo_header(wth, wth->random_fh, length,
+ phdr_len = pcap_process_pseudo_header(wth, wth->file_encap, wth->random_fh, length,
FALSE, NULL, pseudo_header, err, err_info);
if (phdr_len < 0)
return FALSE; /* error */
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c
index e096fc9f36..9184bfd484 100644
--- a/wiretap/pcap-common.c
+++ b/wiretap/pcap-common.c
@@ -1115,14 +1115,14 @@ pcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, i
}
int
-pcap_process_pseudo_header(wtap *wth, FILE_T fh, guint packet_size,
+pcap_process_pseudo_header(wtap *wth, int encap, FILE_T fh, 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;
guint size;
- switch (wth->file_encap) {
+ switch (encap) {
case WTAP_ENCAP_ATM_PDUS:
if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
diff --git a/wiretap/pcap-common.h b/wiretap/pcap-common.h
index a0a7da91d9..c8f1944ca9 100644
--- a/wiretap/pcap-common.h
+++ b/wiretap/pcap-common.h
@@ -26,7 +26,7 @@
extern int wtap_wtap_encap_to_pcap_encap(int encap);
-extern int pcap_process_pseudo_header(wtap *wth, FILE_T fh, guint packet_size,
+extern int pcap_process_pseudo_header(wtap *wth, int encap, FILE_T fh, guint packet_size,
gboolean check_packet_size, struct wtap_pkthdr *phdr,
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index 13158b8695..433fdc4291 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -198,6 +198,7 @@ typedef struct wtapng_packet_s {
guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
/* pack_hash */
+ guint32 pseudo_header_len;
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_packet_t;
@@ -206,6 +207,7 @@ typedef struct wtapng_simple_packet_s {
/* mandatory */
guint32 cap_len; /* data length in the file */
guint32 packet_len; /* data length on the wire */
+ guint32 pseudo_header_len;
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_simple_packet_t;
@@ -260,6 +262,20 @@ typedef struct interface_data_s {
static int
+pcapng_get_encap(gint id, pcapng_t *pn)
+{
+ interface_data_t int_data;
+
+ if ((id >= 0) && ((guint)id < pn->number_of_interfaces)) {
+ int_data = g_array_index(pn->interface_data, interface_data_t, id);
+ return int_data.wtab_encap;
+ } else {
+ return WTAP_ERR_UNSUPPORTED_ENCAP;
+ }
+}
+
+
+static int
pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
char *content, int len, int *err, gchar **err_info _U_)
{
@@ -501,8 +517,10 @@ pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
wblock->data.if_descr.snap_len = idb.snaplen;
}
- pcapng_debug2("pcapng_read_if_descr_block: IDB link_type %u, snap %u",
- wblock->data.if_descr.link_type, wblock->data.if_descr.snap_len);
+ pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
+ wblock->data.if_descr.link_type,
+ wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
+ wblock->data.if_descr.snap_len);
/* XXX - sanity check of snapshot length */
/* XXX - while a very big snapshot length is valid, it's more likely that it's a bug in the file */
@@ -654,7 +672,7 @@ pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
static int
-pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info _U_, gboolean enhanced)
+pcapng_read_packet_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info _U_, gboolean enhanced)
{
int bytes_read;
int block_read;
@@ -664,6 +682,8 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
pcapng_packet_block_t pb;
guint32 block_total_length;
pcapng_option_header_t oh;
+ gint encap;
+ int pseudo_header_len;
char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
@@ -736,20 +756,37 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
wblock->data.packet.cap_len,
wblock->data.packet.interface_id);
- /* XXX - implement other linktypes then Ethernet */
- /* (or even better share the code with libpcap.c) */
+ encap = pcapng_get_encap(wblock->data.packet.interface_id, pn);
+ pcapng_debug1("pcapng_read_packet_block: Need to read pseudo header of size %d",
+ pcap_get_phdr_size(encap, wblock->pseudo_header));
- /* Ethernet FCS length, might be overwritten by "per packet" options */
memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
- ((union wtap_pseudo_header *) wblock->pseudo_header)->eth.fcs_len = pn->if_fcslen;
+ pseudo_header_len = pcap_process_pseudo_header(wth, /* XXX get rid of... */
+ encap,
+ fh,
+ wblock->data.packet.cap_len,
+ TRUE,
+ &wth->phdr,
+ (union wtap_pseudo_header *)wblock->pseudo_header,
+ err,
+ err_info);
+ if (pseudo_header_len < 0) {
+ return 0;
+ }
+ wblock->data.packet.pseudo_header_len = (guint32)pseudo_header_len;
+ block_read += pseudo_header_len;
+ if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
+ pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
+ pseudo_header_len);
+ }
/* "(Enhanced) Packet Block" read capture data */
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read((guchar *) (wblock->frame_buffer), 1, wblock->data.packet.cap_len, fh);
- if (bytes_read != (int) wblock->data.packet.cap_len) {
+ bytes_read = file_read((guchar *) (wblock->frame_buffer), 1, wblock->data.packet.cap_len - pseudo_header_len, fh);
+ if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
*err = file_error(fh);
pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
- wblock->data.packet.cap_len);
+ wblock->data.packet.cap_len - pseudo_header_len);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return 0;
@@ -769,7 +806,7 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
/* add padding bytes to "block total length" */
/* (the "block total length" of some example files don't contain the packet data padding bytes!) */
- if(bh->block_total_length % 4) {
+ if (bh->block_total_length % 4) {
block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
} else {
block_total_length = bh->block_total_length;
@@ -837,11 +874,13 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
static int
-pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info _U_)
+pcapng_read_simple_packet_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info _U_)
{
int bytes_read;
int block_read;
guint64 file_offset64;
+ gint encap;
+ int pseudo_header_len;
pcapng_simple_packet_block_t spb;
@@ -855,7 +894,7 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *
}
block_read = bytes_read;
- if(pn->byte_swapped) {
+ if (pn->byte_swapped) {
wblock->data.simple_packet.packet_len = BSWAP32(spb.packet_len);
} else {
wblock->data.simple_packet.packet_len = spb.packet_len;
@@ -874,6 +913,30 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *
pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
wblock->data.simple_packet.packet_len);
+ encap = pcapng_get_encap(0, pn);
+ pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
+ pcap_get_phdr_size(encap, wblock->pseudo_header));
+
+ memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
+ pseudo_header_len = pcap_process_pseudo_header(wth, /* XXX get rid of... */
+ encap,
+ fh,
+ wblock->data.simple_packet.cap_len,
+ TRUE,
+ &wth->phdr,
+ (union wtap_pseudo_header *)wblock->pseudo_header,
+ err,
+ err_info);
+ if (pseudo_header_len < 0) {
+ return 0;
+ }
+ wblock->data.simple_packet.pseudo_header_len = (guint32)pseudo_header_len;
+ block_read += pseudo_header_len;
+ if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
+ pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
+ pseudo_header_len);
+ }
+
/* XXX - implement other linktypes then Ethernet */
/* (or even better share the code with libpcap.c) */
@@ -1043,12 +1106,12 @@ pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_
return block_read;
}
-
+/* XXX Can we get rid of wth again? */
static int
-pcapng_read_block(FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
+pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
{
- int block_read;
- int bytes_read;
+ int block_read;
+ int bytes_read;
pcapng_block_header_t bh;
guint32 block_total_length;
@@ -1065,9 +1128,9 @@ pcapng_read_block(FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gch
}
block_read = bytes_read;
- if(pn->byte_swapped) {
- bh.block_type = BSWAP32(bh.block_type);
- bh.block_total_length = BSWAP32(bh.block_total_length);
+ if (pn->byte_swapped) {
+ bh.block_type = BSWAP32(bh.block_type);
+ bh.block_total_length = BSWAP32(bh.block_total_length);
}
wblock->type = bh.block_type;
@@ -1082,13 +1145,13 @@ pcapng_read_block(FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gch
bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
break;
case(BLOCK_TYPE_PB):
- bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
+ bytes_read = pcapng_read_packet_block(wth, fh, &bh, pn, wblock, err, err_info, FALSE);
break;
case(BLOCK_TYPE_SPB):
- bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
+ bytes_read = pcapng_read_simple_packet_block(wth, fh, &bh, pn, wblock, err, err_info);
break;
case(BLOCK_TYPE_EPB):
- bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
+ bytes_read = pcapng_read_packet_block(wth, fh, &bh, pn, wblock, err, err_info, TRUE);
break;
case(BLOCK_TYPE_ISB):
bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
@@ -1151,9 +1214,9 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
pcapng_debug0("pcapng_open: opening file");
/* read first block */
- bytes_read = pcapng_read_block(wth->fh, &pn, &wblock, err, err_info);
+ bytes_read = pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info);
if (bytes_read <= 0) {
- pcapng_debug0("pcapng_open_new: couldn't read first SHB");
+ pcapng_debug0("pcapng_open: couldn't read first SHB");
*err = file_error(wth->fh);
if (*err != 0)
return -1;
@@ -1168,7 +1231,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
* between Windows and UN*X as text rather than
* binary data?
*/
- pcapng_debug1("pcapng_open_new: first block type %u not SHB", wblock.type);
+ pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
return 0;
}
@@ -1213,7 +1276,7 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
/* read next block */
while (1) {
- bytes_read = pcapng_read_block(wth->fh, wth->capture.pcapng, &wblock, err, err_info);
+ bytes_read = pcapng_read_block(wth, wth->fh, wth->capture.pcapng, &wblock, err, err_info);
if (bytes_read <= 0) {
pcapng_debug0("pcapng_read: couldn't read packet block");
return FALSE;
@@ -1233,8 +1296,8 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
/* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
- wth->phdr.caplen = wblock.data.packet.cap_len;
- wth->phdr.len = wblock.data.packet.packet_len;
+ wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
+ wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
if (wblock.data.packet.interface_id < wth->capture.pcapng->number_of_interfaces) {
interface_data_t int_data;
guint64 time_units_per_second;
@@ -1284,7 +1347,7 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
wblock.pseudo_header = pseudo_header;
/* read the block */
- bytes_read = pcapng_read_block(wth->random_fh, wth->capture.pcapng, &wblock, err, err_info);
+ bytes_read = pcapng_read_block(wth, wth->random_fh, wth->capture.pcapng, &wblock, err, err_info);
if (bytes_read <= 0) {
*err = file_error(wth->fh);
pcapng_debug0("pcapng_seek_read: couldn't read packet block");
@@ -1454,7 +1517,7 @@ pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
- epb.interface_id = 0; /* XXX */
+ epb.interface_id = wblock->data.packet.interface_id;
epb.timestamp_high = wblock->data.packet.ts_high;
epb.timestamp_low = wblock->data.packet.ts_low;
epb.captured_len = wblock->data.packet.cap_len;
@@ -1551,15 +1614,16 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
ts = (((guint64)phdr->ts.secs) * 1000000) + (phdr->ts.nsecs / 1000);
/* Split the 64-bit timestamp into two 32-bit pieces */
- wblock.data.packet.ts_high = (guint32)(ts >> 32);
- wblock.data.packet.ts_low = (guint32)ts;
+ wblock.data.packet.ts_high = (guint32)(ts >> 32);
+ wblock.data.packet.ts_low = (guint32)ts;
+
+ wblock.data.packet.cap_len = phdr->caplen;
+ wblock.data.packet.packet_len = phdr->len;
+ wblock.data.packet.interface_id = 0; /* XXX */
- wblock.data.packet.cap_len = phdr->caplen;
- wblock.data.packet.packet_len = phdr->len;
-
/* currently unused */
- wblock.data.packet.drop_count = -1;
- wblock.data.packet.opt_comment = NULL;
+ wblock.data.packet.drop_count = -1;
+ wblock.data.packet.opt_comment = NULL;
if (!pcapng_write_block(wdh, &wblock, err)) {
return FALSE;
@@ -1599,14 +1663,14 @@ pcapng_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
}
/* write the interface description block */
- wblock.type = BLOCK_TYPE_IDB;
- wblock.data.if_descr.link_type = wtap_wtap_encap_to_pcap_encap(wdh->encap);
- wblock.data.if_descr.snap_len = wdh->snaplen;
+ wblock.type = BLOCK_TYPE_IDB;
+ wblock.data.if_descr.link_type = wtap_wtap_encap_to_pcap_encap(wdh->encap);
+ wblock.data.if_descr.snap_len = wdh->snaplen;
/* XXX - options unused */
- wblock.data.if_descr.if_speed = -1;
- wblock.data.if_descr.if_tsresol = 6; /* default: usec */
- wblock.data.if_descr.if_os = NULL;
+ wblock.data.if_descr.if_speed = -1;
+ wblock.data.if_descr.if_tsresol = 6; /* default: usec */
+ wblock.data.if_descr.if_os = NULL;
wblock.data.if_descr.if_fcslen = -1;
if (!pcapng_write_block(wdh, &wblock, err)) {