diff options
-rw-r--r-- | wiretap/libpcap.c | 4 | ||||
-rw-r--r-- | wiretap/pcap-common.c | 4 | ||||
-rw-r--r-- | wiretap/pcap-common.h | 2 | ||||
-rw-r--r-- | wiretap/pcapng.c | 152 |
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)) { |