aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorMichael Tüxen <tuexen@fh-muenster.de>2009-04-25 19:11:35 +0000
committerMichael Tüxen <tuexen@fh-muenster.de>2009-04-25 19:11:35 +0000
commit94fc2641e7389820ecb80b936991d71eb25da2a8 (patch)
tree8e40c45e0933dfb1c6147c1a1bdd8044e60e1a60 /wiretap
parentc38c73ee5aa3b854327f7b2064166ea8eca43d82 (diff)
- add support for interface statistic block
- distinguish between packet block and enhanced packet block - fix a bug regarding the handling of unknown blocks svn path=/trunk/; revision=28151
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/pcapng.c186
1 files changed, 165 insertions, 21 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index c804e98a25..78c55b85e9 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -95,7 +95,7 @@ typedef struct pcapng_interface_description_block_s {
/* pcapng: packet block (obsolete) */
typedef struct pcapng_packet_block_s {
guint16 interface_id;
- guint16 reserved;
+ guint16 drops_count;
guint32 timestamp_high;
guint32 timestamp_low;
guint32 captured_len;
@@ -124,6 +124,14 @@ typedef struct pcapng_simple_packet_block_s {
/* ... Padding ... */
} pcapng_simple_packet_block_t;
+/* pcapng: interface statistics block */
+typedef struct pcapng_interface_statistics_block_s {
+ guint32 interface_id;
+ guint32 timestamp_high;
+ guint32 timestamp_low;
+ /* ... Options ... */
+} pcapng_interface_statistics_block_t;
+
/* pcapng: common option header for every option type */
typedef struct pcapng_option_header_s {
guint16 option_code;
@@ -169,7 +177,7 @@ typedef struct wtapng_if_descr_s {
/* XXX: if_EUIaddr */
guint64 if_speed; /* 0xFFFFFFFF if unknown */
guint8 if_tsresol; /* default is 6 for microsecond resolution */
- /* XXX: if_filter */
+ gchar *if_filter; /* NULL if not available */
gchar *if_os; /* NULL if not available */
gchar if_fcslen; /* -1 if unknown or changes between packets */
/* XXX: guint64 if_tsoffset; */
@@ -182,6 +190,8 @@ typedef struct wtapng_packet_s {
guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
guint32 cap_len; /* data length in the file */
guint32 packet_len; /* data length on the wire */
+ guint32 interface_id; /* identifier of the interface. */
+ guint16 drops_count; /* drops count, only valid for packet block */
/* options */
gchar *opt_comment; /* NULL if not available */
guint64 drop_count; /* 0xFFFFFFFF if unknown */
@@ -209,6 +219,7 @@ typedef struct wtapng_name_res_s {
/* Interface Statistics */
typedef struct wtapng_if_stats_s {
/* mandatory */
+ guint64 interface_id;
guint32 ts_high;
guint32 ts_low;
/* options */
@@ -218,8 +229,8 @@ typedef struct wtapng_if_stats_s {
/*guint32 isb_starttime_low;*/
/*guint32 isb_endtime_high;*/
/*guint32 isb_endtime_low;*/
- /*guint64 isb_ifrecv;*/
- /*guint64 isb_ifdrop;*/
+ guint64 isb_ifrecv;
+ guint64 isb_ifdrop;
/*guint64 isb_filteraccept;*/
/*guint64 isb_osdrop;*/
/*guint64 isb_usrdeliv;*/
@@ -499,7 +510,7 @@ pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
/* XXX: if_EUIaddr */
wblock->data.if_descr.if_speed = 0xFFFFFFFF; /* "unknown" */
wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
- /* XXX: if_filter */
+ wblock->data.if_descr.if_filter = NULL;
wblock->data.if_descr.if_os = NULL;
wblock->data.if_descr.if_fcslen = (gchar) -1; /* unknown or changes between packets */
/* XXX: guint64 if_tsoffset; */
@@ -575,6 +586,14 @@ pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
}
break;
+ case(11): /* if_filter */
+ if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
+ wblock->data.if_descr.if_filter = g_strndup(option_content, sizeof(option_content));
+ pcapng_debug1("pcapng_read_if_descr_block: if_filter %s", wblock->data.if_descr.if_filter);
+ } else {
+ pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
+ }
+ break;
case(13): /* if_fcslen */
if(oh.option_length == 1) {
wblock->data.if_descr.if_fcslen = option_content[0];
@@ -596,13 +615,14 @@ 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_)
+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)
{
int bytes_read;
int block_read;
int to_read;
guint64 file_offset64;
pcapng_enhanced_packet_block_t epb;
+ pcapng_packet_block_t *pb;
guint32 block_total_length;
pcapng_option_header_t oh;
char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
@@ -617,22 +637,39 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
return 0;
}
block_read = bytes_read;
+ pb = (pcapng_packet_block_t *)&epb;
/* XXX - as we currently ignore the interface id, both packet blocks are the same for us */
if(pn->byte_swapped) {
- wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
- wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
- wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
- wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
+ if (enhanced) {
+ wblock->data.packet.interface_id = BSWAP32(epb.interface_id);
+ wblock->data.packet.drops_count = -1; /* invalid */
+ } else {
+ wblock->data.packet.interface_id = BSWAP16(pb->interface_id);
+ wblock->data.packet.drops_count = BSWAP16(pb->drops_count);
+ }
+ wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
+ wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
+ wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
+ wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
} else {
- wblock->data.packet.ts_high = epb.timestamp_high;
- wblock->data.packet.ts_low = epb.timestamp_low;
- wblock->data.packet.cap_len = epb.captured_len;
- wblock->data.packet.packet_len = epb.packet_len;
+ if (enhanced) {
+ wblock->data.packet.interface_id = epb.interface_id;
+ wblock->data.packet.drops_count = -1; /* invalid */
+ } else {
+ wblock->data.packet.interface_id = pb->interface_id;
+ wblock->data.packet.drops_count = pb->drops_count;
+ }
+ wblock->data.packet.ts_high = epb.timestamp_high;
+ wblock->data.packet.ts_low = epb.timestamp_low;
+ wblock->data.packet.cap_len = epb.captured_len;
+ wblock->data.packet.packet_len = epb.packet_len;
}
- /*pcapng_debug2("pcapng_read_packet_block: packet data: packet_len %u captured_len %u",
- wblock->data.packet.packet_len, wblock->data.packet.cap_len);*/
+ pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
+ wblock->data.packet.packet_len,
+ 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) */
@@ -798,6 +835,110 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *
return block_read;
}
+static int
+pcapng_read_interface_statistics_block(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;
+ int to_read;
+ pcapng_interface_statistics_block_t isb;
+ pcapng_option_header_t oh;
+ char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
+
+
+ /* "Interface Statistics Block" read fixed part */
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(&isb, 1, sizeof isb, fh);
+ if (bytes_read != sizeof isb) {
+ pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
+ *err = file_error(fh);
+ return 0;
+ }
+ block_read = bytes_read;
+
+ if(pn->byte_swapped) {
+ wblock->data.if_stats.interface_id = BSWAP64(isb.interface_id);
+ wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
+ wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
+ } else {
+ wblock->data.if_stats.interface_id = isb.interface_id;
+ wblock->data.if_stats.ts_high = isb.timestamp_high;
+ wblock->data.if_stats.ts_low = isb.timestamp_low;
+ }
+
+ /* Option defaults */
+ wblock->data.if_stats.opt_comment = NULL;
+ wblock->data.if_stats.isb_ifrecv = -1;
+ wblock->data.if_stats.isb_ifdrop = -1;
+
+ /* Options */
+ errno = WTAP_ERR_CANT_READ;
+ to_read = bh->block_total_length
+ - sizeof(pcapng_block_header_t)
+ - block_read /* fixed and variable part, including padding */
+ - sizeof(bh->block_total_length);
+ while(to_read > 0) {
+ /* read option */
+ bytes_read = pcapng_read_option(fh, pn, &oh, option_content, sizeof(option_content), err, err_info);
+ if (bytes_read <= 0) {
+ pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
+ return bytes_read;
+ }
+ block_read += bytes_read;
+ to_read -= bytes_read;
+
+ /* handle option content */
+ switch(oh.option_code) {
+ case(0): /* opt_endofopt */
+ if(to_read != 0) {
+ pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
+ }
+ /* padding should be ok here, just get out of this */
+ to_read = 0;
+ break;
+ case(1): /* opt_comment */
+ if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
+ wblock->data.section.opt_comment = g_strndup(option_content, sizeof(option_content));
+ pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.section.opt_comment);
+ } else {
+ pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
+ }
+ break;
+ case(4): /* isb_ifrecv */
+ if(oh.option_length == 8) {
+ /* Don't cast a char[] into a guint32--the
+ * char[] may not be aligned correctly.
+ */
+ memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
+ if(pn->byte_swapped)
+ wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
+ pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %llu", wblock->data.if_stats.isb_ifrecv);
+ } else {
+ pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
+ }
+ break;
+ case(5): /* isb_ifdrop */
+ if(oh.option_length == 8) {
+ /* Don't cast a char[] into a guint32--the
+ * char[] may not be aligned correctly.
+ */
+ memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
+ if(pn->byte_swapped)
+ wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
+ pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %llu", wblock->data.if_stats.isb_ifdrop);
+ } else {
+ pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
+ }
+ break;
+ default:
+ pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
+ oh.option_code, oh.option_length);
+ }
+ }
+
+ return block_read;
+}
+
static int
pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_,int *err, gchar **err_info _U_)
@@ -807,7 +948,7 @@ pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_
guint32 block_total_length;
- /* add padding bytes to "block total length" */
+ /* add padding bytes to "block total length" */
/* (the "block total length" of some example files don't contain any padding bytes!) */
if(bh->block_total_length % 4) {
block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
@@ -815,7 +956,7 @@ pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_
block_total_length = bh->block_total_length;
}
- block_read = block_total_length - (guint32)sizeof(bh->block_total_length);
+ block_read = block_total_length - (guint32)sizeof(pcapng_block_header_t) - (guint32)sizeof(bh->block_total_length);
/* jump over this unknown block */
file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
@@ -867,16 +1008,19 @@ 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);
+ bytes_read = pcapng_read_packet_block(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);
break;
case(BLOCK_TYPE_EPB):
- bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info);
+ bytes_read = pcapng_read_packet_block(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);
break;
default:
- pcapng_debug1("pcapng_read_block: Unknown block_type: 0x%x (block ignored)", bh.block_type);
+ pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
}