aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorChris Maynard <Christopher.Maynard@GTECH.COM>2011-04-05 20:21:59 +0000
committerChris Maynard <Christopher.Maynard@GTECH.COM>2011-04-05 20:21:59 +0000
commit595e5e1c1d150812de9cc0d1549acd0ed5d8770d (patch)
treec0101435e5778ab84ef23a5809fa0332e5430fbf /epan
parent4f462b3d09e661d64714187636ddb851457c1c39 (diff)
Add ICMP tap support, and add a tshark tap to measure such things as:
* Number of ICMP echo requests, replies, lost replies and percent loss. * Min, Max, Average SRT (Service Response Time), and standard deviation. (This is my first tap, so hopefully I didn't miss something, but we'll see ...) TODO: Add a Wireshark tap. svn path=/trunk/; revision=36480
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-icmp.c50
-rwxr-xr-xepan/dissectors/packet-icmp.h32
-rw-r--r--epan/tap.h5
4 files changed, 65 insertions, 23 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 8e79a7491f..39f6df6ac2 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -1148,6 +1148,7 @@ DISSECTOR_INCLUDES = \
packet-http.h \
packet-i2c.h \
packet-iax2.h \
+ packet-icmp.h \
packet-idmp.h \
packet-idp.h \
packet-ieee80211.h \
diff --git a/epan/dissectors/packet-icmp.c b/epan/dissectors/packet-icmp.c
index 3d78455adb..d92bc12384 100644
--- a/epan/dissectors/packet-icmp.c
+++ b/epan/dissectors/packet-icmp.c
@@ -40,26 +40,24 @@
#include <epan/in_cksum.h>
#include "packet-ip.h"
+#include "packet-icmp.h"
#include <epan/conversation.h>
#include <epan/emem.h>
+#include <epan/tap.h>
+
+static int icmp_tap = -1;
/* Conversation related data */
static int hf_icmp_resp_in = -1;
static int hf_icmp_resp_to = -1;
static int hf_icmp_resptime = -1;
-typedef struct _icmp_transaction_t {
- guint32 rqst_frame;
- guint32 resp_frame;
- nstime_t rqst_time;
-} icmp_transaction_t;
-
typedef struct _icmp_conv_info_t {
emem_tree_t *pdus;
} icmp_conv_info_t;
-static void transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key);
-static void transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key);
+static icmp_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key);
+static icmp_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key);
/* Decode the end of the ICMP payload as ICMP MPLS extensions
if the packet in the payload has more than 128 bytes */
@@ -705,7 +703,7 @@ dissect_mpls_extensions(tvbuff_t *tvb, gint offset, proto_tree *tree)
} /* end dissect_mpls_extensions */
/* ======================================================================= */
-static void transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key)
+static icmp_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key)
{
conversation_t *conversation;
icmp_conv_info_t *icmp_info;
@@ -734,13 +732,14 @@ static void transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key
icmp_trans->rqst_frame = PINFO_FD_NUM(pinfo);
icmp_trans->resp_frame = 0;
icmp_trans->rqst_time = pinfo->fd->abs_ts;
+ icmp_trans->resp_time = 0.0;
se_tree_insert32_array(icmp_info->pdus, icmp_key, (void *)icmp_trans);
}
else /* Already visited this frame */
icmp_trans = se_tree_lookup32_array(icmp_info->pdus, icmp_key);
if ( icmp_trans == NULL )
- return;
+ return (NULL);
/* Print state tracking in the tree */
if ( icmp_trans->resp_frame &&
@@ -751,10 +750,12 @@ static void transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key
PROTO_ITEM_SET_GENERATED(it);
}
+ return (icmp_trans);
+
} /* transaction_start() */
/* ======================================================================= */
-static void transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key)
+static icmp_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key)
{
conversation_t *conversation;
icmp_conv_info_t *icmp_info;
@@ -762,16 +763,15 @@ static void transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key)
emem_tree_key_t icmp_key[2];
proto_item *it;
nstime_t ns;
- double resptime;
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, 0, 0, 0);
if ( conversation == NULL )
- return;
+ return (NULL);
icmp_info = conversation_get_proto_data(conversation, proto_icmp);
if ( icmp_info == NULL )
- return;
+ return (NULL);
icmp_key[0].length = 2;
icmp_key[0].key = key;
@@ -779,12 +779,12 @@ static void transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key)
icmp_key[1].key = NULL;
icmp_trans = se_tree_lookup32_array(icmp_info->pdus, icmp_key);
if ( icmp_trans == NULL )
- return;
+ return (NULL);
/* Print state tracking in the tree */
if ( icmp_trans->rqst_frame &&
(icmp_trans->rqst_frame < PINFO_FD_NUM(pinfo)) &&
- ((icmp_trans->resp_frame == 0) ||
+ ((icmp_trans->resp_frame == 0) ||
(icmp_trans->resp_frame == PINFO_FD_NUM(pinfo))) )
{
icmp_trans->resp_frame = PINFO_FD_NUM(pinfo);
@@ -793,12 +793,14 @@ static void transaction_end(packet_info *pinfo, proto_tree *tree, guint32 *key)
PROTO_ITEM_SET_GENERATED(it);
nstime_delta(&ns, &pinfo->fd->abs_ts, &icmp_trans->rqst_time);
- resptime = 1000.0 * ns.secs + ns.nsecs/1000000.0;
- it = proto_tree_add_double_format_value(tree, hf_icmp_resptime,
- NULL, 0, 0, resptime, "%.3f ms", resptime);
+ icmp_trans->resp_time = nstime_to_msec(&ns);
+ it = proto_tree_add_double_format_value(tree, hf_icmp_resptime, NULL,
+ 0, 0, icmp_trans->resp_time, "%.3f ms", icmp_trans->resp_time);
PROTO_ITEM_SET_GENERATED(it);
}
+ return (icmp_trans);
+
} /* transaction_end() */
/*
@@ -824,6 +826,7 @@ dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvbuff_t *next_tvb;
proto_item *item;
guint32 conv_key[2];
+ icmp_transaction_t *trans = NULL;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
col_clear(pinfo->cinfo, COL_INFO);
@@ -1010,11 +1013,12 @@ dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
conv_key[0] = (guint32)tvb_get_ntohs(tvb, 2);
conv_key[1] = (guint32)((tvb_get_ntohs(tvb, 4) << 16) |
tvb_get_ntohs(tvb, 6));
- transaction_end(pinfo, icmp_tree, conv_key);
+ trans = transaction_end(pinfo, icmp_tree, conv_key);
}
call_dissector(data_handle, tvb_new_subset_remaining(tvb, 8), pinfo,
icmp_tree);
break;
+
case ICMP_ECHO:
if ( !pinfo->in_error_pkt ) {
guint16 tmp[2];
@@ -1024,7 +1028,7 @@ dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
conv_key[0] = ip_checksum((guint8 *)&tmp, sizeof(tmp));
conv_key[1] = (guint32)((tvb_get_ntohs(tvb, 4) << 16) |
tvb_get_ntohs(tvb, 6));
- transaction_start(pinfo, icmp_tree, conv_key);
+ trans = transaction_start(pinfo, icmp_tree, conv_key);
}
call_dissector(data_handle, tvb_new_subset_remaining(tvb, 8), pinfo,
icmp_tree);
@@ -1063,6 +1067,9 @@ dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvb_ip_to_str(tvb, 8), tvb_get_ntohl(tvb, 8));
break;
}
+
+ if (trans)
+ tap_queue_packet(icmp_tap, pinfo, trans);
}
void
@@ -1269,6 +1276,7 @@ proto_register_icmp(void)
&favor_icmp_mpls_ext);
register_dissector("icmp", dissect_icmp, proto_icmp);
+ icmp_tap = register_tap("icmp");
}
void
diff --git a/epan/dissectors/packet-icmp.h b/epan/dissectors/packet-icmp.h
new file mode 100755
index 0000000000..a8ef789f3f
--- /dev/null
+++ b/epan/dissectors/packet-icmp.h
@@ -0,0 +1,32 @@
+/* packet-icmp.h
+ * Definitions for ICMP: http://tools.ietf.org/html/rfc792.
+ *
+ * $Id$
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ICMP_H__
+#define __PACKET_ICMP_H__
+
+/* ICMP echo request/reply transaction statistics ... used by ICMP tap(s) */
+typedef struct _icmp_transaction_t {
+ guint32 rqst_frame;
+ guint32 resp_frame;
+ nstime_t rqst_time;
+ double resp_time;
+} icmp_transaction_t;
+
+#endif
diff --git a/epan/tap.h b/epan/tap.h
index 94a681339f..4624a5fe92 100644
--- a/epan/tap.h
+++ b/epan/tap.h
@@ -34,8 +34,9 @@ typedef void (*tap_draw_cb)(void *tapdata);
/*
* Flags to indicate what a tap listener's packet routine requires.
*/
-#define TL_REQUIRES_PROTO_TREE 0x00000001 /**< full protocol tree */
-#define TL_REQUIRES_COLUMNS 0x00000002 /**< columns */
+#define TL_REQUIRES_NOTHING 0x00000000 /**< nothing */
+#define TL_REQUIRES_PROTO_TREE 0x00000001 /**< full protocol tree */
+#define TL_REQUIRES_COLUMNS 0x00000002 /**< columns */
extern void tap_init(void);
extern int register_tap(const char *name);