aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/asn1/h225/packet-h225-template.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/asn1/h225/packet-h225-template.c')
-rw-r--r--epan/dissectors/asn1/h225/packet-h225-template.c1184
1 files changed, 1184 insertions, 0 deletions
diff --git a/epan/dissectors/asn1/h225/packet-h225-template.c b/epan/dissectors/asn1/h225/packet-h225-template.c
new file mode 100644
index 0000000000..1fbfe4a07a
--- /dev/null
+++ b/epan/dissectors/asn1/h225/packet-h225-template.c
@@ -0,0 +1,1184 @@
+/* packet-h225.c
+ * Routines for h225 packet dissection
+ * Copyright 2005, Anders Broman <anders.broman@ericsson.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * To quote the author of the previous H323/H225/H245 dissector:
+ * "This is a complete replacement of the previous limitied dissector
+ * that Ronnie was crazy enough to write by hand. It was a lot of time
+ * to hack it by hand, but it is incomplete and buggy and it is good when
+ * it will go away."
+ * Ronnie did a great job and all the VoIP users had made good use of it!
+ * Credit to Tomas Kukosa for developing the asn2wrs compiler.
+ *
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <epan/prefs.h>
+#include <epan/oids.h>
+#include <epan/next_tvb.h>
+#include <epan/asn1.h>
+#include <epan/t35.h>
+#include <epan/tap.h>
+#include <epan/stat_tap_ui.h>
+#include <epan/rtd_table.h>
+#include "packet-tpkt.h"
+#include "packet-per.h"
+#include "packet-h225.h"
+#include "packet-h235.h"
+#include "packet-h245.h"
+#include "packet-h323.h"
+#include "packet-q931.h"
+#include "packet-ssl.h"
+
+#define PNAME "H323-MESSAGES"
+#define PSNAME "H.225.0"
+#define PFNAME "h225"
+
+#define UDP_PORT_RAS1 1718
+#define UDP_PORT_RAS2 1719
+#define TCP_PORT_CS 1720
+#define TLS_PORT_CS 1300
+
+void proto_register_h225(void);
+static void reset_h225_packet_info(h225_packet_info *pi);
+static void h225_init_routine(void);
+static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
+
+/* Item of ras request list*/
+typedef struct _h225ras_call_t {
+ guint32 requestSeqNum;
+ e_guid_t guid;
+ guint32 req_num; /* frame number request seen */
+ guint32 rsp_num; /* frame number response seen */
+ nstime_t req_time; /* arrival time of request */
+ gboolean responded; /* true, if request has been responded */
+ struct _h225ras_call_t *next_call; /* pointer to next ras request with same SequenceNumber and conversation handle */
+} h225ras_call_t;
+
+
+/* Item of ras-request key list*/
+typedef struct _h225ras_call_info_key {
+ guint reqSeqNum;
+ conversation_t *conversation;
+} h225ras_call_info_key;
+
+static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H.225 messages per packet */
+static int pi_current=0;
+static h225_packet_info *h225_pi=&pi_arr[0];
+
+/* Global Memory Chunks for lists and Global hash tables*/
+
+static GHashTable *ras_calls[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+/* functions, needed using ras-request and halfcall matching*/
+static h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category);
+static h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category);
+static h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category);
+
+static dissector_handle_t data_handle;
+/* Subdissector tables */
+static dissector_table_t nsp_object_dissector_table;
+static dissector_table_t nsp_h221_dissector_table;
+static dissector_table_t tp_dissector_table;
+static dissector_table_t gef_name_dissector_table;
+static dissector_table_t gef_content_dissector_table;
+
+
+static dissector_handle_t h245_handle=NULL;
+static dissector_handle_t h245dg_handle=NULL;
+static dissector_handle_t h4501_handle=NULL;
+
+static dissector_handle_t nsp_handle;
+static dissector_handle_t tp_handle;
+
+static next_tvb_list_t h245_list;
+static next_tvb_list_t tp_list;
+
+/* Initialize the protocol and registered fields */
+static int h225_tap = -1;
+static int proto_h225 = -1;
+
+static int hf_h221Manufacturer = -1;
+static int hf_h225_ras_req_frame = -1;
+static int hf_h225_ras_rsp_frame = -1;
+static int hf_h225_ras_dup = -1;
+static int hf_h225_ras_deltatime = -1;
+static int hf_h225_debug_dissector_try_string = -1;
+
+#include "packet-h225-hf.c"
+
+/* Initialize the subtree pointers */
+static gint ett_h225 = -1;
+#include "packet-h225-ett.c"
+
+/* Preferences */
+static guint h225_tls_port = TLS_PORT_CS;
+static gboolean h225_reassembly = TRUE;
+static gboolean h225_h245_in_tree = TRUE;
+static gboolean h225_tp_in_tree = TRUE;
+
+/* Global variables */
+static guint32 ipv4_address;
+static struct e_in6_addr ipv6_address;
+static struct e_in6_addr ipv6_address_zeros = {{0}};
+static guint32 ip_port;
+static gboolean contains_faststart = FALSE;
+static e_guid_t *call_id_guid;
+
+/* NonStandardParameter */
+static const char *nsiOID;
+static guint32 h221NonStandard;
+static guint32 t35CountryCode;
+static guint32 t35Extension;
+static guint32 manufacturerCode;
+
+/* TunnelledProtocol */
+static const char *tpOID;
+
+static const value_string ras_message_category[] = {
+ { 0, "Gatekeeper "},
+ { 1, "Registration "},
+ { 2, "UnRegistration"},
+ { 3, "Admission "},
+ { 4, "Bandwidth "},
+ { 5, "Disengage "},
+ { 6, "Location "},
+ { 0, NULL }
+};
+
+typedef enum _ras_type {
+ RAS_REQUEST,
+ RAS_CONFIRM,
+ RAS_REJECT,
+ RAS_OTHER
+}ras_type;
+
+typedef enum _ras_category {
+ RAS_GATEKEEPER,
+ RAS_REGISTRATION,
+ RAS_UNREGISTRATION,
+ RAS_ADMISSION,
+ RAS_BANDWIDTH,
+ RAS_DISENGAGE,
+ RAS_LOCATION,
+ RAS_OTHERS
+}ras_category;
+
+#define NUM_RAS_STATS 7
+
+static gboolean
+h225rassrt_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
+{
+ rtd_data_t* rtd_data = (rtd_data_t*)phs;
+ rtd_stat_table* rs = &rtd_data->stat_table;
+ const h225_packet_info *pi=(const h225_packet_info *)phi;
+
+ ras_type rasmsg_type = RAS_OTHER;
+ ras_category rascategory = RAS_OTHERS;
+
+ if (pi->msg_type != H225_RAS || pi->msg_tag == -1) {
+ /* No RAS Message or uninitialized msg_tag -> return */
+ return FALSE;
+ }
+
+ if (pi->msg_tag < 21) {
+ /* */
+ rascategory = (ras_category)(pi->msg_tag / 3);
+ rasmsg_type = (ras_type)(pi->msg_tag % 3);
+ }
+ else {
+ /* No SRT yet (ToDo) */
+ return FALSE;
+ }
+
+ switch(rasmsg_type) {
+
+ case RAS_REQUEST:
+ if(pi->is_duplicate){
+ rs->time_stats[rascategory].req_dup_num++;
+ }
+ else {
+ rs->time_stats[rascategory].open_req_num++;
+ }
+ break;
+
+ case RAS_CONFIRM:
+ /* no break - delay stats are identical for Confirm and Reject */
+ case RAS_REJECT:
+ if(pi->is_duplicate){
+ /* Duplicate is ignored */
+ rs->time_stats[rascategory].rsp_dup_num++;
+ }
+ else if (!pi->request_available) {
+ /* no request was seen, ignore response */
+ rs->time_stats[rascategory].disc_rsp_num++;
+ }
+ else {
+ rs->time_stats[rascategory].open_req_num--;
+ time_stat_update(&(rs->time_stats[rascategory].rtd[0]),&(pi->delta_time), pinfo);
+ }
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#include "packet-h225-fn.c"
+
+/* Forward declaration we need below */
+void proto_reg_handoff_h225(void);
+
+/*
+ * Functions needed for Ras-Hash-Table
+ */
+
+/* compare 2 keys */
+static gint h225ras_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const h225ras_call_info_key* key1 = (const h225ras_call_info_key*) k1;
+ const h225ras_call_info_key* key2 = (const h225ras_call_info_key*) k2;
+
+ return (key1->reqSeqNum == key2->reqSeqNum &&
+ key1->conversation == key2->conversation);
+}
+
+/* calculate a hash key */
+static guint h225ras_call_hash(gconstpointer k)
+{
+ const h225ras_call_info_key* key = (const h225ras_call_info_key*) k;
+
+ return key->reqSeqNum + GPOINTER_TO_UINT(key->conversation);
+}
+
+
+h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category)
+{
+ h225ras_call_t *h225ras_call = NULL;
+ h225ras_call = (h225ras_call_t *)g_hash_table_lookup(ras_calls[category], h225ras_call_key);
+
+ return h225ras_call;
+}
+
+h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category)
+{
+ h225ras_call_info_key *new_h225ras_call_key;
+ h225ras_call_t *h225ras_call = NULL;
+
+
+ /* Prepare the value data.
+ "req_num" and "rsp_num" are frame numbers;
+ frame numbers are 1-origin, so we use 0
+ to mean "we don't yet know in which frame
+ the reply for this call appears". */
+ new_h225ras_call_key = wmem_new(wmem_file_scope(), h225ras_call_info_key);
+ new_h225ras_call_key->reqSeqNum = h225ras_call_key->reqSeqNum;
+ new_h225ras_call_key->conversation = h225ras_call_key->conversation;
+ h225ras_call = wmem_new(wmem_file_scope(), h225ras_call_t);
+ h225ras_call->req_num = pinfo->num;
+ h225ras_call->rsp_num = 0;
+ h225ras_call->requestSeqNum = h225ras_call_key->reqSeqNum;
+ h225ras_call->responded = FALSE;
+ h225ras_call->next_call = NULL;
+ h225ras_call->req_time=pinfo->abs_ts;
+ h225ras_call->guid=*guid;
+ /* store it */
+ g_hash_table_insert(ras_calls[category], new_h225ras_call_key, h225ras_call);
+
+ return h225ras_call;
+}
+
+h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category _U_)
+{
+ h225ras_call_t *h225ras_call = NULL;
+
+ /* Prepare the value data.
+ "req_num" and "rsp_num" are frame numbers;
+ frame numbers are 1-origin, so we use 0
+ to mean "we don't yet know in which frame
+ the reply for this call appears". */
+ h225ras_call = wmem_new(wmem_file_scope(), h225ras_call_t);
+ h225ras_call->req_num = pinfo->num;
+ h225ras_call->rsp_num = 0;
+ h225ras_call->requestSeqNum = prev_call->requestSeqNum;
+ h225ras_call->responded = FALSE;
+ h225ras_call->next_call = NULL;
+ h225ras_call->req_time=pinfo->abs_ts;
+ h225ras_call->guid=*guid;
+
+ prev_call->next_call = h225ras_call;
+ return h225ras_call;
+}
+
+/* Init routine for hash tables and delay calculation
+ This routine will be called by Wireshark, before it
+ is (re-)dissecting a trace file from beginning.
+ We need to discard and init any state we've saved */
+
+static void
+h225_init_routine(void)
+{
+ int i;
+ /* create new hash-tables for RAS SRT */
+
+ for(i=0;i<7;i++) {
+ ras_calls[i] = g_hash_table_new(h225ras_call_hash, h225ras_call_equal);
+ }
+
+}
+
+static void
+h225_cleanup_routine(void)
+{
+ int i;
+
+ /* free hash-tables for RAS SRT */
+ for(i=0;i<7;i++) {
+ g_hash_table_destroy(ras_calls[i]);
+ }
+}
+
+static int
+dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ proto_item *it;
+ 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;
+
+ next_tvb_init(&h245_list);
+ next_tvb_init(&tp_list);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, -1, PSNAME" CS");
+ tr=proto_item_add_subtree(it, ett_h225);
+
+ offset = dissect_H323_UserInformation_PDU(tvb, pinfo, tr, NULL);
+
+ if (h245_list.count){
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
+ col_set_fence(pinfo->cinfo, COL_PROTOCOL);
+ }
+
+ next_tvb_call(&h245_list, pinfo, tree, h245dg_handle, data_handle);
+ next_tvb_call(&tp_list, pinfo, tree, NULL, data_handle);
+
+ tap_queue_packet(h225_tap, pinfo, h225_pi);
+
+ return offset;
+}
+static int
+dissect_h225_h225_RasMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_){
+ proto_item *it;
+ 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;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
+
+ it=proto_tree_add_protocol_format(tree, proto_h225, tvb, offset, -1, PSNAME" RAS");
+ tr=proto_item_add_subtree(it, ett_h225);
+
+ offset = dissect_RasMessage_PDU(tvb, pinfo, tr, NULL);
+
+ ras_call_matching(tvb, pinfo, tr, h225_pi);
+
+ tap_queue_packet(h225_tap, pinfo, h225_pi);
+
+ return offset;
+}
+
+
+/* The following values represent the size of their valuestring arrays */
+
+#define RAS_MSG_TYPES (sizeof(h225_RasMessage_vals) / sizeof(value_string))
+#define CS_MSG_TYPES (sizeof(T_h323_message_body_vals) / sizeof(value_string))
+
+#define GRJ_REASONS (sizeof(GatekeeperRejectReason_vals) / sizeof(value_string))
+#define RRJ_REASONS (sizeof(RegistrationRejectReason_vals) / sizeof(value_string))
+#define URQ_REASONS (sizeof(UnregRequestReason_vals) / sizeof(value_string))
+#define URJ_REASONS (sizeof(UnregRejectReason_vals) / sizeof(value_string))
+#define ARJ_REASONS (sizeof(AdmissionRejectReason_vals) / sizeof(value_string))
+#define BRJ_REASONS (sizeof(BandRejectReason_vals) / sizeof(value_string))
+#define DRQ_REASONS (sizeof(DisengageReason_vals) / sizeof(value_string))
+#define DRJ_REASONS (sizeof(DisengageRejectReason_vals) / sizeof(value_string))
+#define LRJ_REASONS (sizeof(LocationRejectReason_vals) / sizeof(value_string))
+#define IRQNAK_REASONS (sizeof(InfoRequestNakReason_vals) / sizeof(value_string))
+#define REL_CMP_REASONS (sizeof(h225_ReleaseCompleteReason_vals) / sizeof(value_string))
+#define FACILITY_REASONS (sizeof(FacilityReason_vals) / sizeof(value_string))
+
+/* TAP STAT INFO */
+typedef enum
+{
+ MESSAGE_TYPE_COLUMN = 0,
+ COUNT_COLUMN
+} h225_stat_columns;
+
+typedef struct _h225_table_item {
+ guint count; /* Message count */
+ guint table_idx; /* stat_table index */
+} h225_table_item_t;
+
+static stat_tap_table_item h225_stat_fields[] = {{TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "Message Type or Reason", "%-25s"}, {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Count", "%d"}};
+
+static guint ras_msg_idx[RAS_MSG_TYPES];
+static guint cs_msg_idx[CS_MSG_TYPES];
+
+static guint grj_reason_idx[GRJ_REASONS];
+static guint rrj_reason_idx[RRJ_REASONS];
+static guint urq_reason_idx[URQ_REASONS];
+static guint urj_reason_idx[URJ_REASONS];
+static guint arj_reason_idx[ARJ_REASONS];
+static guint brj_reason_idx[BRJ_REASONS];
+static guint drq_reason_idx[DRQ_REASONS];
+static guint drj_reason_idx[DRJ_REASONS];
+static guint lrj_reason_idx[LRJ_REASONS];
+static guint irqnak_reason_idx[IRQNAK_REASONS];
+static guint rel_cmp_reason_idx[REL_CMP_REASONS];
+static guint facility_reason_idx[FACILITY_REASONS];
+
+static guint other_idx;
+
+static void h225_stat_init(stat_tap_table_ui* new_stat, new_stat_tap_gui_init_cb gui_callback, void* gui_data)
+{
+ int num_fields = sizeof(h225_stat_fields)/sizeof(stat_tap_table_item);
+ stat_tap_table* table = new_stat_tap_init_table("H.225 Messages and Message Reasons", num_fields, 0, NULL, gui_callback, gui_data);
+ int row_idx = 0, msg_idx;
+ stat_tap_table_item_type items[sizeof(h225_stat_fields)/sizeof(stat_tap_table_item)];
+
+ new_stat_tap_add_table(new_stat, table);
+
+ items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING;
+ items[COUNT_COLUMN].type = TABLE_ITEM_UINT;
+ items[COUNT_COLUMN].value.uint_value = 0;
+
+ /* Add a row for each value type */
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ h225_RasMessage_vals[msg_idx].strptr
+ ? h225_RasMessage_vals[msg_idx].strptr
+ : "Unknown RAS message";
+ ras_msg_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (h225_RasMessage_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ T_h323_message_body_vals[msg_idx].strptr
+ ? T_h323_message_body_vals[msg_idx].strptr
+ : "Unknown CS message";
+ cs_msg_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (T_h323_message_body_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ GatekeeperRejectReason_vals[msg_idx].strptr
+ ? GatekeeperRejectReason_vals[msg_idx].strptr
+ : "Unknown gatekeeper reject reason";
+ grj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (GatekeeperRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ RegistrationRejectReason_vals[msg_idx].strptr
+ ? RegistrationRejectReason_vals[msg_idx].strptr
+ : "Unknown registration reject reason";
+ rrj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (RegistrationRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ UnregRequestReason_vals[msg_idx].strptr
+ ? UnregRequestReason_vals[msg_idx].strptr
+ : "Unknown unregistration request reason";
+ urq_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (UnregRequestReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ UnregRejectReason_vals[msg_idx].strptr
+ ? UnregRejectReason_vals[msg_idx].strptr
+ : "Unknown unregistration reject reason";
+ urj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (UnregRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ AdmissionRejectReason_vals[msg_idx].strptr
+ ? AdmissionRejectReason_vals[msg_idx].strptr
+ : "Unknown admission reject reason";
+ arj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (AdmissionRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ BandRejectReason_vals[msg_idx].strptr
+ ? BandRejectReason_vals[msg_idx].strptr
+ : "Unknown band reject reason";
+ brj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (BandRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ DisengageReason_vals[msg_idx].strptr
+ ? DisengageReason_vals[msg_idx].strptr
+ : "Unknown disengage reason";
+ drq_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (DisengageReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ DisengageRejectReason_vals[msg_idx].strptr
+ ? DisengageRejectReason_vals[msg_idx].strptr
+ : "Unknown disengage reject reason";
+ drj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (DisengageRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ LocationRejectReason_vals[msg_idx].strptr
+ ? LocationRejectReason_vals[msg_idx].strptr
+ : "Unknown location reject reason";
+ lrj_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (LocationRejectReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ InfoRequestNakReason_vals[msg_idx].strptr
+ ? InfoRequestNakReason_vals[msg_idx].strptr
+ : "Unknown info request nak reason";
+ irqnak_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (InfoRequestNakReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ h225_ReleaseCompleteReason_vals[msg_idx].strptr
+ ? h225_ReleaseCompleteReason_vals[msg_idx].strptr
+ : "Unknown release complete reason";
+ rel_cmp_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (h225_ReleaseCompleteReason_vals[msg_idx].strptr);
+
+ msg_idx = 0;
+ do
+ {
+ items[MESSAGE_TYPE_COLUMN].value.string_value =
+ FacilityReason_vals[msg_idx].strptr
+ ? FacilityReason_vals[msg_idx].strptr
+ : "Unknown facility reason";
+ facility_reason_idx[msg_idx] = row_idx;
+
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ row_idx++;
+ msg_idx++;
+ } while (FacilityReason_vals[msg_idx].strptr);
+
+
+ items[MESSAGE_TYPE_COLUMN].value.string_value = "Unknown H.225 message";
+ new_stat_tap_init_table_row(table, row_idx, num_fields, items);
+ other_idx = row_idx;
+}
+
+static gboolean
+h225_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *hpi_ptr)
+{
+ new_stat_data_t* stat_data = (new_stat_data_t*)tapdata;
+ const h225_packet_info *hpi = (const h225_packet_info *)hpi_ptr;
+ int tag_idx = -1;
+ int reason_idx = -1;
+
+ if(hpi->msg_tag < 0) { /* uninitialized */
+ return FALSE;
+ }
+
+ switch (hpi->msg_type) {
+
+ case H225_RAS:
+ tag_idx = ras_msg_idx[MIN(hpi->msg_tag, (int)RAS_MSG_TYPES-1)];
+
+ /* Look for reason tag */
+ if(hpi->reason < 0) { /* uninitialized */
+ break;
+ }
+
+ switch(hpi->msg_tag) {
+
+ case 2: /* GRJ */
+ reason_idx = grj_reason_idx[MIN(hpi->reason, (int)GRJ_REASONS-1)];
+ break;
+ case 5: /* RRJ */
+ reason_idx = rrj_reason_idx[MIN(hpi->reason, (int)RRJ_REASONS-1)];
+ break;
+ case 6: /* URQ */
+ reason_idx = urq_reason_idx[MIN(hpi->reason, (int)URQ_REASONS-1)];
+ break;
+ case 8: /* URJ */
+ reason_idx = urj_reason_idx[MIN(hpi->reason, (int)URJ_REASONS-1)];
+ break;
+ case 11: /* ARJ */
+ reason_idx = arj_reason_idx[MIN(hpi->reason, (int)ARJ_REASONS-1)];
+ break;
+ case 14: /* BRJ */
+ reason_idx = brj_reason_idx[MIN(hpi->reason, (int)BRJ_REASONS-1)];
+ break;
+ case 15: /* DRQ */
+ reason_idx = drq_reason_idx[MIN(hpi->reason, (int)DRQ_REASONS-1)];
+ break;
+ case 17: /* DRJ */
+ reason_idx = drj_reason_idx[MIN(hpi->reason, (int)DRJ_REASONS-1)];
+ break;
+ case 20: /* LRJ */
+ reason_idx = lrj_reason_idx[MIN(hpi->reason, (int)LRJ_REASONS-1)];
+ break;
+ case 29: /* IRQ Nak */
+ reason_idx = irqnak_reason_idx[MIN(hpi->reason, (int)IRQNAK_REASONS-1)];
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ break;
+
+ case H225_CS:
+ tag_idx = cs_msg_idx[MIN(hpi->msg_tag, (int)CS_MSG_TYPES-1)];
+
+ /* Look for reason tag */
+ if(hpi->reason < 0) { /* uninitialized */
+ break;
+ }
+
+ switch(hpi->msg_tag) {
+
+ case 5: /* ReleaseComplete */
+ reason_idx = rel_cmp_reason_idx[MIN(hpi->reason, (int)REL_CMP_REASONS-1)];
+ break;
+ case 6: /* Facility */
+ reason_idx = facility_reason_idx[MIN(hpi->reason, (int)FACILITY_REASONS-1)];
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ break;
+
+ case H225_OTHERS:
+ default:
+ tag_idx = other_idx;
+ }
+
+ if (tag_idx >= 0) {
+ stat_tap_table*table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0);
+ stat_tap_table_item_type* msg_data = new_stat_tap_get_field_data(table, tag_idx, COUNT_COLUMN);;
+ msg_data->value.uint_value++;
+ new_stat_tap_set_field_data(table, tag_idx, COUNT_COLUMN, msg_data);
+
+ if (reason_idx >= 0) {
+ msg_data = new_stat_tap_get_field_data(table, reason_idx, COUNT_COLUMN);;
+ msg_data->value.uint_value++;
+ new_stat_tap_set_field_data(table, reason_idx, COUNT_COLUMN, msg_data);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+h225_stat_reset(stat_tap_table* table)
+{
+ guint element;
+ stat_tap_table_item_type* item_data;
+
+ for (element = 0; element < table->num_elements; element++)
+ {
+ item_data = new_stat_tap_get_field_data(table, element, COUNT_COLUMN);
+ item_data->value.uint_value = 0;
+ new_stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data);
+ }
+}
+
+/*--- proto_register_h225 -------------------------------------------*/
+void proto_register_h225(void) {
+
+ /* List of fields */
+ static hf_register_info hf[] = {
+ { &hf_h221Manufacturer,
+ { "H.225 Manufacturer", "h225.Manufacturer", FT_UINT32, BASE_HEX,
+ VALS(H221ManufacturerCode_vals), 0, "h225.H.221 Manufacturer", HFILL }},
+
+ { &hf_h225_ras_req_frame,
+ { "RAS Request Frame", "h225.ras.reqframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_h225_ras_rsp_frame,
+ { "RAS Response Frame", "h225.ras.rspframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_h225_ras_dup,
+ { "Duplicate RAS Message", "h225.ras.dup", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_h225_ras_deltatime,
+ { "RAS Service Response Time", "h225.ras.timedelta", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Timedelta between RAS-Request and RAS-Response", HFILL }},
+
+ { &hf_h225_debug_dissector_try_string,
+ { "*** DEBUG dissector_try_string", "h225.debug.dissector_try_string", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+#include "packet-h225-hfarr.c"
+ };
+
+ /* List of subtrees */
+ static gint *ett[] = {
+ &ett_h225,
+#include "packet-h225-ettarr.c"
+ };
+
+ static tap_param h225_stat_params[] = {
+ { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
+ };
+
+ static stat_tap_table_ui h225_stat_table = {
+ REGISTER_STAT_GROUP_TELEPHONY,
+ "H.225",
+ PFNAME,
+ "h225,counter",
+ h225_stat_init,
+ h225_stat_packet,
+ h225_stat_reset,
+ NULL,
+ NULL,
+ sizeof(h225_stat_fields)/sizeof(stat_tap_table_item), h225_stat_fields,
+ sizeof(h225_stat_params)/sizeof(tap_param), h225_stat_params,
+ NULL
+ };
+
+ module_t *h225_module;
+ int proto_h225_ras;
+
+ /* Register protocol */
+ proto_h225 = proto_register_protocol(PNAME, PSNAME, PFNAME);
+
+ /* Create a "fake" protocol to get proper display strings for SRT dialogs */
+ proto_h225_ras = proto_register_protocol("H.225 RAS", "H.225 RAS", "h225_ras");
+
+ /* Register fields and subtrees */
+ proto_register_field_array(proto_h225, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ h225_module = prefs_register_protocol(proto_h225, proto_reg_handoff_h225);
+ prefs_register_uint_preference(h225_module, "tls.port",
+ "H.225 TLS Port",
+ "H.225 Server TLS Port",
+ 10, &h225_tls_port);
+ prefs_register_bool_preference(h225_module, "reassembly",
+ "Reassemble H.225 messages spanning multiple TCP segments",
+ "Whether the H.225 dissector should reassemble messages spanning multiple TCP segments."
+ " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &h225_reassembly);
+ prefs_register_bool_preference(h225_module, "h245_in_tree",
+ "Display tunnelled H.245 inside H.225.0 tree",
+ "ON - display tunnelled H.245 inside H.225.0 tree, OFF - display tunnelled H.245 in root tree after H.225.0",
+ &h225_h245_in_tree);
+ prefs_register_bool_preference(h225_module, "tp_in_tree",
+ "Display tunnelled protocols inside H.225.0 tree",
+ "ON - display tunnelled protocols inside H.225.0 tree, OFF - display tunnelled protocols in root tree after H.225.0",
+ &h225_tp_in_tree);
+
+ register_dissector(PFNAME, dissect_h225_H323UserInformation, proto_h225);
+ register_dissector("h323ui",dissect_h225_H323UserInformation, proto_h225);
+ register_dissector("h225.ras", dissect_h225_h225_RasMessage, proto_h225);
+
+ nsp_object_dissector_table = register_dissector_table("h225.nsp.object", "H.225 NonStandardParameter (object)", FT_STRING, BASE_NONE, DISSECTOR_TABLE_ALLOW_DUPLICATE);
+ nsp_h221_dissector_table = register_dissector_table("h225.nsp.h221", "H.225 NonStandardParameter (h221)", FT_UINT32, BASE_HEX, DISSECTOR_TABLE_ALLOW_DUPLICATE);
+ tp_dissector_table = register_dissector_table("h225.tp", "H.225 TunnelledProtocol", FT_STRING, BASE_NONE, DISSECTOR_TABLE_ALLOW_DUPLICATE);
+ gef_name_dissector_table = register_dissector_table("h225.gef.name", "H.225 Generic Extensible Framework (names)", FT_STRING, BASE_NONE, DISSECTOR_TABLE_ALLOW_DUPLICATE);
+ gef_content_dissector_table = register_dissector_table("h225.gef.content", "H.225 Generic Extensible Framework", FT_STRING, BASE_NONE, DISSECTOR_TABLE_ALLOW_DUPLICATE);
+
+ register_init_routine(&h225_init_routine);
+ register_cleanup_routine(&h225_cleanup_routine);
+ h225_tap = register_tap(PFNAME);
+
+ register_rtd_table(proto_h225_ras, PFNAME, NUM_RAS_STATS, 1, ras_message_category, h225rassrt_packet, NULL);
+
+ register_stat_tap_table_ui(&h225_stat_table);
+
+ oid_add_from_string("Version 1","0.0.8.2250.0.1");
+ oid_add_from_string("Version 2","0.0.8.2250.0.2");
+ oid_add_from_string("Version 3","0.0.8.2250.0.3");
+ oid_add_from_string("Version 4","0.0.8.2250.0.4");
+ oid_add_from_string("Version 5","0.0.8.2250.0.5");
+ oid_add_from_string("Version 6","0.0.8.2250.0.6");
+}
+
+
+/*--- proto_reg_handoff_h225 ---------------------------------------*/
+void
+proto_reg_handoff_h225(void)
+{
+ static gboolean h225_prefs_initialized = FALSE;
+ static dissector_handle_t h225ras_handle, q931_tpkt_handle;
+ static guint saved_h225_tls_port;
+
+ if (!h225_prefs_initialized) {
+ h225ras_handle=find_dissector("h225.ras");
+ dissector_add_uint("udp.port", UDP_PORT_RAS1, h225ras_handle);
+ dissector_add_uint("udp.port", UDP_PORT_RAS2, h225ras_handle);
+
+ h245_handle = find_dissector("h245");
+ h245dg_handle = find_dissector("h245dg");
+ h4501_handle = find_dissector("h4501");
+ data_handle = find_dissector("data");
+ h225_prefs_initialized = TRUE;
+ q931_tpkt_handle = find_dissector("q931.tpkt");
+ } else {
+ ssl_dissector_delete(saved_h225_tls_port, q931_tpkt_handle);
+ }
+
+ saved_h225_tls_port = h225_tls_port;
+ ssl_dissector_add(saved_h225_tls_port, q931_tpkt_handle);
+}
+
+
+static void reset_h225_packet_info(h225_packet_info *pi)
+{
+ if(pi == NULL) {
+ return;
+ }
+
+ pi->msg_type = H225_OTHERS;
+ pi->cs_type = H225_OTHER;
+ pi->msg_tag = -1;
+ pi->reason = -1;
+ pi->requestSeqNum = 0;
+ memset(&pi->guid,0,sizeof pi->guid);
+ pi->is_duplicate = FALSE;
+ 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';
+ pi->dialedDigits[0] = '\0';
+ pi->is_destinationInfo = FALSE;
+}
+
+/*
+ The following function contains the routines for RAS request/response matching.
+ A RAS response matches with a request, if both messages have the same
+ RequestSequenceNumber, belong to the same IP conversation and belong to the same
+ RAS "category" (e.g. Admission, Registration).
+
+ We use hashtables to access the lists of RAS calls (request/response pairs).
+ We have one hashtable for each RAS category. The hashkeys consist of the
+ non-unique 16-bit RequestSequenceNumber and values representing the conversation.
+
+ In big capture files, we might get different requests with identical keys.
+ These requests aren't necessarily duplicates. They might be valid new requests.
+ At the moment we just use the timedelta between the last valid and the new request
+ to decide if the new request is a duplicate or not. There might be better ways.
+ Two thresholds are defined below.
+
+ However the decision is made, another problem arises. We can't just add those
+ requests to our hashtables. Instead we create lists of RAS calls with identical keys.
+ The hashtables for RAS calls contain now pointers to the first RAS call in a list of
+ RAS calls with identical keys.
+ These lists aren't expected to contain more than 3 items and are usually single item
+ lists. So we don't need an expensive but intelligent way to access these lists
+ (e.g. hashtables). Just walk through such a list.
+*/
+
+#define THRESHOLD_REPEATED_RESPONDED_CALL 300
+#define THRESHOLD_REPEATED_NOT_RESPONDED_CALL 1800
+
+static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi)
+{
+ proto_item *hidden_item;
+ conversation_t* conversation = NULL;
+ h225ras_call_info_key h225ras_call_key;
+ h225ras_call_t *h225ras_call = NULL;
+ nstime_t delta;
+ guint msg_category;
+
+ if(pi->msg_type == H225_RAS && pi->msg_tag < 21) {
+ /* make RAS request/response matching only for tags from 0 to 20 for now */
+
+ msg_category = pi->msg_tag / 3;
+ if(pi->msg_tag % 3 == 0) { /* Request Message */
+ conversation = find_or_create_conversation(pinfo);
+
+ /* prepare the key data */
+ h225ras_call_key.reqSeqNum = pi->requestSeqNum;
+ h225ras_call_key.conversation = conversation;
+
+ /* look up the request */
+ h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
+
+ if (h225ras_call != NULL) {
+ /* We've seen requests with this reqSeqNum, with the same
+ source and destination, before - do we have
+ *this* request already? */
+ /* Walk through list of ras requests with identical keys */
+ do {
+ if (pinfo->num == h225ras_call->req_num) {
+ /* We have seen this request before -> do nothing */
+ break;
+ }
+
+ /* if end of list is reached, exit loop and decide if request is duplicate or not. */
+ if (h225ras_call->next_call == NULL) {
+ if ( (pinfo->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0
+ && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) )
+ ||(pinfo->num > h225ras_call->req_num && h225ras_call->rsp_num == 0
+ && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) )
+ {
+ /* if last request has been responded
+ and this request appears after last response (has bigger frame number)
+ and last request occurred more than 300 seconds ago,
+ or if last request hasn't been responded
+ and this request appears after last request (has bigger frame number)
+ and last request occurred more than 1800 seconds ago,
+ we decide that we have a new request */
+ /* Append new ras call to list */
+ h225ras_call = append_h225ras_call(h225ras_call, pinfo, &pi->guid, msg_category);
+ } else {
+ /* No, so it's a duplicate request.
+ Mark it as such. */
+ pi->is_duplicate = TRUE;
+ hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+ break;
+ }
+ h225ras_call = h225ras_call->next_call;
+ } while (h225ras_call != NULL );
+ }
+ else {
+ h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, &pi->guid, msg_category);
+ }
+
+ /* add link to response frame, if available */
+ if(h225ras_call && h225ras_call->rsp_num != 0){
+ proto_item *ti =
+ proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num,
+ "The response to this request is in frame %u",
+ h225ras_call->rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+
+ /* end of request message handling*/
+ }
+ else { /* Confirm or Reject Message */
+ conversation = find_conversation(pinfo->num, &pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation != NULL) {
+ /* look only for matching request, if
+ matching conversation is available. */
+ h225ras_call_key.reqSeqNum = pi->requestSeqNum;
+ h225ras_call_key.conversation = conversation;
+ h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
+ if(h225ras_call) {
+ /* find matching ras_call in list of ras calls with identical keys */
+ do {
+ if (pinfo->num == h225ras_call->rsp_num) {
+ /* We have seen this response before -> stop now with matching ras call */
+ break;
+ }
+
+ /* Break when list end is reached */
+ if(h225ras_call->next_call == NULL) {
+ break;
+ }
+ h225ras_call = h225ras_call->next_call;
+ } while (h225ras_call != NULL) ;
+
+ if (!h225ras_call) {
+ return;
+ }
+
+ /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */
+ if (msg_category == 3 || msg_category == 5) {
+ pi->guid = h225ras_call->guid;
+ hidden_item = proto_tree_add_guid(tree, hf_h225_guid, tvb, 0, GUID_LEN, &pi->guid);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+
+ if (h225ras_call->rsp_num == 0) {
+ /* We have not yet seen a response to that call, so
+ this must be the first response; remember its
+ frame number. */
+ h225ras_call->rsp_num = pinfo->num;
+ }
+ else {
+ /* We have seen a response to this call - but was it
+ *this* response? */
+ if (h225ras_call->rsp_num != pinfo->num) {
+ /* No, so it's a duplicate response.
+ Mark it as such. */
+ pi->is_duplicate = TRUE;
+ hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+ }
+
+ if(h225ras_call->req_num != 0){
+ proto_item *ti;
+ h225ras_call->responded = TRUE;
+ pi->request_available = TRUE;
+
+ /* Indicate the frame to which this is a reply. */
+ ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num,
+ "This is a response to a request in frame %u", h225ras_call->req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+
+ /* Calculate RAS Service Response Time */
+ nstime_delta(&delta, &pinfo->abs_ts, &h225ras_call->req_time);
+ pi->delta_time = delta; /* give it to tap */
+
+ /* display Ras Service Response Time and make it filterable */
+ ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time));
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */