forked from osmocom/wireshark
From Jean-Michel Fayard: BOOTP/DHCP, HTTP, and WSP statistics taps.
svn path=/trunk/; revision=8345
This commit is contained in:
parent
71034c5a3f
commit
75ae0e30c7
1
AUTHORS
1
AUTHORS
|
@ -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:
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
24
packet-wsp.c
24
packet-wsp.c
|
@ -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
|
||||
|
|
12
packet-wsp.h
12
packet-wsp.h
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue