From Jean-Michel Fayard: BOOTP/DHCP, HTTP, and WSP statistics taps.

svn path=/trunk/; revision=8345
This commit is contained in:
Guy Harris 2003-09-02 22:47:59 +00:00
parent 71034c5a3f
commit 75ae0e30c7
16 changed files with 2309 additions and 15 deletions

View File

@ -1814,6 +1814,7 @@ Vincent Jardin <vincent.jardin [AT] 6wind.com> {
Jean-Michel Fayard <jean-michel.fayard [AT] moufrei.de> {
Show in Tools:Summary window statistics about packets that
passed the current display filter
BOOTP/DHCP, HTTP, and WSP statistics taps
}
And assorted fixes and enhancements by the people listed above and by:

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
# $Id: Makefile.am,v 1.616 2003/08/29 22:27:14 guy Exp $
# $Id: Makefile.am,v 1.617 2003/09/02 22:47:56 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -862,7 +862,9 @@ ethereal_LDADD = \
@PCAP_LIBS@ @GTK_LIBS@ @ADNS_LIBS@
TETHEREAL_TAP_SRC = \
tap-bootpstat.c \
tap-dcerpcstat.c \
tap-httpstat.c \
tap-iostat.c \
tap-iousers.c \
tap-mgcpstat.c \
@ -871,7 +873,8 @@ TETHEREAL_TAP_SRC = \
tap-rpcstat.c \
tap-rpcprogs.c \
tap-smbsids.c \
tap-smbstat.c
tap-smbstat.c \
tap-wspstat.c
tethereal_SOURCES = \
$(DISSECTOR_SRC) \

View File

@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
# $Id: Makefile.nmake,v 1.329 2003/08/29 22:27:14 guy Exp $
# $Id: Makefile.nmake,v 1.330 2003/09/02 22:47:56 guy Exp $
include config.nmake
include <win32.mak>
@ -383,7 +383,9 @@ DISSECTOR_SRC = \
DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
TETHEREAL_TAP_SRC = \
tap-bootpstat.c \
tap-dcerpcstat.c \
tap-httpstat.c \
tap-iostat.c \
tap-iousers.c \
tap-mgcpstat.c \
@ -392,7 +394,8 @@ TETHEREAL_TAP_SRC = \
tap-rpcstat.c \
tap-rpcprogs.c \
tap-smbsids.c \
tap-smbstat.c
tap-smbstat.c \
tap-wspstat.c
TETHEREAL_TAP_OBJECTS = $(TETHEREAL_TAP_SRC:.c=.obj)

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for the GTK interface routines for Ethereal
#
# $Id: Makefile.am,v 1.65 2003/08/29 10:59:12 sahlberg Exp $
# $Id: Makefile.am,v 1.66 2003/09/02 22:47:58 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -28,6 +28,7 @@ CLEANFILES = \
*~
ETHEREAL_TAP_SRC = \
bootp_stat.c \
dcerpc_stat.c \
endpoint_talkers_eth.c \
endpoint_talkers_fc.c \
@ -38,12 +39,14 @@ ETHEREAL_TAP_SRC = \
endpoint_talkers_tr.c \
endpoint_talkers_udpip.c \
fc_stat.c \
http_stat.c \
io_stat.c \
mgcp_stat.c \
rpc_stat.c \
rpc_progs.c \
smb_stat.c \
tap_rtp.c
tap_rtp.c \
wsp_stat.c
ethereal-tap-register.c: $(ETHEREAL_TAP_SRC) $(top_srcdir)/make-tapreg-dotc
@echo Making ethereal-tap-register.c

View File

@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
# $Id: Makefile.nmake,v 1.50 2003/08/29 10:59:12 sahlberg Exp $
# $Id: Makefile.nmake,v 1.51 2003/09/02 22:47:58 guy Exp $
include ..\config.nmake
@ -20,6 +20,7 @@ CVARSDLL=-DWIN32 -DNULL=0 -D_MT -D_DLL
$(CC) $(CVARSDLL) $(CFLAGS) -Fd.\ -c $<
ETHEREAL_TAP_SRC = \
bootp_stat.c \
dcerpc_stat.c \
endpoint_talkers_eth.c \
endpoint_talkers_fc.c \
@ -30,12 +31,14 @@ ETHEREAL_TAP_SRC = \
endpoint_talkers_tr.c \
endpoint_talkers_udpip.c \
fc_stat.c \
http_stat.c \
io_stat.c \
mgcp_stat.c \
rpc_stat.c \
rpc_progs.c \
smb_stat.c \
tap_rtp.c
tap_rtp.c \
wsp_stat.c
ETHEREAL_TAP_OBJECTS = $(ETHEREAL_TAP_SRC:.c=.obj)

335
gtk/bootp_stat.c Normal file
View File

@ -0,0 +1,335 @@
/* bootp_stat.c
* boop_stat 2003 Jean-Michel FAYARD
*
* $Id: bootp_stat.c,v 1.1 2003/09/02 22:47:58 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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.
*/
/* #define DEBUG do{ printf("%s:%d ",__FILE__,__LINE__);} while(0); */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gtk/gtk.h>
#include "menu.h"
#include "epan/packet_info.h"
#include "simple_dialog.h"
#include "tap.h"
#include "../register.h"
#include "../globals.h"
#include "compat_macros.h"
#include <string.h>
typedef const char* bootp_info_value_t;
/* used to keep track of the statictics for an entire program interface */
typedef struct _dhcp_stats_t {
char *filter;
GtkWidget *win;
GHashTable *hash;
GtkWidget *table_message_type;
guint index; /* Number of to display */
} dhcpstat_t;
/* used to keep track of a single DHCP message type */
typedef struct _dhcp_message_type_t {
const char *name;
guint32 packets;
GtkWidget *widget;/* label in which we print the number of packets */
dhcpstat_t *sp; /* entire program interface */
} dhcp_message_type_t;
static GtkWidget *dlg=NULL, *dlg_box;
static GtkWidget *filter_box;
static GtkWidget *filter_label, *filter_entry;
static GtkWidget *start_button;
static void
dhcp_free_hash( gpointer key _U_ , gpointer value, gpointer user_data _U_ )
{
g_free(value);
}
static void
dhcp_reset_hash(gchar *key _U_ , dhcp_message_type_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
/* Update the entry corresponding to the number of packets of a special DHCP Message Type
* or create it if it don't exist.
*/
static void
dhcp_draw_message_type(gchar *key _U_, dhcp_message_type_t *data, gchar * string_buff )
{
if ((data==NULL) || (data->packets==0))
return;
if (data->widget==NULL){ /* create an entry in the table */
GtkWidget *tmp;
int x = 2*((data->sp->index) % 2);
int y = (data->sp->index) /2;
/* Maybe we should display the hexadecimal value ? */
/* sprintf(string_buff, "%s (0X%x)", data->name, *key); */
tmp = gtk_label_new( data->name /* string_buff */ );
gtk_table_attach_defaults(GTK_TABLE(data->sp->table_message_type), tmp, x, x+1, y, y+1);
gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
gtk_widget_show(tmp);
sprintf( string_buff, "%9d", data->packets );
data->widget = gtk_label_new( string_buff );
gtk_table_attach_defaults(GTK_TABLE(data->sp->table_message_type), data->widget, x+1, x+2, y, y+1);
gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_LEFT);
gtk_widget_show( data->widget );
data->sp->index++;
} else {
/* Just update the label string */
sprintf( string_buff, "%9d", data->packets );
gtk_label_set( GTK_LABEL(data->widget), string_buff);
}
}
static void
dhcpstat_reset(void *psp)
{
dhcpstat_t *sp=psp;
g_hash_table_foreach( sp->hash, (GHFunc)dhcp_reset_hash, NULL);
}
static int
dhcpstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
dhcpstat_t *sp=psp;
bootp_info_value_t value=pri;
dhcp_message_type_t *sc;
if (sp==NULL)
return 0;
sc = g_hash_table_lookup(
sp->hash,
value);
if (!sc) {
/*g_warning("%s:%d What's Wrong for %s, doc ?", __FILE__, __LINE__, value);*/
sc = g_malloc( sizeof(dhcp_message_type_t) );
sc -> packets = 1;
sc -> name = value;
sc -> widget=NULL;
sc -> sp = sp;
g_hash_table_insert(
sp->hash,
(gpointer) value,
sc);
} else {
/*g_warning("sc(%s)->packets++", sc->name);*/
sc->packets++;
}
return 1;
}
static void
dhcpstat_draw(void *psp)
{
dhcpstat_t *sp=psp;
char str[256];
guint index;
index=sp->index;
g_hash_table_foreach( sp->hash, (GHFunc) dhcp_draw_message_type, str );
if (index != sp->index){
/* We have inserted a new entry corresponding to a status code ,
* let's resize the table */
gtk_table_resize ( GTK_TABLE(sp->table_message_type), sp->index % 2 , 4);
}
}
/* since the gtk2 implementation of tap is multithreaded we must protect
* remove_tap_listener() from modifying the list while draw_tap_listener()
* is running. the other protected block is in main.c
*
* there should not be any other critical regions in gtk2
*/
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
static void
win_destroy_cb(GtkWindow *win _U_, gpointer data)
{
dhcpstat_t *sp=(dhcpstat_t *)data;
protect_thread_critical_region();
remove_tap_listener(sp);
unprotect_thread_critical_region();
g_free(sp->filter);
g_hash_table_foreach( sp->hash, (GHFunc)dhcp_free_hash, NULL);
g_hash_table_destroy( sp->hash);
g_free(sp);
}
/* When called, this function will create a new instance of gtk2-dhcpstat.
*/
static void
gtk_dhcpstat_init(char *optarg)
{
dhcpstat_t *sp;
char *filter=NULL;
char *title=NULL;
GString *error_string;
GtkWidget *message_type_fr ;
if (!strncmp (optarg, "bootp,stat,", 11)){
filter=optarg+11;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(dhcpstat_t) );
sp->hash = g_hash_table_new( g_str_hash, g_str_equal);
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
title=g_strdup_printf("DHCP Stats with filter: %s", filter);
} else {
sp->filter=NULL;
title=g_strdup("DHCP Stats");
}
sp->win = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_title( GTK_WINDOW(sp->win), title );
g_free(title);
SIGNAL_CONNECT( sp->win, "destroy", win_destroy_cb, sp);
/* Status Codes frame */
message_type_fr = gtk_frame_new("DHCP Message Type");
gtk_container_add(GTK_CONTAINER(sp->win), message_type_fr);
gtk_widget_show(message_type_fr);
sp->table_message_type = gtk_table_new( 0, 4, FALSE);
gtk_table_set_col_spacings( GTK_TABLE(sp->table_message_type), 10);
gtk_container_add( GTK_CONTAINER( message_type_fr), sp->table_message_type);
gtk_container_set_border_width( GTK_CONTAINER(sp->table_message_type) , 10);
sp->index = 0; /* Nothing to display yet */
error_string = register_tap_listener(
"bootp",
sp,
filter,
dhcpstat_reset,
dhcpstat_packet,
dhcpstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
simple_dialog( ESD_TYPE_WARN, NULL, error_string->str );
g_free(sp->filter);
g_free(sp);
g_string_free(error_string, TRUE);
return ;
}
if (dlg){
gtk_widget_destroy( dlg );
}
gtk_widget_show_all( sp->win );
redissect_packets(&cfile);
}
static void
dhcp_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
{
char *filter;
char str[256];
filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
if(filter[0]==0){
gtk_dhcpstat_init("dhcp,stat,");
} else {
sprintf(str, "dhcp,stat,%s", filter);
gtk_dhcpstat_init(str);
}
}
static void
dlg_destroy_cb(void)
{
dlg=NULL;
}
static void
gtk_dhcpstat_cb(GtkWidget *w _U_, gpointer d _U_)
{
/* if the window is already open, bring it to front */
if(dlg){
gdk_window_raise(dlg->window);
return;
}
dlg=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(dlg), "WSP Statistics");
SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
dlg_box=gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
gtk_widget_show(dlg_box);
/* filter box */
filter_box=gtk_hbox_new(FALSE, 10);
/* Filter label */
gtk_container_set_border_width(GTK_CONTAINER(filter_box), 10);
filter_label=gtk_label_new("Filter:");
gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
gtk_widget_show(filter_label);
filter_entry=gtk_entry_new_with_max_length(250);
gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, FALSE, FALSE, 0);
gtk_widget_show(filter_entry);
gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
gtk_widget_show(filter_box);
/* the start button */
start_button=gtk_button_new_with_label("Create Stat");
SIGNAL_CONNECT_OBJECT(start_button, "clicked",
dhcp_start_button_clicked, NULL);
gtk_box_pack_start(GTK_BOX(dlg_box), start_button, TRUE, TRUE, 0);
gtk_widget_show(start_button);
gtk_widget_show_all(dlg);
}
void
register_tap_listener_gtkdhcpstat(void)
{
register_ethereal_tap("bootp,stat,", gtk_dhcpstat_init);
}
void
register_tap_menu_gtkdhcpstat(void)
{
register_tap_menu_item("Watch protocol/BOOTP-DHCP", gtk_dhcpstat_cb);
}

579
gtk/http_stat.c Normal file
View File

@ -0,0 +1,579 @@
/* http_stat.c
* http_stat 2003 Jean-Michel FAYARD
*
* $Id: http_stat.c,v 1.1 2003/09/02 22:47:59 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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 <gtk/gtk.h>
#include "menu.h"
#include "epan/packet_info.h"
#include "simple_dialog.h"
#include "tap.h"
#include "../register.h"
#include "../globals.h"
#include "compat_macros.h"
#include "../packet-http.h"
#include <string.h>
/* used to keep track of the statictics for an entire program interface */
typedef struct _http_stats_t {
char *filter;
GtkWidget *win;
GHashTable *hash_responses;
GHashTable *hash_requests;
guint32 packets; /* number of http packets, including HTTP continuation */
GtkWidget *packets_label;
GtkWidget *request_box; /* container for GET, ... */
GtkWidget *informational_table; /* Status code between 100 and 199 */
GtkWidget *success_table; /* 200 and 299 */
GtkWidget *redirection_table; /* 300 and 399 */
GtkWidget *client_error_table; /* 400 and 499 */
GtkWidget *server_errors_table; /* 500 and 599 */
} httpstat_t;
/* used to keep track of the stats for a specific response code
* for example it can be { 3, 404, "Not Found" ,...}
* which means we captured 3 reply http/1.1 404 Not Found */
typedef struct _http_response_methode_t {
guint32 packets; /* 3 */
guint response_method; /* 404 */
gchar *name; /* Not Found */
GtkWidget *widget; /* Label where we display it */
GtkWidget *table; /* Table in which we put it, e.g. client_error_box */
httpstat_t *sp;
} http_response_methode_t;
/* used to keep track of the stats for a specific request string */
typedef struct _http_request_methode_t {
gchar *response; /* eg. : GET */
guint32 packets;
GtkWidget *widget;
httpstat_t *sp;
} http_request_methode_t;
static GtkWidget *dlg=NULL, *dlg_box;
static GtkWidget *filter_box;
static GtkWidget *filter_label, *filter_entry;
static GtkWidget *start_button;
static const value_string vals_status_code[] = {
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 199, "Informational - Others" },
{ 200, "OK"},
{ 201, "Created"},
{ 202, "Accepted"},
{ 203, "Non-authoritative Information"},
{ 204, "No Content"},
{ 205, "Reset Content"},
{ 206, "Partial Content"},
{ 299, "Success - Others"}, /* used to keep track of others Success packets */
{ 300, "Multiple Choices"},
{ 301, "Moved Permanently"},
{ 302, "Moved Temporarily"},
{ 303, "See Other"},
{ 304, "Not Modified"},
{ 305, "Use Proxy"},
{ 399, "Redirection - Others"},
{ 400, "Bad Request"},
{ 401, "Unauthorized"},
{ 402, "Payment Required"},
{ 403, "Forbidden"},
{ 404, "Not Found"},
{ 405, "Method Not Allowed"},
{ 406, "Not Acceptable"},
{ 407, "Proxy Authentication Required"},
{ 408, "Request Time-out"},
{ 409, "Conflict"},
{ 410, "Gone"},
{ 411, "Length Required"},
{ 412, "Precondition Failed"},
{ 413, "Request Entity Too Large"},
{ 414, "Request-URI Too Large"},
{ 415, "Unsupported Media Type"},
{ 499, "Client Error - Others"},
{ 500, "Internal Server Error"},
{ 501, "Not Implemented"},
{ 502, "Bad Gateway"},
{ 503, "Service Unavailable"},
{ 504, "Gateway Time-out"},
{ 505, "HTTP Version not supported"},
{ 599, "Server Error - Others"},
{ 0, NULL}
} ;
/* insert some entries */
static void
http_init_hash( httpstat_t *sp)
{
int i;
sp->hash_responses = g_hash_table_new( g_int_hash, g_int_equal);
for (i=0 ; vals_status_code[i].strptr ; i++ )
{
gint *key = g_malloc (sizeof(gint));
http_response_methode_t *sc = g_malloc (sizeof(http_response_methode_t));
*key = vals_status_code[i].value;
sc->packets=0;
sc->response_method = *key;
sc->name=vals_status_code[i].strptr;
sc->widget=NULL;
sc->table=NULL;
sc->sp = sp;
g_hash_table_insert( sc->sp->hash_responses, key, sc);
}
sp->hash_requests = g_hash_table_new( g_str_hash, g_str_equal);
}
static void
http_draw_hash_requests( gchar *key _U_ , http_request_methode_t *data, gchar * string_buff)
{
if (data->packets==0)
return;
sprintf(string_buff, " %-11s : %3d packets", data->response, data->packets);
if (data->widget==NULL){
data->widget=gtk_label_new( string_buff );
gtk_misc_set_alignment(GTK_MISC(data->widget), 0.0, 0.5);
gtk_box_pack_start(GTK_BOX(data->sp->request_box), data->widget,FALSE,FALSE, 0);
gtk_widget_show(data->widget);
} else {
gtk_label_set( GTK_LABEL(data->widget), string_buff);
}
}
static void
http_draw_hash_responses( gint * key _U_ , http_response_methode_t *data, gchar * string_buff)
{
if (data==NULL)
g_warning("C'est quoi ce borderl key=%d\n", *key);
if (data->packets==0)
return;
/*sprintf(string_buff, "%d packets %d:%s", data->packets, data->response_method, data->name); */
if (data->widget==NULL){ /* create an entry in the relevant box of the window */
guint16 x;
GtkWidget *tmp;
guint i = data->response_method;
if ( (i<100)||(i>=600) )
return;
if (i<200)
data->table = data->sp->informational_table;
else if (i<300)
data->table = data->sp->success_table;
else if (i<400)
data->table = data->sp->redirection_table;
else if (i<500)
data->table = data->sp->client_error_table;
else
data->table = data->sp->server_errors_table;
x=GTK_TABLE( data->table)->nrows;
sprintf(string_buff, "HTTP %3d %s ", data->response_method, data->name );
tmp = gtk_label_new( string_buff );
gtk_table_attach_defaults( GTK_TABLE(data->table), tmp, 0,1, x, x+1);
gtk_label_set_justify( GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
gtk_widget_show( tmp );
sprintf(string_buff, "%9d", data->packets);
data->widget=gtk_label_new( string_buff);
gtk_table_attach_defaults( GTK_TABLE(data->table), data->widget, 1, 2,x,x+1);
gtk_label_set_justify( GTK_LABEL(data->widget), GTK_JUSTIFY_RIGHT);
gtk_widget_show( data->widget );
gtk_table_resize( GTK_TABLE(data->table), x+1, 4);
} else {
/* Just update the label string */
sprintf(string_buff, "%9d", data->packets );
gtk_label_set( GTK_LABEL(data->widget), string_buff);
}
}
static void
http_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
{
g_free(key);
g_free(value);
}
static void
http_reset_hash_responses(gchar *key _U_ , http_response_methode_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
static void
http_reset_hash_requests(gchar *key _U_ , http_request_methode_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
static void
httpstat_reset(void *psp )
{
httpstat_t *sp=psp;
if (!sp) {
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_reset_hash_responses, NULL);
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_reset_hash_requests, NULL);
}
}
static int
httpstat_packet(void *psp , packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
http_info_value_t *value=pri;
httpstat_t *sp=(httpstat_t *) psp;
/* total number of packets, including HTTP continuation packets */
sp->packets++;
/* We are only interested in reply packets with a status code */
/* Request or reply packets ? */
if (value->response_method!=0) {
guint *key=g_malloc( sizeof(guint) );
http_response_methode_t *sc;
*key=value->response_method ;
sc = g_hash_table_lookup(
sp->hash_responses,
key);
if (sc==NULL){
/* non standard status code ; we classify it as others
* in the relevant category (Informational,Success,Redirection,Client Error,Server Error)
*/
int i = value->response_method;
if ((i<100) || (i>=600)) {
return 0;
}
else if (i<200){
*key=199; /* Hopefully, this status code will never be used */
}
else if (i<300){
*key=299;
}
else if (i<400){
*key=399;
}
else if (i<500){
*key=499;
}
else{
*key=599;
}
sc = g_hash_table_lookup(
sp->hash_responses,
key);
if (sc==NULL)
return 0;
}
sc->packets++;
}
else if (value->request_method){
http_request_methode_t *sc;
sc = g_hash_table_lookup(
sp->hash_requests,
value->request_method);
if (sc==NULL){
sc=g_malloc( sizeof(http_request_methode_t) );
sc->response=g_strdup( value->request_method );
sc->packets=1;
sc->widget=NULL;
sc->sp = sp;
g_hash_table_insert( sp->hash_requests, sc->response, sc);
} else {
sc->packets++;
}
/* g_free( value->request_method ); */
} else {
return 0;
}
return 1;
}
#define SUM_STR_MAX 1024
static void
httpstat_draw(void *psp )
{
gchar string_buff[SUM_STR_MAX];
httpstat_t *sp=psp;
sprintf( string_buff, "HTTP stats (%d packets)", sp->packets);
gtk_label_set( GTK_LABEL(sp->packets_label), string_buff);
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_draw_hash_responses, string_buff);
g_hash_table_foreach( sp->hash_requests, (GHFunc)http_draw_hash_requests, string_buff);
}
/* since the gtk2 implementation of tap is multithreaded we must protect
* remove_tap_listener() from modifying the list while draw_tap_listener()
* is running. the other protected block is in main.c
*
* there should not be any other critical regions in gtk2
*/
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
static void
win_destroy_cb(GtkWindow *win _U_, gpointer data)
{
httpstat_t *sp=(httpstat_t *)data;
protect_thread_critical_region();
remove_tap_listener(sp);
unprotect_thread_critical_region();
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_free_hash, NULL);
g_hash_table_destroy( sp->hash_responses);
g_hash_table_foreach( sp->hash_requests, (GHFunc)http_free_hash, NULL);
g_hash_table_destroy( sp->hash_requests);
g_free(sp->filter);
g_free(sp);
}
/* When called, this function will create a new instance of gtk_httpstat.
*/
static void
gtk_httpstat_init(char *optarg)
{
httpstat_t *sp;
char *filter=NULL;
char *title=NULL;
GString *error_string;
GtkWidget *main_vb, *separator,
*informational_fr, *success_fr, *redirection_fr,
*client_errors_fr, *server_errors_fr, *request_fr;
if (!strncmp (optarg, "http,stat,", 10)){
filter=optarg+10;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(httpstat_t) );
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
title=g_strdup_printf("HTTP Stats with filter: %s", filter);
} else {
sp->filter=NULL;
title=g_strdup("HTTP Stats");
}
/* top level window */
sp->win = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_title( GTK_WINDOW(sp->win), title );
g_free(title);
SIGNAL_CONNECT( sp->win, "destroy", win_destroy_cb, sp);
/* container for each group of status code */
main_vb = gtk_vbox_new(FALSE, 10);
gtk_container_border_width(GTK_CONTAINER(main_vb), 10);
gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
gtk_widget_show(main_vb);
/* number of packets */
sp->packets=0;
sp->packets_label = gtk_label_new("HTTP stats (0 HTTP packets)");
gtk_container_add( GTK_CONTAINER(main_vb), sp->packets_label);
gtk_widget_show(sp->packets_label);
/* Informational response frame */
informational_fr = gtk_frame_new("Informational HTTP 1xx");
gtk_container_add(GTK_CONTAINER(main_vb), informational_fr);
gtk_widget_show(informational_fr);
sp->informational_table = gtk_table_new( 0, 2, FALSE);
gtk_container_add(GTK_CONTAINER(informational_fr), sp->informational_table);
gtk_widget_show(sp->informational_table);
/* success response frame */
success_fr = gtk_frame_new ("Success HTTP 2xx");
gtk_container_add(GTK_CONTAINER(main_vb), success_fr);
gtk_widget_show(success_fr);
sp->success_table = gtk_table_new( 0, 2, FALSE);
gtk_container_add(GTK_CONTAINER(success_fr), sp->success_table);
gtk_widget_show(sp->success_table);
/* redirection response frame */
redirection_fr = gtk_frame_new ("Redirection HTTP 3xx");
gtk_container_add(GTK_CONTAINER(main_vb), redirection_fr);
gtk_widget_show(redirection_fr);
sp->redirection_table = gtk_table_new( 0, 2, FALSE);
gtk_container_add(GTK_CONTAINER(redirection_fr), sp->redirection_table);
gtk_widget_show(sp->redirection_table);
/* client_errors response frame */
client_errors_fr = gtk_frame_new("Client errors HTTP 4xx");
gtk_container_add(GTK_CONTAINER(main_vb), client_errors_fr);
gtk_widget_show(client_errors_fr);
sp->client_error_table = gtk_table_new( 0, 2, FALSE);
gtk_container_add(GTK_CONTAINER(client_errors_fr), sp->client_error_table);
gtk_widget_show(sp->client_error_table);
/* server_errors response frame */
server_errors_fr = gtk_frame_new("Server errors HTTP 5xx");
gtk_container_add(GTK_CONTAINER(main_vb), server_errors_fr);
gtk_widget_show(server_errors_fr);
sp->server_errors_table = gtk_table_new( 0, 2, FALSE);
gtk_container_add(GTK_CONTAINER(server_errors_fr), sp->server_errors_table);
gtk_widget_show(sp->server_errors_table);
separator = gtk_hseparator_new();
gtk_container_add(GTK_CONTAINER(main_vb), separator );
/* request response frame */
request_fr = gtk_frame_new("List of request methods");
gtk_container_add(GTK_CONTAINER(main_vb), request_fr);
gtk_container_border_width(GTK_CONTAINER(request_fr), 0);
gtk_widget_show(request_fr);
sp->request_box = gtk_vbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(request_fr), sp->request_box);
gtk_widget_show(sp->request_box);
error_string = register_tap_listener(
"http",
sp,
filter,
httpstat_reset,
httpstat_packet,
httpstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
simple_dialog( ESD_TYPE_WARN, NULL, error_string->str );
g_free(sp->filter);
g_free(sp);
g_string_free(error_string, TRUE);
return ;
}
if (dlg)
{
gtk_widget_destroy( dlg );
}
gtk_widget_show_all( sp->win );
http_init_hash(sp);
redissect_packets(&cfile);
}
static void
httpstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
{
char *filter;
char str[256];
filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
if(filter[0]==0){
gtk_httpstat_init("http,stat,");
} else {
sprintf(str, "http,stat,%s", filter);
gtk_httpstat_init(str);
}
}
static void
dlg_destroy_cb(void)
{
dlg=NULL;
}
static void
gtk_httpstat_cb(GtkWidget *w _U_, gpointer d _U_)
{
/* if the window is already open, bring it to front */
if(dlg){
gdk_window_raise(dlg->window);
return;
}
dlg=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(dlg), "HTTP Statistics");
SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
dlg_box=gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
gtk_widget_show(dlg_box);
/* filter box */
filter_box=gtk_hbox_new(FALSE, 10);
/* Filter label */
gtk_container_set_border_width(GTK_CONTAINER(filter_box), 10);
filter_label=gtk_label_new("Filter:");
gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
gtk_widget_show(filter_label);
filter_entry=gtk_entry_new_with_max_length(250);
gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, FALSE, FALSE, 0);
gtk_widget_show(filter_entry);
gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
gtk_widget_show(filter_box);
/* the start button */
start_button=gtk_button_new_with_label("Create Stat");
SIGNAL_CONNECT_OBJECT(start_button, "clicked",
httpstat_start_button_clicked, NULL);
gtk_box_pack_start(GTK_BOX(dlg_box), start_button, TRUE, TRUE, 0);
gtk_widget_show(start_button);
gtk_widget_show_all(dlg);
}
void
register_tap_listener_gtkhttpstat(void)
{
register_ethereal_tap("http,stat,", gtk_httpstat_init);
}
void
register_tap_menu_gtkhttpstat(void)
{
register_tap_menu_item("Watch protocol/HTTP", gtk_httpstat_cb);
}

483
gtk/wsp_stat.c Normal file
View File

@ -0,0 +1,483 @@
/* wsp_stat.c
* wsp_stat 2003 Jean-Michel FAYARD
*
* $Id: wsp_stat.c,v 1.1 2003/09/02 22:47:59 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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.
*/
/* #define DEBUG do{ printf("%s:%d ",__FILE__,__LINE__);} while(0); */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gtk/gtk.h>
#include "menu.h"
#include "epan/packet_info.h"
#include "simple_dialog.h"
#include "tap.h"
#include "../register.h"
#include "../globals.h"
#include "compat_macros.h"
#include "../packet-wsp.h"
#include <string.h>
/* used to keep track of the stats for a specific PDU type*/
typedef struct _wsp_pdu_t {
GtkLabel *widget;
guint32 packets;
} wsp_pdu_t;
/* used to keep track of the statictics for an entire program interface */
typedef struct _wsp_stats_t {
char *filter;
wsp_pdu_t *pdu_stats;
guint32 num_pdus;
GtkWidget *win;
GHashTable *hash;
GtkWidget *table_pdu_types;
GtkWidget *table_status_code;
guint index; /* Number of status code to display */
} wspstat_t;
/* used to keep track of a single type of status code */
typedef struct _wsp_status_code_t {
gchar *name;
guint32 packets;
GtkWidget *widget;/* label in which we print the number of packets */
wspstat_t *sp; /* entire program interface */
} wsp_status_code_t;
static GtkWidget *dlg=NULL, *dlg_box;
static GtkWidget *filter_box;
static GtkWidget *filter_label, *filter_entry;
static GtkWidget *start_button;
static void
wsp_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
{
g_free(key);
g_free(value);
}
static void
wsp_reset_hash(gchar *key _U_ , wsp_status_code_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
/* Update the entry corresponding to the number of packets of a special status code
* or create it if it don't exist.
*/
static void
wsp_draw_statuscode(gchar *key _U_, wsp_status_code_t *data, gchar * string_buff )
{
if ((data==NULL) || (data->packets==0))
return;
if (data->widget==NULL){ /* create an entry in the table */
GtkWidget *tmp;
int x = 2*((data->sp->index) % 2);
int y = (data->sp->index) /2;
/* Maybe we should display the hexadecimal value ? */
/* sprintf(string_buff, "%s (0X%x)", data->name, *key); */
tmp = gtk_label_new( data->name /* string_buff */ );
gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), tmp, x, x+1, y, y+1);
gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
gtk_widget_show(tmp);
sprintf( string_buff, "%9d", data->packets );
data->widget = gtk_label_new( string_buff );
gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), data->widget, x+1, x+2, y, y+1);
gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_LEFT);
gtk_widget_show( data->widget );
data->sp->index++;
} else {
/* Just update the label string */
sprintf( string_buff, "%9d", data->packets );
gtk_label_set( GTK_LABEL(data->widget), string_buff);
}
}
static void
wspstat_reset(void *psp)
{
wspstat_t *sp=psp;
guint32 i;
for(i=1;i<=sp->num_pdus;i++)
{
sp->pdu_stats[i].packets=0;
}
g_hash_table_foreach( sp->hash, (GHFunc)wsp_reset_hash, NULL);
}
static gint
pdut2index(gint pdut)
{
if (pdut<=0x09) return pdut;
if (pdut>=0x40){
if (pdut <= 0x44){
return pdut-54;
} else if (pdut==0x60||pdut==0x61){
return pdut-81;
}
}
return 0;
}
static gint
index2pdut(gint pdut)
{
if (pdut<=0x09)
return pdut;
if (pdut<=14)
return pdut+54;
if (pdut<=16)
return pdut+81;
return 0;
}
static int
wspstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
wspstat_t *sp=psp;
wsp_info_value_t *value=pri;
gint index = pdut2index(value->pdut);
int retour=0;
if (value->status_code != 0) {
gint *key=g_malloc( sizeof(gint) );
wsp_status_code_t *sc;
*key=value->status_code ;
sc = g_hash_table_lookup(
sp->hash,
key);
if (!sc) {
g_warning("%s:%d What's Wrong, doc ?\n", __FILE__, __LINE__);
sc = g_malloc( sizeof(wsp_status_code_t) );
sc -> packets = 1;
sc -> name = NULL;
sc -> widget=NULL;
sc -> sp = sp;
g_hash_table_insert(
sp->hash,
key,
sc);
} else {
sc->packets++;
}
retour=1;
}
if (index!=0) {
sp->pdu_stats[ index ].packets++;
retour = 1;
}
return retour;
}
static void
wspstat_draw(void *psp)
{
wspstat_t *sp=psp;
guint32 i;
char str[256];
guint index;
for(i=1;i<=sp->num_pdus ; i++)
{
sprintf(str, "%9d", sp->pdu_stats[i ].packets);
gtk_label_set( GTK_LABEL(sp->pdu_stats[i].widget), str);
}
index=sp->index;
g_hash_table_foreach( sp->hash, (GHFunc) wsp_draw_statuscode, str );
if (index != sp->index){
/* We have inserted a new entry corresponding to a status code ,
* let's resize the table */
gtk_table_resize ( GTK_TABLE(sp->table_status_code), sp->index % 2 , 4);
}
}
/* since the gtk2 implementation of tap is multithreaded we must protect
* remove_tap_listener() from modifying the list while draw_tap_listener()
* is running. the other protected block is in main.c
*
* there should not be any other critical regions in gtk2
*/
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
static void
win_destroy_cb(GtkWindow *win _U_, gpointer data)
{
wspstat_t *sp=(wspstat_t *)data;
protect_thread_critical_region();
remove_tap_listener(sp);
unprotect_thread_critical_region();
g_free(sp->pdu_stats);
g_free(sp->filter);
g_hash_table_foreach( sp->hash, (GHFunc)wsp_free_hash, NULL);
g_hash_table_destroy( sp->hash);
g_free(sp);
}
static void
add_table_entry(wspstat_t *sp, char *str, int x, int y, int index)
{
GtkWidget *tmp;
tmp=gtk_label_new( str );
gtk_table_attach_defaults(GTK_TABLE(sp->table_pdu_types), tmp, x, x+1, y, y+1);
gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
gtk_widget_show(tmp);
if (index != 0) {
sp->pdu_stats [index] .widget = GTK_LABEL( tmp ) ;
}
}
static void
wsp_init_table(wspstat_t *sp)
{
int pos=0;
guint32 i;
/* gchar buffer[51]; */
add_table_entry( sp, "PDU Type " , 0, pos, 0);
add_table_entry( sp, "packets " , 1, pos, 0);
add_table_entry( sp, "PDU Type " , 2, pos, 0);
add_table_entry( sp, "packets " , 3, pos, 0);
pos++;
for (i=1 ; i <= sp->num_pdus ; i++ )
{
int x = 0;
if (i> (sp->num_pdus+1) /2 ){
x=2;
}
/* Maybe we should display the hexadecimal value ? */
/* snprintf(buffer, 50, "%s (0X%x)", match_strval( index2pdut( i ), vals_pdu_type), index2pdut(i) );*/
add_table_entry( sp,
match_strval(index2pdut(i), vals_pdu_type), /* or buffer, */
x,
pos,
0
);
add_table_entry( sp, "0", x+1, pos
, i /* keep a pointer to this widget to update it in _draw() */
);
pos++;
if (i== (sp->num_pdus+1) /2) {
pos=1;
}
}
}
/* When called, this function will create a new instance of gtk2-wspstat.
*/
static void
gtk_wspstat_init(char *optarg)
{
wspstat_t *sp;
char *filter=NULL;
char *title=NULL;
GString *error_string;
GtkWidget *main_vb, *pdutypes_fr, *statuscode_fr ;
guint32 i;
wsp_status_code_t *sc;
if (!strncmp (optarg, "wsp,stat,", 9)){
filter=optarg+9;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(wspstat_t) );
sp->hash = g_hash_table_new( g_int_hash, g_int_equal);
for (i=0 ; vals_status[i].strptr ; i++ )
{
gint *key;
sc=g_malloc( sizeof(wsp_status_code_t) );
key=g_malloc( sizeof(gint) );
sc->name=vals_status[i].strptr;
sc->packets=0;
sc->widget=NULL;
sc->sp = sp;
*key=vals_status[i].value;
g_hash_table_insert(
sp->hash,
key,
sc);
}
sp->num_pdus = 16;
sp->pdu_stats=g_malloc( (sp->num_pdus+1) * sizeof( wsp_pdu_t) );
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
title=g_strdup_printf("WSP Stats with filter: %s", filter);
} else {
sp->filter=NULL;
title=g_strdup("WSP Stats");
}
for (i=0;i<=sp->num_pdus; i++)
{
sp->pdu_stats[i].packets=0;
}
sp->win = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_title( GTK_WINDOW(sp->win), title );
g_free(title);
SIGNAL_CONNECT( sp->win, "destroy", win_destroy_cb, sp);
/* container for the two frames */
main_vb = gtk_vbox_new(FALSE, 10);
gtk_container_border_width(GTK_CONTAINER(main_vb), 10);
gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
gtk_widget_show(main_vb);
/* PDU Types frame */
pdutypes_fr = gtk_frame_new("Summary of PDU Types (wsp.pdu_type)");
gtk_container_add(GTK_CONTAINER(main_vb), pdutypes_fr);
gtk_widget_show(pdutypes_fr);
sp->table_pdu_types = gtk_table_new( (sp->num_pdus+1) / 2 + 1, 4, FALSE);
gtk_container_add( GTK_CONTAINER( pdutypes_fr), sp->table_pdu_types);
gtk_container_set_border_width( GTK_CONTAINER(sp->table_pdu_types) , 10);
wsp_init_table(sp);
gtk_widget_show( sp->table_pdu_types );
/* Status Codes frame */
statuscode_fr = gtk_frame_new("Summary of Status Code (wsp.reply.status)");
gtk_container_add(GTK_CONTAINER(main_vb), statuscode_fr);
gtk_widget_show(statuscode_fr);
sp->table_status_code = gtk_table_new( 0, 4, FALSE);
gtk_container_add( GTK_CONTAINER( statuscode_fr), sp->table_status_code);
gtk_container_set_border_width( GTK_CONTAINER(sp->table_status_code) , 10);
sp->index = 0; /* No answers to display yet */
error_string = register_tap_listener(
"wsp",
sp,
filter,
wspstat_reset,
wspstat_packet,
wspstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
simple_dialog( ESD_TYPE_WARN, NULL, error_string->str );
g_free(sp->pdu_stats);
g_free(sp->filter);
g_free(sp);
g_string_free(error_string, TRUE);
return ;
}
gtk_widget_show_all( sp->win );
redissect_packets(&cfile);
}
static void
wspstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
{
char *filter;
char str[256];
filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
if(filter[0]==0){
gtk_wspstat_init("wsp,stat,");
} else {
sprintf(str, "wsp,stat,%s", filter);
gtk_wspstat_init(str);
}
}
static void
dlg_destroy_cb(void)
{
dlg=NULL;
}
static void
gtk_wspstat_cb(GtkWidget *w _U_, gpointer d _U_)
{
/* if the window is already open, bring it to front */
if(dlg){
gdk_window_raise(dlg->window);
return;
}
dlg=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(dlg), "WSP Statistics");
SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
dlg_box=gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
gtk_widget_show(dlg_box);
/* filter box */
filter_box=gtk_hbox_new(FALSE, 10);
/* Filter label */
gtk_container_set_border_width(GTK_CONTAINER(filter_box), 10);
filter_label=gtk_label_new("Filter:");
gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
gtk_widget_show(filter_label);
filter_entry=gtk_entry_new_with_max_length(250);
gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, FALSE, FALSE, 0);
gtk_widget_show(filter_entry);
gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
gtk_widget_show(filter_box);
/* the start button */
start_button=gtk_button_new_with_label("Create Stat");
SIGNAL_CONNECT_OBJECT(start_button, "clicked",
wspstat_start_button_clicked, NULL);
gtk_box_pack_start(GTK_BOX(dlg_box), start_button, TRUE, TRUE, 0);
gtk_widget_show(start_button);
gtk_widget_show_all(dlg);
}
void
register_tap_listener_gtkwspstat(void)
{
register_ethereal_tap("wsp,stat,", gtk_wspstat_init);
}
void
register_tap_menu_gtkwspstat(void)
{
register_tap_menu_item("Watch protocol/WAP-WSP", gtk_wspstat_cb);
}

