forked from osmocom/wireshark
From Alejandro Vaquero:
New "Fax T38 Analysis" added to the "Statistics" menu to: - Reassemble the HDLC t30 frames and dissect the header. - Analyze the UPDTLPacket seq num for packet lost - Stats of V.x Data: - Count the Data bytes - Duration - Wrong seq num - Max Burst of packet lost svn path=/trunk/; revision=16073
This commit is contained in:
parent
9e273834dc
commit
15a08ae521
|
@ -51,6 +51,7 @@
|
|||
#include <glib.h>
|
||||
#include <epan/packet.h>
|
||||
#include <epan/conversation.h>
|
||||
#include <epan/tap.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -67,6 +68,8 @@
|
|||
static guint global_t38_tcp_port = PORT_T38;
|
||||
static guint global_t38_udp_port = PORT_T38;
|
||||
|
||||
static int t38_tap = -1;
|
||||
|
||||
/*
|
||||
* Variables to allow for proper deletion of dissector registration when
|
||||
* the user changes port from the gui.
|
||||
|
@ -171,6 +174,13 @@ static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
/* Preferences bool to control whether or not setup info should be shown */
|
||||
static gboolean global_t38_show_setup_info = TRUE;
|
||||
|
||||
/* Can tap up to 4 T38 packets within same packet */
|
||||
/* We only tap the primary part, not the redundancy */
|
||||
#define MAX_T38_MESSAGES_IN_PACKET 4
|
||||
static t38_packet_info t38_info_arr[MAX_T38_MESSAGES_IN_PACKET];
|
||||
static int t38_info_current=0;
|
||||
static t38_packet_info *t38_info=NULL;
|
||||
|
||||
/* Set up an T38 conversation */
|
||||
void t38_add_address(packet_info *pinfo,
|
||||
address *addr, int port,
|
||||
|
@ -292,7 +302,7 @@ static const per_choice_t t30_indicator_choice[] = {
|
|||
{ 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const value_string t30_indicator_vals[] = {
|
||||
const value_string t30_indicator_vals[] = {
|
||||
{ 0, "no-signal" },
|
||||
{ 1, "cng" },
|
||||
{ 2, "ced" },
|
||||
|
@ -330,6 +340,11 @@ dissect_t38_t30_indicator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_t
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, " t30ind: %s",
|
||||
val_to_str(T30ind_value,t30_indicator_vals,"<unknown>"));
|
||||
}
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part)
|
||||
t38_info->t30ind_value = T30ind_value;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -397,6 +412,12 @@ dissect_t38_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, " data:%s:",
|
||||
val_to_str(Data_value,data_vals,"<unknown>"));
|
||||
}
|
||||
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part)
|
||||
t38_info->data_value = Data_value;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -419,6 +440,10 @@ dissect_t38_Type_of_msg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto
|
|||
ett_t38_Type_of_msg, Type_of_msg_choice,
|
||||
&Type_of_msg_value);
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part)
|
||||
t38_info->type_msg = Type_of_msg_value;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -511,6 +536,16 @@ dissect_t38_Data_Field_field_type(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
val_to_str(Data_Field_field_type_value,Data_Field_field_type_vals,"<unknown>"));
|
||||
}
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part) {
|
||||
if ( (t38_info->t38_info_data_item_index < MAX_T38_DATA_ITEMS) && (t38_info->t38_info_data_item_index >= 0) ){ /*sanity check */
|
||||
t38_info->data_type[t38_info->t38_info_data_item_index] = Data_Field_field_type_value;
|
||||
|
||||
if (t38_info->t38_info_data_item_index++ == MAX_T38_DATA_ITEMS-1) t38_info->t38_info_data_item_index = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -535,6 +570,16 @@ dissect_t38_Data_Field_field_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
tvb_bytes_to_str(value_tvb,0,7));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part) {
|
||||
if ( (t38_info->t38_info_data_item_index <= MAX_T38_DATA_ITEMS) && (t38_info->t38_info_data_item_index > 0) ){ /*sanity check */
|
||||
t38_info->data_len[t38_info->t38_info_data_item_index-1] = value_len;
|
||||
t38_info->data[t38_info->t38_info_data_item_index-1] = tvb_memdup(value_tvb,0,value_len);
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -591,6 +636,10 @@ dissect_t38_seq_number(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
|
|||
offset=dissect_per_constrained_integer(tvb, offset, pinfo,
|
||||
tree, hf_t38_seq_number, 0, 65535,
|
||||
&seq_number, NULL, FALSE);
|
||||
|
||||
/* info for tap */
|
||||
if (primary_part)
|
||||
t38_info->seq_num = seq_number;
|
||||
|
||||
if (check_col(pinfo->cinfo, COL_INFO)){
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "Seq=%05u ",seq_number);
|
||||
|
@ -630,7 +679,8 @@ dissect_t38_secondary_ifp_packets(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
{
|
||||
/* When the field-data is not present, we MUST offset 1 byte*/
|
||||
if((Data_Field_field_type_value != 0) &&
|
||||
(Data_Field_field_type_value != 6))
|
||||
(Data_Field_field_type_value != 6) &&
|
||||
(Data_Field_field_type_value != 7))
|
||||
{
|
||||
offset=offset+8;
|
||||
}
|
||||
|
@ -745,6 +795,7 @@ dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
proto_item *it;
|
||||
proto_tree *tr;
|
||||
guint32 offset=0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* XXX - heuristic to check for misidentified packets.
|
||||
|
@ -757,6 +808,25 @@ dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
|
||||
/* tap info */
|
||||
t38_info_current++;
|
||||
if (t38_info_current==MAX_T38_MESSAGES_IN_PACKET) {
|
||||
t38_info_current=0;
|
||||
}
|
||||
t38_info = &t38_info_arr[t38_info_current];
|
||||
|
||||
t38_info->seq_num = 0;
|
||||
t38_info->type_msg = 0;
|
||||
t38_info->data_value = 0;
|
||||
t38_info->t30ind_value =0;
|
||||
|
||||
t38_info->t38_info_data_item_index = 0;
|
||||
for (i=0; i<MAX_T38_DATA_ITEMS; i++) {
|
||||
t38_info->data_type[i] = 0;
|
||||
t38_info->data[i] = NULL;
|
||||
t38_info->data_len[i] = 0;
|
||||
}
|
||||
|
||||
if (check_col(pinfo->cinfo, COL_PROTOCOL)){
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38");
|
||||
}
|
||||
|
@ -794,6 +864,18 @@ dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, " [Malformed?]");
|
||||
}
|
||||
}
|
||||
|
||||
/* if is a valid t38 packet, add to tap */
|
||||
if (!pinfo->in_error_pkt)
|
||||
tap_queue_packet(t38_tap, pinfo, t38_info);
|
||||
else { /* if not, free the data */
|
||||
for (i=0; i<MAX_T38_DATA_ITEMS; i++) {
|
||||
t38_info->data_type[i] = 0;
|
||||
g_free(t38_info->data[i]);
|
||||
t38_info->data[i] = NULL;
|
||||
t38_info->data_len[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1037,6 +1119,8 @@ proto_register_t38(void)
|
|||
proto_register_subtree_array(ett, array_length(ett));
|
||||
register_dissector("t38", dissect_t38, proto_t38);
|
||||
|
||||
t38_tap = register_tap("t38");
|
||||
|
||||
t38_module = prefs_register_protocol(proto_t38, proto_reg_handoff_t38);
|
||||
prefs_register_bool_preference(t38_module, "use_pre_corrigendum_asn1_specification",
|
||||
"Use the Pre-Corrigendum ASN.1 specification",
|
||||
|
|
|
@ -25,6 +25,20 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define MAX_T38_DATA_ITEMS 4
|
||||
typedef struct _t38_packet_info {
|
||||
guint16 seq_num; /* UDPTLPacket sequence number */
|
||||
guint32 type_msg; /* 0=t30-indicator 1=data */
|
||||
guint32 t30ind_value;
|
||||
guint32 data_value; /* standard and speed */
|
||||
|
||||
int t38_info_data_item_index; /* this will have the number of Data Items in the packet and is used as the index when decoding the packet */
|
||||
guint32 data_type[MAX_T38_DATA_ITEMS];
|
||||
guint8 *data[MAX_T38_DATA_ITEMS];
|
||||
gint data_len[MAX_T38_DATA_ITEMS];
|
||||
} t38_packet_info;
|
||||
|
||||
|
||||
/* Info to save in T38 conversation / packet-info */
|
||||
#define MAX_T38_SETUP_METHOD_SIZE 7
|
||||
struct _t38_conversation_info
|
||||
|
@ -38,3 +52,5 @@ void t38_add_address(packet_info *pinfo,
|
|||
address *addr, int port,
|
||||
int other_port,
|
||||
const gchar *setup_method, guint32 setup_frame_number);
|
||||
|
||||
ETH_VAR_IMPORT const value_string t30_indicator_vals[];
|
||||
|
|
|
@ -557,6 +557,7 @@ stats_tree_reset
|
|||
stats_tree_tick_pivot
|
||||
stats_tree_tick_range
|
||||
string_to_name_resolve
|
||||
t30_indicator_vals DATA
|
||||
T_h323_message_body_vals DATA
|
||||
tap_push_tapped_queue
|
||||
tap_queue_init
|
||||
|
|
|
@ -157,6 +157,7 @@ ETHEREAL_TAP_SRC = \
|
|||
sctp_stat_dlg.c \
|
||||
sip_stat.c \
|
||||
smb_stat.c \
|
||||
t38_analysis.c \
|
||||
tcp_graph.c \
|
||||
voip_calls_dlg.c \
|
||||
wsp_stat.c
|
||||
|
|
|
@ -136,6 +136,8 @@ static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
|
|||
|
||||
user_data->num_nodes = 0;
|
||||
user_data->num_items = 0;
|
||||
user_data->on_destroy_user_data = NULL;
|
||||
user_data->data = NULL;
|
||||
for (i=0; i<MAX_NUM_NODES; i++){
|
||||
user_data->nodes[i].type = AT_NONE;
|
||||
user_data->nodes[i].len = 0;
|
||||
|
@ -165,13 +167,14 @@ static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
|
|||
user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
|
||||
user_data->dlg.window=NULL;
|
||||
user_data->dlg.inverse = FALSE;
|
||||
user_data->dlg.title=NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* CALLBACKS */
|
||||
|
||||
/****************************************************************************/
|
||||
/* close the dialog window and remove the tap listener */
|
||||
/* close the dialog window */
|
||||
static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
|
||||
{
|
||||
int i;
|
||||
|
@ -183,6 +186,12 @@ static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
|
|||
user_data->nodes[i].data = NULL;
|
||||
}
|
||||
user_data->dlg.window = NULL;
|
||||
g_free(user_data->dlg.title);
|
||||
user_data->dlg.title = NULL;
|
||||
|
||||
if(user_data->on_destroy_user_data){
|
||||
user_data->on_destroy_user_data(user_data->data);
|
||||
}
|
||||
}
|
||||
|
||||
#define RIGHT_ARROW 1
|
||||
|
@ -649,7 +658,7 @@ static void dialog_graph_draw(graph_analysis_data_t* user_data)
|
|||
top_y_border=TOP_Y_BORDER; /* to display the node address */
|
||||
bottom_y_border=2;
|
||||
|
||||
draw_height=user_data->dlg.draw_area->allocation.height-top_y_border-bottom_y_border;
|
||||
draw_height=user_data->dlg.draw_area->allocation.height-top_y_border-bottom_y_border;
|
||||
|
||||
first_item = user_data->dlg.first_item;
|
||||
display_items = draw_height/ITEM_HEIGHT;
|
||||
|
@ -734,7 +743,7 @@ static void dialog_graph_draw(graph_analysis_data_t* user_data)
|
|||
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
||||
#endif
|
||||
|
||||
/* resize the "time" draw area */
|
||||
/* resize the "time" draw area */
|
||||
|
||||
left_x_border=3;
|
||||
user_data->dlg.left_x_border = left_x_border;
|
||||
|
@ -1359,8 +1368,8 @@ static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
|
|||
gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
dialog_graph_redraw(user_data);
|
||||
|
||||
dialog_graph_redraw(user_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1429,6 +1438,7 @@ static gint configure_event_time(GtkWidget *widget, GdkEventConfigure *event _U_
|
|||
|
||||
dialog_graph_redraw(user_data);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#if GTK_MAJOR_VERSION >= 2
|
||||
|
@ -1561,9 +1571,9 @@ static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box)
|
|||
|
||||
gtk_box_pack_start(GTK_BOX(hbox), user_data->dlg.draw_area_time, FALSE, FALSE, 0);
|
||||
|
||||
user_data->dlg.hpane = gtk_hpaned_new();
|
||||
gtk_paned_pack1(GTK_PANED (user_data->dlg.hpane), user_data->dlg.scroll_window, FALSE, TRUE);
|
||||
gtk_paned_pack2(GTK_PANED (user_data->dlg.hpane), scroll_window_comments, TRUE, TRUE);
|
||||
user_data->dlg.hpane = gtk_hpaned_new();
|
||||
gtk_paned_pack1(GTK_PANED (user_data->dlg.hpane), user_data->dlg.scroll_window, FALSE, TRUE);
|
||||
gtk_paned_pack2(GTK_PANED (user_data->dlg.hpane), scroll_window_comments, TRUE, TRUE);
|
||||
#if GTK_MAJOR_VERSION >= 2
|
||||
SIGNAL_CONNECT(user_data->dlg.hpane, "notify::position", pane_callback, user_data);
|
||||
#endif
|
||||
|
@ -1596,7 +1606,10 @@ static void dialog_graph_create_window(graph_analysis_data_t* user_data)
|
|||
GtkTooltips *tooltips = gtk_tooltips_new();
|
||||
|
||||
/* create the main window */
|
||||
user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
|
||||
if (user_data->dlg.title)
|
||||
user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, user_data->dlg.title);
|
||||
else
|
||||
user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
|
||||
|
||||
|
||||
vbox=gtk_vbox_new(FALSE, 0);
|
||||
|
@ -1787,3 +1800,24 @@ void graph_analysis_update(graph_analysis_data_t* user_data)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void graph_analysis_redraw(graph_analysis_data_t* user_data)
|
||||
{
|
||||
/* get nodes (each node is an address) */
|
||||
get_nodes(user_data);
|
||||
|
||||
user_data->dlg.pixmap_width = user_data->num_nodes * NODE_WIDTH;
|
||||
WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
|
||||
if ( user_data->num_nodes < 6)
|
||||
WIDGET_SET_SIZE(user_data->dlg.scroll_window, NODE_WIDTH*user_data->num_nodes, user_data->dlg.pixmap_height);
|
||||
else
|
||||
WIDGET_SET_SIZE(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.pixmap_height);
|
||||
|
||||
|
||||
/* redraw the graph */
|
||||
dialog_graph_redraw(user_data);
|
||||
|
||||
window_present(user_data->dlg.window);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -104,9 +104,10 @@ typedef struct _dialog_data_t {
|
|||
display_items_t items[NUM_DISPLAY_ITEMS];
|
||||
guint32 left_x_border;
|
||||
char *save_file;
|
||||
char *title; /* Graph analysis window's title */
|
||||
} dialog_data_t;
|
||||
|
||||
|
||||
typedef void (*destroy_user_data_cb)(void *data);
|
||||
|
||||
/* structure that holds general information and the dialog */
|
||||
typedef struct _graph_analysis_data_t {
|
||||
|
@ -118,11 +119,14 @@ typedef struct _graph_analysis_data_t {
|
|||
address nodes[MAX_NUM_NODES];
|
||||
guint32 num_nodes;
|
||||
guint32 num_items;
|
||||
destroy_user_data_cb on_destroy_user_data; /* callback info for destroy */
|
||||
void *data; /* data to be passes when on destroy */
|
||||
} graph_analysis_data_t;
|
||||
|
||||
graph_analysis_data_t* graph_analysis_init(void);
|
||||
void graph_analysis_create(graph_analysis_data_t* user_data);
|
||||
void graph_analysis_update(graph_analysis_data_t* user_data);
|
||||
void graph_analysis_redraw(graph_analysis_data_t* user_data);
|
||||
|
||||
|
||||
#endif /*GRAPH_ANALYSIS_H_INCLUDED*/
|
||||
|
|
|
@ -168,6 +168,8 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
|
|||
graph_item = list->data;
|
||||
g_free(graph_item->frame_label);
|
||||
g_free(graph_item->comment);
|
||||
g_free((void *)graph_item->src_addr.data);
|
||||
g_free((void *)graph_item->dst_addr.data);
|
||||
g_free(list->data);
|
||||
list = g_list_next(list);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue