Ethereal-dev: [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 <Lars.Roland@xxxxxxx>
Date: Mon, 03 Mar 2003 04:30:54 +0100
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); } /*
- Follow-Ups:
- Re: [Ethereal-dev] new tap for mgcp
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] new tap for mgcp
- Prev by Date: Re: [Ethereal-dev] ethereal -G (Protocol and fieldnames)
- Next by Date: Re: [Ethereal-dev] "make distcheck" failure
- Previous by thread: Re: [Ethereal-dev] [PATCH] SNA Update
- Next by thread: Re: [Ethereal-dev] new tap for mgcp
- Index(es):