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 WIN32
Index: 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):