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