View File

@ -2,7 +2,7 @@
* Routines for BOOTP/DHCP packet disassembly
* Gilbert Ramirez <gram@alumni.rice.edu>
*
* $Id: packet-bootp.c,v 1.74 2003/07/29 00:35:55 guy Exp $
* $Id: packet-bootp.c,v 1.75 2003/09/02 22:47:57 guy Exp $
*
* The information used comes from:
* RFC 951: Bootstrap Protocol
@ -46,6 +46,9 @@
#include <epan/packet.h>
#include "packet-arp.h"
#include "tap.h"
static int bootp_dhcp_tap = -1;
static int proto_bootp = -1;
static int hf_bootp_type = -1;
static int hf_bootp_hw_type = -1;
@ -1341,6 +1344,7 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (tree)
proto_tree_add_boolean_hidden(bp_tree, hf_bootp_dhcp,
tvb, 0, 0, 1);
tap_queue_packet( bootp_dhcp_tap, pinfo, (gpointer) dhcp_type);
}
/*
@ -1475,6 +1479,7 @@ proto_register_bootp(void)
"bootp");
proto_register_field_array(proto_bootp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
bootp_dhcp_tap = register_tap("bootp");
}
void

View File

@ -6,7 +6,7 @@
* Copyright 2002, Tim Potter <tpot@samba.org>
* Copyright 1999, Andrew Tridgell <tridge@samba.org>
*
* $Id: packet-http.c,v 1.65 2003/06/11 04:25:30 guy Exp $
* $Id: packet-http.c,v 1.66 2003/09/02 22:47:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -48,12 +48,17 @@ typedef enum _http_type {
HTTP_OTHERS
} http_type_t;
#include "tap.h"
static int http_tap = -1;
static int proto_http = -1;
static int hf_http_notification = -1;
static int hf_http_response = -1;
static int hf_http_request = -1;
static int hf_http_basic = -1;
static int hf_http_request_method = -1;
static int hf_http_response_method = -1;
static gint ett_http = -1;
static gint ett_http_ntlmssp = -1;
@ -91,6 +96,7 @@ static heur_dissector_list_t heur_subdissector_list;
static dissector_handle_t ntlmssp_handle=NULL;
/* Return a tvb that contains the binary representation of a base64
string */
@ -189,6 +195,8 @@ check_auth(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
return FALSE;
}
/* TODO: remove this ugly global variable */
http_info_value_t *stat_info;
static void
dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -210,6 +218,10 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
int req_strlen;
proto_tree *req_tree;
stat_info =g_malloc( sizeof(http_info_value_t));
stat_info->response_method = 0;
stat_info->request_method = NULL;
switch (pinfo->match_port) {
case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
@ -429,6 +441,8 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
http_tree);
}
}
tap_queue_packet( http_tap, pinfo, stat_info) ;
}
/* This can be used to dissect an HTTP request until such time
@ -440,6 +454,18 @@ basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int req_strlen)
{
proto_tree_add_item(tree, hf_http_request_method, tvb, 0, req_strlen, FALSE);
}
static void
response_method_request_dissector(tvbuff_t *tvb, proto_tree *tree, int req_strlen _U_ )
{
const guchar *data;
int minor, major, status_code;
data = tvb_get_ptr(tvb, 0, 12);
if (sscanf(data, "HTTP/%d.%d %d", &minor, &major, &status_code)==3)
{
proto_tree_add_uint(tree, hf_http_response_method, tvb, 9, 3, status_code);
stat_info->response_method = status_code;
}
}
/*
@ -473,8 +499,14 @@ is_http_request_or_reply(const guchar *data, int linelen, http_type_t *type,
* SEARCH
*/
if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
*type = HTTP_RESPONSE;
isHttpRequestOrReply = TRUE; /* response */
if (req_dissector && (linelen >= 12) )
{
*req_dissector = response_method_request_dissector ;
*req_strlen = 3;
} else
if (req_dissector) {
*req_dissector = NULL; /* no dissector for this yet. */
}
@ -587,6 +619,12 @@ is_http_request_or_reply(const guchar *data, int linelen, http_type_t *type,
*req_dissector = basic_request_dissector;
*req_strlen = index + prefix_len;
}
if (isHttpRequestOrReply && req_dissector) {
if (!stat_info->request_method)
stat_info->request_method = g_malloc( index+1 );
strncpy( stat_info->request_method, data, index);
stat_info->request_method[index] = '\0';
}
}
return isHttpRequestOrReply;
@ -615,6 +653,10 @@ proto_register_http(void)
{ "Request Method", "http.request.method",
FT_STRING, BASE_NONE, NULL, 0x0,
"HTTP Request Method", HFILL }},
{ &hf_http_response_method,
{ "Response Method", "http.response.method",
FT_UINT16, BASE_DEC, NULL, 0x0,
"HTTP Response Method", HFILL }},
};
static gint *ett[] = {
&ett_http,
@ -650,6 +692,10 @@ proto_register_http(void)
register_heur_dissector_list("http",&heur_subdissector_list);
/*
* Register for tapping
*/
http_tap = register_tap("http");
}
/*

View File

@ -1,6 +1,6 @@
/* packet-http.h
*
* $Id: packet-http.h,v 1.7 2002/08/28 21:00:16 jmayer Exp $
* $Id: packet-http.h,v 1.8 2003/09/02 22:47:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -23,7 +23,13 @@
#ifndef __PACKET_HTTP_H__
#define __PACKET_HTTP_H__
#include <epan/packet.h>
void http_dissector_add(guint32 port, dissector_handle_t handle);
typedef struct _http_info_value_t
{
guint response_method;
gchar *request_method;
} http_info_value_t ;
#endif

View File

@ -2,7 +2,7 @@
*
* Routines to dissect WSP component of WAP traffic.
*
* $Id: packet-wsp.c,v 1.74 2003/08/04 23:36:12 guy Exp $
* $Id: packet-wsp.c,v 1.75 2003/09/02 22:47:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -47,6 +47,10 @@
#include "packet-wap.h"
#include "packet-wsp.h"
/* Statistics (see doc/README.tapping) */
#include "tap.h"
static int wsp_tap = -1;
/* File scoped variables for the protocol and registered fields */
static int proto_wsp = HF_EMPTY;
@ -221,7 +225,7 @@ static dissector_handle_t wtp_fromudp_handle;
/* Handle for WBXML dissector */
static dissector_handle_t wbxml_handle;
static const value_string vals_pdu_type[] = {
const value_string vals_pdu_type[] = {
{ 0x00, "Reserved" },
{ 0x01, "Connect" },
{ 0x02, "ConnectReply" },
@ -288,7 +292,7 @@ static const value_string vals_pdu_type[] = {
};
static const value_string vals_status[] = {
const value_string vals_status[] = {
/* 0x00 - 0x0F Reserved */
{ 0x10, "Continue" },
@ -1282,6 +1286,10 @@ dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *wsp_tree = NULL;
/* proto_tree *wsp_header_fixed; */
wsp_info_value_t *stat_info;
stat_info = g_malloc( sizeof(wsp_info_value_t) );
stat_info->status_code = 0;
/* This field shows up as the "Info" column in the display; you should make
it, if possible, summarize what's in the packet, so that a user looking
at the list of packets can tell what type of packet it is. */
@ -1473,6 +1481,7 @@ dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (tree) {
reply_status = tvb_get_guint8(tvb, offset);
ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
stat_info->status_code = (gint) tvb_get_guint8( tvb, offset);
if (check_col(pinfo->cinfo, COL_INFO))
{ /* Append status code to INFO column */
col_append_fstr(pinfo->cinfo, COL_INFO, ": \"0x%02x %s\"", reply_status,
@ -1554,6 +1563,8 @@ dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
}
stat_info->pdut = pdut ;
tap_queue_packet (wsp_tap, pinfo, stat_info);
}
/*
@ -5214,6 +5225,11 @@ proto_register_wsp(void)
< URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
*/
);
wsp_tap = register_tap("wsp");
/* Init the hash table */
/* wsp_sessions = g_hash_table_new(
(GHashFunc) wsp_session_hash,
(GEqualFunc)wsp_session_equal);*/
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_wsp, hf, array_length(hf));
@ -5227,6 +5243,8 @@ proto_register_wsp(void)
wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
proto_wsp);
};
void

View File

@ -2,7 +2,7 @@
*
* Declarations for disassembly of WSP component of WAP traffic.
*
* $Id: packet-wsp.h,v 1.7 2003/07/08 18:10:39 guy Exp $
* $Id: packet-wsp.h,v 1.8 2003/09/02 22:47:58 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -45,10 +45,20 @@
* assumed to be WSP */
extern const value_string vals_wsp_reason_codes[];
/* These are exported to taps. */
extern const value_string vals_pdu_type[];
extern const value_string vals_status[];
/*
* exported functionality
*/
void add_post_data (proto_tree *, tvbuff_t *, guint, const char *);
guint add_content_type (proto_tree *, tvbuff_t *, guint, guint *, const char **);
/* statistics */
typedef struct _wsp_info_value_t /* see README.tapping and tap-wspstat.c */
{
gint status_code;
guint8 pdut;
} wsp_info_value_t;
#endif /* packet-wsp.h */

186
tap-bootpstat.c Normal file
View File

@ -0,0 +1,186 @@
/* tap-bootpstat.c
* boop_stat 2003 Jean-Michel FAYARD
*
* $Id: tap-bootpstat.c,v 1.1 2003/09/02 22:47:58 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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>
#include "epan/packet_info.h"
#include "tap.h"
#include "register.h"
#include <string.h>
typedef const char* bootp_info_value_t;
/* used to keep track of the statictics for an entire program interface */
typedef struct _dhcp_stats_t {
char *filter;
GHashTable *hash;
guint index; /* Number of to display */
} dhcpstat_t;
/* used to keep track of a single DHCP message type */
typedef struct _dhcp_message_type_t {
const char *name;
guint32 packets;
dhcpstat_t *sp; /* entire program interface */
} dhcp_message_type_t;
/* Not used anywhere at this moment */
/*
static void
dhcp_free_hash( gpointer key _U_ , gpointer value, gpointer user_data _U_ )
{
g_free(value);
}
*/
static void
dhcp_reset_hash(gchar *key _U_ , dhcp_message_type_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
/* Update the entry corresponding to the number of packets of a special DHCP Message Type
* or create it if it don't exist.
*/
static void
dhcp_draw_message_type(gchar *key _U_, dhcp_message_type_t *data, gchar * format )
{
if ((data==NULL) || (data->packets==0))
return;
printf( format, data->name, data->packets);
}
static void
dhcpstat_reset(void *psp)
{
dhcpstat_t *sp=psp;
g_hash_table_foreach( sp->hash, (GHFunc)dhcp_reset_hash, NULL);
}
static int
dhcpstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
dhcpstat_t *sp=psp;
bootp_info_value_t value=pri;
dhcp_message_type_t *sc;
if (sp==NULL)
return 0;
sc = g_hash_table_lookup(
sp->hash,
value);
if (!sc) {
sc = g_malloc( sizeof(dhcp_message_type_t) );
sc -> packets = 1;
sc -> name = value;
sc -> sp = sp;
g_hash_table_insert(
sp->hash,
(gpointer) value,
sc);
} else {
/*g_warning("sc(%s)->packets++", sc->name);*/
sc->packets++;
}
return 1;
}
static void
dhcpstat_draw(void *psp)
{
dhcpstat_t *sp=psp;
printf("\n");
printf("===================================================================\n");
if (sp->filter==NULL)
printf("BOOTP Statistics\n");
else
printf("BOOTP Statistics with filter %s\n", sp->filter);
printf("BOOTP Option 53: DHCP Messages Types:\n");
printf("DHCP Message Type Packets nb\n" );
g_hash_table_foreach( sp->hash, (GHFunc) dhcp_draw_message_type,
"%23s %-9d\n" );
printf("===================================================================\n");
}
/* When called, this function will create a new instance of tap-boopstat.
*/
static void
dhcpstat_init(char *optarg)
{
dhcpstat_t *sp;
char *filter=NULL;
GString *error_string;
if (!strncmp (optarg, "bootp,stat,", 11)){
filter=optarg+11;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(dhcpstat_t) );
sp->hash = g_hash_table_new( g_str_hash, g_str_equal);
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
} else {
sp->filter=NULL;
}
sp->index = 0; /* Nothing to display yet */
error_string = register_tap_listener(
"bootp",
sp,
filter,
dhcpstat_reset,
dhcpstat_packet,
dhcpstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
g_free(sp->filter);
g_free(sp);
fprintf(stderr, "tethereal: Couldn't register dhcp,stat tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}
}
void
register_tap_listener_gtkdhcpstat(void)
{
register_ethereal_tap("bootp,stat,", dhcpstat_init);
}

329
tap-httpstat.c Normal file
View File

@ -0,0 +1,329 @@
/* tap-httpstat.c
* tap-httpstat 2003 Jean-Michel FAYARD
*
* $Id: tap-httpstat.c,v 1.1 2003/09/02 22:47:58 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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>
#include "epan/packet_info.h"
#include "epan/value_string.h"
#include "tap.h"
#include "register.h"
#include "packet-http.h"
#include <string.h>
/* used to keep track of the statictics for an entire program interface */
typedef struct _http_stats_t {
char *filter;
GHashTable *hash_responses;
GHashTable *hash_requests;
} httpstat_t;
/* used to keep track of the stats for a specific response code
* for example it can be { 3, 404, "Not Found" ,...}
* which means we captured 3 reply http/1.1 404 Not Found */
typedef struct _http_response_methode_t {
guint32 packets; /* 3 */
guint response_method; /* 404 */
gchar *name; /* Not Found */
httpstat_t *sp;
} http_response_methode_t;
/* used to keep track of the stats for a specific request string */
typedef struct _http_request_methode_t {
gchar *response; /* eg. : GET */
guint32 packets;
httpstat_t *sp;
} http_request_methode_t;
static const value_string vals_status_code[] = {
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 199, "Informational - Others" },
{ 200, "OK"},
{ 201, "Created"},
{ 202, "Accepted"},
{ 203, "Non-authoritative Information"},
{ 204, "No Content"},
{ 205, "Reset Content"},
{ 206, "Partial Content"},
{ 299, "Success - Others"}, /* used to keep track of others Success packets */
{ 300, "Multiple Choices"},
{ 301, "Moved Permanently"},
{ 302, "Moved Temporarily"},
{ 303, "See Other"},
{ 304, "Not Modified"},
{ 305, "Use Proxy"},
{ 399, "Redirection - Others"},
{ 400, "Bad Request"},
{ 401, "Unauthorized"},
{ 402, "Payment Required"},
{ 403, "Forbidden"},
{ 404, "Not Found"},
{ 405, "Method Not Allowed"},
{ 406, "Not Acceptable"},
{ 407, "Proxy Authentication Required"},
{ 408, "Request Time-out"},
{ 409, "Conflict"},
{ 410, "Gone"},
{ 411, "Length Required"},
{ 412, "Precondition Failed"},
{ 413, "Request Entity Too Large"},
{ 414, "Request-URI Too Large"},
{ 415, "Unsupported Media Type"},
{ 499, "Client Error - Others"},
{ 500, "Internal Server Error"},
{ 501, "Not Implemented"},
{ 502, "Bad Gateway"},
{ 503, "Service Unavailable"},
{ 504, "Gateway Time-out"},
{ 505, "HTTP Version not supported"},
{ 599, "Server Error - Others"},
{ 0, NULL}
} ;
/* insert some entries */
static void
http_init_hash( httpstat_t *sp)
{
int i;
sp->hash_responses = g_hash_table_new( g_int_hash, g_int_equal);
for (i=0 ; vals_status_code[i].strptr ; i++ )
{
gint *key = g_malloc (sizeof(gint));
http_response_methode_t *sc = g_malloc (sizeof(http_response_methode_t));
*key = vals_status_code[i].value;
sc->packets=0;
sc->response_method = *key;
sc->name=vals_status_code[i].strptr;
sc->sp = sp;
g_hash_table_insert( sc->sp->hash_responses, key, sc);
}
sp->hash_requests = g_hash_table_new( g_str_hash, g_str_equal);
}
static void
http_draw_hash_requests( gchar *key _U_ , http_request_methode_t *data, gchar * format)
{
if (data->packets==0)
return;
printf( format, data->response, data->packets);
}
static void
http_draw_hash_responses( gint * key _U_ , http_response_methode_t *data, char * format)
{
if (data==NULL){
g_warning("C'est quoi ce borderl key=%d\n", *key);
exit(EXIT_FAILURE);
}
if (data->packets==0)
return;
/* " HTTP %3d %-35s %9d packets", */
printf(format, data->response_method, data->name, data->packets );
}
/* NOT USED at this moment */
/*
static void
http_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
{
g_free(key);
g_free(value);
}
*/
static void
http_reset_hash_responses(gchar *key _U_ , http_response_methode_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
static void
http_reset_hash_requests(gchar *key _U_ , http_request_methode_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
static void
httpstat_reset(void *psp )
{
httpstat_t *sp=psp;
if (!sp) {
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_reset_hash_responses, NULL);
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_reset_hash_requests, NULL);
}
}
static int
httpstat_packet(void *psp , packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
http_info_value_t *value=pri;
httpstat_t *sp=(httpstat_t *) psp;
/* We are only interested in reply packets with a status code */
/* Request or reply packets ? */
if (value->response_method!=0) {
guint *key=g_malloc( sizeof(guint) );
http_response_methode_t *sc;
*key=value->response_method ;
sc = g_hash_table_lookup(
sp->hash_responses,
key);
if (sc==NULL){
/* non standard status code ; we classify it as others
* in the relevant category (Informational,Success,Redirection,Client Error,Server Error)
*/
int i = value->response_method;
if ((i<100) || (i>=600)) {
return 0;
}
else if (i<200){
*key=199; /* Hopefully, this status code will never be used */
}
else if (i<300){
*key=299;
}
else if (i<400){
*key=399;
}
else if (i<500){
*key=499;
}
else{
*key=599;
}
sc = g_hash_table_lookup(
sp->hash_responses,
key);
if (sc==NULL)
return 0;
}
sc->packets++;
}
else if (value->request_method){
http_request_methode_t *sc;
sc = g_hash_table_lookup(
sp->hash_requests,
value->request_method);
if (sc==NULL){
sc=g_malloc( sizeof(http_request_methode_t) );
sc->response=g_strdup( value->request_method );
sc->packets=1;
sc->sp = sp;
g_hash_table_insert( sp->hash_requests, sc->response, sc);
} else {
sc->packets++;
}
} else {
return 0;
}
return 1;
}
static void
httpstat_draw(void *psp )
{
httpstat_t *sp=psp;
printf("\n");
printf("===================================================================\n");
if (! sp->filter[0])
printf("HTTP Statistics\n");
else
printf("HTTP Statistics with filter %s\n", sp->filter);
printf( "* HTTP Status Codes in reply packets\n");
g_hash_table_foreach( sp->hash_responses, (GHFunc)http_draw_hash_responses,
" HTTP %3d %s\n");
printf("* List of HTTP Request methods\n");
g_hash_table_foreach( sp->hash_requests, (GHFunc)http_draw_hash_requests,
" %9s %d \n");
printf("===================================================================\n");
}
/* When called, this function will create a new instance of gtk_httpstat.
*/
static void
gtk_httpstat_init(char *optarg)
{
httpstat_t *sp;
char *filter=NULL;
GString *error_string;
if (!strncmp (optarg, "http,stat,", 10)){
filter=optarg+10;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(httpstat_t) );
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
} else {
sp->filter=NULL;
}
/*g_hash_table_foreach( http_status, (GHFunc)http_reset_hash_responses, NULL);*/
error_string = register_tap_listener(
"http",
sp,
filter,
httpstat_reset,
httpstat_packet,
httpstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
g_free(sp->filter);
g_free(sp);
fprintf (stderr, "tethereal: Coulnd't register http,stat tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}
http_init_hash(sp);
}
void
register_tap_listener_gtkhttpstat(void)
{
register_ethereal_tap("http,stat,", gtk_httpstat_init);
}

284
tap-wspstat.c Normal file
View File

@ -0,0 +1,284 @@
/* tap-rpcstat.c
* wspstat 2003 Jean-Michel FAYARD
*
* $Id: tap-wspstat.c,v 1.1 2003/09/02 22:47:58 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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.
*/
/* This module provides WSP statistics to tethereal.
* It is only used by tethereal and not ethereal
*
*/
#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 "register.h"
#include "epan/value_string.h"
#include "packet-wsp.h"
/* used to keep track of the stats for a specific PDU type*/
typedef struct _wsp_pdu_t {
gchar *type;
guint32 packets;
} wsp_pdu_t;
/* used to keep track of RTT statistics */
typedef struct _wsp_status_code_t {
gchar *name;
guint32 packets;
} wsp_status_code_t;
/* used to keep track of the statictics for an entire program interface */
typedef struct _wsp_stats_t {
char *filter;
wsp_pdu_t *pdu_stats;
guint32 num_pdus;
GHashTable *hash;
} wspstat_t;
static void
wsp_reset_hash(gchar *key _U_ , wsp_status_code_t *data, gpointer ptr _U_ )
{
data->packets = 0;
}
static void
wsp_print_statuscode(gint *key, wsp_status_code_t *data, char* format)
{
if (data && (data->packets!=0))
printf(format, *key, data->packets ,data->name);
}
static void
wsp_free_hash_table( gpointer key, gpointer value, gpointer user_data _U_ )
{
g_free(key);
g_free(value);
}
static void
wspstat_reset(void *psp)
{
wspstat_t *sp=psp;
guint32 i;
for(i=1;i<=sp->num_pdus;i++)
{
sp->pdu_stats[i].packets=0;
}
g_hash_table_foreach( sp->hash, (GHFunc)wsp_reset_hash, NULL);
}
/* This callback is invoked whenever the tap system has seen a packet
* we might be interested in.
* The function is to be used to only update internal state information
* in the *tapdata structure, and if there were state changes which requires
* the window to be redrawn, return 1 and (*draw) will be called sometime
* later.
*
* We didnt apply a filter when we registered so we will be called for
* ALL packets and not just the ones we are collecting stats for.
*
*/
static gint
pdut2index(gint pdut)
{
if (pdut<=0x09) return pdut;
if (pdut>=0x40){
if (pdut <= 0x44){
return pdut-54;
} else if (pdut==0x60||pdut==0x61){
return pdut-81;
}
}
return 0;
}
static gint
index2pdut(gint pdut)
{
if (pdut<=0x09)
return pdut;
if (pdut<=14)
return pdut+54;
if (pdut<=16)
return pdut+81;
return 0;
}
static int
wspstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
{
wspstat_t *sp=psp;
wsp_info_value_t *value=pri;
gint index = pdut2index(value->pdut);
int retour=0;
if (value->status_code != 0) {
gint *key=g_malloc( sizeof(gint) );
wsp_status_code_t *sc;
*key=value->status_code ;
sc = g_hash_table_lookup(
sp->hash,
key);
if (!sc) {
sc = g_malloc( sizeof(wsp_status_code_t) );
sc -> packets = 1;
sc -> name = NULL;
g_hash_table_insert(
sp->hash,
key,
sc);
} else {
sc->packets++;
}
retour=1;
}
if (index!=0) {
sp->pdu_stats[ index ].packets++;
retour = 1;
}
return retour;
}
/* This callback is used when tethereal wants us to draw/update our
* data to the output device. Since this is tethereal only output is
* stdout.
* Tethereal will only call this callback once, which is when tethereal has
* finished reading all packets and exists.
* If used with ethereal this may be called any time, perhaps once every 3
* seconds or so.
* This function may even be called in parallell with (*reset) or (*draw)
* so make sure there are no races. The data in the rpcstat_t can thus change
* beneath us. Beware.
*/
static void
wspstat_draw(void *psp)
{
wspstat_t *sp=psp;
guint32 i;
printf("\n");
printf("===================================================================\n");
printf("WSP Statistics:\n");
printf("%-23s %9s || %-23s %9s\n","PDU Type", "Packets", "PDU Type", "Packets");
for(i=1; i<= ((sp->num_pdus+1)/2) ; i++)
{
guint32 ii=i+sp->num_pdus/2;
printf("%-23s %9d", sp->pdu_stats[i ].type, sp->pdu_stats[i ].packets);
printf(" || ");
if (ii< (sp->num_pdus) )
printf("%-23s %9d\n", sp->pdu_stats[ii].type, sp->pdu_stats[ii].packets);
else
printf("\n");
}
printf("\nStatus code in reply packets\n");
printf( "Status Code Packets Description\n");
g_hash_table_foreach( sp->hash, (GHFunc) wsp_print_statuscode,
"%11d %9d %s\n" ) ;
printf("===================================================================\n");
}
/* When called, this function will create a new instance of wspstat.
* program and version are whick onc-rpc program/version we want to
* collect statistics for.
* This function is called from tethereal when it parses the -Z wsp, arguments
* and it creates a new instance to store statistics in and registers this
* new instance for the wsp tap.
*/
static void
wspstat_init(char *optarg)
{
wspstat_t *sp;
char *filter=NULL;
guint32 i;
GString *error_string;
wsp_status_code_t *sc;
if (!strncmp (optarg, "wsp,stat," , 9)){
filter=optarg+9;
} else {
filter=NULL;
}
sp = g_malloc( sizeof(wspstat_t) );
sp->hash = g_hash_table_new( g_int_hash, g_int_equal);
for (i=0 ; vals_status[i].strptr ; i++ )
{
gint *key;
sc=g_malloc( sizeof(wsp_status_code_t) );
key=g_malloc( sizeof(gint) );
sc->packets=0;
sc->name=vals_status[i].strptr;
*key=vals_status[i].value;
g_hash_table_insert(
sp->hash,
key,
sc);
}
sp->num_pdus = 16;
sp->pdu_stats=g_malloc( (sp->num_pdus+1) * sizeof( wsp_pdu_t) );
if(filter){
sp->filter=g_malloc(strlen(filter)+1);
strcpy(sp->filter,filter);
} else {
sp->filter=NULL;
}
for (i=0;i<sp->num_pdus; i++)
{
sp->pdu_stats[i].packets=0;
sp->pdu_stats[i].type = match_strval( index2pdut( i ), vals_pdu_type) ;
}
error_string = register_tap_listener(
"wsp",
sp,
filter,
wspstat_reset,
wspstat_packet,
wspstat_draw);
if (error_string){
/* error, we failed to attach to the tap. clean up */
g_free(sp->pdu_stats);
g_free(sp->filter);
g_free(sp);
g_hash_table_foreach( sp->hash, (GHFunc) wsp_free_hash_table, NULL ) ;
g_hash_table_destroy( sp->hash );
fprintf(stderr, "tethereal: Couldn't register wsp,stat tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}
}
void
register_tap_listener_wspstat(void)
{
register_ethereal_tap("wsp,stat,", wspstat_init);
}