Ethereal-dev: [Ethereal-dev] Voip Calls analysis and Graph analysis
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
Date: Sat, 29 Jan 2005 20:06:54 -0700
Hi All,Attached is the new "Voip call analysis" patch file and a screen shot of a SIP to H323 interop call. It is based on Francisco Alcoba source, and added support of H323, RTP and a Graph analysis. The Graph interface can also be used in other no Voip analysis.
Here are the features:- Collect ISUP, SIP and H323 calls from a capture and show them in window with the following info:
- Start and Stop time of the call- Initial Speaker: the IP source address of the first message that started the call - From and To: In H323 and ISUP, it is the calling and called number. In SIP the From and To fields.
- Protocol: H323, SIP and ISUP (from now) - State: the sate of the call- Comments: For H323, it shows if the call is a FastSatrt call and if Tunneling H245 is enable or not.
- Prepare a filter of a particular call when selected. - Select one or multiple calls to "graph analysis" And the "Graph Analysis" has:- Graph up to ten columns or "nodes". Each "node" it is defined as an IP address.
- Shows the direction of the message using arrows- Display a "frame" label on top of the arrow, and a "comment" at the right of each packet.
- For SIP and H323 the "frame" label also shows the Codec used.- The "comment" column will show different info based on the packet. For Setup and INVITE messages, it shows the calling/called number and From/To fields. For Release H323 messages, the Q931 release cause. For H225 messages, if tunneling is enable or not, and if FastStart is present in the packet. - RTP streams involved in the call. It is displayed as a wider arrow. The "frame" label also shows the Codec for the stream and the "comment" shows the number of RTP packets in this stream, the duration, and ssrc. - When "click" on a frame in the graph, the selected frame number will be selected in the Main windows.
- The graph also shows the time, and the UPD/TCP ports per frame.I have tested it in a Windows machine using GTK 1 and 2. There is not support for ISUP calls in the Graph yet (don't have such captures).
Comments and changes are very welcome. Regards Alejandro
Index: rtp_pt.h =================================================================== --- rtp_pt.h (revision 13162) +++ rtp_pt.h (working copy) @@ -63,5 +63,6 @@ #define PT_H263 34 /* from Chunrong Zhu of Intel; see the Web page */ ETH_VAR_IMPORT const value_string rtp_payload_type_vals[]; +ETH_VAR_IMPORT const value_string rtp_payload_type_short_vals[]; #endif Index: asn1/h225/packet-h225-template.c =================================================================== --- asn1/h225/packet-h225-template.c (revision 13162) +++ asn1/h225/packet-h225-template.c (working copy) @@ -67,7 +67,9 @@ static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi); static int dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); -static h225_packet_info h225_pi; +static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H225 messaages per packet */ +static int pi_current=0; +h225_packet_info *h225_pi=NULL; static dissector_handle_t h225ras_handle; static dissector_handle_t H323UserInformation_handle; @@ -132,9 +134,15 @@ proto_tree *tr; int offset = 0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h225_pi=&pi_arr[pi_current]; + /* Init struct for collecting h225_packet_info */ - reset_h225_packet_info(&(h225_pi)); - h225_pi.msg_type = H225_CS; + reset_h225_packet_info(h225_pi); + h225_pi->msg_type = H225_CS; if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0"); @@ -148,7 +156,7 @@ offset = dissect_h225_H323_UserInformation(tvb, offset,pinfo, tr, hf_h225_H323_UserInformation); - tap_queue_packet(h225_tap, pinfo, &h225_pi); + tap_queue_packet(h225_tap, pinfo, h225_pi); return offset; } @@ -158,9 +166,15 @@ proto_tree *tr; guint32 offset=0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h225_pi=&pi_arr[pi_current]; + /* Init struct for collecting h225_packet_info */ - reset_h225_packet_info(&(h225_pi)); - h225_pi.msg_type = H225_RAS; + reset_h225_packet_info(h225_pi); + h225_pi->msg_type = H225_RAS; if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0"); @@ -171,12 +185,13 @@ offset = dissect_h225_RasMessage(tvb, 0, pinfo,tr, hf_h225_RasMessage ); - ras_call_matching(tvb, pinfo, tr, &(h225_pi)); + ras_call_matching(tvb, pinfo, tr, h225_pi); - tap_queue_packet(h225_tap, pinfo, &h225_pi); + tap_queue_packet(h225_tap, pinfo, h225_pi); return offset; } + /*--- proto_register_h225 -------------------------------------------*/ void proto_register_h225(void) { @@ -279,8 +294,10 @@ pi->request_available = FALSE; pi->is_faststart = FALSE; pi->is_h245 = FALSE; + pi->is_h245Tunneling = FALSE; pi->h245_address = 0; pi->h245_port = 0; + pi->frame_label[0] = '\0'; } /* Index: asn1/h225/packet-h225-template.h =================================================================== --- asn1/h225/packet-h225-template.h (revision 13162) +++ asn1/h225/packet-h225-template.h (working copy) @@ -33,12 +33,20 @@ } h225_msg_type; typedef enum _h225_cs_type { - H225_SETUP, - H225_CALL_PROCEDING, - H225_ALERTING, - H225_CONNECT, - H225_RELEASE_COMPLET, - H225_OTHER + H225_SETUP, + H225_CALL_PROCEDING, + H225_CONNECT, + H225_ALERTING, + H225_INFORMATION, + H225_RELEASE_COMPLET, + H225_FACILITY, + H225_PROGRESS, + H225_EMPTY, + H225_STATUS, + H225_STATUS_INQUIRY, + H225_SETUP_ACK, + H225_NOTIFY, + H225_OTHER } h225_cs_type; typedef struct _h225_packet_info { @@ -54,8 +62,10 @@ /* added for h225 conversations analysis */ gboolean is_faststart; /* true, if faststart field is included */ gboolean is_h245; + gboolean is_h245Tunneling; guint32 h245_address; guint16 h245_port; + gchar frame_label[50]; /* the Fram label used by graph_analysis, what is a abreviation of cinfo */ } h225_packet_info; /* Index: asn1/h225/h225.cnf =================================================================== --- asn1/h225/h225.cnf (revision 13162) +++ asn1/h225/h225.cnf (working copy) @@ -147,9 +147,9 @@ val_to_str(message_body_val, T_h323_message_body_vals, "<unknown>")); } - if (h225_pi.msg_type == H225_CS) { + if (h225_pi->msg_type == H225_CS) { /* Don't override msg_tag value from IRR */ - h225_pi.msg_tag = message_body_val; + h225_pi->msg_tag = message_body_val; } if (contains_faststart == TRUE ) @@ -167,14 +167,19 @@ #.FN_BODY FastStart/_item guint32 newoffset; guint32 length; + char codec_str[50]; offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_h225_fastStart_item_length, &length); newoffset=offset + (length<<3); /* please note that offset is in bits in PER dissectors, but the item length is in octets */ - offset=dissect_h245_OpenLogicalChannel(tvb,offset, pinfo, tree, hf_index); + offset=dissect_h245_OpenLogicalChannelCodec(tvb,offset, pinfo, tree, hf_index, codec_str); + + /* Add to packet info */ + g_snprintf(h225_pi->frame_label, 50, "%s %s", h225_pi->frame_label, codec_str); + contains_faststart = TRUE; - h225_pi.is_faststart = TRUE; + h225_pi->is_faststart = TRUE; return newoffset; @@ -192,7 +197,7 @@ val_to_str(rasmessage_value, RasMessage_vals, "<unknown>")); } - h225_pi.msg_tag = rasmessage_value; + h225_pi->msg_tag = rasmessage_value; #.END #---------------------------------------------------------------------------------------- # TODO asn2eth can't handle restriced string ? @@ -241,28 +246,82 @@ #.END #---------------------------------------------------------------------------------------- +#.FN_FTR NULL + if (h225_pi->cs_type == H225_OTHER) h225_pi->cs_type = H225_EMPTY; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR Status-UUIE + /* Add to packet info */ + h225_pi->cs_type = H225_STATUS; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); +#.END +#.FN_FTR Information-UUIE + /* Add to packet info */ + h225_pi->cs_type = H225_INFORMATION; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); +#.END +#.FN_FTR Progress-UUIE + /* Add to packet info */ + h225_pi->cs_type = H225_PROGRESS; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); +#.END +#.FN_FTR Facility-UUIE + /* Add to packet info */ + h225_pi->cs_type = H225_FACILITY; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); +#.END +#---------------------------------------------------------------------------------------- +#.FN_BODY H323-UU-PDU/h245Tunneling + offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_h245Tunneling, &(h225_pi->is_h245Tunneling), NULL); +#.END +#---------------------------------------------------------------------------------------- #.FN_HDR Setup-UUIE contains_faststart = FALSE; #.END #---------------------------------------------------------------------------------------- #.FN_FTR Setup-UUIE - h225_pi.cs_type = H225_SETUP; + /* Add to packet info */ + h225_pi->cs_type = H225_SETUP; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_FTR CallProceeding-UUIE - h225_pi.cs_type = H225_CALL_PROCEDING; + /* Add to packet info */ + h225_pi->cs_type = H225_CALL_PROCEDING; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_FTR Alerting-UUIE - h225_pi.cs_type = H225_ALERTING; + /* Add to packet info */ + h225_pi->cs_type = H225_ALERTING; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_FTR ReleaseComplete-UUIE - h225_pi.cs_type = H225_RELEASE_COMPLET; + /* Add to packet info */ + h225_pi->cs_type = H225_RELEASE_COMPLET; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_FTR Connect-UUIE - h225_pi.cs_type = H225_CONNECT; + /* Add to packet info */ + h225_pi->cs_type = H225_CONNECT; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_HDR H245TransportAddress @@ -273,9 +332,9 @@ #---------------------------------------------------------------------------------------- #.FN_FTR H245TransportAddress /* we need this info for TAPing */ - h225_pi.is_h245 = TRUE; - h225_pi.h245_address = ipv4_address; - h225_pi.h245_port = ipv4_port; + h225_pi->is_h245 = TRUE; + h225_pi->h245_address = ipv4_address; + h225_pi->h245_port = ipv4_port; if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && h245_handle){ address src_addr; @@ -300,7 +359,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_FacilityReason, FacilityReason_choice, "FacilityReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- @@ -310,7 +369,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_GatekeeperRejectReason, GatekeeperRejectReason_choice, "GatekeeperRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- @@ -320,7 +379,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_UnregRequestReason, UnregRequestReason_choice, "UnregRequestReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- @@ -330,7 +389,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_UnregRejectReason, UnregRejectReason_choice, "UnregRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY BandRejectReason @@ -338,7 +397,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_BandRejectReason, BandRejectReason_choice, "BandRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY DisengageReason @@ -347,7 +406,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_DisengageReason, DisengageReason_choice, "DisengageReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #---------------------------------------------------------------------------------------- #.FN_BODY DisengageRejectReason guint32 value; @@ -355,7 +414,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_DisengageRejectReason, DisengageRejectReason_choice, "DisengageRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY AdmissionRejectReason @@ -364,7 +423,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_AdmissionRejectReason, AdmissionRejectReason_choice, "AdmissionRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY LocationRejectReason @@ -373,7 +432,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_LocationRejectReason, LocationRejectReason_choice, "LocationRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY RegistrationRejectReason @@ -382,7 +441,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_RegistrationRejectReason, RegistrationRejectReason_choice, "RegistrationRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY InfoRequestNakReason @@ -391,7 +450,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_InfoRequestNakReason, InfoRequestNakReason_choice, "InfoRequestNakReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY ReleaseCompleteReason @@ -400,19 +459,19 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_ReleaseCompleteReason, ReleaseCompleteReason_choice, "ReleaseCompleteReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; #.END #---------------------------------------------------------------------------------------- #.FN_BODY CallIdentifier/guid guint32 guid_offset,guid_len; offset = dissect_per_octet_string(tvb,offset,pinfo,tree,hf_index,16,16,&guid_offset,&guid_len); - tvb_memcpy(tvb,h225_pi.guid,guid_offset,guid_len); + tvb_memcpy(tvb,h225_pi->guid,guid_offset,guid_len); #.END #---------------------------------------------------------------------------------------- #.FN_BODY RequestSeqNum offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, - 1U, 65535U, &(h225_pi.requestSeqNum), NULL, FALSE); + 1U, 65535U, &(h225_pi->requestSeqNum), NULL, FALSE); #---------------------------------------------------------------------------------------- #.FN_BODY H323-UU-PDU/h4501SupplementaryService/_item Index: asn1/h245/packet-h245-template.c =================================================================== --- asn1/h245/packet-h245-template.c (revision 13162) +++ asn1/h245/packet-h245-template.c (working copy) @@ -70,7 +70,10 @@ static int hf_h245Manufacturer = -1; static int h245_tap = -1; static int ett_h245 = -1; -static h245_packet_info h245_pi; +static int h245dg_tap = -1; +static h245_packet_info pi_arr[5]; /* We assuming a maximum of 5 H245 messaages per packet */ +static int pi_current=0; +h245_packet_info *h245_pi=NULL; static gboolean h245_reassembly = TRUE; static gboolean h245_shorttypes = FALSE; @@ -164,6 +167,34 @@ { 12, "GC" }, { 0, NULL } }; +static const value_string h245_AudioCapability_short_vals[] = { + { 0, "nonStd" }, + { 1, "g711A" }, + { 2, "g711A56k" }, + { 3, "g711U" }, + { 4, "g711U56k" }, + { 5, "g722-64k" }, + { 6, "g722-56k" }, + { 7, "g722-48k" }, + { 8, "g7231" }, + { 9, "g728" }, + { 10, "g729" }, + { 11, "g729A" }, + { 12, "is11172" }, + { 13, "is13818" }, + { 14, "g729B" }, + { 15, "g729AB" }, + { 16, "g7231C" }, + { 17, "gsmFR" }, + { 18, "gsmHR" }, + { 19, "gsmEFR" }, + { 20, "generic" }, + { 21, "g729Ext" }, + { 22, "vbd" }, + { 23, "audioTelEvent" }, + { 24, "audioTone" }, + { 0, NULL } +}; /* To put the codec type only in COL_INFO when an OLC is read */ @@ -199,12 +230,18 @@ void dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { - reset_h245_packet_info(&(h245_pi)); - h245_pi.msg_type = H245_OTHER; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h245_pi=&pi_arr[pi_current]; + reset_h245_packet_info(h245_pi); + h245_pi->msg_type = H245_OTHER; + dissect_tpkt_encap(tvb, pinfo, parent_tree, h245_reassembly, MultimediaSystemControlMessage_handle); - tap_queue_packet(h245_tap, pinfo, &h245_pi); + tap_queue_packet(h245_tap, pinfo, h245_pi); } void @@ -214,7 +251,15 @@ proto_tree *tr; guint32 offset=0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h245_pi=&pi_arr[pi_current]; + reset_h245_packet_info(h245_pi); + h245_pi->msg_type = H245_OTHER; + if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.245"); } @@ -222,9 +267,24 @@ it=proto_tree_add_protocol_format(parent_tree, proto_h245, tvb, 0, tvb_length(tvb), "H.245"); tr=proto_item_add_subtree(it, ett_h245); dissect_h245_MultimediaSystemControlMessage(tvb, offset, pinfo ,tr, hf_h245_pdu_type); + tap_queue_packet(h245dg_tap, pinfo, h245_pi); } +int +dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str) { + offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, + ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence); + + if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; + + if (codec_str){ + strcpy(codec_str, codec_type); + } + + return offset; +} + /*--- proto_register_h245 -------------------------------------------*/ void proto_register_h245(void) { @@ -270,6 +330,7 @@ nsp_object_dissector_table = register_dissector_table("h245.nsp.object", "H.245 NonStandardParameter (object)", FT_STRING, BASE_NONE); nsp_h221_dissector_table = register_dissector_table("h245.nsp.h221", "H.245 NonStandardParameter (h221)", FT_UINT32, BASE_HEX); h245_tap = register_tap("h245"); + h245dg_tap = register_tap("h245dg"); register_ber_oid_name("0.0.8.239.1.1","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ControlCapability(1)"); register_ber_oid_name("0.0.8.239.1.2","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ExtendedVideoCapability(2)"); @@ -309,5 +370,7 @@ } pi->msg_type = H245_OTHER; + pi->frame_label[0] = '\0'; + sprintf(pi->comment, "H245 "); } Index: asn1/h245/packet-h245-template.h =================================================================== --- asn1/h245/packet-h245-template.h (revision 13162) +++ asn1/h245/packet-h245-template.h (working copy) @@ -2,7 +2,7 @@ * Routines for h245 packet dissection * Copyright 2005, Anders Broman <anders.broman@xxxxxxxxxxxx> * - * $Id: packet-h245-template.h 12203 2004-10-05 09:18:55Z guy $ + * $Id$ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -45,11 +45,15 @@ typedef struct _h245_packet_info { h245_msg_type msg_type; /* type of message */ + gchar frame_label[50]; /* the Frame label used by graph_analysis, what is a abreviation of cinfo */ + gchar comment[50]; /* the Frame Comment used by graph_analysis, what is a message desc */ } h245_packet_info; #include "packet-h245-exp.h"*/ +int dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str); + #endif /* PACKET_H245_H */ Index: asn1/h245/h245.cnf =================================================================== --- asn1/h245/h245.cnf (revision 13162) +++ asn1/h245/h245.cnf (working copy) @@ -33,6 +33,20 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + + /* Add to packet info */ + + /* if it is TCS*/ + if ((codec_type != NULL) && ( value == 2)) + g_snprintf(h245_pi->frame_label, 50, "%s (%s) ",val_to_str(value, h245_RequestMessage_short_vals, "UKN"), h245_pi->frame_label); + else + g_snprintf(h245_pi->frame_label, 50, "%s ", val_to_str(value, h245_RequestMessage_short_vals, "UKN")); + + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_RequestMessage_vals, "<unknown>")); + + /* if it is OLC or RM*/ + if ((codec_type != NULL) && (( value == 3) || ( value == 8))) + g_snprintf(h245_pi->frame_label, 50, "%s (%s) ", h245_pi->frame_label, codec_type); #.END #---------------------------------------------------------------------------------------- #.FN_BODY ResponseMessage @@ -56,6 +70,10 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_ResponseMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_ResponseMessage_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_BODY IndicationMessage @@ -79,6 +97,9 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_IndicationMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_IndicationMessage_vals, "<unknown>")); #.END #---------------------------------------------------------------------------------------- #.FN_BODY CommandMessage @@ -102,6 +123,10 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_CommandMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_CommandMessage_vals, "<unknown>")); + #.END #---------------------------------------------------------------------------------------- #.FN_BODY AudioCapability @@ -111,7 +136,9 @@ ett_h245_AudioCapability, AudioCapability_choice, "AudioCapability", &value); - codec_type = val_to_str(value, h245_AudioCapability_vals, "<unknown>"); + codec_type = val_to_str(value, h245_AudioCapability_short_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, val_to_str(value, h245_AudioCapability_short_vals, "ukn")); + #.END #---------------------------------------------------------------------------------------- #.FN_BODY VideoCapability @@ -122,6 +149,8 @@ &value); codec_type = val_to_str(value, h245_VideoCapability_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type); + #.END #---------------------------------------------------------------------------------------- #.FN_BODY Application @@ -132,76 +161,77 @@ &value); codec_type = val_to_str(value, h245_Application_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type); #.END #---------------------------------------------------------------------------------------- #.FN_FTR MasterSlaveDeterminationAck - h245_pi.msg_type = H245_MastSlvDetAck; + h245_pi->msg_type = H245_MastSlvDetAck; #.END #---------------------------------------------------------------------------------------- #.FN_FTR MasterSlaveDeterminationReject - h245_pi.msg_type = H245_MastSlvDetRjc; + h245_pi->msg_type = H245_MastSlvDetRjc; #.END #---------------------------------------------------------------------------------------- #.FN_FTR OpenLogicalChannelReject - h245_pi.msg_type = H245_OpenLogChnRjc; + h245_pi->msg_type = H245_OpenLogChnRjc; #.END #---------------------------------------------------------------------------------------- #.FN_FTR CloseLogicalChannel - h245_pi.msg_type = H245_CloseLogChn; + h245_pi->msg_type = H245_CloseLogChn; #.END #---------------------------------------------------------------------------------------- #.FN_FTR CloseLogicalChannelAck - h245_pi.msg_type = H245_CloseLogChnAck; + h245_pi->msg_type = H245_CloseLogChnAck; #.END #---------------------------------------------------------------------------------------- #.FN_FTR OpenLogicalChannelConfirm - h245_pi.msg_type = H245_OpenLogChnCnf; + h245_pi->msg_type = H245_OpenLogChnCnf; #.END #---------------------------------------------------------------------------------------- #.FN_FTR TerminalCapabilitySetAck - h245_pi.msg_type = H245_TermCapSetAck; + h245_pi->msg_type = H245_TermCapSetAck; #.END #---------------------------------------------------------------------------------------- #.FN_FTR MasterSlaveDetermination - h245_pi.msg_type = H245_MastSlvDet; + h245_pi->msg_type = H245_MastSlvDet; #.END #---------------------------------------------------------------------------------------- #.FN_FTR TerminalCapabilitySetReject - h245_pi.msg_type = H245_TermCapSetRjc; + h245_pi->msg_type = H245_TermCapSetRjc; #.END #---------------------------------------------------------------------------------------- #.FN_FTR MasterSlaveDeterminationRelease - h245_pi.msg_type = H245_MastSlvDetRls; + h245_pi->msg_type = H245_MastSlvDetRls; #.END #---------------------------------------------------------------------------------------- #.FN_FTR TerminalCapabilitySet - h245_pi.msg_type = H245_TermCapSet; + h245_pi->msg_type = H245_TermCapSet; #.END #---------------------------------------------------------------------------------------- #.FN_FTR TerminalCapabilitySetRelease - h245_pi.msg_type = H245_TermCapSetRls; + h245_pi->msg_type = H245_TermCapSetRls; #.END #---------------------------------------------------------------------------------------- #.FN_FTR OpenLogicalChannel - h245_pi.msg_type = H245_OpenLogChn; + if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; #.END #---------------------------------------------------------------------------------------- #.FN_FTR OpenLogicalChannelAck - h245_pi.msg_type = H245_OpenLogChnAck; + h245_pi->msg_type = H245_OpenLogChnAck; #.END #---------------------------------------------------------------------------------------- #.FN_BODY CapabilityIdentifier/standard Index: gtk/voip_calls_dlg.c =================================================================== --- gtk/voip_calls_dlg.c (revision 0) +++ gtk/voip_calls_dlg.c (revision 0) @@ -0,0 +1,719 @@ +/* voip_calls_dlg.c + * VoIP calls summary addition for ethereal + * + * $Id: voip_calls_dlg.c 12185 2004-10-02 11:05:27Z ulfl $ + * + * Copyright 2004, Ericsson , Spain + * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx> + * + * based on h323_calls_dlg.c + * Copyright 2004, Iskratel, Ltd, Kranj + * By Miha Jemec <m.jemec@xxxxxxxxxxx> + * + * H323, RTP and Graph Support + * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx + * Copyright 2005, Verso Technologies Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "register.h" + +#include "graph_analysis.h" +#include "voip_calls_dlg.h" +#include "voip_calls.h" + +#include "globals.h" +#include "epan/filesystem.h" + +#include "tap_menu.h" +#include "dlg_utils.h" +#include "ui_util.h" +#include "compat_macros.h" +#include "gtkglobals.h" + +#include "image/clist_ascend.xpm" +#include "image/clist_descend.xpm" +#include "simple_dialog.h" + +#include <epan/to_str.h> + +#include <string.h> + + +typedef const guint8 * ip_addr_p; + +static const gchar FWD_LABEL_TEXT[] = "Select one call."; + +/****************************************************************************/ +/* pointer to the one and only dialog window */ +static GtkWidget *voip_calls_dlg = NULL; + +static GtkWidget *clist = NULL; +static GtkWidget *top_label = NULL; +static GtkWidget *status_label = NULL; +static GtkWidget *label_fwd = NULL; + +/*static GtkWidet *bt_unselect = NULL;*/ +static GtkWidget *bt_filter = NULL; +static GtkWidget *bt_graph = NULL; + + +static voip_calls_info_t* selected_call_fwd = NULL; /* current selection */ +static GList *last_list = NULL; + +static guint32 calls_nb = 0; /* number of displayed calls */ +static guint32 calls_ns = 0; /* number of selected calls */ + +static graph_analysis_data_t *graph_analysis_data; + +#define NUM_COLS 9 + +/****************************************************************************/ +/* append a line to clist */ +static void add_to_clist(voip_calls_info_t* strinfo) +{ + gchar label_text[256]; + gint added_row; + gchar *data[NUM_COLS]; + gchar field[NUM_COLS][50]; + gint c; + isup_calls_info_t *tmp_isupinfo; + h323_calls_info_t *tmp_h323info; + gboolean tmp_bool = FALSE; + for (c=0;c<NUM_COLS;c++){ + data[c]=&field[c][0]; + } + + + g_snprintf(field[0], 15, "%i.%2i", strinfo->start_sec, strinfo->start_usec/10000); + g_snprintf(field[1], 15, "%i.%2i", strinfo->stop_sec, strinfo->stop_usec/10000); +// xxx display_signed_time(data[0], sizeof(field[0]), strinfo->start_sec, strinfo->start_usec, USECS); +// display_signed_time(data[1], sizeof(field[0]), strinfo->stop_sec, strinfo->stop_usec, USECS); + g_snprintf(field[2], 30, "%s", ip_to_str((const guint8*)&(strinfo->initial_speaker))); + g_snprintf(field[3], 50, "%s", strinfo->from_identity); + g_snprintf(field[4], 50, "%s", strinfo->to_identity); + g_snprintf(field[5], 15, "%s", voip_protocol_name[strinfo->protocol]); + g_snprintf(field[6], 15, "%u", strinfo->npackets); + g_snprintf(field[7], 15, "%s", voip_call_state_name[strinfo->call_state]); + + /* Add comments based on the protocol */ + switch(strinfo->protocol){ + case VOIP_ISUP: + tmp_isupinfo = strinfo->prot_info; + g_snprintf(field[8],30, "%i-%i -> %i-%i", tmp_isupinfo->ni, tmp_isupinfo->opc, + tmp_isupinfo->ni, tmp_isupinfo->dpc); + break; + case VOIP_H323: + tmp_h323info = strinfo->prot_info; + if (strinfo->call_state == VOIP_CALL_SETUP) + tmp_bool = tmp_h323info->is_faststart_Setup; + else + if ((tmp_h323info->is_faststart_Setup == TRUE) && (tmp_h323info->is_faststart_Proc == TRUE)) tmp_bool = TRUE; + g_snprintf(field[8],35, "Tunneling: %s Fast Start: %s", (tmp_h323info->is_h245Tunneling==TRUE?"ON":"OFF"), + (tmp_bool==TRUE?"ON":"OFF")); + break; + default: + field[8][0]='\0'; + } + + + added_row = gtk_clist_append(GTK_CLIST(clist), data); + + /* set data pointer of last row to point to user data for that row */ + gtk_clist_set_row_data(GTK_CLIST(clist), added_row, strinfo); + + /* Update the top label with the number of detected calls */ + calls_nb++; + g_snprintf(label_text, 256, + "Detected %d VoIP %s. Selected %d %s.", + calls_nb, + plurality(calls_nb, "Call", "Calls"), + calls_ns, + plurality(calls_ns, "Call", "Calls")); + gtk_label_set(GTK_LABEL(top_label), label_text); + + /* Update the status label with the number of total messages */ + g_snprintf(label_text, 256, + "Total: Calls: %d Start packets: %d Completed calls: %d Rejected calls: %d", + voip_calls_get_info()->ncalls, + voip_calls_get_info()->start_packets, + voip_calls_get_info()->completed_calls, + voip_calls_get_info()->rejected_calls); + gtk_label_set(GTK_LABEL(status_label), label_text); +} + + +void voip_calls_remove_tap_listener() +{ + /* Remove the calls tap listener */ + remove_tap_listener_sip_calls(); + remove_tap_listener_isup_calls(); + remove_tap_listener_mtp3_calls(); + remove_tap_listener_h225_calls(); + remove_tap_listener_h245dg_calls(); + remove_tap_listener_q931_calls(); + remove_tap_listener_sdp_calls(); +} + +/****************************************************************************/ +/* CALLBACKS */ +/****************************************************************************/ +static void +voip_calls_on_destroy (GtkObject *object _U_, + gpointer user_data _U_) +{ + /* Clean up memory used by calls tap */ + voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info()); + + /* Note that we no longer have a "VoIP Calls" dialog box. */ + voip_calls_dlg = NULL; +} + + +/****************************************************************************/ +static void +voip_calls_on_unselect (GtkButton *button _U_, + gpointer user_data _U_) +{ + selected_call_fwd = NULL; + gtk_clist_unselect_all(GTK_CLIST(clist)); + gtk_label_set_text(GTK_LABEL(label_fwd), FWD_LABEL_TEXT); + + /*gtk_widget_set_sensitive(bt_unselect, FALSE);*/ + gtk_widget_set_sensitive(bt_filter, FALSE); +} + + +/****************************************************************************/ +static void +voip_calls_on_filter (GtkButton *button _U_, + gpointer user_data _U_) +{ + gchar *filter_string = NULL; + gchar *filter_string_fwd = NULL; + gchar filter_prepend[5]; + sip_calls_info_t *tmp_sipinfo; + isup_calls_info_t *tmp_isupinfo; + h323_calls_info_t *tmp_h323info; + h245_address_t *h245_add = NULL; + GList* list; + + if (selected_call_fwd==NULL) + return; + + filter_string=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget)); + if (strcmp(filter_string,"")!=0){ /* this means there is already a display filter, we or it */ + strcpy(filter_prepend," or "); + } + else{ + strcpy(filter_prepend,""); + } + + + switch(selected_call_fwd->protocol){ + case VOIP_SIP: + tmp_sipinfo = selected_call_fwd->prot_info; + filter_string_fwd = g_strdup_printf("%s(sip.Call-ID == \"%s\") ", + filter_prepend, tmp_sipinfo->call_identifier + ); + filter_string = filter_string_fwd; + gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string); + break; + case VOIP_ISUP: + tmp_isupinfo = selected_call_fwd->prot_info; + filter_string_fwd = g_strdup_printf("%s(isup.cic == %i and frame.number >=%i and frame.number<=%i and mtp3.network_indicator == %i and ((mtp3.dpc == %i) and (mtp3.opc == %i)) or((mtp3.dpc == %i) and (mtp3.opc == %i))) ", + filter_prepend, tmp_isupinfo->cic,selected_call_fwd->first_frame_num, + selected_call_fwd->last_frame_num, + tmp_isupinfo->ni, tmp_isupinfo->dpc, tmp_isupinfo->opc, + tmp_isupinfo->opc, tmp_isupinfo->dpc + ); + filter_string = filter_string_fwd; + gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string); + break; + case VOIP_H323: + tmp_h323info = selected_call_fwd->prot_info; + filter_string_fwd = g_strdup_printf("%s((h225.guid == %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x || q931.call_ref == %x:%x || q931.call_ref == %x:%x) ", + filter_prepend, (guint8)tmp_h323info->guid[0], (guint8)tmp_h323info->guid[1], (guint8)tmp_h323info->guid[2], + (guint8)tmp_h323info->guid[3], (guint8)tmp_h323info->guid[4], (guint8)tmp_h323info->guid[5], (guint8)tmp_h323info->guid[6], + (guint8)tmp_h323info->guid[7], (guint8)tmp_h323info->guid[8], (guint8)tmp_h323info->guid[9], (guint8)tmp_h323info->guid[10], + (guint8)tmp_h323info->guid[11], (guint8)tmp_h323info->guid[12], (guint8)tmp_h323info->guid[13], (guint8)tmp_h323info->guid[14], + (guint8)tmp_h323info->guid[15], (guint8)(tmp_h323info->q931_crv & 0xff), (guint8)((tmp_h323info->q931_crv & 0xff00)>>8) + , (guint8)(tmp_h323info->q931_crv2 & 0xff), (guint8)((tmp_h323info->q931_crv2 & 0xff00)>>8)); + + list = g_list_first(tmp_h323info->h245_list); + while (list) + { + h245_add=list->data; + filter_string_fwd = g_strdup_printf("%s || (ip.addr == %s && tcp.port == %d && h245) ", filter_string_fwd, + ip_to_str((guint8 *)&(h245_add->h245_address)), h245_add->h245_port); + list = g_list_next(list); + } + filter_string_fwd = g_strdup_printf("%s ) ", filter_string_fwd); + + filter_string = filter_string_fwd; + gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string); + break; + + } + + + g_free(filter_string); + +/* + main_filter_packets(&cfile, filter_string, FALSE); + voip_calls_dlg_update(voip_calls_get_info()->strinfo_list); +*/ +} + + + + +/****************************************************************************/ +static void +on_graph_bt_clicked (GtkButton *button _U_, + gpointer user_data _U_) +{ + graph_analysis_item_t *gai; + GList* list; + GList* list2; + voip_calls_info_t *tmp_listinfo; + + /* reset the "display" parameter in graph analysis */ + list2 = g_list_first(voip_calls_get_info()->graph_analysis->list); + while (list2){ + gai = list2->data; + gai->display = FALSE; + list2 = g_list_next(list2); + } + + + /* set the display for selected calls */ + list = g_list_first(voip_calls_get_info()->strinfo_list); + while (list){ + tmp_listinfo=list->data; + if (tmp_listinfo->selected){ + list2 = g_list_first(voip_calls_get_info()->graph_analysis->list); + while (list2){ + gai = list2->data; + if (gai->conv_num == tmp_listinfo->call_num){ + gai->display = TRUE; + } + list2 = g_list_next(list2); + } + } + list = g_list_next(list); + } + + /* create or refresh the graph windows */ + if (graph_analysis_data->dlg.window == NULL) /* create the window */ + graph_analysis_create(graph_analysis_data); + else + graph_analysis_update(graph_analysis_data); /* refresh it */ +} + +static const GdkColor COLOR_SELECT = {0, 0x00ff, 0x80ff, 0x80ff}; +static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff}; + +/****************************************************************************/ +/* when the user selects a row in the calls list */ +static void +voip_calls_on_select_row(GtkCList *clist, + gint row _U_, + gint column _U_, + GdkEventButton *event _U_, + gpointer user_data _U_) +{ + GdkColor color = COLOR_DEFAULT; + gchar label_text[80]; + + selected_call_fwd = gtk_clist_get_row_data(GTK_CLIST(clist), row); + + if (!selected_call_fwd->selected) + calls_ns++; + else + calls_ns--; + + g_snprintf(label_text, 256, + "Detected %d VoIP %s. Selected %d %s.", + calls_nb, + plurality(calls_nb, "Call", "Calls"), + calls_ns, + plurality(calls_ns, "Call", "Calls")); + gtk_label_set(GTK_LABEL(top_label), label_text); + + g_snprintf(label_text, 80, "Selected Call: From %s To %s, starting time %i.%i", + selected_call_fwd->from_identity, + selected_call_fwd->to_identity, + selected_call_fwd->start_sec, + selected_call_fwd->start_usec + ); + gtk_label_set_text(GTK_LABEL(label_fwd), label_text); + + selected_call_fwd->selected=!selected_call_fwd->selected; + if (selected_call_fwd->selected) + color = COLOR_SELECT; + else + color = COLOR_DEFAULT; + + gtk_clist_set_background(GTK_CLIST(clist), row, &color); + + /*gtk_widget_set_sensitive(bt_unselect, TRUE);*/ + gtk_widget_set_sensitive(bt_filter, TRUE); + + /* TODO: activate other buttons when implemented */ +} + + +/****************************************************************************/ + +typedef struct column_arrows { + GtkWidget *table; + GtkWidget *ascend_pm; + GtkWidget *descend_pm; +} column_arrows; + + +/****************************************************************************/ +static void +voip_calls_click_column_cb(GtkCList *clist, gint column, gpointer data) +{ + column_arrows *col_arrows = (column_arrows *) data; + int i; + + gtk_clist_freeze(clist); + + for (i=0; i<NUM_COLS; i++) { + gtk_widget_hide(col_arrows[i].ascend_pm); + gtk_widget_hide(col_arrows[i].descend_pm); + } + + if (column == clist->sort_column) { + if (clist->sort_type == GTK_SORT_ASCENDING) { + clist->sort_type = GTK_SORT_DESCENDING; + gtk_widget_show(col_arrows[column].descend_pm); + } else { + clist->sort_type = GTK_SORT_ASCENDING; + gtk_widget_show(col_arrows[column].ascend_pm); + } + } else { + clist->sort_type = GTK_SORT_ASCENDING; + gtk_widget_show(col_arrows[column].ascend_pm); + gtk_clist_set_sort_column(clist, column); + } + gtk_clist_thaw(clist); + + gtk_clist_sort(clist); +} + + +/****************************************************************************/ +static gint +voip_calls_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) +{ + char *text1 = NULL; + char *text2 = NULL; + int i1, i2; + + const GtkCListRow *row1 = (const GtkCListRow *) ptr1; + const GtkCListRow *row2 = (const GtkCListRow *) ptr2; + + text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text; + text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text; + + switch(clist->sort_column){ + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + return strcmp (text1, text2); + case 6: + i1=atoi(text1); + i2=atoi(text2); + return i1-i2; + } + g_assert_not_reached(); + return 0; +} + + +/****************************************************************************/ +/* INTERFACE */ +/****************************************************************************/ + +static void voip_calls_dlg_create (void) +{ + GtkWidget *voip_calls_dlg_w; + GtkWidget *main_vb; + GtkWidget *scrolledwindow; + GtkWidget *hbuttonbox; + GtkWidget *bt_close; + GtkTooltips *tooltips = gtk_tooltips_new(); + + gchar *titles[NUM_COLS] = {"Start Time", "Stop Time", "Initial Speaker", "From", "To", "Protocol", "Packets", "State", "Comments"}; + column_arrows *col_arrows; + GtkWidget *column_lb; + int i; + + voip_calls_dlg_w=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: VoIP VoIP Calls"); + + gtk_window_set_default_size(GTK_WINDOW(voip_calls_dlg_w), 840, 350); + + main_vb = gtk_vbox_new (FALSE, 0); + gtk_container_add(GTK_CONTAINER(voip_calls_dlg_w), main_vb); + gtk_container_set_border_width (GTK_CONTAINER (main_vb), 12); + + top_label = gtk_label_new ("Detected 0 VoIP Calls. Selected 0 Calls."); + gtk_box_pack_start (GTK_BOX (main_vb), top_label, FALSE, FALSE, 8); + + scrolledwindow = scrolled_window_new (NULL, NULL); + gtk_box_pack_start (GTK_BOX (main_vb), scrolledwindow, TRUE, TRUE, 0); + + clist = gtk_clist_new (NUM_COLS); + gtk_container_add (GTK_CONTAINER (scrolledwindow), clist); + + gtk_clist_set_column_width (GTK_CLIST (clist), 0, 60); + gtk_clist_set_column_width (GTK_CLIST (clist), 1, 60); + gtk_clist_set_column_width (GTK_CLIST (clist), 2, 80); + gtk_clist_set_column_width (GTK_CLIST (clist), 3, 130); + gtk_clist_set_column_width (GTK_CLIST (clist), 4, 130); + gtk_clist_set_column_width (GTK_CLIST (clist), 5, 50); + gtk_clist_set_column_width (GTK_CLIST (clist), 6, 45); + gtk_clist_set_column_width (GTK_CLIST (clist), 7, 60); + gtk_clist_set_column_width (GTK_CLIST (clist), 8, 100); + + gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER); + gtk_clist_set_column_justification(GTK_CLIST(clist), 6, GTK_JUSTIFY_CENTER); + gtk_clist_set_column_justification(GTK_CLIST(clist), 7, GTK_JUSTIFY_LEFT); + gtk_clist_set_column_justification(GTK_CLIST(clist), 8, GTK_JUSTIFY_LEFT); + + gtk_clist_column_titles_show (GTK_CLIST (clist)); + + gtk_clist_set_compare_func(GTK_CLIST(clist), voip_calls_sort_column); + gtk_clist_set_sort_column(GTK_CLIST(clist), 0); + gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING); + + gtk_widget_show(voip_calls_dlg_w); + + /* sort by column feature */ + col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS); + + for (i=0; i<NUM_COLS; i++) { + col_arrows[i].table = gtk_table_new(2, 2, FALSE); + gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5); + column_lb = gtk_label_new(titles[i]); + gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); + gtk_widget_show(column_lb); + + col_arrows[i].ascend_pm = xpm_to_widget(clist_ascend_xpm); + gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); + col_arrows[i].descend_pm = xpm_to_widget(clist_descend_xpm); + gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); + /* make start time be the default sort order */ + if (i == 0) { + gtk_widget_show(col_arrows[i].ascend_pm); + } + gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table); + gtk_widget_show(col_arrows[i].table); + } + + SIGNAL_CONNECT(clist, "click-column", voip_calls_click_column_cb, col_arrows); + + label_fwd = gtk_label_new (FWD_LABEL_TEXT); + gtk_box_pack_start (GTK_BOX (main_vb), label_fwd, FALSE, FALSE, 0); + + status_label = gtk_label_new ("Total: Calls: 0 Start packets: 0 Completed calls: 0 Rejected calls: 0"); + gtk_box_pack_start (GTK_BOX (main_vb), status_label, FALSE, FALSE, 8); + + /* button row */ + hbuttonbox = gtk_hbutton_box_new (); + gtk_box_pack_start (GTK_BOX (main_vb), hbuttonbox, FALSE, FALSE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 30); + + /*bt_unselect = gtk_button_new_with_label ("Unselect"); + gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_unselect); + gtk_tooltips_set_tip (tooltips, bt_unselect, "Unselect this conversation", NULL);*/ + + bt_filter = gtk_button_new_with_label ("Prepare filter"); + gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_filter); + gtk_tooltips_set_tip (tooltips, bt_filter, "Prepare a display filter of the selected conversation", NULL); + + bt_graph = gtk_button_new_with_label("Graph"); + gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_graph); + gtk_widget_show(bt_graph); + SIGNAL_CONNECT(bt_graph, "clicked", on_graph_bt_clicked, NULL); + + bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE); + gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_close); + GTK_WIDGET_SET_FLAGS(bt_close, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, bt_close, "Close this dialog", NULL); + + SIGNAL_CONNECT(clist, "select_row", voip_calls_on_select_row, NULL); + /*SIGNAL_CONNECT(bt_unselect, "clicked", voip_calls_on_unselect, NULL);*/ + SIGNAL_CONNECT(bt_filter, "clicked", voip_calls_on_filter, NULL); + + window_set_cancel_button(voip_calls_dlg_w, bt_close, window_cancel_button_cb); + + SIGNAL_CONNECT(voip_calls_dlg_w, "delete_event", window_delete_event_cb, NULL); + SIGNAL_CONNECT(voip_calls_dlg_w, "destroy", voip_calls_on_destroy, NULL); + + gtk_widget_show_all(voip_calls_dlg_w); + window_present(voip_calls_dlg_w); + + voip_calls_on_unselect(NULL, NULL); + + voip_calls_dlg = voip_calls_dlg_w; +} + + +/****************************************************************************/ +/* PUBLIC */ +/****************************************************************************/ + +/****************************************************************************/ +/* update the contents of the dialog box clist */ +/* list: pointer to list of voip_calls_info_t* */ + +void voip_calls_dlg_update(GList *list) +{ + gchar label_text[256]; + + if (voip_calls_dlg != NULL) { + + voip_calls_remove_tap_listener(); + + /* Add the RTP streams info for the graph */ + add_rtp_streams_graph(); + + gtk_clist_clear(GTK_CLIST(clist)); + calls_nb = 0; + calls_ns = 0; + g_snprintf(label_text, 256, + "Total: Calls: %d Start packets: %d Completed calls: %d Rejected calls: %d", + voip_calls_get_info()->ncalls, + voip_calls_get_info()->start_packets, + voip_calls_get_info()->completed_calls, + voip_calls_get_info()->rejected_calls); + gtk_label_set(GTK_LABEL(status_label), label_text); + + list = g_list_first(list); + while (list) + { + add_to_clist((voip_calls_info_t*)(list->data)); + list = g_list_next(list); + } + + g_snprintf(label_text, 256, + "Detected %d VoIP %s. Selected %d %s.", + calls_nb, + plurality(calls_nb, "Call", "Calls"), + calls_ns, + plurality(calls_ns, "Call", "Calls")); + gtk_label_set(GTK_LABEL(top_label), label_text); + + voip_calls_on_unselect(NULL, NULL); + } + + last_list = list; +} + + +/****************************************************************************/ +/* update the contents of the dialog box clist */ +/* list: pointer to list of voip_calls_info_t* */ +void voip_calls_dlg_show(GList *list) +{ + if (voip_calls_dlg != NULL) { + /* There's already a dialog box; reactivate it. */ + reactivate_window(voip_calls_dlg); + /* Another list since last call? */ + if (list != last_list) { + voip_calls_dlg_update(list); + } + } + else { + /* Create and show the dialog box */ + voip_calls_dlg_create(); + voip_calls_dlg_update(list); + } +} + +/* init function for tap */ +static void +voip_calls_init_tap(char *dummy _U_) +{ + graph_analysis_data_init(); + + /* Clean up memory used by calls tap */ + voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info()); + + /* Register the tap listener */ + sip_calls_init_tap(); + mtp3_calls_init_tap(); + isup_calls_init_tap(); + h225_calls_init_tap(); + h245dg_calls_init_tap(); + q931_calls_init_tap(); + sdp_calls_init_tap(); + + /* Scan for VoIP calls calls (redissect all packets) */ + retap_packets(&cfile); + + /* Show the dialog box with the list of calls */ + voip_calls_dlg_show(voip_calls_get_info()->strinfo_list); + + /* Tap listener will be removed and cleaned up in voip_calls_on_destroy */ + +} + + +/****************************************************************************/ +/* entry point when called via the GTK menu */ +void voip_calls_launch(GtkWidget *w _U_, gpointer data _U_) +{ + + voip_calls_init_tap(""); + + /* init the Graph Analysys */ + graph_analysis_data = graph_analysis_init(); + graph_analysis_data->graph_info = voip_calls_get_info()->graph_analysis; + +} + +/****************************************************************************/ +void +register_tap_listener_voip_calls_dlg(void) +{ + register_ethereal_tap("voip,calls",voip_calls_init_tap); + register_tap_menu_item("VoIP Calls...", REGISTER_TAP_GROUP_NONE, + voip_calls_launch, NULL, NULL, NULL); + +} Index: gtk/voip_calls_dlg.h =================================================================== --- gtk/voip_calls_dlg.h (revision 0) +++ gtk/voip_calls_dlg.h (revision 0) @@ -0,0 +1,55 @@ +/* voip_calls_dlg.h + * VoIP conversations addition for ethereal + * + * $Id: voip_calls_dlg.h 12154 2004-09-30 19:49:48Z guy $ + * + * Copyright 2004, Ericsson , Spain + * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx> + * + * based on h323_conversations_dlg.h + * Copyright 2004, Iskratel, Ltd, Kranj + * By Miha Jemec <m.jemec@xxxxxxxxxxx> + * + * H323, RTP and Graph Support + * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx + * Copyright 2005, Verso Technologies Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef VOIP_CALLS_DLG_H_INCLUDED +#define VOIP_CALLS_DLG_H_INCLUDED + +#include <gtk/gtk.h> + +/** + * Create or reactivate the voip calls dialog box. + * + * @param list pointer to list of rtp_stream_info_t* + */ +void voip_calls_dlg_show(GList *list); + +/** + * Update the contents of the dialog box clist with that of list. + * + * @param list pointer to list of rtp_stream_info_t* + */ +void voip_calls_dlg_update(GList *list); + +#endif /* VOIP_CALLS_DLG_H_INCLUDED*/ Index: gtk/rtp_stream.c =================================================================== --- gtk/rtp_stream.c (revision 13162) +++ gtk/rtp_stream.c (working copy) @@ -211,6 +211,8 @@ GList* list; rtp_sample_t sample; + struct _rtp_conversation_info *p_conv_data = NULL; + /* gather infos on the stream this packet is part of */ COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src)); tmp_strinfo.src_port = pinfo->srcport; @@ -238,9 +240,20 @@ tmp_strinfo.first_frame_num = pinfo->fd->num; tmp_strinfo.start_sec = pinfo->fd->abs_secs; tmp_strinfo.start_usec = pinfo->fd->abs_usecs; + tmp_strinfo.start_rel_sec = pinfo->fd->rel_secs; + tmp_strinfo.start_rel_usec = pinfo->fd->rel_usecs; tmp_strinfo.tag_vlan_error = 0; tmp_strinfo.tag_diffserv_error = 0; tmp_strinfo.vlan_id = 0; + + /* Get the Setup frame number who set this RTP stream */ + + p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp")); + if (p_conv_data) + tmp_strinfo.setup_frame_number = p_conv_data->frame_number; + else + tmp_strinfo.setup_frame_number = 0xFFFFFFFF; + strinfo = g_malloc(sizeof(rtp_stream_info_t)); *strinfo = tmp_strinfo; /* memberwise copy of struct */ tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo); @@ -248,6 +261,8 @@ /* increment the packets counter for this stream */ ++(strinfo->npackets); + strinfo->stop_rel_sec = pinfo->fd->rel_secs; + strinfo->stop_rel_usec = pinfo->fd->rel_usecs; /* increment the packets counter of all streams */ ++(tapinfo->npackets); Index: gtk/rtp_stream.h =================================================================== --- gtk/rtp_stream.h (revision 13162) +++ gtk/rtp_stream.h (working copy) @@ -65,10 +65,15 @@ guint32 npackets; guint32 first_frame_num; /* frame number of first frame */ + guint32 setup_frame_number; /* frame number of setup message */ /* start of recording (GMT) of this stream */ guint32 start_sec; /* seconds */ guint32 start_usec; /* microseconds */ gboolean tag_vlan_error; + guint32 start_rel_sec; /* start stream rel seconds */ + guint32 start_rel_usec; /* start stream rel microseconds */ + guint32 stop_rel_sec; /* stop stream rel seconds */ + guint32 stop_rel_usec; /* stop stream rel microseconds */ gboolean tag_diffserv_error; guint16 vlan_id; Index: gtk/graph_analysis.c =================================================================== --- gtk/graph_analysis.c (revision 0) +++ gtk/graph_analysis.c (revision 0) @@ -0,0 +1,1009 @@ +/* graph_analysis.c + * Graphic Analysis addition for ethereal + * + * + * + * Copyright 2004, Verso Technologies Inc. + * By Alejandro Vaquero <alejandrovaquero@xxxxxxxxx> + * + * based on rtp_analysis.c and io_stat + * + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "graph_analysis.h" + +#include <epan/epan_dissect.h> +#include <epan/filesystem.h> + +#include "util.h" +#include <epan/tap.h> +#include "register.h" +#include <epan/dissectors/packet-rtp.h> + +/* in /gtk ... */ +#include <gtk/gtk.h> +#include "gtkglobals.h" + +#include "dlg_utils.h" +#include "ui_util.h" +#include "alert_box.h" +#include "simple_dialog.h" +#include "tap_menu.h" +#include "main.h" +#include "progress_dlg.h" +#include "compat_macros.h" +#include "../color.h" + +#include "image/clist_ascend.xpm" +#include "image/clist_descend.xpm" + +#include <math.h> +#include <fcntl.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_IO_H +#include <io.h> /* open/close on win32 */ +#endif + +/* Win32 needs the O_BINARY flag for open() */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +/****************************************************************************/ + + +#define OK_TEXT "[ Ok ]" +#define PT_UNDEFINED -1 + + +#if GTK_MAJOR_VERSION < 2 +GtkRcStyle *rc_style; +GdkColormap *colormap; +#endif + +typedef const guint8 * ip_addr_p; + + +/****************************************************************************/ +/* Reset the user_data structure */ +static void graph_analysis_reset(graph_analysis_data_t* user_data) +{ + int i; + + user_data->num_nodes = 0; + user_data->num_items = 0; + for (i=0; i<MAX_NUM_NODES; i++){ + user_data->nodes[i] = 0; + } + + user_data->dlg.first_node=0; + user_data->dlg.first_item=0; + user_data->dlg.left_x_border=0; + user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */ +} + +/****************************************************************************/ +/* Reset the user_data structure */ +static void graph_analysis_init_dlg(graph_analysis_data_t* user_data) +{ + /* init dialog_graph */ + user_data->dlg.needs_redraw=TRUE; + user_data->dlg.draw_area=NULL; + user_data->dlg.pixmap=NULL; + user_data->dlg.h_scrollbar=NULL; + user_data->dlg.h_scrollbar_adjustment=NULL; + user_data->dlg.v_scrollbar=NULL; + user_data->dlg.v_scrollbar_adjustment=NULL; + user_data->dlg.pixmap_width=600; + user_data->dlg.pixmap_height=400; + user_data->dlg.first_node=0; + user_data->dlg.first_item=0; + user_data->dlg.left_x_border=0; + user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */ + user_data->dlg.window=NULL; +} + +/****************************************************************************/ +/* CALLBACKS */ + + +/****************************************************************************/ +/* close the dialog window and remove the tap listener */ +static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_) +{ + + g_free(user_data); +} + + +/****************************************************************************/ +static void dialog_graph_set_title(graph_analysis_data_t* user_data) +{ + char *title; + if (!user_data->dlg.window){ + return; + } + title = g_strdup_printf("Ale"); + + gtk_window_set_title(GTK_WINDOW(user_data->dlg.window), title); + g_free(title); +} + +#define RIGHT_ARROW 1 +#define LEFT_ARROW 0 +#define WIDTH_ARROW 8 +#define HEIGHT_ARROW 6 + +/****************************************************************************/ +static void draw_arrow(GdkDrawable *pixmap, GdkGC *gc, gint x, gint y, boolean direction) +{ + GdkPoint arrow_point[3]; + + arrow_point[0].x = x; + arrow_point[0].y = y-HEIGHT_ARROW/2; + if (direction == RIGHT_ARROW) + arrow_point[1].x = x+WIDTH_ARROW; + else + arrow_point[1].x = x-WIDTH_ARROW; + arrow_point[1].y = y; + arrow_point[2].x = x; + arrow_point[2].y = y+HEIGHT_ARROW/2;; + + gdk_draw_polygon(pixmap, gc, TRUE, + arrow_point, 3); +} + +#define MAX_LABEL 50 +#define MAX_COMMENT 60 +#define ITEM_HEIGHT 20 +#define NODE_WIDTH 100 +#define TOP_Y_BORDER 40 +#define BOTTOM_Y_BORDER 0 +#define COMMENT_WIDTH 250 + +/****************************************************************************/ +static void dialog_graph_draw(graph_analysis_data_t* user_data) +{ + guint32 i, last_item, first_item, last_node, first_node, display_items, display_nodes; + guint32 start_arrow, end_arrow, label_x, src_port_x, dst_port_x, arrow_width; + guint32 current_item; + guint32 left_x_border; + guint32 right_x_border; + guint32 top_y_border; + guint32 bottom_y_border; + graph_analysis_item_t *gai; + gboolean display_label; + +#if GTK_MAJOR_VERSION < 2 + GdkFont *font; + FONT_TYPE *big_font; + FONT_TYPE *small_font; +#else + PangoLayout *layout; + PangoLayout *big_layout; + PangoLayout *small_layout; +#endif + guint32 label_width, label_height; + guint32 draw_width, draw_height; + char label_string[MAX_COMMENT]; + GList* list; + + /* new variables */ + +#if GTK_MAJOR_VERSION <2 + font = user_data->dlg.draw_area->style->font; + big_font = gdk_font_load("-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1"); + small_font = gdk_font_load("-adobe-helvetica-bold-r-normal--10-120-75-75-p-70-iso8859-1"); +#endif + if(!user_data->dlg.needs_redraw){ + return; + } + user_data->dlg.needs_redraw=FALSE; + + /* + * Clear out old plot + */ + gdk_draw_rectangle(user_data->dlg.pixmap, + user_data->dlg.draw_area->style->white_gc, + TRUE, + 0, 0, + user_data->dlg.draw_area->allocation.width, + user_data->dlg.draw_area->allocation.height); + + /* Calculate the y border */ + top_y_border=TOP_Y_BORDER; /* to display the node IP address */ + bottom_y_border=BOTTOM_Y_BORDER; + + draw_height=user_data->dlg.pixmap_height-top_y_border-bottom_y_border; + + first_item = user_data->dlg.first_item; + display_items = draw_height/ITEM_HEIGHT; + last_item = first_item+display_items-1; + + /* get the items to display and fill the matrix array */ + list = g_list_first(user_data->graph_info->list); + current_item = 0; + i = 0; + while (list) + { + gai = list->data; + if (gai->display){ + if (current_item>=display_items) break; /* the item is outside the display */ + if (i>=first_item){ + user_data->dlg.items[current_item].frame_num = gai->frame_num; + user_data->dlg.items[current_item].time = gai->time; + user_data->dlg.items[current_item].port_src = gai->port_src; + user_data->dlg.items[current_item].port_dst = gai->port_dst; + /* Add "..." if the length is 50 characters */ + if (strlen(gai->frame_label) > 48) { + gai->frame_label[48] = '.'; + gai->frame_label[47] = '.'; + gai->frame_label[46] = '.'; + } + user_data->dlg.items[current_item].frame_label = gai->frame_label; + user_data->dlg.items[current_item].comment = gai->comment; + user_data->dlg.items[current_item].conv_num = gai->conv_num; + user_data->dlg.items[current_item].src_node = gai->src_node; + user_data->dlg.items[current_item].dst_node = gai->dst_node; + user_data->dlg.items[current_item].line_style = gai->line_style; + current_item++; + } + i++; + } + + list = g_list_next(list); + } + /* in case the windows is resized so we have to move the top item */ + if ((first_item + display_items) > user_data->num_items){ + if (display_items>user_data->num_items) + first_item=0; + else + first_item = user_data->num_items - display_items; + } + + /* in case there are less items than possible displayed */ + display_items = current_item; + last_item = first_item+display_items-1; + + /* if not items to display */ + if (display_items == 0) return; + + + /* Calculate the x borders */ + /* We use time from the last display item to calcultate the x left border */ + g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[display_items-1].time); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(font, label_string); + label_height=gdk_string_height(font, label_string); +#else + layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string); + big_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string); + small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string); + + pango_layout_set_font_description(big_layout, pango_font_description_from_string("Helvetica-Bold 8")); + pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica-Bold 7")); + + pango_layout_get_pixel_size(layout, &label_width, &label_height); +#endif + left_x_border=label_width+10; + user_data->dlg.left_x_border = left_x_border; + + right_x_border=COMMENT_WIDTH; + + /* Calculate the number of nodes to display */ + draw_width=user_data->dlg.pixmap_width-right_x_border-left_x_border; + display_nodes = draw_width/NODE_WIDTH; + first_node = user_data->dlg.first_node; + + /* in case the windows is resized so we have to move the left node */ + if ((first_node + display_nodes) > user_data->num_nodes){ + if (display_nodes>user_data->num_nodes) + first_node=0; + else + first_node=user_data->num_nodes - display_nodes; + } + + /* in case there are less nodes than possible displayed */ + if (display_nodes>user_data->num_nodes) display_nodes=user_data->num_nodes; + + last_node = first_node + display_nodes-1; + + /* Paint the background items */ + for (current_item=0; current_item<display_items; current_item++){ + /* Paint background */ + gdk_draw_rectangle(user_data->dlg.pixmap, + user_data->dlg.bg_gc[user_data->dlg.items[current_item].conv_num%MAX_NUM_COL_CONV], + TRUE, + left_x_border, + top_y_border+current_item*ITEM_HEIGHT, + draw_width, + ITEM_HEIGHT); + } + + + /* Draw the node names on top and the division lines */ + for (i=0; i<display_nodes; i++){ + /* draw the node IPs */ + g_snprintf(label_string, MAX_LABEL, "%s", + ip_to_str((guint8 *)&(user_data->nodes[i+first_node]))); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(font, label_string); + label_height=gdk_string_height(font, label_string); + gdk_draw_string(user_data->dlg.pixmap, + font, + user_data->dlg.draw_area->style->black_gc, + left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i, + top_y_border/2-label_height/2, + label_string); +#else + pango_layout_set_text(layout, label_string, -1); + pango_layout_get_pixel_size(layout, &label_width, &label_height); + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.draw_area->style->black_gc, + left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i, + top_y_border/2-label_height/2, + layout); +#endif + + /* draw the node division lines */ + gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.div_line_gc, + left_x_border+NODE_WIDTH/2+NODE_WIDTH*i, + top_y_border, + left_x_border+NODE_WIDTH/2+NODE_WIDTH*i, + user_data->dlg.pixmap_height-bottom_y_border); + + } + + /* + * Draw the items + */ + + + for (current_item=0; current_item<display_items; current_item++){ + /* draw the time */ + g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[current_item].time); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(font, label_string); + label_height=gdk_string_height(font, label_string); + gdk_draw_string(user_data->dlg.pixmap, + font, + user_data->dlg.draw_area->style->black_gc, + left_x_border-label_width-4, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4, + label_string); +#else + pango_layout_set_text(layout, label_string, -1); + pango_layout_get_pixel_size(layout, &label_width, &label_height); + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.draw_area->style->black_gc, + left_x_border-label_width-4, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2, + layout); +#endif + + /*draw the comments */ + g_snprintf(label_string, MAX_COMMENT, "%s", user_data->dlg.items[current_item].comment); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(small_font, label_string); + label_height=gdk_string_height(small_font, label_string); + gdk_draw_string(user_data->dlg.pixmap, + small_font, + user_data->dlg.draw_area->style->black_gc, + user_data->dlg.pixmap_width-right_x_border+3, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4, + label_string); +#else + pango_layout_set_text(small_layout, label_string, -1); + pango_layout_get_pixel_size(small_layout, &label_width, &label_height); + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.draw_area->style->black_gc, + user_data->dlg.pixmap_width-right_x_border+3, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2, + small_layout); +#endif + + /* draw the arrow an frame label*/ + display_label = FALSE; + if (user_data->dlg.items[current_item].src_node>=first_node){ + if (user_data->dlg.items[current_item].src_node<=last_node){ + start_arrow = left_x_border+(user_data->dlg.items[current_item].src_node-first_node)*NODE_WIDTH+NODE_WIDTH/2; + display_label = TRUE; + } else { + start_arrow = user_data->dlg.pixmap_width - right_x_border; + } + } else { + start_arrow = left_x_border; + } + + if (user_data->dlg.items[current_item].dst_node>=first_node){ + if (user_data->dlg.items[current_item].dst_node<=last_node){ + end_arrow = left_x_border+(user_data->dlg.items[current_item].dst_node-first_node)*NODE_WIDTH+NODE_WIDTH/2; + display_label = TRUE; + } else { + end_arrow = user_data->dlg.pixmap_width - right_x_border; + } + } else { + end_arrow = left_x_border; + } + + if (start_arrow != end_arrow){ + /* draw the arrow line */ + gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, + start_arrow, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, + end_arrow, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7); + + /* draw the additional line when line style is 2 pixels width */ + if (user_data->dlg.items[current_item].line_style == 2){ + gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, + start_arrow, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6, + end_arrow, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6); + } + + /* draw the arrow */ + if (start_arrow<end_arrow) + draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow-WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, RIGHT_ARROW); + else + draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow+WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, LEFT_ARROW); + } + + /* draw the frame comment */ + if (display_label){ + g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].frame_label); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(big_font, label_string); + label_height=gdk_string_height(big_font, label_string); +#else + pango_layout_set_text(big_layout, label_string, -1); + pango_layout_get_pixel_size(big_layout, &label_width, &label_height); +#endif + + if (start_arrow<end_arrow){ + arrow_width = end_arrow-start_arrow; + label_x = arrow_width/2+start_arrow; + } + else { + arrow_width = start_arrow-end_arrow; + label_x = arrow_width/2+end_arrow; + } + + if (label_width>arrow_width) arrow_width = label_width; + + if (left_x_border > (label_x-label_width/2)) label_x = left_x_border + label_width/2; + + if ((user_data->dlg.pixmap_width - right_x_border) < (label_x+label_width/2)) label_x = user_data->dlg.pixmap_width - right_x_border - label_width/2; + +#if GTK_MAJOR_VERSION < 2 + gdk_draw_string(user_data->dlg.pixmap, + big_font, + user_data->dlg.draw_area->style->black_gc, + label_x - label_width/2, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4-3, + label_string); +#else + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.draw_area->style->black_gc, + label_x - label_width/2, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2-3, + big_layout); +#endif + + /* draw the source port number */ + if ((start_arrow != left_x_border) && (start_arrow != (user_data->dlg.pixmap_width - right_x_border))){ + g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_src); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(small_font, label_string); + label_height=gdk_string_height(small_font, label_string); +#else + pango_layout_set_text(small_layout, label_string, -1); + pango_layout_get_pixel_size(small_layout, &label_width, &label_height); +#endif + if (start_arrow<end_arrow){ + src_port_x = start_arrow - label_width - 2; + } + else { + src_port_x = start_arrow + 2; + } +#if GTK_MAJOR_VERSION < 2 + gdk_draw_string(user_data->dlg.pixmap, + small_font, + user_data->dlg.div_line_gc, + src_port_x, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2, + label_string); +#else + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.div_line_gc, + src_port_x, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2, + small_layout); +#endif + } + + /* draw the destination port number */ + if ((end_arrow != left_x_border) && (end_arrow != (user_data->dlg.pixmap_width - right_x_border))){ + g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_dst); +#if GTK_MAJOR_VERSION < 2 + label_width=gdk_string_width(small_font, label_string); + label_height=gdk_string_height(small_font, label_string); +#else + pango_layout_set_text(small_layout, label_string, -1); + pango_layout_get_pixel_size(small_layout, &label_width, &label_height); +#endif + if (start_arrow<end_arrow){ + dst_port_x = end_arrow + 2; + } + else { + dst_port_x = end_arrow - label_width - 2; + } +#if GTK_MAJOR_VERSION < 2 + gdk_draw_string(user_data->dlg.pixmap, + small_font, + user_data->dlg.div_line_gc, + dst_port_x, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2, + label_string); +#else + gdk_draw_layout(user_data->dlg.pixmap, + user_data->dlg.div_line_gc, + dst_port_x, + top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2, + small_layout); +#endif + } + + } + } + +#if GTK_MAJOR_VERSION >= 2 + g_object_unref(G_OBJECT(layout)); +#endif + + /* draw the border on the selected item */ + if ( (user_data->dlg.selected_item != 0xFFFFFFFF) && ( (user_data->dlg.selected_item>=first_item) && (user_data->dlg.selected_item<=last_item) )){ + gdk_draw_rectangle(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, + FALSE, + left_x_border-1, + (user_data->dlg.selected_item-first_item)*ITEM_HEIGHT+TOP_Y_BORDER, + user_data->dlg.pixmap_width-COMMENT_WIDTH-left_x_border+1, + ITEM_HEIGHT); + } + + + + gdk_draw_pixmap(user_data->dlg.draw_area->window, + user_data->dlg.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.draw_area)], + user_data->dlg.pixmap, + 0, 0, + 0, 0, + user_data->dlg.pixmap_width, user_data->dlg.pixmap_height); + + + /* update the h_scrollbar */ + user_data->dlg.h_scrollbar_adjustment->upper=(gfloat) user_data->num_nodes-1; + user_data->dlg.h_scrollbar_adjustment->step_increment=1; + user_data->dlg.h_scrollbar_adjustment->page_increment=(gfloat) (last_node-first_node); + user_data->dlg.h_scrollbar_adjustment->page_size=(gfloat) (last_node-first_node); + user_data->dlg.h_scrollbar_adjustment->value=(gfloat) first_node; + + gtk_adjustment_changed(user_data->dlg.h_scrollbar_adjustment); + gtk_adjustment_value_changed(user_data->dlg.h_scrollbar_adjustment); + + /* update the v_scrollbar */ + user_data->dlg.v_scrollbar_adjustment->upper=(gfloat) user_data->num_items-1; + user_data->dlg.v_scrollbar_adjustment->step_increment=1; + user_data->dlg.v_scrollbar_adjustment->page_increment=(gfloat) (last_item-first_item); + user_data->dlg.v_scrollbar_adjustment->page_size=(gfloat) (last_item-first_item); + user_data->dlg.v_scrollbar_adjustment->value=(gfloat) first_item; + + gtk_adjustment_changed(user_data->dlg.v_scrollbar_adjustment); + gtk_adjustment_value_changed(user_data->dlg.v_scrollbar_adjustment); + +} + +/****************************************************************************/ +static void dialog_graph_redraw(graph_analysis_data_t* user_data) +{ + user_data->dlg.needs_redraw=TRUE; + dialog_graph_draw(user_data); +} + +/****************************************************************************/ +static gint quit(GtkWidget *widget, GdkEventExpose *event _U_) +{ + graph_analysis_data_t *user_data; + + user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t"); + + user_data->dlg.window = NULL; + + user_data = NULL; + return TRUE; +} + +/****************************************************************************/ +static gint button_press_event(GtkWidget *widget, GdkEventButton *event _U_) +{ + graph_analysis_data_t *user_data; + guint32 item; + + user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t"); + + if (event->type != GDK_BUTTON_PRESS) return TRUE; + + if (event->y<TOP_Y_BORDER) return TRUE; + + /* get the item clicked */ + item = ((guint32)event->y - TOP_Y_BORDER) / ITEM_HEIGHT; + user_data->dlg.selected_item = item + user_data->dlg.first_item; + + user_data->dlg.needs_redraw=TRUE; + dialog_graph_draw(user_data); + + goto_frame(&cfile, user_data->dlg.items[item].frame_num); + + return TRUE; +} + +/****************************************************************************/ +static gint expose_event(GtkWidget *widget, GdkEventExpose *event) +{ + graph_analysis_data_t *user_data; + + user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t"); + if(!user_data){ + exit(10); + } + + + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + user_data->dlg.pixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +static const GdkColor COLOR_GRAY = {0, 0x7fff, 0x7fff, 0x7fff}; + +/****************************************************************************/ +static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_) +{ + graph_analysis_data_t *user_data; + int i; + GdkColor color_div_line = COLOR_GRAY; + + static GdkColor col[MAX_NUM_COL_CONV] = { + {0, 0x00FF, 0xFFFF, 0x00FF}, + {0, 0xFFFF, 0xFFFF, 0x00FF}, + {0, 0xFFFF, 0x00FF, 0x00FF}, + {0, 0xFFFF, 0x00FF, 0xFFFF}, + {0, 0x00FF, 0x00FF, 0xFFFF}, + {0, 0x00FF, 0xFFFF, 0xFFFF}, + {0, 0xFFFF, 0x80FF, 0x00FF}, + {0, 0x80FF, 0x00FF, 0xFFFF}, + {0, 0x00FF, 0x80FF, 0xFFFF}, + {0, 0xFFFF, 0x00FF, 0x80FF} + }; + + user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t"); + + if(!user_data){ + exit(10); + } + + if(user_data->dlg.pixmap){ + gdk_pixmap_unref(user_data->dlg.pixmap); + user_data->dlg.pixmap=NULL; + } + + user_data->dlg.pixmap=gdk_pixmap_new(widget->window, + widget->allocation.width, + widget->allocation.height, + -1); + user_data->dlg.pixmap_width=widget->allocation.width; + user_data->dlg.pixmap_height=widget->allocation.height; + + gdk_draw_rectangle(user_data->dlg.pixmap, + widget->style->white_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + /* create gc for division lines and set the line stype to dash*/ + user_data->dlg.div_line_gc=gdk_gc_new(user_data->dlg.pixmap); + gdk_gc_set_line_attributes(user_data->dlg.div_line_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0); +#if GTK_MAJOR_VERSION < 2 + colormap = gtk_widget_get_colormap (widget); + if (!gdk_color_alloc (colormap, &color_div_line)){ + g_warning ("Couldn't allocate color"); + } + gdk_gc_set_foreground(user_data->dlg.div_line_gc, &color_div_line); +#else + gdk_gc_set_rgb_fg_color(user_data->dlg.div_line_gc, &color_div_line); +#endif + + /* create gcs for the background items */ + + for (i=0; i<MAX_NUM_COL_CONV; i++){ + user_data->dlg.bg_gc[i]=gdk_gc_new(user_data->dlg.pixmap); +#if GTK_MAJOR_VERSION < 2 + colormap = gtk_widget_get_colormap (widget); + if (!gdk_color_alloc (colormap, &col[i])){ + g_warning ("Couldn't allocate color"); + } + gdk_gc_set_foreground(user_data->dlg.bg_gc[i], &col[i]); +#else + gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]); +#endif + } + + dialog_graph_redraw(user_data); + return TRUE; +} + +/****************************************************************************/ +static gint h_scrollbar_changed(GtkWidget *widget _U_, gpointer data) +{ + graph_analysis_data_t *user_data=(graph_analysis_data_t *)data; + + if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes) + && (user_data->dlg.h_scrollbar_adjustment->value >= user_data->dlg.first_node )) + return TRUE; + + if (user_data->dlg.first_node == (guint16) user_data->dlg.h_scrollbar_adjustment->value) + return TRUE; + + user_data->dlg.first_node = (guint16) user_data->dlg.h_scrollbar_adjustment->value; + + dialog_graph_redraw(user_data); + return TRUE; +} + +/****************************************************************************/ +static gint v_scrollbar_changed(GtkWidget *widget _U_, gpointer data) +{ + graph_analysis_data_t *user_data=(graph_analysis_data_t *)data; + if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items) + && (user_data->dlg.v_scrollbar_adjustment->value >= user_data->dlg.first_item )) + return TRUE; + + if (user_data->dlg.first_item == user_data->dlg.v_scrollbar_adjustment->value) + return TRUE; + + user_data->dlg.first_item = (guint32) user_data->dlg.v_scrollbar_adjustment->value; + + dialog_graph_redraw(user_data); + return TRUE; +} + +/****************************************************************************/ +static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box) +{ + GtkWidget *vbox; + GtkWidget *hbox; + + hbox=gtk_hbox_new(FALSE, 0); + gtk_widget_show(hbox); + + vbox=gtk_vbox_new(FALSE, 0); + gtk_widget_show(vbox); + + + user_data->dlg.draw_area=gtk_drawing_area_new(); + SIGNAL_CONNECT(user_data->dlg.draw_area, "destroy", quit, user_data); + OBJECT_SET_DATA(user_data->dlg.draw_area, "graph_analysis_data_t", user_data); + + WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height); + + /* signals needed to handle backing pixmap */ + SIGNAL_CONNECT(user_data->dlg.draw_area, "expose_event", expose_event, NULL); + SIGNAL_CONNECT(user_data->dlg.draw_area, "configure_event", configure_event, user_data); + + gtk_widget_add_events (user_data->dlg.draw_area, + GDK_BUTTON_PRESS_MASK); + SIGNAL_CONNECT(user_data->dlg.draw_area, "button_press_event", button_press_event, user_data); + + gtk_widget_show(user_data->dlg.draw_area); + gtk_box_pack_start(GTK_BOX(vbox), user_data->dlg.draw_area, TRUE, TRUE, 0); + + /* create the associated h_scrollbar */ + user_data->dlg.h_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0); + user_data->dlg.h_scrollbar=gtk_hscrollbar_new(user_data->dlg.h_scrollbar_adjustment); + gtk_widget_show(user_data->dlg.h_scrollbar); + gtk_box_pack_end(GTK_BOX(vbox), user_data->dlg.h_scrollbar, FALSE, FALSE, 0); + SIGNAL_CONNECT(user_data->dlg.h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, user_data); + + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + + /* create the associated v_scrollbar */ + user_data->dlg.v_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0); + user_data->dlg.v_scrollbar=gtk_vscrollbar_new(user_data->dlg.v_scrollbar_adjustment); + gtk_widget_show(user_data->dlg.v_scrollbar); + gtk_box_pack_end(GTK_BOX(hbox), user_data->dlg.v_scrollbar, FALSE, FALSE, 0); + SIGNAL_CONNECT(user_data->dlg.v_scrollbar_adjustment, "value_changed", v_scrollbar_changed, user_data); + + gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0); +} + + +/****************************************************************************/ +static void dialog_graph_create_window(graph_analysis_data_t* user_data) +{ + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *bt_close; + GtkWidget *label = NULL; + + /* create the main window */ + user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis"); + + + vbox=gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(user_data->dlg.window), vbox); + gtk_widget_show(vbox); + + create_draw_area(user_data, vbox); + + hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE); + window_set_cancel_button(user_data->dlg.window, bt_close, window_cancel_button_cb); + + SIGNAL_CONNECT(user_data->dlg.window, "delete_event", window_delete_event_cb, NULL); + + gtk_widget_show(user_data->dlg.window); + window_present(user_data->dlg.window); +} + +/* Return the index array if the node is in the array. Return -1 if there is room in the array + * and Return -2 if the array is full + */ +/****************************************************************************/ +gint is_node_array(graph_analysis_data_t* user_data, guint32 node) +{ + int i; + for (i=0; i<MAX_NUM_NODES; i++){ + if (user_data->nodes[i] == 0) return -1; /* it is not in the array */ + if (user_data->nodes[i] == node) return i; /* it is in the array */ + } + return -2; /* array full */ +} + + +/* Get the nodes (IPs) from the list */ +/****************************************************************************/ +void get_nodes(graph_analysis_data_t* user_data) +{ + GList* list; + graph_analysis_item_t *gai; + gint index; + + /* fill the node array */ + list = g_list_first(user_data->graph_info->list); + while (list) + { + gai = list->data; + if (gai->display){ + user_data->num_items++; + /* check source IP node */ + index = is_node_array(user_data, gai->ip_src); + switch(index){ + case -2: /* array full */ + gai->src_node = NODE_OVERFLOW; + break; + case -1: /* not in array */ + user_data->nodes[user_data->num_nodes] = gai->ip_src; + gai->src_node = user_data->num_nodes; + user_data->num_nodes++; + break; + default: /* it is in the array, just update the src_node */ + gai->src_node = (guint16)index; + } + + /* check destination IP node */ + index = is_node_array(user_data, gai->ip_dst); + switch(index){ + case -2: /* array full */ + gai->dst_node = NODE_OVERFLOW; + break; + case -1: /* not in array */ + user_data->nodes[user_data->num_nodes] = gai->ip_dst; + gai->dst_node = user_data->num_nodes; + user_data->num_nodes++; + break; + default: /* it is in the array, just update the dst_node */ + gai->dst_node = (guint16)index; + } + } + + list = g_list_next(list); + } +} + +/****************************************************************************/ +/* XXX only handles IPv4, should add IPv6 support */ +graph_analysis_data_t* graph_analysis_init() +{ + graph_analysis_data_t* user_data; + /* init */ + user_data = g_malloc(sizeof(graph_analysis_data_t)); + + /* init user_data */ + graph_analysis_init_dlg(user_data); + + return user_data; +} + +/****************************************************************************/ +void graph_analysis_create(graph_analysis_data_t* user_data) +{ + /* reset the data */ + graph_analysis_reset(user_data); + + /* get nodes (each node is an IP address) */ + get_nodes(user_data); + + /* create the graph windows */ + dialog_graph_create_window(user_data); + + /* redraw the graph */ + dialog_graph_redraw(user_data); + + return; +} + +/****************************************************************************/ +void graph_analysis_update(graph_analysis_data_t* user_data) +{ + /* reset the data */ + graph_analysis_reset(user_data); + + /* get nodes (each node is an IP address) */ + get_nodes(user_data); + + /* redraw the graph */ + dialog_graph_redraw(user_data); + + window_present(user_data->dlg.window); + return; +} Index: gtk/graph_analysis.h =================================================================== --- gtk/graph_analysis.h (revision 0) +++ gtk/graph_analysis.h (revision 0) @@ -0,0 +1,121 @@ +/* graph_analysis.h + * Graphic Analysis addition for ethereal + * + * + * + * Copyright 2004, Verso Technologies Inc. + * By Alejandro Vaquero <alejandrovaquero@xxxxxxxxx> + * + * based on rtp_analysis.c and io_stat + * + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef GRAPH_ANALYSIS_H_INCLUDED +#define GRAPH_ANALYSIS_H_INCLUDED + +#include <glib.h> +#include <gtk/gtk.h> +#include "gtkglobals.h" + +#define MAX_NUM_NODES 10 + +/* defines an entry in for the graph analysis */ +typedef struct _graph_analysis_item { + guint32 frame_num; /* frame number used to "go to" that frame */ + double time; /* frame time */ + guint32 ip_src; /* XXX we currently support only IP v4 */ + guint16 port_src; + guint32 ip_dst; + guint16 port_dst; + gchar *frame_label; /* the label on top of the arrow */ + gchar *comment; /* a comment that appears at the left of the graph */ + guint16 conv_num; /* the conversation number, each conversation will be colored */ + gboolean display; /* indicate if the packet is displayed or not in the graph */ + guint16 src_node; /* this is used by graph_analysis.c to identify the node */ + guint16 dst_node; /* a node is an IP address that will be displayed in columns */ + guint16 line_style; /* the arrow line width in pixels*/ +} graph_analysis_item_t; + +/* defines the graph analysis structure */ +typedef struct _graph_analysis_info { + int nconv; /* number of conversations in the list */ + GList* list; /* list with the graph analysis items */ +} graph_analysis_info_t; + +/* max number of nodes to display, each node will be an IP address */ +#define MAX_NUM_COL_CONV 10 +#define NODE_OVERFLOW MAX_NUM_NODES+1 +#define NUM_DISPLAY_ITEMS 1000 + +typedef struct _display_items { + guint32 frame_num; /* frame number used to "go to" that frame */ + double time; /* frame time */ + guint16 port_src; + guint16 port_dst; + gchar *frame_label; /* the label on top of the arrow */ + gchar *comment; /* a comment that appears at the left of the graph */ + guint16 conv_num; /* the conversation number, each conversation will be colored */ + guint16 src_node; /* this is used by graph_analysis.c to identify the node */ + guint16 dst_node; /* a node is an IP address that will be displayed in columns */ + guint16 line_style; /* the arrow line width in pixels*/ +} display_items_t; + +typedef struct _dialog_data_t { + GtkWidget *window; + gboolean needs_redraw; + gint selected_row; + GtkWidget *draw_area; + GdkPixmap *pixmap; + GtkAdjustment *h_scrollbar_adjustment; + GtkWidget *h_scrollbar; + GtkWidget *v_scrollbar; + GtkAdjustment *v_scrollbar_adjustment; + GdkGC *div_line_gc; + GdkGC *bg_gc[MAX_NUM_COL_CONV]; + int pixmap_width; + int pixmap_height; + guint16 first_node; /* the first node on the left to show in the screen */ + guint32 first_item; /* the first item (row) to show from the top */ + guint32 selected_item; /* the selected item */ + display_items_t items[NUM_DISPLAY_ITEMS]; + guint32 left_x_border; +} dialog_data_t; + + + +/* structure that holds general information and the dialog */ +typedef struct _graph_analysis_data_t { + /* graphic data */ + graph_analysis_info_t *graph_info; + + /* dialog associated data */ + dialog_data_t dlg; + guint32 nodes[MAX_NUM_NODES]; + guint32 num_nodes; + guint32 num_items; +} graph_analysis_data_t; + +graph_analysis_data_t* graph_analysis_init(); +void graph_analysis_create(graph_analysis_data_t* user_data); +void graph_analysis_update(graph_analysis_data_t* user_data); + + +#endif /*GRAPH_ANALYSIS_H_INCLUDED*/ Index: gtk/Makefile.common =================================================================== --- gtk/Makefile.common (revision 13162) +++ gtk/Makefile.common (working copy) @@ -84,6 +84,7 @@ text_page.c \ toolbar.c \ ui_util.c \ + voip_calls.c \ webbrowser.c @@ -102,6 +103,7 @@ conversations_wlan.c \ dcerpc_stat.c \ fc_stat.c \ + graph_analysis.c \ gsm_a_stat.c \ gsm_map_stat.c \ gsm_map_summary.c \ @@ -131,4 +133,5 @@ sip_stat.c \ smb_stat.c \ tcp_graph.c \ + voip_calls_dlg.c \ wsp_stat.c Index: gtk/voip_calls.c =================================================================== --- gtk/voip_calls.c (revision 0) +++ gtk/voip_calls.c (revision 0) @@ -0,0 +1,1312 @@ +/* voip_calls.c + * VoIP calls summary addition for ethereal + * + * $Id: voip_calls.c 12179 2004-10-01 22:09:38Z guy $ + * + * Copyright 2004, Ericsson, Spain + * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx> + * + * based on h323_calls.c + * Copyright 2004, Iskratel, Ltd, Kranj + * By Miha Jemec <m.jemec@xxxxxxxxxxx> + * + * H323, RTP and Graph Support + * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx + * Copyright 2005, Verso Technologies Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "graph_analysis.h" +#include "voip_calls.h" +#include "voip_calls_dlg.h" +#include "rtp_stream.h" + +#include "globals.h" + +#include <epan/tap.h> +#include <epan/dissectors/packet-sip.h> +#include <epan/dissectors/packet-mtp3.h> +#include <epan/dissectors/packet-isup.h> +#include <epan/dissectors/packet-h225.h> +#include <epan/dissectors/packet-h245.h> +#include <epan/dissectors/packet-q931.h> +#include <epan/dissectors/packet-sdp.h> +#include <epan/dissectors/packet-rtp.h> +#include "rtp_pt.h" + +#include "alert_box.h" +#include "simple_dialog.h" + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#include <string.h> + + +char *voip_call_state_name[6]={ + "CALL SETUP", + "IN CALL", + "CANCELLED", + "COMPLETED", + "REJECTED", + "UNKNOWN" + }; + +/* defines whether we can consider the call active */ +char *voip_protocol_name[3]={ + "SIP", + "ISUP", + "H323" + }; + + + +/****************************************************************************/ +/* the one and only global voip_calls_tapinfo_t structure */ +static voip_calls_tapinfo_t the_tapinfo_struct = + {0, NULL, 0, NULL, 0, 0, 0, 0, NULL}; + +/* static voip_calls_tapinfo_t the_tapinfo_struct; +*/ + +/****************************************************************************/ +/* when there is a [re]reading of packet's */ +void voip_calls_reset(voip_calls_tapinfo_t *tapinfo) +{ + voip_calls_info_t *strinfo; + sip_calls_info_t *tmp_sipinfo; + h323_calls_info_t *tmp_h323info; + + graph_analysis_item_t *graph_item; + + GList* list; + GList* list2; + + /* free the data items first */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + strinfo = list->data; + g_free(strinfo->from_identity); + g_free(strinfo->to_identity); + if (strinfo->protocol == VOIP_SIP){ + tmp_sipinfo = strinfo->prot_info; + g_free(tmp_sipinfo->call_identifier); + } + if (strinfo->protocol == VOIP_H323){ + tmp_h323info = strinfo->prot_info; + g_free(tmp_h323info->guid); + /* free the H245 list address */ + list2 = g_list_first(tmp_h323info->h245_list); + while (list2) + { + g_free(list2->data); + list2 = g_list_next(list2); + } + g_list_free(tmp_h323info->h245_list); + tmp_h323info->h245_list = NULL; + } + g_free(strinfo->prot_info); + + g_free(list->data); + list = g_list_next(list); + } + g_list_free(tapinfo->strinfo_list); + tapinfo->strinfo_list = NULL; + tapinfo->ncalls = 0; + tapinfo->npackets = 0; + tapinfo->start_packets = 0; + tapinfo->completed_calls = 0; + tapinfo->rejected_calls = 0; + + /* free the graph data items first */ + list = g_list_first(tapinfo->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(tapinfo->graph_analysis->list); + tapinfo->graph_analysis->nconv = 0; + tapinfo->graph_analysis->list = NULL; + + ++(tapinfo->launch_count); + + return; +} + +/****************************************************************************/ +void graph_analysis_data_init(){ + the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t)); + the_tapinfo_struct.graph_analysis->nconv = 0; + the_tapinfo_struct.graph_analysis->list = NULL; + +} + +/****************************************************************************/ +/* Add the RTP streams into the graph data */ +void add_rtp_streams_graph() +{ + rtp_stream_info_t *strinfo; + GList *strinfo_list; + guint nfound; + guint item; + GList* voip_calls_graph_list; + graph_analysis_item_t *gai; + graph_analysis_item_t *new_gai; + guint16 conv_num; + guint32 duration; + + /* Scan for rtpstream */ + rtpstream_scan(); + + /* assigne the RTP streams to calls */ + nfound = 0; + strinfo_list = g_list_first(rtpstream_get_info()->strinfo_list); + while (strinfo_list) + { + strinfo = (rtp_stream_info_t*)(strinfo_list->data); + + /* look in the voip calls graph list if there is a match for this RTP stream */ + voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list); + item = 0; + while (voip_calls_graph_list) + { + gai = voip_calls_graph_list->data; + conv_num = gai->conv_num; + if (strinfo->setup_frame_number == gai->frame_num){ + while(voip_calls_graph_list){ + gai = voip_calls_graph_list->data; + /* add the RTP item to the graph */ + if (strinfo->first_frame_num<gai->frame_num){ + new_gai = g_malloc(sizeof(graph_analysis_item_t)); + new_gai->frame_num = strinfo->first_frame_num; + new_gai->time = (double)strinfo->start_rel_sec + (double)strinfo->start_rel_usec/1000000; + g_memmove(&new_gai->ip_src, strinfo->src_addr.data, 4); + g_memmove(&new_gai->ip_dst, strinfo->dest_addr.data, 4); + new_gai->port_src = strinfo->src_port; + new_gai->port_dst = strinfo->dest_port; + duration = (strinfo->stop_rel_sec*1000000 + strinfo->stop_rel_usec) - (strinfo->start_rel_sec*1000000 + strinfo->start_rel_usec); + new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u")); + new_gai->comment = g_strdup_printf("RTP Num packets:%d Duration:%d.%03ds ssrc:%d", strinfo->npackets, duration/1000000,(duration%1000000)/1000, strinfo->ssrc); + new_gai->conv_num = conv_num; + new_gai->display=FALSE; + new_gai->line_style = 2; /* the arrow line will be 2 pixels width */ + the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item); + + break; + } + voip_calls_graph_list = g_list_next(voip_calls_graph_list); + item++; + } + break; + } + voip_calls_graph_list = g_list_next(voip_calls_graph_list); + item++; + } + strinfo_list = g_list_next(strinfo_list); + } +} + +/****************************************************************************/ +/* Add a new item into the graph */ +int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *frame_label, gchar *comment, guint16 call_num) +{ + graph_analysis_item_t *gai; + + gai = g_malloc(sizeof(graph_analysis_item_t)); + gai->frame_num = pinfo->fd->num; + gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000; + g_memmove(&gai->ip_src, pinfo->src.data, 4); + g_memmove(&gai->ip_dst, pinfo->dst.data, 4); + gai->port_src=pinfo->srcport; + gai->port_dst=pinfo->destport; + if (frame_label != NULL) + gai->frame_label = g_strdup(frame_label); + else + gai->frame_label = g_strdup(""); + + if (comment != NULL) + gai->comment = g_strdup(comment); + else + gai->comment = g_strdup(""); + gai->conv_num=call_num; + gai->line_style=1; + gai->display=FALSE; + + tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai); + + return 1; + +} + +/****************************************************************************/ +/* Append str to frame_label and comment in a graph item */ +/* return 0 if the frame_num is not in the graph list */ +int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, gchar *new_frame_label, gchar *new_comment) +{ + graph_analysis_item_t *gai; + GList* list; + gchar *tmp_str = NULL; + gchar *tmp_str2 = NULL; + + list = g_list_first(tapinfo->graph_analysis->list); + while (list) + { + gai = list->data; + if (gai->frame_num == frame_num){ + tmp_str = gai->frame_label; + tmp_str2 = gai->comment; + + if (new_frame_label != NULL){ + gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label); + g_free(tmp_str); + } + + + if (new_comment != NULL){ + gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment); + g_free(tmp_str2); + } + break; + } + list = g_list_next (list); + } + if (tmp_str == NULL) return 0; /* it is not in the list */ + return 1; + +} + +/****************************************************************************/ +/* ***************************TAP for SIP **********************************/ +/****************************************************************************/ + +/****************************************************************************/ +/* whenever a SIP packet is seen by the tap listener */ +int SIPcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *SIPinfo) +{ + + /* we just take note of the ISUP data here; when we receive the MTP3 part everything will + be compared with existing calls */ + + voip_calls_info_t *tmp_listinfo; + voip_calls_info_t *strinfo = NULL; + sip_calls_info_t *tmp_sipinfo; + GList* list; + guint32 tmp_src, tmp_dst; + gchar *frame_label = NULL; + gchar *comment = NULL; + + sip_info_value_t *pi = SIPinfo; + + /* do not consider packets without call_id */ + if (pi->tap_call_id ==NULL){ + return 0; + } + + /* check wether we already have a call with these parameters in the list */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + tmp_listinfo=list->data; + if (tmp_listinfo->protocol == VOIP_SIP){ + tmp_sipinfo = tmp_listinfo->prot_info; + if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){ + strinfo = (voip_calls_info_t*)(list->data); + break; + } + } + list = g_list_next (list); + } + + /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/ + if ((strinfo==NULL) &&(pi->request_method!=NULL)){ + if (strcmp(pi->request_method,"INVITE")==0){ + strinfo = g_malloc(sizeof(voip_calls_info_t)); + strinfo->call_active_state = VOIP_ACTIVE; + strinfo->call_state = VOIP_CALL_SETUP; + strinfo->from_identity=g_strdup(pi->tap_from_addr); + strinfo->to_identity=g_strdup(pi->tap_to_addr); + g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4); + strinfo->first_frame_num=pinfo->fd->num; + strinfo->selected=FALSE; + strinfo->start_sec=pinfo->fd->rel_secs; + strinfo->start_usec=pinfo->fd->rel_usecs; + strinfo->protocol=VOIP_SIP; + strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t)); + tmp_sipinfo=strinfo->prot_info; + tmp_sipinfo->call_identifier=strdup(pi->tap_call_id); + tmp_sipinfo->sip_state=SIP_INVITE_SENT; + tmp_sipinfo->invite_cseq=pi->tap_cseq_number; + strinfo->npackets = 0; + strinfo->call_num = tapinfo->ncalls++; + tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo); + } + } + + g_free(pi->tap_from_addr); + g_free(pi->tap_to_addr); + g_free(pi->tap_call_id); + + if (strinfo!=NULL){ + + /* let's analyze the call state */ + + g_memmove(&(tmp_src), pinfo->src.data, 4); + g_memmove(&(tmp_dst), pinfo->dst.data, 4); + + if (pi->request_method == NULL){ + frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase ); + comment = g_strdup_printf("SIP Status"); + + if ((pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){ + if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){ + tmp_sipinfo->sip_state = SIP_200_REC; + } + else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){ + strinfo->call_state = VOIP_REJECTED; + tapinfo->rejected_calls++; + } + } + + } + else{ + frame_label = g_strdup(pi->request_method); + + if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){ + tmp_sipinfo->invite_cseq = pi->tap_cseq_number; + comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity); + } + else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq) + &&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){ + strinfo->call_state = VOIP_IN_CALL; + comment = g_strdup_printf("SIP Request"); + } + else if (strcmp(pi->request_method,"BYE")==0){ + strinfo->call_state = VOIP_COMPLETED; + tapinfo->completed_calls++; + comment = g_strdup_printf("SIP Request"); + } + else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq) + &&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){ + strinfo->call_state = VOIP_CANCELLED; + tmp_sipinfo->sip_state = SIP_CANCEL_SENT; + comment = g_strdup_printf("SIP Request"); + } else { + comment = g_strdup_printf("SIP Request"); + } + } + + strinfo->stop_sec=pinfo->fd->rel_secs; + strinfo->stop_usec=pinfo->fd->rel_usecs; + strinfo->last_frame_num=pinfo->fd->num; + ++(strinfo->npackets); + /* increment the packets counter of all calls */ + ++(tapinfo->npackets); + + /* add to the graph */ + add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num); + g_free(comment); + g_free(frame_label); + } + return 1; /* refresh output */ +} + + +/****************************************************************************/ +const voip_calls_tapinfo_t* voip_calls_get_info(void) +{ + return &the_tapinfo_struct; +} + + +/****************************************************************************/ +/* TAP INTERFACE */ +/****************************************************************************/ +static gboolean have_SIP_tap_listener=FALSE; +/****************************************************************************/ +void +sip_calls_init_tap(void) +{ + GString *error_string; + + if(have_SIP_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + error_string = register_tap_listener("sip", &the_tapinfo_struct, NULL, + NULL, (void*)SIPcalls_packet, NULL); + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_SIP_tap_listener=TRUE; + } +} + + + +/* XXX just copied from gtk/rpc_stat.c */ +void protect_thread_critical_region(void); +void unprotect_thread_critical_region(void); + +/****************************************************************************/ +void +remove_tap_listener_sip_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_SIP_tap_listener=FALSE; +} + +/****************************************************************************/ +/* ***************************TAP for ISUP **********************************/ +/****************************************************************************/ + +static gchar isup_called_number[255], isup_calling_number[255]; +static guint16 isup_cic; +static guint8 isup_message_type; + +/****************************************************************************/ +/* whenever a isup_ packet is seen by the tap listener */ +int isup_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *isup_info _U_) +{ + + isup_tap_rec_t *pi = isup_info; + + if (pi->calling_number!=NULL){ + strcpy(isup_calling_number, pi->calling_number); + } + if (pi->called_number!=NULL){ + strcpy(isup_called_number, pi->called_number); + } + isup_message_type = pi->message_type; + isup_cic = pinfo->circuit_id; + + return 0; +} + +/****************************************************************************/ + +static gboolean have_isup_tap_listener=FALSE; + +void +isup_calls_init_tap(void) +{ + GString *error_string; + + + if(have_isup_tap_listener==FALSE) + { + error_string = register_tap_listener("isup", &the_tapinfo_struct, + NULL, + NULL, (void*)isup_calls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_isup_tap_listener=TRUE; + } +} + +/****************************************************************************/ + +void +remove_tap_listener_isup_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_isup_tap_listener=FALSE; +} + + +/****************************************************************************/ +/* ***************************TAP for MTP3 **********************************/ +/****************************************************************************/ + + +/****************************************************************************/ +/* whenever a mtp3_ packet is seen by the tap listener */ +int mtp3_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *mtp3_info _U_) +{ + + voip_calls_info_t *tmp_listinfo; + voip_calls_info_t *strinfo = NULL; + isup_calls_info_t *tmp_isupinfo; + gboolean found = FALSE; + gboolean forward; + gboolean right_pair = TRUE; + GList* list; + + mtp3_tap_rec_t *pi = mtp3_info; + + /* check wether we already have a call with these parameters in the list */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + tmp_listinfo=list->data; + if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){ + tmp_isupinfo = tmp_listinfo->prot_info; + if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)){ + if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){ + forward = TRUE; + } + else if ((tmp_isupinfo->dpc == pi->addr_opc.pc)&&(tmp_isupinfo->opc == pi->addr_dpc.pc)){ + forward = FALSE; + } + else{ + right_pair = FALSE; + } + if (right_pair){ + /* if there is an IAM for a call that is not in setup state, that means the previous call in the same + cic is no longer active */ + if (tmp_listinfo->call_state == VOIP_CALL_SETUP){ + found = TRUE; + } + else if (isup_message_type != 1){ + found = TRUE; + } + else{ + tmp_listinfo->call_active_state=VOIP_INACTIVE; + } + } + if (found){ + strinfo = (voip_calls_info_t*)(list->data); + break; + } + } + } + list = g_list_next (list); + } + + /* not in the list? then create a new entry if the message is IAM + -i.e. if this session is a call*/ + + + if ((strinfo==NULL) &&(isup_message_type==1)){ + + strinfo = g_malloc(sizeof(voip_calls_info_t)); + strinfo->call_active_state = VOIP_ACTIVE; + strinfo->call_state = VOIP_UNKNOWN; + g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4); + strinfo->selected=FALSE; + strinfo->first_frame_num=pinfo->fd->num; + strinfo->start_sec=pinfo->fd->rel_secs; + strinfo->start_usec=pinfo->fd->rel_usecs; + strinfo->protocol=VOIP_ISUP; + strinfo->from_identity=g_strdup(isup_calling_number); + strinfo->to_identity=g_strdup(isup_called_number); + strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t)); + tmp_isupinfo=strinfo->prot_info; + tmp_isupinfo->opc = pi->addr_opc.pc; + tmp_isupinfo->dpc = pi->addr_dpc.pc; + tmp_isupinfo->ni = pi->addr_opc.ni; + tmp_isupinfo->cic = pinfo->circuit_id; + strinfo->npackets = 0; + strinfo->call_num = tapinfo->ncalls++; + tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo); + } + + if (strinfo!=NULL){ + strinfo->stop_sec=pinfo->fd->rel_secs; + strinfo->stop_usec=pinfo->fd->rel_usecs; + strinfo->last_frame_num=pinfo->fd->num; + ++(strinfo->npackets); + + /* Let's analyze the call state */ + + switch(isup_message_type){ + case 1: /* IAM */ + strinfo->call_state=VOIP_CALL_SETUP; + break; + case 7: /* CONNECT */ + case 9: /* ANSWER */ + strinfo->call_state=VOIP_IN_CALL; + break; + case 12: /* RELEASE */ + if (strinfo->call_state==VOIP_CALL_SETUP){ + if (forward){ + strinfo->call_state=VOIP_CANCELLED; + } + else{ + strinfo->call_state=VOIP_REJECTED; + tapinfo->rejected_calls++; + } + } + else if (strinfo->call_state == VOIP_IN_CALL){ + strinfo->call_state = VOIP_COMPLETED; + tapinfo->completed_calls++; + } + break; + } + + /* increment the packets counter of all calls */ + ++(tapinfo->npackets); + } + + + return 1; +} + +/****************************************************************************/ + +static gboolean have_mtp3_tap_listener=FALSE; + +void +mtp3_calls_init_tap(void) +{ + GString *error_string; + + + if(have_mtp3_tap_listener==FALSE) + { + error_string = register_tap_listener("mtp3", &the_tapinfo_struct, + NULL, + NULL, (void*)mtp3_calls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_mtp3_tap_listener=TRUE; + } +} + +/****************************************************************************/ + +void +remove_tap_listener_mtp3_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_mtp3_tap_listener=FALSE; +} + +/****************************************************************************/ +/* ***************************TAP for Q931 **********************************/ +/****************************************************************************/ + +static gchar *q931_calling_number; +static gchar *q931_called_number; +static guint8 q931_cause_value; +static gint32 q931_crv; +static guint8 q931_message_type; +static guint32 q931_frame_num; + +/****************************************************************************/ +/* whenever a q931_ packet is seen by the tap listener */ +int q931_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *q931_info _U_) +{ + + q931_packet_info *pi = q931_info; + + /* free previously allocated q931_calling/ed_number */ + g_free(q931_calling_number); + g_free(q931_called_number); + + if (pi->calling_number!=NULL) + q931_calling_number = g_strdup(pi->calling_number); + else + q931_calling_number = g_strdup(""); + + if (pi->called_number!=NULL) + q931_called_number = g_strdup(pi->called_number); + else + q931_called_number = g_strdup(""); + q931_cause_value = pi->cause_value; + q931_frame_num = pinfo->fd->num; + q931_crv = pi->crv; + + return 0; +} + +/****************************************************************************/ +static gboolean have_q931_tap_listener=FALSE; + +void +q931_calls_init_tap(void) +{ + GString *error_string; + + + if(have_q931_tap_listener==FALSE) + { + error_string = register_tap_listener("q931", &the_tapinfo_struct, + NULL, + NULL, (void*)q931_calls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_q931_tap_listener=TRUE; + } +} + +/****************************************************************************/ + +void +remove_tap_listener_q931_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_q931_tap_listener=FALSE; +} + +/****************************************************************************/ +/****************************TAP for H323 ***********************************/ +/****************************************************************************/ + +#define GUID_LEN 16 +static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +/* defines specific H323 data */ + +void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port) +{ + h245_address_t *h245_add = NULL; + + h245_add = g_malloc(sizeof(h245_address_t)); + h245_add->h245_address = h245_address; + h245_add->h245_port = h245_port; + + h323info->h245_list = g_list_append(h323info->h245_list, h245_add); +} + +/****************************************************************************/ +/* whenever a H225 packet is seen by the tap listener */ +int H225calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *H225info) +{ + + voip_calls_info_t *tmp_listinfo; + voip_calls_info_t *strinfo = NULL; + h323_calls_info_t *tmp_h323info; + gchar *frame_label; + gchar *comment; + GList* list; + guint32 tmp_src, tmp_dst; + + h225_packet_info *pi = H225info; + + /* we ignore packets that are not displayed */ + if (pinfo->fd->flags.passed_dfilter == 0) + return 0; + + /* if not guid and RAS return because did not belong to a call */ + if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS)) + return 0; + + + if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){ + /* check wether we already have a call with this Q931 CRV */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + tmp_listinfo=list->data; + if (tmp_listinfo->protocol == VOIP_H323){ + tmp_h323info = tmp_listinfo->prot_info; + if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){ + strinfo = (voip_calls_info_t*)(list->data); + break; + } + } + list = g_list_next (list); + } + if (strinfo==NULL) return 0; + } else { + /* check wether we already have a call with this guid in the list */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + tmp_listinfo=list->data; + if (tmp_listinfo->protocol == VOIP_H323){ + tmp_h323info = tmp_listinfo->prot_info; + if (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0){ + strinfo = (voip_calls_info_t*)(list->data); + break; + } + } + list = g_list_next (list); + } + } + + /* not in the list? then create a new entry */ + if ((strinfo==NULL)){ + strinfo = g_malloc(sizeof(voip_calls_info_t)); + strinfo->call_active_state = VOIP_ACTIVE; + strinfo->call_state = VOIP_UNKNOWN; + strinfo->from_identity=g_strdup(""); + strinfo->to_identity=g_strdup(""); + + g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4); + strinfo->selected=FALSE; + strinfo->first_frame_num=pinfo->fd->num; + strinfo->start_sec=pinfo->fd->rel_secs; + strinfo->start_usec=pinfo->fd->rel_usecs; + strinfo->protocol=VOIP_H323; + strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t)); + tmp_h323info = strinfo->prot_info; + tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN); + tmp_h323info->h225SetupAddr = 0; + tmp_h323info->h245_list = NULL; + tmp_h323info->is_faststart_Setup = FALSE; + tmp_h323info->is_faststart_Proc = FALSE; + tmp_h323info->is_h245Tunneling = FALSE; + tmp_h323info->is_h245 = FALSE; + tmp_h323info->q931_crv = -1; + tmp_h323info->q931_crv2 = -1; + strinfo->call_num = tapinfo->ncalls++; + strinfo->npackets = 0; + + tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo); + } + + if (strinfo!=NULL){ + + /* let's analyze the call state */ + + g_memmove(&(tmp_src), pinfo->src.data, 4); + g_memmove(&(tmp_dst), pinfo->dst.data, 4); + + strinfo->stop_sec=pinfo->fd->rel_secs; + strinfo->stop_usec=pinfo->fd->rel_usecs; + strinfo->last_frame_num=pinfo->fd->num; + ++(strinfo->npackets); + /* increment the packets counter of all calls */ + ++(tapinfo->npackets); + + /* change the status */ + if (pi->msg_type == H225_CS){ + if (tmp_h323info->q931_crv == -1) { + tmp_h323info->q931_crv = q931_crv; + } else if (tmp_h323info->q931_crv != q931_crv) { + tmp_h323info->q931_crv2 = q931_crv; + } + + if (pi->is_h245 == TRUE){ + add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port); + } + + if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling; + + frame_label = g_strdup(pi->frame_label); + + switch(pi->cs_type){ + case H225_SETUP: + tmp_h323info->is_faststart_Setup = pi->is_faststart; + + /* set te calling and called number from the Q931 packet */ + if (q931_frame_num == pinfo->fd->num){ + if (q931_calling_number != NULL){ + g_free(strinfo->from_identity); + strinfo->from_identity=g_strdup(q931_calling_number); + } + if (q931_called_number != NULL){ + g_free(strinfo->to_identity); + strinfo->to_identity=g_strdup(q931_called_number); + } + } + if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4); + strinfo->call_state=VOIP_CALL_SETUP; + comment = g_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", strinfo->from_identity, strinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), + (pi->is_faststart==TRUE?"on":"off")); + break; + case H225_CONNECT: + strinfo->call_state=VOIP_IN_CALL; + if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE; + comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), + (pi->is_faststart==TRUE?"on":"off")); + break; + case H225_RELEASE_COMPLET: + g_memmove(&(tmp_src), pinfo->src.data, 4); + if (strinfo->call_state==VOIP_CALL_SETUP){ + if (tmp_h323info->h225SetupAddr == tmp_src){ /* forward direction */ + strinfo->call_state=VOIP_CANCELLED; + } + else{ /* reverse */ + strinfo->call_state=VOIP_REJECTED; + tapinfo->rejected_calls++; + } + } + else if (strinfo->call_state == VOIP_IN_CALL){ + strinfo->call_state = VOIP_COMPLETED; + tapinfo->completed_calls++; + } + /* get the Q931 Release cause code */ + if (q931_frame_num == pinfo->fd->num){ + if (q931_cause_value != 0xFF){ + comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>")); + } else { /* Cause not set */ + comment = g_strdup("H225 No Q931 Rel Cause"); + } + } + break; + case H225_PROGRESS: + case H225_ALERTING: + case H225_CALL_PROCEDING: + if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE; + comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), + (pi->is_faststart==TRUE?"on":"off")); + break; + default: + comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), + (pi->is_faststart==TRUE?"on":"off")); + + } + } else if (pi->msg_type == H225_RAS){ + frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>")); + comment = g_strdup("H225 RAS"); + } else { + frame_label = g_strdup("H225: Unknown"); + comment = g_strdup(""); + } + + /* add to graph analysis */ + if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) /* if the frame number exists in graph, append to it*/ + add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num); /* if not exist, add to the graph */ + + g_free(frame_label); + g_free(comment); + } + + return 1; /* refresh output */ +} + + +/****************************************************************************/ +/* TAP INTERFACE */ +/****************************************************************************/ +static gboolean have_H225_tap_listener=FALSE; +/****************************************************************************/ +void +h225_calls_init_tap(void) +{ + GString *error_string; + + if(have_H225_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + error_string = register_tap_listener("h225", &the_tapinfo_struct, NULL, + NULL, (void*)H225calls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_H225_tap_listener=TRUE; + } +} + + + +/* XXX just copied from gtk/rpc_stat.c */ +void protect_thread_critical_region(void); +void unprotect_thread_critical_region(void); + +/****************************************************************************/ +void +remove_tap_listener_h225_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_H225_tap_listener=FALSE; +} + + +/****************************************************************************/ +/* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */ +int H245dgcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *H245info) +{ + + voip_calls_info_t *tmp_listinfo; + voip_calls_info_t *strinfo = NULL; + h323_calls_info_t *tmp_h323info; + gchar *frame_label; + gchar *comment; + GList* list; + GList* list2; + guint32 tmp_src, tmp_dst; + h245_address_t *h245_add = NULL; + + h245_packet_info *pi = H245info; + + /* we ignore packets that are not displayed */ + if (pinfo->fd->flags.passed_dfilter == 0) + return 0; + + /* if H245 tunneling is on, append to graph */ + if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1; + + + /* it is not Tunneling or it is not in the list. So check if there is no tunneling + and there is a call with this H245 address */ + list = g_list_first(tapinfo->strinfo_list); + while (list) + { + tmp_listinfo=list->data; + if (tmp_listinfo->protocol == VOIP_H323){ + tmp_h323info = tmp_listinfo->prot_info; + + g_memmove(&(tmp_src), pinfo->src.data, 4); + g_memmove(&(tmp_dst), pinfo->dst.data, 4); + list2 = g_list_first(tmp_h323info->h245_list); + while (list2) + { + h245_add=list2->data; + if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport)) + || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){ + strinfo = (voip_calls_info_t*)(list->data); + + ++(strinfo->npackets); + /* increment the packets counter of all calls */ + ++(tapinfo->npackets); + + break; + } + list2 = g_list_next(list2); + } + if (strinfo!=NULL) break; + } + list = g_list_next(list); + } + + if (strinfo!=NULL){ + frame_label = g_strdup(pi->frame_label); + comment = g_strdup(pi->comment); + add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num); + g_free(frame_label); + g_free(comment); + } + + return 1; /* refresh output */ +} + + +/****************************************************************************/ +/* TAP INTERFACE */ +/****************************************************************************/ +static gboolean have_H245dg_tap_listener=FALSE; +/****************************************************************************/ +void +h245dg_calls_init_tap(void) +{ + GString *error_string; + + if(have_H245dg_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + error_string = register_tap_listener("h245dg", &the_tapinfo_struct, NULL, + NULL, (void*)H245dgcalls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_H245dg_tap_listener=TRUE; + } +} + + +/* XXX just copied from gtk/rpc_stat.c */ +void protect_thread_critical_region(void); +void unprotect_thread_critical_region(void); + +/****************************************************************************/ +void +remove_tap_listener_h245dg_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_H245dg_tap_listener=FALSE; +} + + +/****************************************************************************/ +/****************************TAP for SDP PROTOCOL ***************************/ +/****************************************************************************/ +/* whenever a SDP packet is seen by the tap listener */ +int SDPcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *SDPinfo) +{ + sdp_packet_info *pi = SDPinfo; + + /* we ignore packets that are not displayed */ + if (pinfo->fd->flags.passed_dfilter == 0) + return 0; + + /* Append to graph the SDP summary if the packet exists */ + g_snprintf(pi->summary_str, 50, "SDP (%s)", pi->summary_str); + append_to_frame_graph(tapinfo, pinfo->fd->num, pi->summary_str, NULL); + + return 1; /* refresh output */ +} + + +/****************************************************************************/ +/* TAP INTERFACE */ +/****************************************************************************/ +static gboolean have_sdp_tap_listener=FALSE; +/****************************************************************************/ +void +sdp_calls_init_tap(void) +{ + GString *error_string; + + if(have_sdp_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + error_string = register_tap_listener("sdp", &the_tapinfo_struct, NULL, + NULL, (void*)SDPcalls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_sdp_tap_listener=TRUE; + } +} + + +/* XXX just copied from gtk/rpc_stat.c */ +void protect_thread_critical_region(void); +void unprotect_thread_critical_region(void); + +/****************************************************************************/ +void +remove_tap_listener_sdp_calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_sdp_tap_listener=FALSE; +} + + + + + +/****************************************************************************/ +/* ***************************TAP for OTHER PROTOCOL **********************************/ +/****************************************************************************/ + +/****************************************************************************/ +/* redraw the output */ +/*void prot_calls_draw(voip_calls_tapinfo_t *tapinfo _U_) +{ + return; +} +*/ +/****************************************************************************/ +/* whenever a prot_ packet is seen by the tap listener */ +/*int prot_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *prot_info _U_) +{ + if (strinfo!=NULL){ + strinfo->stop_sec=pinfo->fd->rel_secs; + strinfo->stop_usec=pinfo->fd->rel_usecs; + strinfo->last_frame_num=pinfo->fd->num; + ++(strinfo->npackets); + ++(tapinfo->npackets); + } + + return 1; +} +*/ +/****************************************************************************/ +/* +static gboolean have_prot__tap_listener=FALSE; + +void +prot_calls_init_tap(void) +{ + GString *error_string; + + if(have_prot__tap_listener==FALSE) + { + error_string = register_tap_listener("prot_", &the_tapinfo_struct, + NULL, + NULL, (void*)prot_calls_packet, NULL); + + if (error_string != NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + error_string->str); + g_string_free(error_string, TRUE); + exit(1); + } + have_prot__tap_listener=TRUE; + } +} +*/ +/****************************************************************************/ +/* +void +remove_tap_listener_prot__calls(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&the_tapinfo_struct); + unprotect_thread_critical_region(); + + have_prot__tap_listener=FALSE; +} +*/ + +/****************************************************************************/ + +/*void prot_calls_reset(voip_calls_tapinfo_t *tapinfo _U_) +{ + return; +} +*/ Index: gtk/voip_calls.h =================================================================== --- gtk/voip_calls.h (revision 0) +++ gtk/voip_calls.h (revision 0) @@ -0,0 +1,191 @@ +/* voip_calls.h + * VoIP calls summary addition for ethereal + * + * $Id: voip_calls.h 12179 2004-10-01 22:09:38Z guy $ + * + * Copyright 2004, Ericsson , Spain + * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx> + * + * based on h323_calls.h + * Copyright 2004, Iskratel, Ltd, Kranj + * By Miha Jemec <m.jemec@xxxxxxxxxxx> + * + * H323, RTP and Graph Support + * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx + * Copyright 2005, Verso Technologies Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef VOIP_CALLS_H_INCLUDED +#define VOIP_CALLS_H_INCLUDED + +#include <glib.h> +#include <stdio.h> + +/****************************************************************************/ +/* defines voip call state */ +typedef enum _voip_call_state { + VOIP_CALL_SETUP, + VOIP_IN_CALL, + VOIP_CANCELLED, + VOIP_COMPLETED, + VOIP_REJECTED, + VOIP_UNKNOWN +} voip_call_state; + +extern char *voip_call_state_name[6]; + +typedef enum _voip_call_active_state { + VOIP_ACTIVE, + VOIP_INACTIVE +} voip_call_active_state; + +typedef enum _voip_protocol { + VOIP_SIP, + VOIP_ISUP, + VOIP_H323 +} voip_protocol; + +extern char *voip_protocol_name[3]; + +/* defines specific SIP data */ + +typedef enum _sip_call_state { + SIP_INVITE_SENT, + SIP_200_REC, + SIP_CANCEL_SENT +} sip_call_state; + +typedef struct _sip_calls_info { + gchar *call_identifier; + guint32 invite_cseq; + sip_call_state sip_state; +} sip_calls_info_t; + +/* defines specific ISUP data */ + +typedef struct _isup_calls_info { + guint16 cic; + guint32 opc, dpc; + guint8 ni; +} isup_calls_info_t; + +typedef struct _h245_address { + guint32 h245_address; + guint16 h245_port; +} h245_address_t; + +/* defines specific H323 data */ +typedef struct _h323_calls_info { + guint8 *guid; /* Call ID to identify a H225 */ + GList* h245_list; /* list of H245 Address and ports for tunneling off calls*/ + guint32 h225SetupAddr; /* we use the SETUP H225 IP to determine if packets are forward or reverse */ + gboolean is_h245; + gboolean is_faststart_Setup; /* if faststart field is included in Setup*/ + gboolean is_faststart_Proc; /* if faststart field is included in Proce, Alerting, Progress or Connect*/ + gboolean is_h245Tunneling; + gint32 q931_crv; + gint32 q931_crv2; +} h323_calls_info_t; + +/* defines a voip call */ +typedef struct _voip_calls_info { + voip_call_state call_state; + voip_call_active_state call_active_state; + gchar *from_identity; + gchar *to_identity; + gpointer prot_info; + guint32 initial_speaker; + guint32 npackets; + guint32 first_frame_num; /* frame number of first frame */ + guint32 last_frame_num; + voip_protocol protocol; + guint16 call_num; + gint32 start_sec, start_usec, stop_sec, stop_usec; + gboolean selected; + +} voip_calls_info_t; + +/* structure that holds the information about all detected calls */ +/* struct holding all information of the tap */ + +typedef struct _voip_calls_tapinfo { + int ncalls; /* number of calls in the list */ + GList* strinfo_list; /* list with all calls */ + int npackets; /* total number of packets of all calls */ + voip_calls_info_t* filter_calls_fwd; /* used as filter in some tap modes */ + guint32 launch_count; /* number of times the tap has been run */ + int start_packets; + int completed_calls; + int rejected_calls; + graph_analysis_info_t* graph_analysis; +} voip_calls_tapinfo_t; + + +/****************************************************************************/ +/* INTERFACE */ + +/* +* Registers the voip_calls tap listeners (if not already done). +* From that point on, the calls list will be updated with every redissection. +* This function is also the entry point for the initialization routine of the tap system. +* So whenever voip_calls.c is added to the list of ETHEREAL_TAP_SRCs, the tap will be registered on startup. +* If not, it will be registered on demand by the voip_calls functions that need it. +*/ +void sip_calls_init_tap(void); +void isup_calls_init_tap(void); +void mtp3_calls_init_tap(void); +void h225_calls_init_tap(void); +void h245dg_calls_init_tap(void); +void q931_calls_init_tap(void); +void sdp_calls_init_tap(void); + + +/* +* Removes the voip_calls tap listener (if not already done) +* From that point on, the voip calls list won't be updated any more. +*/ +void remove_tap_listener_sip_calls(void); +void remove_tap_listener_isup_calls(void); +void remove_tap_listener_mtp3_calls(void); +void remove_tap_listener_h225_calls(void); +void remove_tap_listener_h245dg_calls(void); +void remove_tap_listener_q931_calls(void); +void remove_tap_listener_sdp_calls(void); + +/* +* Retrieves a constant reference to the unique info structure of the voip_calls tap listener. +* The user should not modify the data pointed to. +*/ +const voip_calls_tapinfo_t* voip_calls_get_info(void); + +/* +* Cleans up memory of voip calls tap. +*/ +void voip_calls_reset(voip_calls_tapinfo_t *tapinfo); +void isup_calls_reset(voip_calls_tapinfo_t *tapinfo); +void mtp3_calls_reset(voip_calls_tapinfo_t *tapinfo); +void q931_calls_reset(voip_calls_tapinfo_t *tapinfo); + +void graph_analysis_data_init(); + +void add_rtp_streams_graph(); + +#endif /*VOIP_CALLS_H_INCLUDED*/ Index: epan/dissectors/packet-sip.c =================================================================== --- epan/dissectors/packet-sip.c (revision 13162) +++ epan/dissectors/packet-sip.c (working copy) @@ -605,12 +605,17 @@ char *media_type_str_lower_case = NULL; char *content_type_parameter_str = NULL; guint resend_for_packet = 0; + char *string; /* Initialise stat info for passing to tap */ stat_info = g_malloc(sizeof(sip_info_value_t)); stat_info->response_code = 0; stat_info->request_method = NULL; + stat_info->reason_phrase = NULL; stat_info->resend = 0; + stat_info->tap_call_id = NULL; + stat_info->tap_from_addr = NULL; + stat_info->tap_to_addr = NULL; /* * Note that "tvb_find_line_end()" will return a value that @@ -660,6 +665,11 @@ col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s", tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1)); } + string = tvb_get_string(tvb, SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5)); + stat_info->reason_phrase = g_malloc(linelen - (SIP2_HDR_LEN + 5) + 1); + strncpy(stat_info->reason_phrase, string, linelen - (SIP2_HDR_LEN + 5) + 1); + /* String no longer needed */ + g_free(string); break; case OTHER_LINE: @@ -843,6 +853,9 @@ parameter_len = parameter_end_offset - parameter_offset; proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset, parameter_len, FALSE); + /*info for the tap for voip_calls.c*/ + stat_info->tap_to_addr=tvb_get_string(tvb, parameter_offset, parameter_len); + parameter_offset = parameter_end_offset + 1; /* * URI parameters ? @@ -875,6 +888,8 @@ parameter_len = parameter_end_offset - parameter_offset; proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset, parameter_len, FALSE); + /*info for the tap for voip_calls.c*/ + stat_info->tap_to_addr=tvb_get_string(tvb, parameter_offset, parameter_len); offset = parameter_end_offset; } /* Find parameter tag if present. @@ -948,6 +963,8 @@ parameter_len = parameter_end_offset - parameter_offset; dfilter_store_sip_from_addr(tvb, sip_element_tree, parameter_offset, parameter_len); + /*info for the tap for voip_calls.c*/ + stat_info->tap_from_addr=tvb_get_string(tvb, parameter_offset, parameter_len); parameter_offset = parameter_end_offset + 1; /* * URI parameters ? @@ -980,6 +997,8 @@ parameter_len = parameter_end_offset - parameter_offset; proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset, parameter_len, FALSE); + /*info for the tap for voip_calls.c*/ + stat_info->tap_from_addr=tvb_get_string(tvb, parameter_offset, parameter_len); offset = parameter_end_offset; } /* Find parameter tag if present. @@ -1008,6 +1027,7 @@ /* Store the sequence number */ cseq_number = atoi(value); cseq_number_set = 1; + stat_info->tap_cseq_number=cseq_number; /* Extract method name from value */ for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++) @@ -1034,7 +1054,8 @@ strlen(value)+1 < MAX_CALL_ID_SIZE ? strlen(value)+1 : MAX_CALL_ID_SIZE); - + stat_info->tap_call_id = g_strdup(call_id); + /* Add 'Call-id' string item to tree */ if(hdr_tree) { proto_tree_add_string_format(hdr_tree, Index: epan/dissectors/packet-sip.h =================================================================== --- epan/dissectors/packet-sip.h (revision 13162) +++ epan/dissectors/packet-sip.h (working copy) @@ -31,6 +31,12 @@ gchar *request_method; guint response_code; guchar resend; + /* added for VoIP calls analysis, see gtk/voip_calls.c*/ + gchar *tap_call_id; + gchar *tap_from_addr; + gchar *tap_to_addr; + guint32 tap_cseq_number; + gchar *reason_phrase; } sip_info_value_t; extern void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset, Index: epan/dissectors/packet-h225.c =================================================================== --- epan/dissectors/packet-h225.c (revision 13162) +++ epan/dissectors/packet-h225.c (working copy) @@ -1,6 +1,6 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Ethereal dissector compiler */ -/* .\packet-h225.c */ +/* ./packet-h225.c */ /* ../../tools/asn2eth.py -X -e -p h225 -c h225.cnf -s packet-h225-template h225.asn */ /* Input file: packet-h225-template.c */ @@ -74,7 +74,9 @@ static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi); static int dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); -static h225_packet_info h225_pi; +static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H225 messaages per packet */ +static int pi_current=0; +h225_packet_info *h225_pi=NULL; static dissector_handle_t h225ras_handle; static dissector_handle_t H323UserInformation_handle; @@ -129,7 +131,7 @@ static int hf_h225_nonStandardData = -1; /* NonStandardParameter */ static int hf_h225_h4501SupplementaryService = -1; /* T_h4501SupplementaryService */ static int hf_h225_h4501SupplementaryService_item = -1; /* T_h4501SupplementaryService_item */ -static int hf_h225_h245Tunneling = -1; /* BOOLEAN */ +static int hf_h225_h245Tunneling = -1; /* T_h245Tunneling */ static int hf_h225_h245Control = -1; /* H245Control */ static int hf_h225_nonStandardControl = -1; /* SEQUENCE_OF_NonStandardParameter */ static int hf_h225_nonStandardControl_item = -1; /* NonStandardParameter */ @@ -1345,6 +1347,7 @@ proto_item_append_text(ti_tmp, ": NULL"); } + if (h225_pi->cs_type == H225_OTHER) h225_pi->cs_type = H225_EMPTY; return offset; } static int dissect_empty_flg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -2209,9 +2212,9 @@ NULL); /* we need this info for TAPing */ - h225_pi.is_h245 = TRUE; - h225_pi.h245_address = ipv4_address; - h225_pi.h245_port = ipv4_port; + h225_pi->is_h245 = TRUE; + h225_pi->h245_address = ipv4_address; + h225_pi->h245_port = ipv4_port; if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && h245_handle){ address src_addr; @@ -3506,9 +3509,6 @@ return offset; } -static int dissect_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h225_BOOLEAN(tvb, offset, pinfo, tree, hf_h225_h245Tunneling); -} static int dissect_multipleCalls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h225_BOOLEAN(tvb, offset, pinfo, tree, hf_h225_multipleCalls); } @@ -4002,7 +4002,7 @@ guint32 guid_offset,guid_len; offset = dissect_per_octet_string(tvb,offset,pinfo,tree,hf_index,16,16,&guid_offset,&guid_len); - tvb_memcpy(tvb,h225_pi.guid,guid_offset,guid_len); + tvb_memcpy(tvb,h225_pi->guid,guid_offset,guid_len); return offset; } @@ -4242,14 +4242,19 @@ dissect_h225_FastStart_item(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { guint32 newoffset; guint32 length; + char codec_str[50]; offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_h225_fastStart_item_length, &length); newoffset=offset + (length<<3); /* please note that offset is in bits in PER dissectors, but the item length is in octets */ - offset=dissect_h245_OpenLogicalChannel(tvb,offset, pinfo, tree, hf_index); + offset=dissect_h245_OpenLogicalChannelCodec(tvb,offset, pinfo, tree, hf_index, codec_str); + + /* Add to packet info */ + g_snprintf(h225_pi->frame_label, 50, "%s %s", h225_pi->frame_label, codec_str); + contains_faststart = TRUE; - h225_pi.is_faststart = TRUE; + h225_pi->is_faststart = TRUE; return newoffset; @@ -5337,7 +5342,12 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Setup_UUIE, Setup_UUIE_sequence); - h225_pi.cs_type = H225_SETUP; + /* Add to packet info */ + h225_pi->cs_type = H225_SETUP; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_setup(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5384,7 +5394,12 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_CallProceeding_UUIE, CallProceeding_UUIE_sequence); - h225_pi.cs_type = H225_CALL_PROCEDING; + /* Add to packet info */ + h225_pi->cs_type = H225_CALL_PROCEDING; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_callProceeding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5431,7 +5446,12 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Connect_UUIE, Connect_UUIE_sequence); - h225_pi.cs_type = H225_CONNECT; + /* Add to packet info */ + h225_pi->cs_type = H225_CONNECT; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_connect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5464,7 +5484,12 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Alerting_UUIE, Alerting_UUIE_sequence); - h225_pi.cs_type = H225_ALERTING; + /* Add to packet info */ + h225_pi->cs_type = H225_ALERTING; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_alerting(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5487,6 +5512,9 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Information_UUIE, Information_UUIE_sequence); + /* Add to packet info */ + h225_pi->cs_type = H225_INFORMATION; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_information(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5618,7 +5646,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_ReleaseCompleteReason, ReleaseCompleteReason_choice, "ReleaseCompleteReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -5646,7 +5674,9 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_ReleaseComplete_UUIE, ReleaseComplete_UUIE_sequence); - h225_pi.cs_type = H225_RELEASE_COMPLET; + /* Add to packet info */ + h225_pi->cs_type = H225_RELEASE_COMPLET; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_releaseComplete(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5691,7 +5721,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_FacilityReason, FacilityReason_choice, "FacilityReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; @@ -5760,6 +5790,9 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Facility_UUIE, Facility_UUIE_sequence); + /* Add to packet info */ + h225_pi->cs_type = H225_FACILITY; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_facility(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5786,6 +5819,12 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Progress_UUIE, Progress_UUIE_sequence); + /* Add to packet info */ + h225_pi->cs_type = H225_PROGRESS; + if (contains_faststart == TRUE ) + g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label); + else + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_progress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5805,6 +5844,9 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h225_Status_UUIE, Status_UUIE_sequence); + /* Add to packet info */ + h225_pi->cs_type = H225_STATUS; + g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>")); return offset; } static int dissect_status(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5917,9 +5959,9 @@ val_to_str(message_body_val, T_h323_message_body_vals, "<unknown>")); } - if (h225_pi.msg_type == H225_CS) { + if (h225_pi->msg_type == H225_CS) { /* Don't override msg_tag value from IRR */ - h225_pi.msg_tag = message_body_val; + h225_pi->msg_tag = message_body_val; } if (contains_faststart == TRUE ) @@ -5974,6 +6016,17 @@ static int +dissect_h225_T_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_h245Tunneling, &(h225_pi->is_h245Tunneling), NULL); + + return offset; +} +static int dissect_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h225_T_h245Tunneling(tvb, offset, pinfo, tree, hf_h225_h245Tunneling); +} + + +static int dissect_h225_H245Control_item(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { tvbuff_t *h245_tvb; @@ -6428,7 +6481,7 @@ static int dissect_h225_RequestSeqNum(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, - 1U, 65535U, &(h225_pi.requestSeqNum), NULL, FALSE); + 1U, 65535U, &(h225_pi->requestSeqNum), NULL, FALSE); return offset; @@ -7055,7 +7108,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_GatekeeperRejectReason, GatekeeperRejectReason_choice, "GatekeeperRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; @@ -7328,7 +7381,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_RegistrationRejectReason, RegistrationRejectReason_choice, "RegistrationRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -7390,7 +7443,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_UnregRequestReason, UnregRequestReason_choice, "UnregRequestReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; @@ -7478,7 +7531,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_UnregRejectReason, UnregRejectReason_choice, "UnregRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -7784,7 +7837,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_AdmissionRejectReason, AdmissionRejectReason_choice, "AdmissionRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -7917,7 +7970,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_BandRejectReason, BandRejectReason_choice, "BandRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -7971,7 +8024,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_DisengageReason, DisengageReason_choice, "DisengageReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -8061,7 +8114,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_DisengageRejectReason, DisengageRejectReason_choice, "DisengageRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -8212,7 +8265,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_LocationRejectReason, LocationRejectReason_choice, "LocationRejectReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -8605,7 +8658,7 @@ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index, ett_h225_InfoRequestNakReason, InfoRequestNakReason_choice, "InfoRequestNakReason", &value); - h225_pi.reason = value; + h225_pi->reason = value; return offset; } @@ -8832,7 +8885,7 @@ val_to_str(rasmessage_value, RasMessage_vals, "<unknown>")); } - h225_pi.msg_tag = rasmessage_value; + h225_pi->msg_tag = rasmessage_value; return offset; } @@ -8849,9 +8902,15 @@ proto_tree *tr; int offset = 0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h225_pi=&pi_arr[pi_current]; + /* Init struct for collecting h225_packet_info */ - reset_h225_packet_info(&(h225_pi)); - h225_pi.msg_type = H225_CS; + reset_h225_packet_info(h225_pi); + h225_pi->msg_type = H225_CS; if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0"); @@ -8865,7 +8924,7 @@ offset = dissect_h225_H323_UserInformation(tvb, offset,pinfo, tr, hf_h225_H323_UserInformation); - tap_queue_packet(h225_tap, pinfo, &h225_pi); + tap_queue_packet(h225_tap, pinfo, h225_pi); return offset; } @@ -8875,9 +8934,15 @@ proto_tree *tr; guint32 offset=0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h225_pi=&pi_arr[pi_current]; + /* Init struct for collecting h225_packet_info */ - reset_h225_packet_info(&(h225_pi)); - h225_pi.msg_type = H225_RAS; + reset_h225_packet_info(h225_pi); + h225_pi->msg_type = H225_RAS; if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0"); @@ -8888,12 +8953,13 @@ offset = dissect_h225_RasMessage(tvb, 0, pinfo,tr, hf_h225_RasMessage ); - ras_call_matching(tvb, pinfo, tr, &(h225_pi)); + ras_call_matching(tvb, pinfo, tr, h225_pi); - tap_queue_packet(h225_tap, pinfo, &h225_pi); + tap_queue_packet(h225_tap, pinfo, h225_pi); return offset; } + /*--- proto_register_h225 -------------------------------------------*/ void proto_register_h225(void) { @@ -12231,8 +12297,10 @@ pi->request_available = FALSE; pi->is_faststart = FALSE; pi->is_h245 = FALSE; + pi->is_h245Tunneling = FALSE; pi->h245_address = 0; pi->h245_port = 0; + pi->frame_label[0] = '\0'; } /* Index: epan/dissectors/packet-h225.h =================================================================== --- epan/dissectors/packet-h225.h (revision 13162) +++ epan/dissectors/packet-h225.h (working copy) @@ -1,6 +1,6 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Ethereal dissector compiler */ -/* .\packet-h225.h */ +/* ./packet-h225.h */ /* ../../tools/asn2eth.py -X -e -p h225 -c h225.cnf -s packet-h225-template h225.asn */ /* Input file: packet-h225-template.h */ @@ -40,12 +40,20 @@ } h225_msg_type; typedef enum _h225_cs_type { - H225_SETUP, - H225_CALL_PROCEDING, - H225_ALERTING, - H225_CONNECT, - H225_RELEASE_COMPLET, - H225_OTHER + H225_SETUP, + H225_CALL_PROCEDING, + H225_CONNECT, + H225_ALERTING, + H225_INFORMATION, + H225_RELEASE_COMPLET, + H225_FACILITY, + H225_PROGRESS, + H225_EMPTY, + H225_STATUS, + H225_STATUS_INQUIRY, + H225_SETUP_ACK, + H225_NOTIFY, + H225_OTHER } h225_cs_type; typedef struct _h225_packet_info { @@ -61,8 +69,10 @@ /* added for h225 conversations analysis */ gboolean is_faststart; /* true, if faststart field is included */ gboolean is_h245; + gboolean is_h245Tunneling; guint32 h245_address; guint16 h245_port; + gchar frame_label[50]; /* the Fram label used by graph_analysis, what is a abreviation of cinfo */ } h225_packet_info; /* Index: epan/dissectors/packet-q931.c =================================================================== --- epan/dissectors/packet-q931.c (revision 13162) +++ epan/dissectors/packet-q931.c (working copy) @@ -33,6 +33,7 @@ #include <glib.h> #include <string.h> #include <epan/packet.h> +#include <epan/tap.h> #include <epan/strutil.h> #include "nlpid.h" #include "packet-q931.h" @@ -54,6 +55,9 @@ * http://www.andrews-arnold.co.uk/isdn/q931cause.html * http://www.tulatelecom.ru/staff/german/DSSHelp/MessList/InfEl/InfElList.html */ +static void reset_q931_packet_info(q931_packet_info *pi); +static q931_packet_info q931_pi; +static int q931_tap = -1; static int proto_q931 = -1; static int hf_q931_discriminator = -1; @@ -1211,6 +1215,10 @@ return; octet = tvb_get_guint8(tvb, offset); cause_value = octet & 0x7F; + + /* add cause value to packet info for use in tap */ + q931_pi.cause_value = cause_value; + proto_tree_add_uint(tree, hf_cause_value, tvb, offset, 1, cause_value); proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet); offset += 1; @@ -2112,6 +2120,11 @@ } } + /* Collect q931_packet_info */ + if ( e164_info.e164_number_type == CALLING_PARTY_NUMBER) + q931_pi.calling_number = tvb_get_string(tvb, offset, len); + if ( e164_info.e164_number_type == CALLED_PARTY_NUMBER) + q931_pi.called_number = tvb_get_string(tvb, offset, len); } /* @@ -2352,6 +2365,9 @@ fragment_data *fd_head; tvbuff_t *next_tvb = NULL; + /* Init struct for collecting q931_packet_info */ + reset_q931_packet_info(&(q931_pi)); + if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.931"); @@ -2382,6 +2398,10 @@ call_ref[0] &= 0x7F; proto_tree_add_bytes(q931_tree, hf_q931_call_ref, tvb, offset, call_ref_len, call_ref); + } else + { /* info for the tap */ + call_ref[0] &= 0x7F; + g_memmove(&q931_pi.crv, call_ref, call_ref_len); } offset += call_ref_len; } @@ -2689,196 +2709,199 @@ proto_tree_add_text(q931_tree, tvb, offset + 4, tvb_reported_length_remaining(tvb, offset + 4), "Message segment"); info_element_len += tvb_reported_length_remaining(tvb, offset + 4); } - } else if (q931_tree != NULL) { - switch ((codeset << 8) | info_element) { + } else { + /* we move calling, called number and release cause to not check tree=NULL for the tap used in Voip Calls... */ + switch ((codeset << 8) | info_element){ + case CS0 | Q931_IE_CALLING_PARTY_NUMBER: + e164_info.e164_number_type = CALLING_PARTY_NUMBER; + dissect_q931_number_ie(tvb, + offset + 2, info_element_len, + ie_tree, + hf_q931_calling_party_number, e164_info); + break; + case CS0 | Q931_IE_CALLED_PARTY_NUMBER: + e164_info.e164_number_type = CALLED_PARTY_NUMBER; + dissect_q931_number_ie(tvb, + offset + 2, info_element_len, + ie_tree, + hf_q931_called_party_number, e164_info); + break; + case CS0 | Q931_IE_CAUSE: + dissect_q931_cause_ie(tvb, + offset + 2, info_element_len, + ie_tree, + hf_q931_cause_value); + break; + } + if (q931_tree != NULL) { + switch ((codeset << 8) | info_element) { - case CS0 | Q931_IE_BEARER_CAPABILITY: - case CS0 | Q931_IE_LOW_LAYER_COMPAT: - dissect_q931_bearer_capability_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_BEARER_CAPABILITY: + case CS0 | Q931_IE_LOW_LAYER_COMPAT: + dissect_q931_bearer_capability_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CAUSE: - dissect_q931_cause_ie(tvb, - offset + 2, info_element_len, - ie_tree, - hf_q931_cause_value); - break; + case CS0 | Q931_IE_CALL_STATE: + dissect_q931_call_state_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CALL_STATE: - dissect_q931_call_state_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_CHANNEL_IDENTIFICATION: + dissect_q931_channel_identification_ie( + tvb, offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CHANNEL_IDENTIFICATION: - dissect_q931_channel_identification_ie( - tvb, offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_PROGRESS_INDICATOR: + dissect_q931_progress_indicator_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_PROGRESS_INDICATOR: - dissect_q931_progress_indicator_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL: + case CS0 | Q931_IE_TRANSIT_NETWORK_SEL: + dissect_q931_ns_facilities_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL: - case CS0 | Q931_IE_TRANSIT_NETWORK_SEL: - dissect_q931_ns_facilities_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_NOTIFICATION_INDICATOR: + dissect_q931_notification_indicator_ie( + tvb, offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_NOTIFICATION_INDICATOR: - dissect_q931_notification_indicator_ie( - tvb, offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_DISPLAY: + dissect_q931_ia5_ie(tvb, offset + 2, + info_element_len, ie_tree, + "Display information"); + break; - case CS0 | Q931_IE_DISPLAY: - dissect_q931_ia5_ie(tvb, offset + 2, - info_element_len, ie_tree, - "Display information"); - break; + case CS0 | Q931_IE_DATE_TIME: + dissect_q931_date_time_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_DATE_TIME: - dissect_q931_date_time_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_KEYPAD_FACILITY: + dissect_q931_ia5_ie(tvb, offset + 2, + info_element_len, ie_tree, + "Keypad facility"); + break; - case CS0 | Q931_IE_KEYPAD_FACILITY: - dissect_q931_ia5_ie(tvb, offset + 2, - info_element_len, ie_tree, - "Keypad facility"); - break; + case CS0 | Q931_IE_SIGNAL: + dissect_q931_signal_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_SIGNAL: - dissect_q931_signal_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_INFORMATION_RATE: + dissect_q931_information_rate_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_INFORMATION_RATE: - dissect_q931_information_rate_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_E2E_TRANSIT_DELAY: + dissect_q931_e2e_transit_delay_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_E2E_TRANSIT_DELAY: - dissect_q931_e2e_transit_delay_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_TD_SELECTION_AND_INT: + dissect_q931_td_selection_and_int_ie( + tvb, offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_TD_SELECTION_AND_INT: - dissect_q931_td_selection_and_int_ie( - tvb, offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_PL_BINARY_PARAMETERS: + dissect_q931_pl_binary_parameters_ie( + tvb, offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_PL_BINARY_PARAMETERS: - dissect_q931_pl_binary_parameters_ie( - tvb, offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_PL_WINDOW_SIZE: + dissect_q931_pl_window_size_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_PL_WINDOW_SIZE: - dissect_q931_pl_window_size_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_PACKET_SIZE: + dissect_q931_packet_size_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_PACKET_SIZE: - dissect_q931_packet_size_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_CUG: + dissect_q931_cug_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CUG: - dissect_q931_cug_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_REVERSE_CHARGE_IND: + dissect_q931_reverse_charge_ind_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_REVERSE_CHARGE_IND: - dissect_q931_reverse_charge_ind_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT: + dissect_q931_number_ie(tvb, + offset + 2, info_element_len, + ie_tree, + hf_q931_connected_number, e164_info); + break; - case CS0 | Q931_IE_CALLING_PARTY_NUMBER: - e164_info.e164_number_type = CALLING_PARTY_NUMBER; - dissect_q931_number_ie(tvb, - offset + 2, info_element_len, - ie_tree, - hf_q931_calling_party_number, e164_info); - break; + case CS0 | Q931_IE_REDIRECTING_NUMBER: + dissect_q931_number_ie(tvb, + offset + 2, info_element_len, + ie_tree, + hf_q931_redirecting_number, e164_info); + break; - case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT: - dissect_q931_number_ie(tvb, - offset + 2, info_element_len, - ie_tree, - hf_q931_connected_number, e164_info); - break; + case CS0 | Q931_IE_CALLING_PARTY_SUBADDR: + case CS0 | Q931_IE_CALLED_PARTY_SUBADDR: + dissect_q931_party_subaddr_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CALLED_PARTY_NUMBER: - e164_info.e164_number_type = CALLED_PARTY_NUMBER; - dissect_q931_number_ie(tvb, - offset + 2, info_element_len, - ie_tree, - hf_q931_called_party_number, e164_info); - break; + case CS0 | Q931_IE_RESTART_INDICATOR: + dissect_q931_restart_indicator_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_REDIRECTING_NUMBER: - dissect_q931_number_ie(tvb, - offset + 2, info_element_len, - ie_tree, - hf_q931_redirecting_number, e164_info); - break; + case CS0 | Q931_IE_HIGH_LAYER_COMPAT: + dissect_q931_high_layer_compat_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_CALLING_PARTY_SUBADDR: - case CS0 | Q931_IE_CALLED_PARTY_SUBADDR: - dissect_q931_party_subaddr_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; + case CS0 | Q931_IE_USER_USER: + dissect_q931_user_user_ie(tvb, + offset + 2, info_element_len, + ie_tree); + break; - case CS0 | Q931_IE_RESTART_INDICATOR: - dissect_q931_restart_indicator_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; - - case CS0 | Q931_IE_HIGH_LAYER_COMPAT: - dissect_q931_high_layer_compat_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; - - case CS0 | Q931_IE_USER_USER: - dissect_q931_user_user_ie(tvb, - offset + 2, info_element_len, - ie_tree); - break; - - default: - proto_tree_add_text(ie_tree, tvb, - offset + 2, info_element_len, - "Data: %s", - bytes_to_str( - tvb_get_ptr(tvb, offset + 2, - info_element_len), - info_element_len)); - break; + default: + proto_tree_add_text(ie_tree, tvb, + offset + 2, info_element_len, + "Data: %s", + bytes_to_str( + tvb_get_ptr(tvb, offset + 2, + info_element_len), + info_element_len)); + break; + } } } offset += 1 + 1 + info_element_len; } codeset = locked_codeset; } + tap_queue_packet(q931_tap, pinfo, &q931_pi); } /* @@ -3143,6 +3166,8 @@ "Reassemble segmented Q.931 messages", "Reassemble segmented Q.931 messages (Q.931 - Annex H)", &q931_reassembly); + /* Register for tapping */ + q931_tap = register_tap("q931"); } void @@ -3166,3 +3191,17 @@ */ heur_dissector_add("tcp", dissect_q931_tpkt, proto_q931); } + +static void reset_q931_packet_info(q931_packet_info *pi) +{ + if(pi == NULL) { + return; + } + + g_free(pi->calling_number); + g_free(pi->called_number); + pi->calling_number = NULL; + pi->called_number = NULL; + pi->cause_value = 0xFF; + pi->crv = -1; +} Index: epan/dissectors/packet-q931.h =================================================================== --- epan/dissectors/packet-q931.h (revision 13162) +++ epan/dissectors/packet-q931.h (working copy) @@ -44,8 +44,20 @@ extern const value_string q931_cause_location_vals[]; -extern const value_string q931_cause_code_vals[]; +typedef struct _q931_packet_info { + gchar *calling_number; + gchar *called_number; + guint8 cause_value; + gint32 crv; +} q931_packet_info; +/* + * the following allows TAP code access to the messages + * without having to duplicate it. With MSVC and a + * libethereal.dll, we need a special declaration. + */ +ETH_VAR_IMPORT const value_string q931_cause_code_vals[]; + extern const value_string q931_protocol_discriminator_vals[]; #endif Index: epan/dissectors/packet-sdp.c =================================================================== --- epan/dissectors/packet-sdp.c (revision 13162) +++ epan/dissectors/packet-sdp.c (working copy) @@ -57,6 +57,9 @@ #include <epan/conversation.h> #include <epan/strutil.h> +#include "tap.h" +#include "packet-sdp.h" + #include "packet-rtp.h" #include "rtp_pt.h" #include "packet-rtcp.h" @@ -68,6 +71,10 @@ static dissector_handle_t t38_handle=NULL; +static void reset_sdp_packet_info(sdp_packet_info *pi); +static int sdp_tap = -1; +static sdp_packet_info *sdp_pi; + static int proto_sdp = -1; /* Top level fields */ @@ -213,6 +220,10 @@ guint32 ipaddr[4]; gint n; + /* Initialise packet info for passing to tap */ + sdp_pi = g_malloc(sizeof(sdp_packet_info)); + sdp_pi->summary_str[0] = '\0'; + /* Initialise RTP channel info */ transport_info.connection_address=NULL; transport_info.connection_type=NULL; @@ -436,6 +447,8 @@ proto_tree_add_text(sdp_tree, tvb, offset, datalen, "Data (%d bytes)", datalen); } + /* Report this packet to the tap */ + tap_queue_packet(sdp_tap, pinfo, sdp_pi); } static void @@ -884,6 +897,7 @@ media_format = tvb_get_string(tvb, offset, tokenlen); proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset, tokenlen, val_to_str(atol(media_format), rtp_payload_type_vals, "%u")); + g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, val_to_str(atol(media_format), rtp_payload_type_short_vals, "%u")); g_free(media_format); } else { proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, @@ -1167,6 +1181,9 @@ * on Windows without stuffing it into the Big Transfer Vector). */ register_dissector("sdp", dissect_sdp, proto_sdp); + + /* Register for tapping */ + sdp_tap = register_tap("sdp"); } void Index: epan/dissectors/packet-sdp.h =================================================================== --- epan/dissectors/packet-sdp.h (revision 0) +++ epan/dissectors/packet-sdp.h (revision 0) @@ -0,0 +1,31 @@ +/* packet-sdp.h + * Routines for SDP packet disassembly (RFC 2327) + * + * Jason Lango <jal@xxxxxxxxxx> + * Liberally copied from packet-http.c, by Guy Harris <guy@xxxxxxxxxxxx> + * 2005 Alejandro Vaquero <alejandro.vaquero@xxxxxxxxx>, add support for tap + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +typedef struct _sdp_packet_info { + gchar summary_str[50]; /* SDP summary string for VoIP calls graph analysis */ +} sdp_packet_info; Index: epan/dissectors/packet-h245.c =================================================================== --- epan/dissectors/packet-h245.c (revision 13162) +++ epan/dissectors/packet-h245.c (working copy) @@ -1,6 +1,6 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Ethereal dissector compiler */ -/* .\packet-h245.c */ +/* ./packet-h245.c */ /* ../../tools/asn2eth.py -X -e -p h245 -c h245.cnf -s packet-h245-template h245.asn */ /* Input file: packet-h245-template.c */ @@ -77,7 +77,10 @@ static int hf_h245Manufacturer = -1; static int h245_tap = -1; static int ett_h245 = -1; -static h245_packet_info h245_pi; +static int h245dg_tap = -1; +static h245_packet_info pi_arr[5]; /* We assuming a maximum of 5 H245 messaages per packet */ +static int pi_current=0; +h245_packet_info *h245_pi=NULL; static gboolean h245_reassembly = TRUE; static gboolean h245_shorttypes = FALSE; @@ -171,6 +174,34 @@ { 12, "GC" }, { 0, NULL } }; +static const value_string h245_AudioCapability_short_vals[] = { + { 0, "nonStd" }, + { 1, "g711A" }, + { 2, "g711A56k" }, + { 3, "g711U" }, + { 4, "g711U56k" }, + { 5, "g722-64k" }, + { 6, "g722-56k" }, + { 7, "g722-48k" }, + { 8, "g7231" }, + { 9, "g728" }, + { 10, "g729" }, + { 11, "g729A" }, + { 12, "is11172" }, + { 13, "is13818" }, + { 14, "g729B" }, + { 15, "g729AB" }, + { 16, "g7231C" }, + { 17, "gsmFR" }, + { 18, "gsmHR" }, + { 19, "gsmEFR" }, + { 20, "generic" }, + { 21, "g729Ext" }, + { 22, "vbd" }, + { 23, "audioTelEvent" }, + { 24, "audioTone" }, + { 0, NULL } +}; /* To put the codec type only in COL_INFO when an OLC is read */ @@ -2418,7 +2449,7 @@ ett_h245_MasterSlaveDetermination, MasterSlaveDetermination_sequence); - h245_pi.msg_type = H245_MastSlvDet; + h245_pi->msg_type = H245_MastSlvDet; return offset; } static int dissect_masterSlaveDetermination(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -5460,6 +5491,7 @@ &value); codec_type = val_to_str(value, h245_Application_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type); return offset; } @@ -7226,7 +7258,9 @@ &value); codec_type = val_to_str(value, h245_VideoCapability_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type); + return offset; } @@ -7595,8 +7629,10 @@ ett_h245_AudioCapability, AudioCapability_choice, "AudioCapability", &value); - codec_type = val_to_str(value, h245_AudioCapability_vals, "<unknown>"); + codec_type = val_to_str(value, h245_AudioCapability_short_vals, "<unknown>"); + if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, val_to_str(value, h245_AudioCapability_short_vals, "ukn")); + return offset; } @@ -8187,7 +8223,7 @@ ett_h245_TerminalCapabilitySet, TerminalCapabilitySet_sequence); - h245_pi.msg_type = H245_TermCapSet; + h245_pi->msg_type = H245_TermCapSet; return offset; } static int dissect_terminalCapabilitySet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -10089,7 +10125,7 @@ ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence); - h245_pi.msg_type = H245_OpenLogChn; + if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; return offset; } static int dissect_openLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -10161,7 +10197,7 @@ ett_h245_CloseLogicalChannel, CloseLogicalChannel_sequence); - h245_pi.msg_type = H245_CloseLogChn; + h245_pi->msg_type = H245_CloseLogChn; return offset; } static int dissect_closeLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12166,6 +12202,20 @@ col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + + /* if it is TCS*/ + if ((codec_type != NULL) && ( value == 2)) + g_snprintf(h245_pi->frame_label, 50, "%s (%s) ",val_to_str(value, h245_RequestMessage_short_vals, "UKN"), h245_pi->frame_label); + else + g_snprintf(h245_pi->frame_label, 50, "%s ", val_to_str(value, h245_RequestMessage_short_vals, "UKN")); + + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_RequestMessage_vals, "<unknown>")); + + /* if it is OLC or RM*/ + if ((codec_type != NULL) && (( value == 3) || ( value == 8))) + g_snprintf(h245_pi->frame_label, 50, "%s (%s) ", h245_pi->frame_label, codec_type); + return offset; } static int dissect_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12208,7 +12258,7 @@ ett_h245_MasterSlaveDeterminationAck, MasterSlaveDeterminationAck_sequence); - h245_pi.msg_type = H245_MastSlvDetAck; + h245_pi->msg_type = H245_MastSlvDetAck; return offset; } static int dissect_masterSlaveDeterminationAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12249,7 +12299,7 @@ ett_h245_MasterSlaveDeterminationReject, MasterSlaveDeterminationReject_sequence); - h245_pi.msg_type = H245_MastSlvDetRjc; + h245_pi->msg_type = H245_MastSlvDetRjc; return offset; } static int dissect_masterSlaveDeterminationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12267,7 +12317,7 @@ ett_h245_TerminalCapabilitySetAck, TerminalCapabilitySetAck_sequence); - h245_pi.msg_type = H245_TermCapSetAck; + h245_pi->msg_type = H245_TermCapSetAck; return offset; } static int dissect_terminalCapabilitySetAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12340,7 +12390,7 @@ ett_h245_TerminalCapabilitySetReject, TerminalCapabilitySetReject_sequence); - h245_pi.msg_type = H245_TermCapSetRjc; + h245_pi->msg_type = H245_TermCapSetRjc; return offset; } static int dissect_terminalCapabilitySetReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12510,7 +12560,7 @@ ett_h245_OpenLogicalChannelAck, OpenLogicalChannelAck_sequence); - h245_pi.msg_type = H245_OpenLogChnAck; + h245_pi->msg_type = H245_OpenLogChnAck; return offset; } static int dissect_openLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12578,7 +12628,7 @@ ett_h245_OpenLogicalChannelReject, OpenLogicalChannelReject_sequence); - h245_pi.msg_type = H245_OpenLogChnRjc; + h245_pi->msg_type = H245_OpenLogChnRjc; return offset; } static int dissect_openLogicalChannelReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12596,7 +12646,7 @@ ett_h245_CloseLogicalChannelAck, CloseLogicalChannelAck_sequence); - h245_pi.msg_type = H245_CloseLogChnAck; + h245_pi->msg_type = H245_CloseLogChnAck; return offset; } static int dissect_closeLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -13867,6 +13917,10 @@ col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_ResponseMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_ResponseMessage_vals, "<unknown>")); + return offset; } static int dissect_response(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -15032,7 +15086,11 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_CommandMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_CommandMessage_vals, "<unknown>")); + return offset; } static int dissect_command(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -15076,7 +15134,7 @@ ett_h245_MasterSlaveDeterminationRelease, MasterSlaveDeterminationRelease_sequence); - h245_pi.msg_type = H245_MastSlvDetRls; + h245_pi->msg_type = H245_MastSlvDetRls; return offset; } static int dissect_masterSlaveDeterminationRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -15093,7 +15151,7 @@ ett_h245_TerminalCapabilitySetRelease, TerminalCapabilitySetRelease_sequence); - h245_pi.msg_type = H245_TermCapSetRls; + h245_pi->msg_type = H245_TermCapSetRls; return offset; } static int dissect_terminalCapabilitySetRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -15111,7 +15169,7 @@ ett_h245_OpenLogicalChannelConfirm, OpenLogicalChannelConfirm_sequence); - h245_pi.msg_type = H245_OpenLogChnCnf; + h245_pi->msg_type = H245_OpenLogChnCnf; return offset; } static int dissect_openLogicalChannelConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -16193,6 +16251,9 @@ } col_set_fence(pinfo->cinfo,COL_INFO); + /* Add to packet info */ + g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_IndicationMessage_short_vals, "UKN")); + g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_IndicationMessage_vals, "<unknown>")); return offset; } @@ -16255,12 +16316,18 @@ void dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { - reset_h245_packet_info(&(h245_pi)); - h245_pi.msg_type = H245_OTHER; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h245_pi=&pi_arr[pi_current]; + reset_h245_packet_info(h245_pi); + h245_pi->msg_type = H245_OTHER; + dissect_tpkt_encap(tvb, pinfo, parent_tree, h245_reassembly, MultimediaSystemControlMessage_handle); - tap_queue_packet(h245_tap, pinfo, &h245_pi); + tap_queue_packet(h245_tap, pinfo, h245_pi); } void @@ -16270,7 +16337,15 @@ proto_tree *tr; guint32 offset=0; + pi_current++; + if(pi_current==5){ + pi_current=0; + } + h245_pi=&pi_arr[pi_current]; + reset_h245_packet_info(h245_pi); + h245_pi->msg_type = H245_OTHER; + if (check_col(pinfo->cinfo, COL_PROTOCOL)){ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.245"); } @@ -16278,9 +16353,24 @@ it=proto_tree_add_protocol_format(parent_tree, proto_h245, tvb, 0, tvb_length(tvb), "H.245"); tr=proto_item_add_subtree(it, ett_h245); dissect_h245_MultimediaSystemControlMessage(tvb, offset, pinfo ,tr, hf_h245_pdu_type); + tap_queue_packet(h245dg_tap, pinfo, h245_pi); } +int +dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str) { + offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, + ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence); + + if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; + + if (codec_str){ + strcpy(codec_str, codec_type); + } + + return offset; +} + /*--- proto_register_h245 -------------------------------------------*/ void proto_register_h245(void) { @@ -22148,6 +22238,7 @@ nsp_object_dissector_table = register_dissector_table("h245.nsp.object", "H.245 NonStandardParameter (object)", FT_STRING, BASE_NONE); nsp_h221_dissector_table = register_dissector_table("h245.nsp.h221", "H.245 NonStandardParameter (h221)", FT_UINT32, BASE_HEX); h245_tap = register_tap("h245"); + h245dg_tap = register_tap("h245dg"); register_ber_oid_name("0.0.8.239.1.1","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ControlCapability(1)"); register_ber_oid_name("0.0.8.239.1.2","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ExtendedVideoCapability(2)"); @@ -22187,5 +22278,7 @@ } pi->msg_type = H245_OTHER; + pi->frame_label[0] = '\0'; + sprintf(pi->comment, "H245 "); } Index: epan/dissectors/packet-h245.h =================================================================== --- epan/dissectors/packet-h245.h (revision 13162) +++ epan/dissectors/packet-h245.h (working copy) @@ -1,6 +1,6 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Ethereal dissector compiler */ -/* .\packet-h245.h */ +/* ./packet-h245.h */ /* ../../tools/asn2eth.py -X -e -p h245 -c h245.cnf -s packet-h245-template h245.asn */ /* Input file: packet-h245-template.h */ @@ -52,6 +52,8 @@ typedef struct _h245_packet_info { h245_msg_type msg_type; /* type of message */ + gchar frame_label[50]; /* the Frame label used by graph_analysis, what is a abreviation of cinfo */ + gchar comment[50]; /* the Frame Comment used by graph_analysis, what is a message desc */ } h245_packet_info; @@ -65,7 +67,9 @@ /*--- End of included file: packet-h245-exp.h ---*/ +int dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str); + #endif /* PACKET_H245_H */ Index: epan/dissectors/packet-isup.c =================================================================== --- epan/dissectors/packet-isup.c (revision 13162) +++ epan/dissectors/packet-isup.c (working copy) @@ -1315,6 +1315,10 @@ static dissector_handle_t sdp_handle = NULL; static dissector_handle_t q931_ie_handle = NULL; +/* Info for the tap that must be passed between procedures */ +gchar *tap_called_number = NULL; +gchar *tap_calling_number = NULL; + /* ------------------------------------------------------------------ Mapping number to ASCII-character ------------------------------------------------------------------ */ @@ -1461,6 +1465,7 @@ proto_tree_add_string(address_digits_tree, hf_isup_called, parameter_tvb, offset - length, length, called_number); } + tap_called_number = g_strdup(called_number); } /* ------------------------------------------------------------------ Dissector Parameter Subsequent number @@ -2868,8 +2873,8 @@ } else { proto_tree_add_string(address_digits_tree, hf_isup_calling, parameter_tvb, offset - length, length, calling_number); - } + tap_calling_number = g_strdup(calling_number); } /* ------------------------------------------------------------------ Dissector Parameter Original called number @@ -5143,9 +5148,9 @@ offset += MESSAGE_TYPE_LENGTH; tap_rec.message_type = message_type; + tap_rec.calling_number = NULL; + tap_rec.called_number = NULL; - tap_queue_packet(isup_tap, pinfo, &tap_rec); - parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1); /* distinguish between message types:*/ @@ -5359,7 +5364,11 @@ } else if (message_type !=MESSAGE_TYPE_CHARGE_INFO) proto_tree_add_text(isup_tree, message_tvb, 0, 0, "No optional parameters are possible with this message type"); + /* if there are calling/called number, we'll get them for the tap */ + tap_rec.calling_number=tap_calling_number; + tap_rec.called_number=tap_called_number; + tap_queue_packet(isup_tap, pinfo, &tap_rec); } /* ------------------------------------------------------------------ */ Index: epan/dissectors/packet-isup.h =================================================================== --- epan/dissectors/packet-isup.h (revision 13162) +++ epan/dissectors/packet-isup.h (working copy) @@ -28,6 +28,9 @@ typedef struct _isup_tap_rec_t { guint8 message_type; + /* added for VoIP calls analysis, see gtk/voip_calls.c*/ + gchar *called_number; + gchar *calling_number; } isup_tap_rec_t; Index: epan/dissectors/packet-rtp.c =================================================================== --- epan/dissectors/packet-rtp.c (revision 13162) +++ epan/dissectors/packet-rtp.c (working copy) @@ -190,6 +190,38 @@ { 0, NULL }, }; +const value_string rtp_payload_type_short_vals[] = +{ + { PT_PCMU, "g711U" }, + { PT_1016, "fs-1016" }, + { PT_G721, "g721" }, + { PT_GSM, "GSM" }, + { PT_G723, "g723" }, + { PT_DVI4_8000, "DVI4 8k" }, + { PT_DVI4_16000, "DVI4 16k" }, + { PT_LPC, "Exp. from Xerox PARC" }, + { PT_PCMA, "g711A" }, + { PT_G722, "g722" }, + { PT_L16_STEREO, "16-bit audio, stereo" }, + { PT_L16_MONO, "16-bit audio, monaural" }, + { PT_QCELP, "Qualcomm" }, + { PT_CN, "CN" }, + { PT_MPA, "MPEG-I/II Audio"}, + { PT_G728, "g728" }, + { PT_DVI4_11025, "DVI4 11k" }, + { PT_DVI4_22050, "DVI4 22k" }, + { PT_G729, "g729" }, + { PT_CN_OLD, "CN(old)" }, + { PT_CELB, "CellB" }, + { PT_JPEG, "JPEG" }, + { PT_NV, "NV" }, + { PT_H261, "h261" }, + { PT_MPV, "MPEG-I/II Video"}, + { PT_MP2T, "MPEG-II streams"}, + { PT_H263, "h263" }, + { 0, NULL }, +}; + /* Set up an RTP conversation */ void rtp_add_address(packet_info *pinfo, address *addr, int port, Index: epan/libethereal.def =================================================================== --- epan/libethereal.def (revision 13162) +++ epan/libethereal.def (working copy) @@ -424,6 +424,7 @@ proto_tree_get_parent p_add_proto_data p_get_proto_data +q931_cause_code_vals DATA range_convert_range range_convert_str range_copy @@ -464,6 +465,7 @@ rtcp_add_address rtp_add_address rtp_payload_type_vals DATA +rtp_payload_type_short_vals DATA set_actual_length set_timestamp_setting show_fragment_seq_tree
- Follow-Ups:
- Re: [Ethereal-dev] Voip Calls analysis and Graph analysis
- From: Lars Roland
- Re: [Ethereal-dev] Voip Calls analysis and Graph analysis
- Prev by Date: [Ethereal-dev] 0.10.9: plugins/mate/mate.h - attributes in prototypes for unnamed pointers
- Next by Date: Re: [Ethereal-dev] 0.10.9: plugins/mate/mate.h - attributes in prototypes for unnamed pointers
- Previous by thread: Re: [Ethereal-dev] 0.10.9: plugins/mate/mate.h - attributes in prototypes for unnamed pointers
- Next by thread: Re: [Ethereal-dev] Voip Calls analysis and Graph analysis
- Index(es):