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: "Ronnie Sahlberg" <ronnie_sahlberg@xxxxxxxxxxxxxx>
Date: Tue, 4 Mar 2003 14:23:54 +1100
In the code you match requests with responses explicitely inside the mgcpstat_packet() function. while this will work, it would be much better to do the request/response matching inside the actual mgcp dissector instead and then make thet dissector always place Response In:xx Request In:xxx Time from request:xxx in the tree pane. The first two would be proto_item's of type FT_FRAMENUM which would make ethereal offer a GoTo: menu item when rightclicking the item. It would also allow you to use a displayfilter to find those responses that took more than x.yyy seconds to complete. This is how RPC and the other request/response matching is done. See packet-rpc.c . Then you just pass the three values above to the tap system inside the pmi structure passed to _packet() ----- Original Message ----- From: "Lars Roland" Sent: Monday, March 03, 2003 2:30 PM Subject: [Ethereal-dev] new tap for mgcp > Hi, > > I wrote a new tap for mgcp, so here is it. I have used some code from > tap-smbstat, which was very useful. > > Two functions had to be added to the plugin-api. all changes are > attached in the patch. > > Has to be tested on linux. It can be invoked by "-z mgcp,rtd[,filter]" > (like smb,rtt). > > There is still a small bug (at least on MS Win). If you invoke without > second comma and without any second invocation with second comma > present, calculation fails (all results are zero). I have looked at it, > but I can't find the reason. > This is coded in the same way as in "tap-smbstat.c". > Does this happen with "smb,rtt" , too? > > Best regards, > Lars > ---------------------------------------------------------------------------- ---- > /* 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" > > /* 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]; > long transid; > } mgcp_info_t; > > /* Item of request list */ > typedef struct _mgcp_call_t { > long transid; > char code[5]; > nstime_t req_time; > nstime_t rsp_time; > gboolean responded; > struct _mgcp_call_t *prev; > struct _mgcp_call_t *next; > } mgcp_call_t; > > /* 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; > mgcp_call_t *liststart; > mgcp_call_t *listend; > long int num; > long int req_num; > long int rsp_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; > mgcp_call_t *active_mc=NULL; > int i; > > ms->num++; > if(mi->mgcp_type==MGCP_REQUEST){ > if(ms->liststart==NULL){ > /* init open-request list */ > ms->liststart=g_malloc(sizeof(mgcp_call_t)); > ms->listend=ms->liststart; > ms->listend->prev=NULL; > ms->listend->next=NULL; > ms->listend->transid=mi->transid; > strcpy(ms->listend->code,mi->code); > ms->listend->req_time.secs=pinfo->fd->abs_secs; > ms->listend->req_time.nsecs=pinfo->fd->abs_usecs*1000; > ms->listend->rsp_time.secs=0; > ms->listend->rsp_time.nsecs=0; > ms->listend->responded=FALSE; > } > else { > /* add item to open-request list*/ > ms->listend->next=g_malloc(sizeof(mgcp_call_t)); > ms->listend->next->prev=ms->listend; > ms->listend->next->next=NULL; > ms->listend=ms->listend->next; > ms->listend->transid=mi->transid; > strcpy(ms->listend->code,mi->code); > ms->listend->req_time.secs=pinfo->fd->abs_secs; > ms->listend->req_time.nsecs=pinfo->fd->abs_usecs*1000; > ms->listend->rsp_time.secs=0; > ms->listend->rsp_time.nsecs=0; > ms->listend->responded=FALSE; > } > ms->req_num++; > } > else if(mi->mgcp_type==MGCP_RESPONSE){ > /* Packet is a response, look for matching request */ > ms->rsp_num++; > if(ms->listend!=NULL){ > /* walk through list*/ > active_mc=ms->listend; > for(i=0;i<ms->req_num;i++){ > /* check for match */ > if(active_mc->transid==mi->transid && !(active_mc->responded)){ > active_mc->rsp_time.secs=pinfo->fd->abs_secs; > active_mc->rsp_time.nsecs=pinfo->fd->abs_usecs*1000; > active_mc->responded=TRUE; > return 1; > } > active_mc=active_mc->prev; > } > } > } > return 0; > } > > static void > mgcpstat_draw(void *pms) > { > mgcpstat_t *ms=(mgcpstat_t *)pms; > rtd_t mr; > mgcp_call_t *active_mc=NULL; > nstime_t delta; > int i; > > #ifdef G_HAVE_UINT64 > guint64 avg; > #else > guint32 avg; > #endif > mr.num=0; > mr.min.secs=0; > mr.min.nsecs=0; > mr.max.secs=0; > mr.max.nsecs=0; > mr.tot.secs=0; > mr.tot.nsecs=0; > > active_mc=ms->liststart; > /* Calculation of rtd-statistics */ > for(i=0;i<ms->req_num;i++){ > if(active_mc->responded==TRUE){ > /* rtd-calculation */ > > delta.secs=active_mc->rsp_time.secs-active_mc->req_time.secs; > delta.nsecs=active_mc->rsp_time.nsecs-active_mc->req_time.nsecs; > > if(delta.nsecs<0){ > delta.nsecs+=1000000000; > delta.secs--; > } > > rtd_stat_update(&mr,delta); > > } > active_mc=active_mc->next; > } > > /* calculating average rtd */ > /* scale it to units of 10us.*/ > /* for long captures with a large tot time, this can overflow on 32bit */ > avg=(int)mr.tot.secs; > avg=avg*100000+(int)mr.tot.nsecs/10000; > if(mr.num){ > avg/=mr.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("Open requests: %d\n",ms->req_num-mr.num); > printf("Messages | Min RTD | Max RTD | Avg RTD \n"); > printf("%7d | %5d.%03d msec | %5d.%03d msec | %5d.%03d msec\n", > mr.num, > (int)((mr.min.secs*1000)+(mr.min.nsecs/1000000)),(mr.min.nsecs%1000000)/1000 , > (int)((mr.max.secs*1000)+(mr.max.nsecs/1000000)),(mr.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->liststart=NULL; > ms->listend=NULL; > > ms->req_num=0; > ms->rsp_num=0; > ms->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); > } > > ---------------------------------------------------------------------------- ---- > 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 3 Mar 2003 02:09:54 -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 \ > 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 3 Mar 2003 02:09:56 -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/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 3 Mar 2003 02:09:57 -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 3 Mar 2003 02:09:57 -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 3 Mar 2003 02:09:57 -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 3 Mar 2003 02:09:58 -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/plugins/mgcp/packet-mgcp.c > =================================================================== > RCS file: /cvsroot/ethereal/plugins/mgcp/packet-mgcp.c,v > retrieving revision 1.35 > diff -u -r1.35 packet-mgcp.c > --- ethereal/plugins/mgcp/packet-mgcp.c 28 Aug 2002 20:39:07 -0000 1.35 > +++ ethereal/plugins/mgcp/packet-mgcp.c 3 Mar 2003 02:10:00 -0000 > @@ -105,6 +105,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,7 +144,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, > @@ -148,6 +151,13 @@ > MGCP_OTHERS > } mgcp_type_t; > > +/* Container for tapping relevant data */ > +typedef struct _mgcp_info_t { > + mgcp_type_t mgcp_type; > + char code[5]; > + long transid; > +} mgcp_info_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,7 +171,7 @@ > */ > 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, > +static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, > proto_tree *tree); > static void dissect_mgcp_params(tvbuff_t *tvb, > proto_tree *tree); > @@ -287,7 +297,7 @@ > gint sectionlen; > gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len; > tvbuff_t *next_tvb; > - > + > /* Initialize variables */ > tvb_sectionend = 0; > tvb_sectionbegin = tvb_sectionend; > @@ -312,7 +322,7 @@ > 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), > + sectionlen,-1), pinfo, > mgcp_tree); > } > tvb_sectionbegin = tvb_sectionend; > @@ -548,6 +558,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,10 +876,13 @@ > * 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, > +static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, > proto_tree *tree){ > gint tvb_current_offset,tvb_previous_offset,tvb_len,tvb_current_len; > gint tokennum, tokenlen; > + static mgcp_info_t mi; > + char *transid; > + char *code; > mgcp_type_t mgcp_type = MGCP_OTHERS; > proto_item* (*my_proto_tree_add_string)(proto_tree*, int, tvbuff_t*, gint, > gint, const char*); > @@ -875,6 +890,8 @@ > tvb_len = tvb_length(tvb); > tvb_current_len = tvb_len; > tvb_current_offset = tvb_previous_offset; > + code = NULL; > + transid = NULL; > > if(tree){ > tokennum = 0; > @@ -898,29 +915,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){ > @@ -975,7 +996,9 @@ > default: > break; > } > + mi.mgcp_type = mgcp_type; > } > + tap_queue_packet(mgcp_tap, pinfo, &mi); > } > > /* >
- References:
- [Ethereal-dev] new tap for mgcp
- From: Lars Roland
- [Ethereal-dev] new tap for mgcp
- Prev by Date: Re: [Ethereal-dev] Creating a contrib directory?
- Next by Date: Re: [Ethereal-dev] Improved NetFlow v9 dissector
- Previous by thread: [Ethereal-dev] new tap for mgcp
- Next by thread: Re: [Ethereal-dev] new tap for mgcp
- Index(es):