Ethereal-dev: Re: [Ethereal-dev] new tap for mgcp
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Lars.Roland@xxxxxxx
Date: Thu, 6 Mar 2003 01:36:08 +0100 (MET)
Hello all, I have attached all files and patches for a new mgcp tap including the patches for the plugin_api of ethereal. I have only very little knowledge about automake and configure, .. so I have added only a patch to the nmake makefile. I exported some struct definitions into the new header file \plugins\mgcp\packet-mgcp.h . Thanks to Ronnie Sahlberg for his input. Please checkin, if acceptable. Request/Response matching stuff has been moved to mgcp dissector routine and provides now a display filter field for response delay. MGCP responses have now a field containing the frame number of the matching request. One question is left for now. How can I give the frame number of the response to the request? the changes to packet-mgcp.c are quiet big, so we should also think about bumping the mgcp-plugin version to 0.0.9 . All inputs are welcome. -- Best Regards, Lars Roland
/* tap-mgcpstat.c
* mgcpstat 2003 Lars Roland
*
* $Id: $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxxxxxx>
* Copyright 1998 Gerald Combs
*
* 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <string.h>
#include "epan/packet_info.h"
#include "tap.h"
#include "epan/value_string.h"
#include "register.h"
#include "plugins/mgcp/packet-mgcp.h"
/* Summary of response-time calculations*/
typedef struct _rtd_t {
long int num;
nstime_t min;
nstime_t max;
nstime_t tot;
} rtd_t;
/* used to keep track of the statistics for an entire program interface */
typedef struct _mgcpstat_t {
char *filter;
rtd_t rtd;
long int open_req_num;
long int disc_rsp_num;
long int req_dup_num;
long int rsp_dup_num;
} mgcpstat_t;
/* A Function to update a mgcp_rtd_t struct */
void
rtd_stat_update(rtd_t *rtd,nstime_t delta)
{
rtd->num++;
if((rtd->max.secs==0)
&& (rtd->max.nsecs==0) ){
rtd->max.secs=delta.secs;
rtd->max.nsecs=delta.nsecs;
}
if((rtd->min.secs==0)
&& (rtd->min.nsecs==0) ){
rtd->min.secs=delta.secs;
rtd->min.nsecs=delta.nsecs;
}
if( (delta.secs<rtd->min.secs)
||( (delta.secs==rtd->min.secs)
&&(delta.nsecs<rtd->min.nsecs) ) ){
rtd->min.secs=delta.secs;
rtd->min.nsecs=delta.nsecs;
}
if( (delta.secs>rtd->max.secs)
||( (delta.secs==rtd->max.secs)
&&(delta.nsecs>rtd->max.nsecs) ) ){
rtd->max.secs=delta.secs;
rtd->max.nsecs=delta.nsecs;
}
rtd->tot.secs += delta.secs;
rtd->tot.nsecs += delta.nsecs;
if(rtd->tot.nsecs>1000000000){
rtd->tot.nsecs-=1000000000;
rtd->tot.secs++;
}
}
static int
mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, void *pmi)
{
mgcpstat_t *ms=(mgcpstat_t *)pms;
mgcp_info_t *mi=pmi;
nstime_t delta;
switch (mi->mgcp_type) {
case MGCP_REQUEST:
if(mi->is_duplicate){
/* Duplicate is ignored */
ms->req_dup_num++;
return 0;
}
else {
ms->open_req_num++;
return 0;
}
break;
case MGCP_RESPONSE:
if(mi->is_duplicate){
/* Duplicate is ignored */
ms->rsp_dup_num++;
return 0;
}
else if (!mi->request_available) {
/* no request was seen */
ms->disc_rsp_num++;
return 0;
}
else {
ms->open_req_num--;
/* calculate time delta between request and response */
delta.secs=pinfo->fd->abs_secs-mi->req_time.secs;
delta.nsecs=pinfo->fd->abs_usecs*1000-mi->req_time.nsecs;
if(delta.nsecs<0){
delta.nsecs+=1000000000;
delta.secs--;
}
rtd_stat_update(&(ms->rtd),delta);
return 1;
}
break;
default:
return 0;
break;
}
}
static void
mgcpstat_draw(void *pms)
{
mgcpstat_t *ms=(mgcpstat_t *)pms;
#ifdef G_HAVE_UINT64
guint64 avg;
#else
guint32 avg;
#endif
/* calculating average rtd */
/* scale it to units of 10us.*/
/* for long captures with a large tot time, this can overflow on 32bit */
avg=(int)ms->rtd.tot.secs;
avg=avg*100000+(int)ms->rtd.tot.nsecs/10000;
if(ms->rtd.num){
avg/=ms->rtd.num;
} else {
avg=0;
}
/* printing results */
printf("\n");
printf("===================================================================\n");
printf("MGCP Response Time Delay (RTD) Statistics:\n");
printf("Filter: %s\n",ms->filter?ms->filter:"");
printf("Duplicate requests: %d\n",ms->req_dup_num);
printf("Duplicate responses: %d\n",ms->rsp_dup_num);
printf("Open requests: %d\n",ms->open_req_num);
printf("Discarded responses: %d\n",ms->disc_rsp_num);
printf("Messages | Min RTD | Max RTD | Avg RTD \n");
printf("%7d | %5d.%03d msec | %5d.%03d msec | %5d.%03d msec\n",
ms->rtd.num,
(int)((ms->rtd.min.secs*1000)+(ms->rtd.min.nsecs/1000000)),(ms->rtd.min.nsecs%1000000)/1000,
(int)((ms->rtd.max.secs*1000)+(ms->rtd.max.nsecs/1000000)),(ms->rtd.min.nsecs%1000000)/1000,
avg/100, avg%100
);
printf("===================================================================\n");
}
static void
mgcpstat_init(char *optarg)
{
mgcpstat_t *ms;
char *filter=NULL;
if(!strncmp(optarg,"mgcp,rtd,",9)){
filter=optarg+9;
} else {
filter=NULL;
}
ms=g_malloc(sizeof(mgcpstat_t));
if(filter){
ms->filter=g_malloc(strlen(filter)+1);
strcpy(ms->filter, filter);
} else {
ms->filter=NULL;
}
ms->rtd.num=0;
ms->rtd.min.secs=0;
ms->rtd.min.nsecs=0;
ms->rtd.max.secs=0;
ms->rtd.max.nsecs=0;
ms->rtd.tot.secs=0;
ms->rtd.tot.nsecs=0;
ms->open_req_num=0;
ms->disc_rsp_num=0;
ms->req_dup_num=0;
ms->rsp_dup_num=0;
if(register_tap_listener("mgcp", ms, filter, NULL, mgcpstat_packet, mgcpstat_draw)){
/* error, we failed to attach to the tap. clean up */
g_free(ms->filter);
g_free(ms);
fprintf(stderr,"tethereal: mgcpstat_init() failed to attach to tap.\n");
exit(1);
}
}
void
register_tap_listener_mgcpstat(void)
{
register_ethereal_tap("mgcp,rtd", mgcpstat_init, NULL, NULL);
}
/* packet-mgcp.h
* Routines for mgcp packet disassembly
* RFC 2705
*
* $Id: $
*
* Copyright (c) 2000 by Ed Warnicke <hagbard@xxxxxxxxxxxxxxxxxxx>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxxxxxx>
* Copyright 1999 Gerald Combs
*
* 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.
*/
/* A simple MGCP type that is occasionally handy */
typedef enum _mgcp_type {
MGCP_REQUEST,
MGCP_RESPONSE,
MGCP_OTHERS
} mgcp_type_t;
/* Container for tapping relevant data */
typedef struct _mgcp_info_t {
mgcp_type_t mgcp_type;
char code[5];
guint32 transid;
nstime_t req_time;
gboolean is_duplicate;
gboolean request_available;
} mgcp_info_t;
/* Item of request list */
typedef struct _mgcp_call_t {
guint32 transid;
char code[5];
guint32 req_num; /* frame number request seen */
guint32 rsp_num; /* frame number response seen */
nstime_t req_time;
gboolean responded;
} mgcp_call_t; Index: packet-mgcp.c
===================================================================
RCS file: /cvsroot/ethereal/plugins/mgcp/packet-mgcp.c,v
retrieving revision 1.35
diff -u -r1.35 packet-mgcp.c
--- packet-mgcp.c 28 Aug 2002 20:39:07 -0000 1.35
+++ packet-mgcp.c 5 Mar 2003 23:06:59 -0000
@@ -43,6 +43,8 @@
#include <epan/resolv.h>
#include "prefs.h"
#include <epan/strutil.h>
+#include <epan/conversation.h>
+#include "packet-mgcp.h"
#include "plugins/plugin_api_defs.h"
@@ -65,7 +67,10 @@
static int hf_mgcp_req = -1;
static int hf_mgcp_req_verb = -1;
static int hf_mgcp_req_endpoint = -1;
+static int hf_mgcp_req_frame = -1;
static int hf_mgcp_rsp = -1;
+static int hf_mgcp_rsp_frame = -1;
+static int hf_mgcp_time = -1;
static int hf_mgcp_transid = -1;
static int hf_mgcp_version = -1;
static int hf_mgcp_rsp_rspcode = -1;
@@ -97,6 +102,9 @@
static int hf_mgcp_param_extention = -1;
static int hf_mgcp_param_invalid = -1;
static int hf_mgcp_messagecount = -1;
+static int hf_mgcp_dup = -1;
+static int hf_mgcp_req_dup = -1;
+static int hf_mgcp_rsp_dup = -1;
/*
* Define the trees for mgcp
@@ -105,6 +113,10 @@
static int ett_mgcp = -1;
static int ett_mgcp_param = -1;
+/*
+ * Define the tap for mgcp
+ */
+static int mgcp_tap = -1;
/*
* Here are the global variables associated with
@@ -140,14 +152,6 @@
static int callagent_tcp_port = 0;
static int callagent_udp_port = 0;
-
-/* A simple MGCP type that is occasionally handy */
-typedef enum _mgcp_type {
- MGCP_REQUEST,
- MGCP_RESPONSE,
- MGCP_OTHERS
-} mgcp_type_t;
-
/* Some basic utility functions that are specific to this dissector */
static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength);
static gboolean is_mgcp_rspcode(tvbuff_t *tvb, gint offset, gint maxlength);
@@ -161,8 +165,8 @@
*/
static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree,proto_tree *mgcp_tree, proto_tree *ti);
-static void dissect_mgcp_firstline(tvbuff_t *tvb,
- proto_tree *tree);
+static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, mgcp_info_t *mi);
static void dissect_mgcp_params(tvbuff_t *tvb,
proto_tree *tree);
static void mgcp_raw_text_add(tvbuff_t *tvb,
@@ -181,6 +185,43 @@
static dissector_handle_t sdp_handle;
+
+/*
+ * Init Hash table stuff
+ */
+
+typedef struct _mgcp_call_info_key {
+ guint32 transid;
+ conversation_t *conversation;
+} mgcp_call_info_key;
+
+static GMemChunk *mgcp_call_info_key_chunk;
+
+static GMemChunk *mgcp_call_info_value_chunk;
+
+static GHashTable *mgcp_calls;
+
+/* compare 2 keys */
+static gint
+mgcp_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const mgcp_call_info_key* key1 = (const mgcp_call_info_key*) k1;
+ const mgcp_call_info_key* key2 = (const mgcp_call_info_key*) k2;
+
+ return (key1->transid == key2->transid &&
+ key1->conversation == key2->conversation);
+}
+
+
+/* calculate a hash key */
+static guint
+mgcp_call_hash(gconstpointer k)
+{
+ const mgcp_call_info_key* key = (const mgcp_call_info_key*) k;
+
+ return key->transid + (guint32)(key->conversation);
+}
+
/*
* dissect_mgcp - The dissector for the Media Gateway Control Protocol
*/
@@ -273,7 +314,7 @@
if (check_col(pinfo->cinfo, COL_INFO) ){
sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin,-1,
&tvb_sectionend,FALSE);
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s",
tvb_format_text(tvb,tvb_sectionbegin,sectionlen));
}
}
@@ -287,7 +328,8 @@
gint sectionlen;
gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len;
tvbuff_t *next_tvb;
-
+ static mgcp_info_t mi;
+
/* Initialize variables */
tvb_sectionend = 0;
tvb_sectionbegin = tvb_sectionend;
@@ -312,8 +354,8 @@
sectionlen = tvb_find_line_end(tvb,0,-1,&tvb_sectionend,FALSE);
if( sectionlen > 0){
dissect_mgcp_firstline(tvb_new_subset(tvb, tvb_sectionbegin,
- sectionlen,-1),
- mgcp_tree);
+ sectionlen,-1), pinfo,
+ mgcp_tree, &mi);
}
tvb_sectionbegin = tvb_sectionend;
@@ -373,6 +415,35 @@
} while ( tvb_lineend < tvb_len );
}
+/* Discard and init any state we've saved */
+
+static void
+mgcp_init_protocol(void)
+{
+ if (mgcp_calls != NULL) {
+ g_hash_table_destroy(mgcp_calls);
+ mgcp_calls = NULL;
+ }
+ if (mgcp_call_info_key_chunk != NULL) {
+ g_mem_chunk_destroy(mgcp_call_info_key_chunk);
+ mgcp_call_info_key_chunk = NULL;
+ }
+ if (mgcp_call_info_value_chunk != NULL) {
+ g_mem_chunk_destroy(mgcp_call_info_value_chunk);
+ mgcp_call_info_value_chunk = NULL;
+ }
+
+ mgcp_calls = g_hash_table_new(mgcp_call_hash, mgcp_call_equal);
+ mgcp_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
+ sizeof(mgcp_call_info_key),
+ 200 * sizeof(mgcp_call_info_key),
+ G_ALLOC_ONLY);
+ mgcp_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
+ sizeof(mgcp_call_t),
+ 200 * sizeof(mgcp_call_t),
+ G_ALLOC_ONLY);
+}
+
/* Register all the bits needed with the filtering engine */
void
@@ -385,6 +456,15 @@
{ &hf_mgcp_rsp,
{ "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if MGCP response", HFILL }},
+ { &hf_mgcp_req_frame,
+ { "Request Frame", "mgcp.reqframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "Request Frame", HFILL }},
+ { &hf_mgcp_rsp_frame,
+ { "Response Frame", "mgcp.rspframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "Response Frame", HFILL }},
+ { &hf_mgcp_time,
+ { "Time from request", "mgcp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
+ "Timedelta between Request and Response", HFILL }},
{ &hf_mgcp_req_verb,
{ "Verb", "mgcp.req.verb", FT_STRING, BASE_DEC, NULL, 0x0,
"Name of the verb", HFILL }},
@@ -484,6 +564,15 @@
{ &hf_mgcp_messagecount,
{ "MGCP Message Count", "mgcp.messagecount", FT_UINT32,
BASE_DEC, NULL, 0x0, "Number of MGCP message in a packet", HFILL }},
+ { &hf_mgcp_dup,
+ { "Duplicate Message", "mgcp.dup", FT_UINT32, BASE_DEC,
+ NULL, 0, "Duplicate Message", HFILL }},
+ { &hf_mgcp_req_dup,
+ { "Duplicate Request", "mgcp.req.dup", FT_UINT32, BASE_DEC,
+ NULL, 0, "Duplicate Request", HFILL }},
+ { &hf_mgcp_rsp_dup,
+ { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32, BASE_DEC,
+ NULL, 0, "Duplicate Response", HFILL }},
/* Add more fields here */
};
static gint *ett[] = {
@@ -497,6 +586,7 @@
proto_register_field_array(proto_mgcp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&mgcp_init_protocol);
/* Register our configuration options for , particularly our ports */
@@ -548,6 +638,8 @@
"Display the number of MGCP messages "
"found in a packet in the protocol column.",
&global_mgcp_message_count);
+
+ mgcp_tap = register_tap("mgcp");
}
/* The registration hand-off routine */
@@ -864,17 +956,28 @@
* tree - The tree from which to hang the structured information parsed
* from the first line of the MGCP message.
*/
-static void dissect_mgcp_firstline(tvbuff_t *tvb,
- proto_tree *tree){
+static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, mgcp_info_t *mi){
gint tvb_current_offset,tvb_previous_offset,tvb_len,tvb_current_len;
gint tokennum, tokenlen;
+ char *transid = NULL;
+ char *code = NULL;
mgcp_type_t mgcp_type = MGCP_OTHERS;
+ conversation_t* conversation;
+ mgcp_call_info_key mgcp_call_key;
+ mgcp_call_info_key *new_mgcp_call_key = NULL;
+ mgcp_call_t *mgcp_call = NULL;
+ nstime_t delta;
+
+ static address null_address = { AT_NONE, 0, NULL };
proto_item* (*my_proto_tree_add_string)(proto_tree*, int, tvbuff_t*, gint,
gint, const char*);
tvb_previous_offset = 0;
tvb_len = tvb_length(tvb);
tvb_current_len = tvb_len;
tvb_current_offset = tvb_previous_offset;
+ mi->is_duplicate = FALSE;
+ mi->request_available = FALSE;
if(tree){
tokennum = 0;
@@ -898,29 +1001,33 @@
tokenlen = tvb_current_offset - tvb_previous_offset;
}
if(tokennum == 0){
+ code = g_malloc(tokenlen);
+ code = tvb_format_text(tvb,tvb_previous_offset,tokenlen);
+ strncpy(mi->code,code,4);
+ mi->code[4] = '\0';
if(is_mgcp_verb(tvb,tvb_previous_offset,tvb_current_len)){
mgcp_type = MGCP_REQUEST;
my_proto_tree_add_string(tree,hf_mgcp_req_verb, tvb,
tvb_previous_offset, tokenlen,
- tvb_format_text(tvb,tvb_previous_offset
- ,tokenlen));
+ code);
}
else if (is_mgcp_rspcode(tvb,tvb_previous_offset,tvb_current_len)){
mgcp_type = MGCP_RESPONSE;
my_proto_tree_add_string(tree,hf_mgcp_rsp_rspcode, tvb,
tvb_previous_offset, tokenlen,
- tvb_format_text(tvb,tvb_previous_offset
- ,tokenlen));
+ code);
}
else {
break;
}
}
if(tokennum == 1){
+ transid = g_malloc(tokenlen);
+ transid = tvb_format_text(tvb,tvb_previous_offset,tokenlen);
+ mi->transid = atol(transid);
my_proto_tree_add_string(tree,hf_mgcp_transid, tvb,
tvb_previous_offset, tokenlen,
- tvb_format_text(tvb,tvb_previous_offset,
- tokenlen));
+ transid);
}
if(tokennum == 2){
if(mgcp_type == MGCP_REQUEST){
@@ -967,15 +1074,200 @@
&& tokennum <= 3);
switch (mgcp_type){
case MGCP_RESPONSE:
- proto_tree_add_boolean_hidden(tree, hf_mgcp_rsp, tvb, 0, 0, TRUE);
+ proto_tree_add_boolean_hidden(tree, hf_mgcp_rsp, tvb, 0, 0, TRUE);
+ /* Check for MGCP response. A response must match a call that
+ we've seen, and the response must be sent to the same
+ port and address that the call came from, and must
+ come from the port to which the call was sent.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&null_address,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ if (conversation != NULL) {
+ /* look only for matching request, if
+ matching conversation is available. */
+ mgcp_call_key.transid = mi->transid;
+ mgcp_call_key.conversation = conversation;
+ mgcp_call = g_hash_table_lookup(mgcp_calls, &mgcp_call_key);
+ if(mgcp_call) {
+ /* Indicate the frame to which this is a reply. */
+ if(mgcp_call->req_num){
+ mi->request_available = TRUE;
+ mgcp_call->responded = TRUE;
+ proto_tree_add_uint_format(tree, hf_mgcp_req_frame,
+ tvb, 0, 0, mgcp_call->req_num,
+ "This is a response to a request in frame %u",
+ mgcp_call->req_num);
+ delta.secs= pinfo->fd->abs_secs-mgcp_call->req_time.secs;
+ delta.nsecs=pinfo->fd->abs_usecs*1000-mgcp_call->req_time.nsecs;
+ if(delta.nsecs<0){
+ delta.nsecs+=1000000000;
+ delta.secs--;
+ }
+ proto_tree_add_time(tree, hf_mgcp_time, tvb, 0, 0,
+ &delta);
+ }
+
+ if (mgcp_call->rsp_num == 0) {
+ /* We have not yet seen a response to that call, so
+ this must be the first response; remember its
+ frame number. */
+ mgcp_call->rsp_num = pinfo->fd->num;
+ } else {
+ /* We have seen a response to this call - but was it
+ *this* response? */
+ if (mgcp_call->rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response.
+ Mark it as such. */
+ mi->is_duplicate = TRUE;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Duplicate Response %ld",mi->transid);
+ if (tree) {
+ proto_tree_add_uint_hidden(tree,
+ hf_mgcp_dup, tvb, 0,0, mi->transid);
+ proto_tree_add_uint_hidden(tree,
+ hf_mgcp_rsp_dup, tvb, 0,0, mi->transid);
+ }
+ }
+ }
+ }
+ }
+ }
break;
case MGCP_REQUEST:
- proto_tree_add_boolean_hidden(tree, hf_mgcp_req, tvb, 0, 0, TRUE);
+ proto_tree_add_boolean_hidden(tree, hf_mgcp_req, tvb, 0, 0, TRUE);
+ /* Keep track of the address and port whence the call came,
+ and the port to which the call is being sent, so that
+ we can match up calls with replies.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new
+ one. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ conversation = conversation_new(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ }
+
+ /* prepare the key data */
+ mgcp_call_key.transid = mi->transid;
+ mgcp_call_key.conversation = conversation;
+
+ /* look up the request */
+ mgcp_call = g_hash_table_lookup(mgcp_calls, &mgcp_call_key);
+ if (mgcp_call != NULL) {
+ /* We've seen a request with this TRANSID, with the same
+ source and destination, before - but was it
+ *this* request? */
+ if (pinfo->fd->num != mgcp_call->req_num) {
+ /* No, so it's a duplicate request.
+ Mark it as such. */
+ mi->is_duplicate = TRUE;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Duplicate Request %ld",mi->transid);
+ if (tree) {
+ proto_tree_add_uint_hidden(tree,
+ hf_mgcp_dup, tvb, 0,0, mi->transid);
+ proto_tree_add_uint_hidden(tree,
+ hf_mgcp_req_dup, tvb, 0,0, mi->transid);
+ }
+ }
+ }
+ }
+ else {
+ /* Prepare the value data.
+ "req_num" and "rsp_num" are frame numbers;
+ frame numbers are 1-origin, so we use 0
+ to mean "we don't yet know in which frame
+ the reply for this call appears". */
+ new_mgcp_call_key = g_mem_chunk_alloc(mgcp_call_info_key_chunk);
+ *new_mgcp_call_key = mgcp_call_key;
+ mgcp_call = g_mem_chunk_alloc(mgcp_call_info_value_chunk);
+ mgcp_call->req_num = pinfo->fd->num;
+ mgcp_call->rsp_num = 0;
+ mgcp_call->transid = mi->transid;
+ mgcp_call->responded = FALSE;
+ mgcp_call->req_time.secs=pinfo->fd->abs_secs;
+ mgcp_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+ strcpy(mgcp_call->code,mi->code);
+ /* store it */
+ g_hash_table_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
+ }
+ if(mgcp_call && mgcp_call->rsp_num){
+ proto_tree_add_uint_format(tree, hf_mgcp_rsp_frame,
+ tvb, 0, 0, mgcp_call->rsp_num,
+ "The response to this request is in frame %u",
+ mgcp_call->rsp_num);
+ }
break;
default:
break;
}
+ mi->mgcp_type = mgcp_type;
+ if(mgcp_call) {
+ mi->req_time.secs=mgcp_call->req_time.secs;
+ mi->req_time.nsecs=mgcp_call->req_time.nsecs;
+ }
}
+ tap_queue_packet(mgcp_tap, pinfo, mi);
}
/*
Index: ethereal/plugins/plugin_api.c
===================================================================
RCS file: /cvsroot/ethereal/plugins/plugin_api.c,v
retrieving revision 1.43
diff -u -r1.43 plugin_api.c
--- ethereal/plugins/plugin_api.c 14 Nov 2002 18:54:53 -0000 1.43
+++ ethereal/plugins/plugin_api.c 5 Mar 2003 23:15:48 -0000
@@ -210,4 +210,7 @@
p_fragment_delete = pat->p_fragment_delete;
p_show_fragment_tree = pat->p_show_fragment_tree;
p_show_fragment_seq_tree = pat->p_show_fragment_seq_tree;
+
+ p_register_tap = pat->p_register_tap;
+ p_tap_queue_packet = pat->p_tap_queue_packet;
}
Index: ethereal/plugins/plugin_api.h
===================================================================
RCS file: /cvsroot/ethereal/plugins/plugin_api.h,v
retrieving revision 1.44
diff -u -r1.44 plugin_api.h
--- ethereal/plugins/plugin_api.h 14 Nov 2002 18:54:53 -0000 1.44
+++ ethereal/plugins/plugin_api.h 5 Mar 2003 23:15:48 -0000
@@ -240,7 +240,10 @@
#define fragment_delete (*p_fragment_delete)
#define show_fragment_tree (*p_show_fragment_tree)
#define show_fragment_seq_tree (*p_show_fragment_seq_tree)
-
+
+#define register_tap (*p_register_tap)
+#define tap_queue_packet (*p_tap_queue_packet)
+
#endif
#include <epan/packet.h>
@@ -250,6 +253,7 @@
#include "packet-giop.h"
#include "packet-tpkt.h"
#include "packet-tcp.h"
+#include "tap.h"
#include "plugin_table.h"
Index: ethereal/plugins/plugin_api_decls.h
===================================================================
RCS file: /cvsroot/ethereal/plugins/plugin_api_decls.h,v
retrieving revision 1.6
diff -u -r1.6 plugin_api_decls.h
--- ethereal/plugins/plugin_api_decls.h 14 Nov 2002 18:54:53 -0000 1.6
+++ ethereal/plugins/plugin_api_decls.h 5 Mar 2003 23:15:49 -0000
@@ -250,3 +250,5 @@
addr_show_fragment_tree p_show_fragment_tree;
addr_show_fragment_seq_tree p_show_fragment_seq_tree;
+addr_register_tap p_register_tap;
+addr_tap_queue_packet p_tap_queue_packet;
Index: ethereal/plugins/plugin_table.h
===================================================================
RCS file: /cvsroot/ethereal/plugins/plugin_table.h,v
retrieving revision 1.56
diff -u -r1.56 plugin_table.h
--- ethereal/plugins/plugin_table.h 2 Dec 2002 23:34:40 -0000 1.56
+++ ethereal/plugins/plugin_table.h 5 Mar 2003 23:15:49 -0000
@@ -279,6 +279,9 @@
typedef gboolean (*addr_show_fragment_tree)(fragment_data *, const fragment_items *, proto_tree *, packet_info *, tvbuff_t *);
typedef gboolean (*addr_show_fragment_seq_tree)(fragment_data *, const fragment_items *, proto_tree *, packet_info *, tvbuff_t *);
+typedef int (*addr_register_tap)(char *);
+typedef void (*addr_tap_queue_packet)(int, packet_info *, void *);
+
typedef struct {
#include "plugin_api_decls.h"
Index: ethereal/epan/plugins.c
===================================================================
RCS file: /cvsroot/ethereal/epan/plugins.c,v
retrieving revision 1.62
diff -u -r1.62 plugins.c
--- ethereal/epan/plugins.c 8 Dec 2002 22:22:03 -0000 1.62
+++ ethereal/epan/plugins.c 5 Mar 2003 23:15:47 -0000
@@ -65,6 +65,7 @@
#include "packet-giop.h"
#include "packet-tpkt.h"
#include "packet-tcp.h"
+#include "tap.h"
#include "plugins/plugin_table.h"
static plugin_address_table_t patable;
#endif
@@ -487,7 +488,10 @@
patable.p_fragment_delete = fragment_delete;
patable.p_show_fragment_tree = show_fragment_tree;
patable.p_show_fragment_seq_tree = show_fragment_seq_tree;
-
+
+ patable.p_register_tap = register_tap;
+ patable.p_tap_queue_packet = tap_queue_packet;
+
#endif
#ifdef WIN32Index: ethereal/Makefile.nmake =================================================================== RCS file: /cvsroot/ethereal/Makefile.nmake,v retrieving revision 1.284 diff -u -r1.284 Makefile.nmake --- ethereal/Makefile.nmake 2 Mar 2003 21:52:09 -0000 1.284 +++ ethereal/Makefile.nmake 5 Mar 2003 23:15:44 -0000 @@ -357,6 +357,7 @@ tap-dcerpcstat.c \ tap-iostat.c \ tap-iousers.c \ + tap-mgcpstat.c \ tap-protocolinfo.c \ tap-protohierstat.c \ tap-rpcstat.c \
- Follow-Ups:
- Re: [Ethereal-dev] new tap for mgcp
- From: Tomas Kukosa
- Re: [Ethereal-dev] new tap for mgcp
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] new tap for mgcp
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] new tap for mgcp
- Prev by Date: Re: [Ethereal-dev] Firestorm Network Intrusion Detection support for Ethereal
- Next by Date: [Ethereal-dev] BICC CS2 (BICC/IP) decoder
- Previous by thread: Re: [Ethereal-dev] new tap for mgcp
- Next by thread: Re: [Ethereal-dev] new tap for mgcp
- Index(es):