2005-07-17 23:12:12 +00:00
|
|
|
/* flow_graph.c
|
2006-02-11 13:05:24 +00:00
|
|
|
* $Id$
|
2005-07-17 23:12:12 +00:00
|
|
|
* Allows to display a flow graph of the currently displayed packets
|
|
|
|
*
|
|
|
|
* Copyright 2004, Ericsson , Spain
|
|
|
|
* By Francisco Alcoba <francisco.alcoba@ericsson.com>
|
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2005-07-17 23:12:12 +00:00
|
|
|
* 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
|
2008-04-13 01:54:20 +00:00
|
|
|
#include <string.h>
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-04-13 01:54:20 +00:00
|
|
|
#include <gtk/gtk.h>
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-04-13 01:54:20 +00:00
|
|
|
#include <epan/epan.h>
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/filesystem.h>
|
2005-08-20 20:06:05 +00:00
|
|
|
#include <epan/stat_cmd_args.h>
|
2005-07-17 23:12:12 +00:00
|
|
|
#include <epan/to_str.h>
|
|
|
|
#include <epan/tap.h>
|
|
|
|
#include <epan/dissectors/packet-tcp.h>
|
2008-03-01 10:23:57 +00:00
|
|
|
#include <epan/strutil.h>
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-04-13 01:54:20 +00:00
|
|
|
#include "../stat_menu.h"
|
2012-01-16 01:07:52 +00:00
|
|
|
#include "ui/simple_dialog.h"
|
2008-04-13 01:54:20 +00:00
|
|
|
|
2012-01-15 21:59:11 +00:00
|
|
|
#include "ui/gtk/graph_analysis.h"
|
|
|
|
#include "ui/gtk/gui_stat_menu.h"
|
|
|
|
#include "ui/gtk/dlg_utils.h"
|
|
|
|
#include "ui/gtk/gui_utils.h"
|
|
|
|
#include "ui/gtk/stock_icons.h"
|
|
|
|
#include "ui/gtk/gtkglobals.h"
|
|
|
|
#include "ui/gtk/main.h"
|
2008-04-13 01:54:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
#define TYPE_OF_PACKETS_DISPLAYED 0
|
|
|
|
#define TYPE_OF_PACKETS_ALL 1
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
#define TYPE_OF_FLOW_GENERAL 0
|
|
|
|
#define TYPE_OF_FLOW_TCP 1
|
|
|
|
|
|
|
|
#define NODE_ADDR_TYPE_SRCDST 0
|
|
|
|
#define NODE_ADDR_TYPE_NET_SRCDST 1
|
|
|
|
|
|
|
|
static int type_of_packets = TYPE_OF_PACKETS_DISPLAYED;
|
|
|
|
static int type_of_flow = TYPE_OF_FLOW_GENERAL;
|
|
|
|
static int node_addr_type = NODE_ADDR_TYPE_SRCDST;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
static int tap_identifier;
|
|
|
|
static gboolean have_frame_tap_listener=FALSE;
|
|
|
|
static gboolean have_tcp_tap_listener=FALSE;
|
|
|
|
static graph_analysis_info_t *graph_analysis = NULL;
|
2010-08-12 01:54:10 +00:00
|
|
|
static graph_analysis_data_t *graph_analysis_data = NULL;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
static GtkWidget *flow_graph_dlg = NULL;
|
|
|
|
|
|
|
|
static GtkWidget *select_all_rb;
|
|
|
|
static GtkWidget *select_displayed_rb;
|
|
|
|
static GtkWidget *select_general_rb;
|
|
|
|
static GtkWidget *select_tcp_rb;
|
2005-12-16 07:20:13 +00:00
|
|
|
static GtkWidget *src_dst_rb;
|
|
|
|
static GtkWidget *net_src_dst_rb;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* free up memory and initialize the pointers */
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
static void
|
|
|
|
flow_graph_reset(void *ptr _U_)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
|
|
|
graph_analysis_item_t *graph_item;
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2005-07-17 23:12:12 +00:00
|
|
|
GList* list;
|
|
|
|
|
|
|
|
if (graph_analysis !=NULL){
|
|
|
|
|
|
|
|
/* free the graph data items */
|
|
|
|
list = g_list_first(graph_analysis->list);
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
graph_item = list->data;
|
|
|
|
g_free(graph_item->frame_label);
|
|
|
|
g_free(graph_item->comment);
|
|
|
|
g_free(list->data);
|
|
|
|
list = g_list_next(list);
|
|
|
|
}
|
|
|
|
g_list_free(graph_analysis->list);
|
|
|
|
graph_analysis->nconv = 0;
|
|
|
|
graph_analysis->list = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
2010-08-12 01:54:10 +00:00
|
|
|
static void
|
|
|
|
flow_graph_data_init(void) {
|
2005-07-17 23:12:12 +00:00
|
|
|
graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
|
|
|
|
graph_analysis->nconv = 0;
|
|
|
|
graph_analysis->list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
2005-08-20 14:02:00 +00:00
|
|
|
static void
|
2005-07-17 23:12:12 +00:00
|
|
|
remove_tap_listener_flow_graph(void)
|
|
|
|
{
|
|
|
|
protect_thread_critical_region();
|
|
|
|
remove_tap_listener(&(tap_identifier));
|
|
|
|
unprotect_thread_critical_region();
|
|
|
|
|
|
|
|
have_frame_tap_listener=FALSE;
|
|
|
|
have_tcp_tap_listener=FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* CALLBACKS */
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
2011-08-16 10:35:42 +00:00
|
|
|
flow_graph_on_destroy(GObject *object _U_, gpointer user_data _U_)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
|
|
|
/* remove_tap_listeners */
|
|
|
|
remove_tap_listener_flow_graph();
|
|
|
|
|
|
|
|
/* Clean up memory used by tap */
|
|
|
|
flow_graph_reset(NULL);
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
g_assert(graph_analysis != NULL);
|
|
|
|
g_assert(graph_analysis_data != NULL);
|
|
|
|
|
|
|
|
g_free(graph_analysis);
|
|
|
|
graph_analysis = NULL;
|
|
|
|
|
|
|
|
g_free(graph_analysis_data);
|
|
|
|
graph_analysis_data = NULL;
|
|
|
|
|
2005-07-17 23:12:12 +00:00
|
|
|
/* Note that we no longer have a "Flow Graph" dialog box. */
|
|
|
|
flow_graph_dlg = NULL;
|
|
|
|
}
|
|
|
|
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2005-07-17 23:12:12 +00:00
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_all(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-07-17 23:12:12 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_all_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
type_of_packets = TYPE_OF_PACKETS_ALL;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_displayed(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-07-17 23:12:12 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_displayed_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
type_of_packets = TYPE_OF_PACKETS_DISPLAYED;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_general(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-07-17 23:12:12 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_general_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
type_of_flow = TYPE_OF_FLOW_GENERAL;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_tcp(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-07-17 23:12:12 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_tcp_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
type_of_flow = TYPE_OF_FLOW_TCP;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-16 07:20:13 +00:00
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_srcdst(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-12-16 07:20:13 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(src_dst_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
node_addr_type = NODE_ADDR_TYPE_SRCDST;
|
2005-12-16 07:20:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
toggle_select_netsrcdst(GtkWidget *widget _U_, gpointer user_data _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* is the button now active? */
|
2005-12-16 07:20:13 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(net_src_dst_rb))) {
|
2010-08-12 01:54:10 +00:00
|
|
|
node_addr_type = NODE_ADDR_TYPE_NET_SRCDST;
|
2005-12-16 07:20:13 +00:00
|
|
|
}
|
|
|
|
}
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Add a new frame into the graph */
|
2010-08-12 01:54:10 +00:00
|
|
|
static int
|
|
|
|
flow_graph_frame_add_to_graph(packet_info *pinfo)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
|
|
|
graph_analysis_item_t *gai;
|
|
|
|
int i;
|
2006-01-07 11:10:50 +00:00
|
|
|
gchar *protocol;
|
|
|
|
gchar *colinfo;
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2006-01-07 11:10:50 +00:00
|
|
|
protocol=NULL;
|
|
|
|
colinfo=NULL;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
2006-03-14 05:49:15 +00:00
|
|
|
if (pinfo->net_src.type!=AT_NONE && pinfo->net_dst.type!=AT_NONE) {
|
|
|
|
gai = g_malloc(sizeof(graph_analysis_item_t));
|
|
|
|
COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src));
|
|
|
|
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst));
|
|
|
|
}
|
|
|
|
else return 0;
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2006-01-07 11:10:50 +00:00
|
|
|
} else {
|
2006-03-14 05:49:15 +00:00
|
|
|
if (pinfo->src.type!=AT_NONE && pinfo->dst.type!=AT_NONE) {
|
|
|
|
gai = g_malloc(sizeof(graph_analysis_item_t));
|
|
|
|
COPY_ADDRESS(&(gai->src_addr),&(pinfo->src));
|
|
|
|
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst));
|
|
|
|
}
|
|
|
|
else return 0;
|
2006-01-07 11:10:50 +00:00
|
|
|
}
|
2006-03-14 05:49:15 +00:00
|
|
|
|
2011-09-13 12:39:11 +00:00
|
|
|
gai->fd = pinfo->fd;
|
2006-03-14 05:49:15 +00:00
|
|
|
|
2005-07-17 23:12:12 +00:00
|
|
|
gai->port_src=pinfo->srcport;
|
|
|
|
gai->port_dst=pinfo->destport;
|
|
|
|
gai->comment=NULL;
|
|
|
|
gai->frame_label=NULL;
|
|
|
|
|
2009-03-13 22:06:48 +00:00
|
|
|
/* this code doesn't make sense.
|
|
|
|
g_free(gai->comment);
|
|
|
|
g_free(gai->frame_label);
|
|
|
|
*/
|
2006-01-07 11:10:50 +00:00
|
|
|
|
2006-12-01 02:55:45 +00:00
|
|
|
if(pinfo->cinfo) {
|
|
|
|
if (pinfo->cinfo->col_first[COL_INFO]>=0){
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2006-12-01 02:55:45 +00:00
|
|
|
for (i = pinfo->cinfo->col_first[COL_INFO]; i <= pinfo->cinfo->col_last[COL_INFO]; i++) {
|
|
|
|
if (pinfo->cinfo->fmt_matx[i][COL_INFO]) {
|
|
|
|
colinfo = g_strdup(pinfo->cinfo->col_data[i]);
|
2009-03-13 22:06:48 +00:00
|
|
|
/* break; ? or g_free(colinfo); before g_strdup() */
|
2006-12-01 02:55:45 +00:00
|
|
|
}
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2006-12-01 02:55:45 +00:00
|
|
|
if (pinfo->cinfo->col_first[COL_PROTOCOL]>=0){
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2006-12-01 02:55:45 +00:00
|
|
|
for (i = pinfo->cinfo->col_first[COL_PROTOCOL]; i <= pinfo->cinfo->col_last[COL_PROTOCOL]; i++) {
|
|
|
|
if (pinfo->cinfo->fmt_matx[i][COL_PROTOCOL]) {
|
|
|
|
protocol = g_strdup(pinfo->cinfo->col_data[i]);
|
2009-03-13 22:06:48 +00:00
|
|
|
/* break; ? or g_free(protocol); before g_strdup() */
|
2006-12-01 02:55:45 +00:00
|
|
|
}
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-12-01 02:55:45 +00:00
|
|
|
|
2006-01-07 11:10:50 +00:00
|
|
|
if (colinfo != NULL) {
|
|
|
|
if (protocol != NULL) {
|
|
|
|
gai->frame_label = g_strdup_printf("%.19s", colinfo);
|
|
|
|
gai->comment = g_strdup_printf("%s: %s", protocol, colinfo);
|
|
|
|
} else {
|
|
|
|
gai->frame_label = g_strdup_printf("%.19s", colinfo);
|
|
|
|
gai->comment = g_strdup_printf("%s", colinfo);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* This will probably never happen...*/
|
|
|
|
if (protocol != NULL) {
|
|
|
|
gai->frame_label = g_strdup_printf("%.19s", protocol);
|
|
|
|
gai->comment = g_strdup_printf("%s", protocol);
|
|
|
|
}
|
|
|
|
}
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2009-03-13 22:06:48 +00:00
|
|
|
g_free(protocol);
|
|
|
|
g_free(colinfo);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
gai->line_style=1;
|
|
|
|
gai->conv_num=0;
|
|
|
|
gai->display=TRUE;
|
|
|
|
|
|
|
|
graph_analysis->list = g_list_append(graph_analysis->list, gai);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Add a new tcp frame into the graph */
|
2010-08-12 01:54:10 +00:00
|
|
|
static int
|
|
|
|
flow_graph_tcp_add_to_graph(packet_info *pinfo, const struct tcpheader *tcph)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
graph_analysis_item_t *gai;
|
|
|
|
/* copied from packet-tcp */
|
|
|
|
const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
|
|
|
|
guint i, bpos;
|
|
|
|
gboolean flags_found = FALSE;
|
|
|
|
gchar flags[64];
|
|
|
|
|
|
|
|
gai = g_malloc(sizeof(graph_analysis_item_t));
|
2011-09-13 12:39:11 +00:00
|
|
|
gai->fd = pinfo->fd;
|
2010-08-12 01:54:10 +00:00
|
|
|
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
|
|
|
COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src));
|
|
|
|
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst));
|
|
|
|
} else {
|
|
|
|
COPY_ADDRESS(&(gai->src_addr),&(pinfo->src));
|
|
|
|
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst));
|
|
|
|
}
|
|
|
|
gai->port_src=pinfo->srcport;
|
|
|
|
gai->port_dst=pinfo->destport;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
flags[0] = '\0';
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
bpos = 1 << i;
|
|
|
|
if (tcph->th_flags & bpos) {
|
|
|
|
if (flags_found) {
|
|
|
|
g_strlcat(flags, ", ", sizeof(flags));
|
|
|
|
}
|
|
|
|
g_strlcat(flags, fstr[i], sizeof(flags));
|
|
|
|
flags_found = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flags[0] == '\0') {
|
|
|
|
g_snprintf (flags, sizeof(flags), "<None>");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){
|
|
|
|
gai->frame_label = g_strdup_printf("%s - Len: %u",flags, tcph->th_seglen);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
gai->frame_label = g_strdup(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tcph->th_flags & TH_ACK)
|
|
|
|
gai->comment = g_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack);
|
|
|
|
else
|
|
|
|
gai->comment = g_strdup_printf("Seq = %u",tcph->th_seq);
|
|
|
|
|
|
|
|
gai->line_style=1;
|
|
|
|
gai->conv_num=0;
|
|
|
|
gai->display=TRUE;
|
|
|
|
|
|
|
|
graph_analysis->list = g_list_append(graph_analysis->list, gai);
|
|
|
|
|
|
|
|
return 1;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* whenever a frame packet is seen by the tap listener */
|
2010-08-12 01:54:10 +00:00
|
|
|
static gboolean
|
2005-07-17 23:12:12 +00:00
|
|
|
flow_graph_frame_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *dummy _U_)
|
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){
|
2008-08-05 17:33:14 +00:00
|
|
|
flow_graph_frame_add_to_graph(pinfo);
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
return TRUE;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* whenever a TCP packet is seen by the tap listener */
|
2010-08-12 01:54:10 +00:00
|
|
|
static gboolean
|
2005-07-17 23:12:12 +00:00
|
|
|
flow_graph_tcp_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info)
|
|
|
|
{
|
|
|
|
const struct tcpheader *tcph = tcp_info;
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){
|
2008-08-05 17:33:14 +00:00
|
|
|
flow_graph_tcp_add_to_graph(pinfo,tcph);
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
return TRUE;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
static void
|
|
|
|
flow_graph_packet_draw(void *prs _U_)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
2008-08-05 17:33:14 +00:00
|
|
|
return;
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
static void
|
|
|
|
flow_graph_on_ok (GtkButton *button _U_,
|
2010-08-12 01:54:10 +00:00
|
|
|
gpointer user_data)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
|
|
|
if ((have_frame_tap_listener==TRUE)
|
|
|
|
||(have_tcp_tap_listener==TRUE))
|
2008-08-05 17:33:14 +00:00
|
|
|
{
|
2005-07-17 23:12:12 +00:00
|
|
|
/* remove_tap_listeners */
|
|
|
|
remove_tap_listener_flow_graph();
|
|
|
|
}
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2005-09-14 08:59:41 +00:00
|
|
|
/* Scan for displayed packets (retap all packets) */
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
if (type_of_flow == TYPE_OF_FLOW_GENERAL){
|
2005-07-17 23:12:12 +00:00
|
|
|
/* Register the tap listener */
|
|
|
|
|
|
|
|
if(have_frame_tap_listener==FALSE)
|
|
|
|
{
|
|
|
|
/* don't register tap listener, if we have it already */
|
|
|
|
register_tap_listener("frame", &tap_identifier, NULL,
|
2009-06-05 22:42:47 +00:00
|
|
|
TL_REQUIRES_COLUMNS,
|
2008-08-05 17:33:14 +00:00
|
|
|
flow_graph_reset,
|
|
|
|
flow_graph_frame_packet,
|
2005-07-17 23:12:12 +00:00
|
|
|
flow_graph_packet_draw
|
|
|
|
);
|
|
|
|
have_frame_tap_listener=TRUE;
|
|
|
|
}
|
|
|
|
|
2009-06-05 22:42:47 +00:00
|
|
|
cf_retap_packets(&cfile);
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
else if (type_of_flow == TYPE_OF_FLOW_TCP){
|
2005-07-17 23:12:12 +00:00
|
|
|
/* Register the tap listener */
|
|
|
|
|
|
|
|
if(have_tcp_tap_listener==FALSE)
|
|
|
|
{
|
|
|
|
/* don't register tap listener, if we have it already */
|
|
|
|
register_tap_listener("tcp", &tap_identifier, NULL,
|
2009-06-05 22:42:47 +00:00
|
|
|
0,
|
2008-08-05 17:33:14 +00:00
|
|
|
flow_graph_reset,
|
|
|
|
flow_graph_tcp_packet,
|
2005-07-17 23:12:12 +00:00
|
|
|
flow_graph_packet_draw
|
|
|
|
);
|
|
|
|
have_tcp_tap_listener=TRUE;
|
|
|
|
}
|
|
|
|
|
2009-06-05 22:42:47 +00:00
|
|
|
cf_retap_packets(&cfile);
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (graph_analysis_data->dlg.window != NULL){ /* if we still have a window */
|
|
|
|
graph_analysis_update(graph_analysis_data); /* refresh it xxx */
|
|
|
|
}
|
|
|
|
else{
|
2007-05-29 23:09:09 +00:00
|
|
|
graph_analysis_data->dlg.parent_w = user_data;
|
2005-07-17 23:12:12 +00:00
|
|
|
graph_analysis_create(graph_analysis_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* INTERFACE */
|
|
|
|
/****************************************************************************/
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
static void
|
|
|
|
flow_graph_dlg_create (void)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
|
|
|
GtkWidget *flow_graph_dlg_w;
|
|
|
|
GtkWidget *main_vb;
|
|
|
|
GtkWidget *hbuttonbox;
|
2008-04-16 00:46:16 +00:00
|
|
|
GtkWidget *bt_cancel, *bt_ok;
|
2005-07-17 23:12:12 +00:00
|
|
|
#if 0
|
|
|
|
GtkWidget *top_label = NULL;
|
|
|
|
#endif
|
2005-12-16 07:20:13 +00:00
|
|
|
GtkWidget *flow_type_fr, *range_fr, *range_tb, *flow_type_tb, *node_addr_fr, *node_addr_tb;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2009-06-21 20:42:07 +00:00
|
|
|
flow_graph_dlg_w = dlg_window_new("Wireshark: Flow Graph"); /* transient_for top_level */
|
|
|
|
gtk_window_set_destroy_with_parent (GTK_WINDOW(flow_graph_dlg_w), TRUE);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_window_set_default_size(GTK_WINDOW(flow_graph_dlg_w), 250, 150);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
main_vb = gtk_vbox_new (FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(flow_graph_dlg_w), main_vb);
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_vb), 7);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
top_label = gtk_label_new ("Choose packets to include in the graph");
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vb), top_label, FALSE, FALSE, 8);
|
|
|
|
#endif
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_widget_show(flow_graph_dlg_w);
|
|
|
|
|
|
|
|
/*** Packet range frame ***/
|
|
|
|
range_fr = gtk_frame_new("Choose packets");
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 5);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-12-01 08:50:37 +00:00
|
|
|
range_tb = gtk_table_new(4, 4, FALSE);
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(range_tb), 5);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
|
|
|
|
|
|
|
|
/* Process all packets */
|
2008-04-11 19:26:22 +00:00
|
|
|
select_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_All packets");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (select_all_rb, ("Process all packets"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(select_all_rb, "toggled", G_CALLBACK(toggle_select_all), NULL);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 0, 1);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (type_of_packets == TYPE_OF_PACKETS_ALL) {
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(select_all_rb);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/* Process displayed packets */
|
2010-08-12 01:54:10 +00:00
|
|
|
select_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(select_all_rb),
|
|
|
|
"_Displayed packets");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (select_displayed_rb, ("Process displayed packets"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(select_displayed_rb, "toggled", G_CALLBACK(toggle_select_displayed), NULL);
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(range_tb), select_displayed_rb, 0, 1, 1, 2);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (type_of_packets == TYPE_OF_PACKETS_DISPLAYED) {
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_displayed_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(select_displayed_rb);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
gtk_widget_show(range_tb);
|
|
|
|
gtk_widget_show(range_fr);
|
|
|
|
|
|
|
|
/*** Flow type frame ***/
|
|
|
|
flow_type_fr = gtk_frame_new("Choose flow type");
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(main_vb), flow_type_fr, FALSE, FALSE, 5);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-12-01 08:50:37 +00:00
|
|
|
flow_type_tb = gtk_table_new(4, 4, FALSE);
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(flow_type_tb), 5);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(flow_type_fr), flow_type_tb);
|
|
|
|
|
|
|
|
/* General information */
|
2008-04-11 19:26:22 +00:00
|
|
|
select_general_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_General flow");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (select_general_rb, ("Show all packets, with general information"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(select_general_rb, "toggled", G_CALLBACK(toggle_select_general), NULL);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(flow_type_tb), select_general_rb, 0, 1, 0, 1);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (type_of_flow == TYPE_OF_FLOW_GENERAL) {
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_general_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(select_general_rb);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/* TCP specific information */
|
2010-08-12 01:54:10 +00:00
|
|
|
select_tcp_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(select_general_rb),
|
|
|
|
"_TCP flow");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (select_tcp_rb, ("Show only TCP packets, with TCP specific information"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(select_tcp_rb, "toggled", G_CALLBACK(toggle_select_tcp), NULL);
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(flow_type_tb), select_tcp_rb, 0, 1, 1, 2);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (type_of_flow == TYPE_OF_FLOW_TCP) {
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_tcp_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(select_tcp_rb);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
gtk_widget_show(flow_type_tb);
|
|
|
|
gtk_widget_show(flow_type_fr);
|
|
|
|
|
2005-12-16 07:20:13 +00:00
|
|
|
/*** Node address type frame ***/
|
|
|
|
node_addr_fr = gtk_frame_new("Choose node address type");
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(main_vb), node_addr_fr, FALSE, FALSE, 5);
|
2005-12-16 07:20:13 +00:00
|
|
|
|
2008-12-01 08:50:37 +00:00
|
|
|
node_addr_tb = gtk_table_new(4, 4, FALSE);
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(node_addr_tb), 5);
|
2005-12-16 07:20:13 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(node_addr_fr), node_addr_tb);
|
|
|
|
|
|
|
|
/* Source / Dest address */
|
2008-04-11 19:26:22 +00:00
|
|
|
src_dst_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Standard source/destination addresses");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (src_dst_rb,
|
|
|
|
("Nodes in the diagram are identified with source and destination addresses"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(src_dst_rb, "toggled", G_CALLBACK(toggle_select_srcdst), NULL);
|
2005-12-16 07:20:13 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(node_addr_tb), src_dst_rb, 0, 1, 0, 1);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (node_addr_type == NODE_ADDR_TYPE_SRCDST) {
|
2005-12-16 07:20:13 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(src_dst_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(src_dst_rb);
|
2005-12-16 07:20:13 +00:00
|
|
|
|
|
|
|
/* Network source / dest address */
|
2010-08-12 01:54:10 +00:00
|
|
|
net_src_dst_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(src_dst_rb),
|
|
|
|
"_Network source/destination addresses");
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (net_src_dst_rb,
|
|
|
|
("Nodes in the diagram are identified with network source and destination addresses"));
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(net_src_dst_rb, "toggled", G_CALLBACK(toggle_select_netsrcdst), NULL);
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_table_attach_defaults(GTK_TABLE(node_addr_tb), net_src_dst_rb, 0, 1, 1, 2);
|
2010-08-12 01:54:10 +00:00
|
|
|
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
2005-12-16 07:20:13 +00:00
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net_src_dst_rb),TRUE);
|
|
|
|
}
|
2010-08-12 01:54:10 +00:00
|
|
|
gtk_widget_show(net_src_dst_rb);
|
2005-12-16 07:20:13 +00:00
|
|
|
|
|
|
|
gtk_widget_show(node_addr_tb);
|
|
|
|
gtk_widget_show(node_addr_fr);
|
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
/* button row */
|
2005-07-17 23:12:12 +00:00
|
|
|
hbuttonbox = gtk_hbutton_box_new ();
|
2008-12-01 08:50:37 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vb), hbuttonbox, FALSE, FALSE, 5);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD);
|
2008-07-08 02:43:40 +00:00
|
|
|
gtk_box_set_spacing (GTK_BOX (hbuttonbox), 30);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-04-11 18:58:19 +00:00
|
|
|
bt_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_ok);
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (bt_ok, "Show the flow graph");
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(bt_ok, "clicked", G_CALLBACK(flow_graph_on_ok), flow_graph_dlg_w);
|
2005-07-17 23:12:12 +00:00
|
|
|
gtk_widget_show(bt_ok);
|
|
|
|
|
2008-04-16 00:46:16 +00:00
|
|
|
bt_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
|
|
|
|
gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_cancel);
|
2011-07-14 00:04:37 +00:00
|
|
|
#if GTK_CHECK_VERSION(2,18,0)
|
|
|
|
gtk_widget_set_can_default(bt_cancel, TRUE);
|
|
|
|
#else
|
2008-04-16 00:46:16 +00:00
|
|
|
GTK_WIDGET_SET_FLAGS(bt_cancel, GTK_CAN_DEFAULT);
|
2011-07-14 00:04:37 +00:00
|
|
|
#endif
|
2011-07-13 08:48:13 +00:00
|
|
|
gtk_widget_set_tooltip_text (bt_cancel, "Cancel this dialog");
|
2008-04-16 00:46:16 +00:00
|
|
|
window_set_cancel_button(flow_graph_dlg_w, bt_cancel, window_cancel_button_cb);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2008-04-11 22:10:36 +00:00
|
|
|
g_signal_connect(flow_graph_dlg_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
|
|
|
|
g_signal_connect(flow_graph_dlg_w, "destroy", G_CALLBACK(flow_graph_on_destroy), NULL);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
gtk_widget_show_all(flow_graph_dlg_w);
|
|
|
|
window_present(flow_graph_dlg_w);
|
|
|
|
|
|
|
|
flow_graph_dlg = flow_graph_dlg_w;
|
2008-08-05 17:33:14 +00:00
|
|
|
}
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* PUBLIC */
|
|
|
|
/****************************************************************************/
|
|
|
|
|
|
|
|
/* init function for tap */
|
|
|
|
static void
|
2006-02-11 13:05:24 +00:00
|
|
|
flow_graph_init_tap(const char *dummy _U_, void* userdata _U_)
|
2005-07-17 23:12:12 +00:00
|
|
|
{
|
2010-08-12 01:54:10 +00:00
|
|
|
/* The storage allocated by flow_graph_data_init() and graph_analysis_init() */
|
|
|
|
/* will be considered to be "associated with" the flow_graph_dlg dialog box. */
|
|
|
|
/* It will be freed when the flow_graph_dlg dialog box is destroyed. */
|
|
|
|
if (flow_graph_dlg != NULL) {
|
|
|
|
g_assert(graph_analysis != NULL);
|
|
|
|
g_assert(graph_analysis_data != NULL);
|
|
|
|
/* There's already a dialog box; reactivate it. */
|
|
|
|
reactivate_window(flow_graph_dlg);
|
|
|
|
} else {
|
|
|
|
g_assert(graph_analysis == NULL);
|
|
|
|
g_assert(graph_analysis_data == NULL);
|
2005-07-17 23:12:12 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
/* initialize graph items store */
|
|
|
|
flow_graph_data_init();
|
2008-08-05 17:33:14 +00:00
|
|
|
|
2010-08-12 01:54:10 +00:00
|
|
|
/* init the Graph Analysis */
|
|
|
|
graph_analysis_data = graph_analysis_init();
|
|
|
|
graph_analysis_data->graph_info = graph_analysis;
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
flow_graph_dlg_create();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* entry point when called via the GTK menu */
|
2011-05-10 05:31:45 +00:00
|
|
|
void
|
2011-05-03 16:45:37 +00:00
|
|
|
flow_graph_launch(GtkAction *action _U_, gpointer user_data _U_)
|
|
|
|
{
|
|
|
|
flow_graph_init_tap("",NULL);
|
|
|
|
}
|
2005-07-17 23:12:12 +00:00
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
void
|
|
|
|
register_tap_listener_flow_graph(void)
|
|
|
|
{
|
2006-02-11 13:05:24 +00:00
|
|
|
register_stat_cmd_arg("flow_graph",flow_graph_init_tap,NULL);
|
2005-07-17 23:12:12 +00:00
|
|
|
}
|
|
|
|
|