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);
>  }
>
>  /*
>