2 * Routines for h225 packet dissection
3 * Copyright 2005, Anders Broman <anders.broman@ericsson.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * To quote the author of the previous H323/H225/H245 dissector:
12 * "This is a complete replacement of the previous limitied dissector
13 * that Ronnie was crazy enough to write by hand. It was a lot of time
14 * to hack it by hand, but it is incomplete and buggy and it is good when
16 * Ronnie did a great job and all the VoIP users had made good use of it!
17 * Credit to Tomas Kukosa for developing the asn2wrs compiler.
23 #include <epan/packet.h>
24 #include <epan/conversation.h>
25 #include <epan/proto_data.h>
27 #include <epan/prefs.h>
28 #include <epan/oids.h>
29 #include <epan/next_tvb.h>
30 #include <epan/asn1.h>
33 #include <epan/stat_tap_ui.h>
34 #include <epan/rtd_table.h>
35 #include "packet-frame.h"
36 #include "packet-tpkt.h"
37 #include "packet-per.h"
38 #include "packet-h225.h"
39 #include "packet-h235.h"
40 #include "packet-h245.h"
41 #include "packet-h323.h"
42 #include "packet-q931.h"
43 #include "packet-ssl.h"
45 #define PNAME "H323-MESSAGES"
46 #define PSNAME "H.225.0"
49 #define UDP_PORT_RAS_RANGE "1718-1719"
50 #define TCP_PORT_CS 1720
51 #define TLS_PORT_CS 1300
53 void proto_register_h225(void);
54 static h225_packet_info* create_h225_packet_info(packet_info *pinfo);
55 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
57 /* Item of ras request list*/
58 typedef struct _h225ras_call_t {
59 guint32 requestSeqNum;
61 guint32 req_num; /* frame number request seen */
62 guint32 rsp_num; /* frame number response seen */
63 nstime_t req_time; /* arrival time of request */
64 gboolean responded; /* true, if request has been responded */
65 struct _h225ras_call_t *next_call; /* pointer to next ras request with same SequenceNumber and conversation handle */
69 /* Item of ras-request key list*/
70 typedef struct _h225ras_call_info_key {
72 conversation_t *conversation;
73 } h225ras_call_info_key;
75 /* Global Memory Chunks for lists and Global hash tables*/
77 static wmem_map_t *ras_calls[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
79 /* functions, needed using ras-request and halfcall matching*/
80 static h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category);
81 static h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category);
82 static h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category);
85 static dissector_handle_t h225ras_handle;
86 static dissector_handle_t data_handle;
87 /* Subdissector tables */
88 static dissector_table_t nsp_object_dissector_table;
89 static dissector_table_t nsp_h221_dissector_table;
90 static dissector_table_t tp_dissector_table;
91 static dissector_table_t gef_name_dissector_table;
92 static dissector_table_t gef_content_dissector_table;
95 static dissector_handle_t h245_handle=NULL;
96 static dissector_handle_t h245dg_handle=NULL;
97 static dissector_handle_t h4501_handle=NULL;
99 static dissector_handle_t nsp_handle;
100 static dissector_handle_t tp_handle;
102 static next_tvb_list_t h245_list;
103 static next_tvb_list_t tp_list;
105 /* Initialize the protocol and registered fields */
106 static int h225_tap = -1;
107 static int proto_h225 = -1;
109 static int hf_h221Manufacturer = -1;
110 static int hf_h225_ras_req_frame = -1;
111 static int hf_h225_ras_rsp_frame = -1;
112 static int hf_h225_ras_dup = -1;
113 static int hf_h225_ras_deltatime = -1;
114 static int hf_h225_debug_dissector_try_string = -1;
116 #include "packet-h225-hf.c"
118 /* Initialize the subtree pointers */
119 static gint ett_h225 = -1;
120 #include "packet-h225-ett.c"
123 static guint h225_tls_port = TLS_PORT_CS;
124 static gboolean h225_reassembly = TRUE;
125 static gboolean h225_h245_in_tree = TRUE;
126 static gboolean h225_tp_in_tree = TRUE;
128 /* Global variables */
129 static guint32 ipv4_address;
130 static ws_in6_addr ipv6_address;
131 static ws_in6_addr ipv6_address_zeros = {{0}};
132 static guint32 ip_port;
133 static gboolean contains_faststart = FALSE;
134 static e_guid_t *call_id_guid;
136 /* NonStandardParameter */
137 static const char *nsiOID;
138 static guint32 h221NonStandard;
139 static guint32 t35CountryCode;
140 static guint32 t35Extension;
141 static guint32 manufacturerCode;
143 /* TunnelledProtocol */
144 static const char *tpOID;
146 static const value_string ras_message_category[] = {
148 { 1, "Registration "},
149 { 2, "UnRegistration"},
157 typedef enum _ras_type {
164 typedef enum _ras_category {
175 #define NUM_RAS_STATS 7
178 h225rassrt_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
180 rtd_data_t* rtd_data = (rtd_data_t*)phs;
181 rtd_stat_table* rs = &rtd_data->stat_table;
182 const h225_packet_info *pi=(const h225_packet_info *)phi;
184 ras_type rasmsg_type = RAS_OTHER;
185 ras_category rascategory = RAS_OTHERS;
187 if (pi->msg_type != H225_RAS || pi->msg_tag == -1) {
188 /* No RAS Message or uninitialized msg_tag -> return */
192 if (pi->msg_tag < 21) {
194 rascategory = (ras_category)(pi->msg_tag / 3);
195 rasmsg_type = (ras_type)(pi->msg_tag % 3);
198 /* No SRT yet (ToDo) */
202 switch(rasmsg_type) {
205 if(pi->is_duplicate){
206 rs->time_stats[rascategory].req_dup_num++;
209 rs->time_stats[rascategory].open_req_num++;
214 /* no break - delay stats are identical for Confirm and Reject */
216 if(pi->is_duplicate){
217 /* Duplicate is ignored */
218 rs->time_stats[rascategory].rsp_dup_num++;
220 else if (!pi->request_available) {
221 /* no request was seen, ignore response */
222 rs->time_stats[rascategory].disc_rsp_num++;
225 rs->time_stats[rascategory].open_req_num--;
226 time_stat_update(&(rs->time_stats[rascategory].rtd[0]),&(pi->delta_time), pinfo);
236 #include "packet-h225-fn.c"
238 /* Forward declaration we need below */
239 void proto_reg_handoff_h225(void);
242 * Functions needed for Ras-Hash-Table
246 static gint h225ras_call_equal(gconstpointer k1, gconstpointer k2)
248 const h225ras_call_info_key* key1 = (const h225ras_call_info_key*) k1;
249 const h225ras_call_info_key* key2 = (const h225ras_call_info_key*) k2;
251 return (key1->reqSeqNum == key2->reqSeqNum &&
252 key1->conversation == key2->conversation);
255 /* calculate a hash key */
256 static guint h225ras_call_hash(gconstpointer k)
258 const h225ras_call_info_key* key = (const h225ras_call_info_key*) k;
260 return key->reqSeqNum + GPOINTER_TO_UINT(key->conversation);
264 h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category)
266 h225ras_call_t *h225ras_call = (h225ras_call_t *)wmem_map_lookup(ras_calls[category], h225ras_call_key);
271 h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category)
273 h225ras_call_info_key *new_h225ras_call_key;
274 h225ras_call_t *h225ras_call = NULL;
277 /* Prepare the value data.
278 "req_num" and "rsp_num" are frame numbers;
279 frame numbers are 1-origin, so we use 0
280 to mean "we don't yet know in which frame
281 the reply for this call appears". */
282 new_h225ras_call_key = wmem_new(wmem_file_scope(), h225ras_call_info_key);
283 new_h225ras_call_key->reqSeqNum = h225ras_call_key->reqSeqNum;
284 new_h225ras_call_key->conversation = h225ras_call_key->conversation;
285 h225ras_call = wmem_new(wmem_file_scope(), h225ras_call_t);
286 h225ras_call->req_num = pinfo->num;
287 h225ras_call->rsp_num = 0;
288 h225ras_call->requestSeqNum = h225ras_call_key->reqSeqNum;
289 h225ras_call->responded = FALSE;
290 h225ras_call->next_call = NULL;
291 h225ras_call->req_time=pinfo->abs_ts;
292 h225ras_call->guid=*guid;
294 wmem_map_insert(ras_calls[category], new_h225ras_call_key, h225ras_call);
299 h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category _U_)
301 h225ras_call_t *h225ras_call = NULL;
303 /* Prepare the value data.
304 "req_num" and "rsp_num" are frame numbers;
305 frame numbers are 1-origin, so we use 0
306 to mean "we don't yet know in which frame
307 the reply for this call appears". */
308 h225ras_call = wmem_new(wmem_file_scope(), h225ras_call_t);
309 h225ras_call->req_num = pinfo->num;
310 h225ras_call->rsp_num = 0;
311 h225ras_call->requestSeqNum = prev_call->requestSeqNum;
312 h225ras_call->responded = FALSE;
313 h225ras_call->next_call = NULL;
314 h225ras_call->req_time=pinfo->abs_ts;
315 h225ras_call->guid=*guid;
317 prev_call->next_call = h225ras_call;
324 /* next_tvb pointers are allocated in packet scope, clear it. */
325 next_tvb_init(&h245_list);
326 next_tvb_init(&tp_list);
330 dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
335 h225_packet_info* h225_pi;
337 /* Init struct for collecting h225_packet_info */
338 h225_pi = create_h225_packet_info(pinfo);
339 h225_pi->msg_type = H225_CS;
340 p_add_proto_data(pinfo->pool, pinfo, proto_h225, 0, h225_pi);
342 register_frame_end_routine(pinfo, h225_frame_end);
343 next_tvb_init(&h245_list);
344 next_tvb_init(&tp_list);
346 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
347 col_clear(pinfo->cinfo, COL_INFO);
349 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, -1, PSNAME" CS");
350 tr=proto_item_add_subtree(it, ett_h225);
352 offset = dissect_H323_UserInformation_PDU(tvb, pinfo, tr, NULL);
354 if (h245_list.count){
355 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
356 col_set_fence(pinfo->cinfo, COL_PROTOCOL);
359 next_tvb_call(&h245_list, pinfo, tree, h245dg_handle, data_handle);
360 next_tvb_call(&tp_list, pinfo, tree, NULL, data_handle);
362 tap_queue_packet(h225_tap, pinfo, h225_pi);
367 dissect_h225_h225_RasMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_){
371 h225_packet_info* h225_pi;
373 /* Init struct for collecting h225_packet_info */
374 h225_pi = create_h225_packet_info(pinfo);
375 h225_pi->msg_type = H225_RAS;
376 p_add_proto_data(pinfo->pool, pinfo, proto_h225, 0, h225_pi);
378 register_frame_end_routine(pinfo, h225_frame_end);
380 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
382 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, offset, -1, PSNAME" RAS");
383 tr=proto_item_add_subtree(it, ett_h225);
385 offset = dissect_RasMessage_PDU(tvb, pinfo, tr, NULL);
387 ras_call_matching(tvb, pinfo, tr, h225_pi);
389 tap_queue_packet(h225_tap, pinfo, h225_pi);
395 /* The following values represent the size of their valuestring arrays */
397 #define RAS_MSG_TYPES (sizeof(h225_RasMessage_vals) / sizeof(value_string))
398 #define CS_MSG_TYPES (sizeof(T_h323_message_body_vals) / sizeof(value_string))
400 #define GRJ_REASONS (sizeof(GatekeeperRejectReason_vals) / sizeof(value_string))
401 #define RRJ_REASONS (sizeof(RegistrationRejectReason_vals) / sizeof(value_string))
402 #define URQ_REASONS (sizeof(UnregRequestReason_vals) / sizeof(value_string))
403 #define URJ_REASONS (sizeof(UnregRejectReason_vals) / sizeof(value_string))
404 #define ARJ_REASONS (sizeof(AdmissionRejectReason_vals) / sizeof(value_string))
405 #define BRJ_REASONS (sizeof(BandRejectReason_vals) / sizeof(value_string))
406 #define DRQ_REASONS (sizeof(DisengageReason_vals) / sizeof(value_string))
407 #define DRJ_REASONS (sizeof(DisengageRejectReason_vals) / sizeof(value_string))
408 #define LRJ_REASONS (sizeof(LocationRejectReason_vals) / sizeof(value_string))
409 #define IRQNAK_REASONS (sizeof(InfoRequestNakReason_vals) / sizeof(value_string))
410 #define REL_CMP_REASONS (sizeof(h225_ReleaseCompleteReason_vals) / sizeof(value_string))
411 #define FACILITY_REASONS (sizeof(FacilityReason_vals) / sizeof(value_string))
416 MESSAGE_TYPE_COLUMN = 0,
420 typedef struct _h225_table_item {
421 guint count; /* Message count */
422 guint table_idx; /* stat_table index */
425 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"}};
427 static guint ras_msg_idx[RAS_MSG_TYPES];
428 static guint cs_msg_idx[CS_MSG_TYPES];
430 static guint grj_reason_idx[GRJ_REASONS];
431 static guint rrj_reason_idx[RRJ_REASONS];
432 static guint urq_reason_idx[URQ_REASONS];
433 static guint urj_reason_idx[URJ_REASONS];
434 static guint arj_reason_idx[ARJ_REASONS];
435 static guint brj_reason_idx[BRJ_REASONS];
436 static guint drq_reason_idx[DRQ_REASONS];
437 static guint drj_reason_idx[DRJ_REASONS];
438 static guint lrj_reason_idx[LRJ_REASONS];
439 static guint irqnak_reason_idx[IRQNAK_REASONS];
440 static guint rel_cmp_reason_idx[REL_CMP_REASONS];
441 static guint facility_reason_idx[FACILITY_REASONS];
443 static guint other_idx;
445 static void h225_stat_init(stat_tap_table_ui* new_stat, stat_tap_gui_init_cb gui_callback, void* gui_data)
447 int num_fields = sizeof(h225_stat_fields)/sizeof(stat_tap_table_item);
448 stat_tap_table* table = stat_tap_init_table("H.225 Messages and Message Reasons", num_fields, 0, NULL, gui_callback, gui_data);
449 int row_idx = 0, msg_idx;
450 stat_tap_table_item_type items[sizeof(h225_stat_fields)/sizeof(stat_tap_table_item)];
452 stat_tap_add_table(new_stat, table);
454 items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING;
455 items[COUNT_COLUMN].type = TABLE_ITEM_UINT;
456 items[COUNT_COLUMN].value.uint_value = 0;
458 /* Add a row for each value type */
463 items[MESSAGE_TYPE_COLUMN].value.string_value =
464 h225_RasMessage_vals[msg_idx].strptr
465 ? h225_RasMessage_vals[msg_idx].strptr
466 : "Unknown RAS message";
467 ras_msg_idx[msg_idx] = row_idx;
469 stat_tap_init_table_row(table, row_idx, num_fields, items);
472 } while (h225_RasMessage_vals[msg_idx].strptr);
477 items[MESSAGE_TYPE_COLUMN].value.string_value =
478 T_h323_message_body_vals[msg_idx].strptr
479 ? T_h323_message_body_vals[msg_idx].strptr
480 : "Unknown CS message";
481 cs_msg_idx[msg_idx] = row_idx;
483 stat_tap_init_table_row(table, row_idx, num_fields, items);
486 } while (T_h323_message_body_vals[msg_idx].strptr);
491 items[MESSAGE_TYPE_COLUMN].value.string_value =
492 GatekeeperRejectReason_vals[msg_idx].strptr
493 ? GatekeeperRejectReason_vals[msg_idx].strptr
494 : "Unknown gatekeeper reject reason";
495 grj_reason_idx[msg_idx] = row_idx;
497 stat_tap_init_table_row(table, row_idx, num_fields, items);
500 } while (GatekeeperRejectReason_vals[msg_idx].strptr);
505 items[MESSAGE_TYPE_COLUMN].value.string_value =
506 RegistrationRejectReason_vals[msg_idx].strptr
507 ? RegistrationRejectReason_vals[msg_idx].strptr
508 : "Unknown registration reject reason";
509 rrj_reason_idx[msg_idx] = row_idx;
511 stat_tap_init_table_row(table, row_idx, num_fields, items);
514 } while (RegistrationRejectReason_vals[msg_idx].strptr);
519 items[MESSAGE_TYPE_COLUMN].value.string_value =
520 UnregRequestReason_vals[msg_idx].strptr
521 ? UnregRequestReason_vals[msg_idx].strptr
522 : "Unknown unregistration request reason";
523 urq_reason_idx[msg_idx] = row_idx;
525 stat_tap_init_table_row(table, row_idx, num_fields, items);
528 } while (UnregRequestReason_vals[msg_idx].strptr);
533 items[MESSAGE_TYPE_COLUMN].value.string_value =
534 UnregRejectReason_vals[msg_idx].strptr
535 ? UnregRejectReason_vals[msg_idx].strptr
536 : "Unknown unregistration reject reason";
537 urj_reason_idx[msg_idx] = row_idx;
539 stat_tap_init_table_row(table, row_idx, num_fields, items);
542 } while (UnregRejectReason_vals[msg_idx].strptr);
547 items[MESSAGE_TYPE_COLUMN].value.string_value =
548 AdmissionRejectReason_vals[msg_idx].strptr
549 ? AdmissionRejectReason_vals[msg_idx].strptr
550 : "Unknown admission reject reason";
551 arj_reason_idx[msg_idx] = row_idx;
553 stat_tap_init_table_row(table, row_idx, num_fields, items);
556 } while (AdmissionRejectReason_vals[msg_idx].strptr);
561 items[MESSAGE_TYPE_COLUMN].value.string_value =
562 BandRejectReason_vals[msg_idx].strptr
563 ? BandRejectReason_vals[msg_idx].strptr
564 : "Unknown band reject reason";
565 brj_reason_idx[msg_idx] = row_idx;
567 stat_tap_init_table_row(table, row_idx, num_fields, items);
570 } while (BandRejectReason_vals[msg_idx].strptr);
575 items[MESSAGE_TYPE_COLUMN].value.string_value =
576 DisengageReason_vals[msg_idx].strptr
577 ? DisengageReason_vals[msg_idx].strptr
578 : "Unknown disengage reason";
579 drq_reason_idx[msg_idx] = row_idx;
581 stat_tap_init_table_row(table, row_idx, num_fields, items);
584 } while (DisengageReason_vals[msg_idx].strptr);
589 items[MESSAGE_TYPE_COLUMN].value.string_value =
590 DisengageRejectReason_vals[msg_idx].strptr
591 ? DisengageRejectReason_vals[msg_idx].strptr
592 : "Unknown disengage reject reason";
593 drj_reason_idx[msg_idx] = row_idx;
595 stat_tap_init_table_row(table, row_idx, num_fields, items);
598 } while (DisengageRejectReason_vals[msg_idx].strptr);
603 items[MESSAGE_TYPE_COLUMN].value.string_value =
604 LocationRejectReason_vals[msg_idx].strptr
605 ? LocationRejectReason_vals[msg_idx].strptr
606 : "Unknown location reject reason";
607 lrj_reason_idx[msg_idx] = row_idx;
609 stat_tap_init_table_row(table, row_idx, num_fields, items);
612 } while (LocationRejectReason_vals[msg_idx].strptr);
617 items[MESSAGE_TYPE_COLUMN].value.string_value =
618 InfoRequestNakReason_vals[msg_idx].strptr
619 ? InfoRequestNakReason_vals[msg_idx].strptr
620 : "Unknown info request nak reason";
621 irqnak_reason_idx[msg_idx] = row_idx;
623 stat_tap_init_table_row(table, row_idx, num_fields, items);
626 } while (InfoRequestNakReason_vals[msg_idx].strptr);
631 items[MESSAGE_TYPE_COLUMN].value.string_value =
632 h225_ReleaseCompleteReason_vals[msg_idx].strptr
633 ? h225_ReleaseCompleteReason_vals[msg_idx].strptr
634 : "Unknown release complete reason";
635 rel_cmp_reason_idx[msg_idx] = row_idx;
637 stat_tap_init_table_row(table, row_idx, num_fields, items);
640 } while (h225_ReleaseCompleteReason_vals[msg_idx].strptr);
645 items[MESSAGE_TYPE_COLUMN].value.string_value =
646 FacilityReason_vals[msg_idx].strptr
647 ? FacilityReason_vals[msg_idx].strptr
648 : "Unknown facility reason";
649 facility_reason_idx[msg_idx] = row_idx;
651 stat_tap_init_table_row(table, row_idx, num_fields, items);
654 } while (FacilityReason_vals[msg_idx].strptr);
657 items[MESSAGE_TYPE_COLUMN].value.string_value = "Unknown H.225 message";
658 stat_tap_init_table_row(table, row_idx, num_fields, items);
663 h225_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *hpi_ptr)
665 stat_data_t* stat_data = (stat_data_t*)tapdata;
666 const h225_packet_info *hpi = (const h225_packet_info *)hpi_ptr;
670 if(hpi->msg_tag < 0) { /* uninitialized */
674 switch (hpi->msg_type) {
677 tag_idx = ras_msg_idx[MIN(hpi->msg_tag, (int)RAS_MSG_TYPES-1)];
679 /* Look for reason tag */
680 if(hpi->reason < 0) { /* uninitialized */
684 switch(hpi->msg_tag) {
687 reason_idx = grj_reason_idx[MIN(hpi->reason, (int)GRJ_REASONS-1)];
690 reason_idx = rrj_reason_idx[MIN(hpi->reason, (int)RRJ_REASONS-1)];
693 reason_idx = urq_reason_idx[MIN(hpi->reason, (int)URQ_REASONS-1)];
696 reason_idx = urj_reason_idx[MIN(hpi->reason, (int)URJ_REASONS-1)];
699 reason_idx = arj_reason_idx[MIN(hpi->reason, (int)ARJ_REASONS-1)];
702 reason_idx = brj_reason_idx[MIN(hpi->reason, (int)BRJ_REASONS-1)];
705 reason_idx = drq_reason_idx[MIN(hpi->reason, (int)DRQ_REASONS-1)];
708 reason_idx = drj_reason_idx[MIN(hpi->reason, (int)DRJ_REASONS-1)];
711 reason_idx = lrj_reason_idx[MIN(hpi->reason, (int)LRJ_REASONS-1)];
713 case 29: /* IRQ Nak */
714 reason_idx = irqnak_reason_idx[MIN(hpi->reason, (int)IRQNAK_REASONS-1)];
724 tag_idx = cs_msg_idx[MIN(hpi->msg_tag, (int)CS_MSG_TYPES-1)];
726 /* Look for reason tag */
727 if(hpi->reason < 0) { /* uninitialized */
731 switch(hpi->msg_tag) {
733 case 5: /* ReleaseComplete */
734 reason_idx = rel_cmp_reason_idx[MIN(hpi->reason, (int)REL_CMP_REASONS-1)];
736 case 6: /* Facility */
737 reason_idx = facility_reason_idx[MIN(hpi->reason, (int)FACILITY_REASONS-1)];
752 stat_tap_table*table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0);
753 stat_tap_table_item_type* msg_data = stat_tap_get_field_data(table, tag_idx, COUNT_COLUMN);;
754 msg_data->value.uint_value++;
755 stat_tap_set_field_data(table, tag_idx, COUNT_COLUMN, msg_data);
757 if (reason_idx >= 0) {
758 msg_data = stat_tap_get_field_data(table, reason_idx, COUNT_COLUMN);;
759 msg_data->value.uint_value++;
760 stat_tap_set_field_data(table, reason_idx, COUNT_COLUMN, msg_data);
769 h225_stat_reset(stat_tap_table* table)
772 stat_tap_table_item_type* item_data;
774 for (element = 0; element < table->num_elements; element++)
776 item_data = stat_tap_get_field_data(table, element, COUNT_COLUMN);
777 item_data->value.uint_value = 0;
778 stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data);
782 /*--- proto_register_h225 -------------------------------------------*/
783 void proto_register_h225(void) {
786 static hf_register_info hf[] = {
787 { &hf_h221Manufacturer,
788 { "H.225 Manufacturer", "h225.Manufacturer", FT_UINT32, BASE_HEX,
789 VALS(H221ManufacturerCode_vals), 0, "h225.H.221 Manufacturer", HFILL }},
791 { &hf_h225_ras_req_frame,
792 { "RAS Request Frame", "h225.ras.reqframe", FT_FRAMENUM, BASE_NONE,
793 NULL, 0, NULL, HFILL }},
795 { &hf_h225_ras_rsp_frame,
796 { "RAS Response Frame", "h225.ras.rspframe", FT_FRAMENUM, BASE_NONE,
797 NULL, 0, NULL, HFILL }},
800 { "Duplicate RAS Message", "h225.ras.dup", FT_UINT32, BASE_DEC,
801 NULL, 0, NULL, HFILL }},
803 { &hf_h225_ras_deltatime,
804 { "RAS Service Response Time", "h225.ras.timedelta", FT_RELATIVE_TIME, BASE_NONE,
805 NULL, 0, "Timedelta between RAS-Request and RAS-Response", HFILL }},
807 { &hf_h225_debug_dissector_try_string,
808 { "*** DEBUG dissector_try_string", "h225.debug.dissector_try_string", FT_STRING, BASE_NONE,
809 NULL, 0, NULL, HFILL }},
811 #include "packet-h225-hfarr.c"
814 /* List of subtrees */
815 static gint *ett[] = {
817 #include "packet-h225-ettarr.c"
820 static tap_param h225_stat_params[] = {
821 { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
824 static stat_tap_table_ui h225_stat_table = {
825 REGISTER_STAT_GROUP_TELEPHONY,
834 sizeof(h225_stat_fields)/sizeof(stat_tap_table_item), h225_stat_fields,
835 sizeof(h225_stat_params)/sizeof(tap_param), h225_stat_params,
840 module_t *h225_module;
841 int i, proto_h225_ras;
843 /* Register protocol */
844 proto_h225 = proto_register_protocol(PNAME, PSNAME, PFNAME);
846 /* Create a "fake" protocol to get proper display strings for SRT dialogs */
847 proto_h225_ras = proto_register_protocol("H.225 RAS", "H.225 RAS", "h225_ras");
849 /* Register fields and subtrees */
850 proto_register_field_array(proto_h225, hf, array_length(hf));
851 proto_register_subtree_array(ett, array_length(ett));
853 h225_module = prefs_register_protocol(proto_h225, proto_reg_handoff_h225);
854 prefs_register_uint_preference(h225_module, "tls.port",
856 "H.225 Server TLS Port",
858 prefs_register_bool_preference(h225_module, "reassembly",
859 "Reassemble H.225 messages spanning multiple TCP segments",
860 "Whether the H.225 dissector should reassemble messages spanning multiple TCP segments."
861 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
863 prefs_register_bool_preference(h225_module, "h245_in_tree",
864 "Display tunnelled H.245 inside H.225.0 tree",
865 "ON - display tunnelled H.245 inside H.225.0 tree, OFF - display tunnelled H.245 in root tree after H.225.0",
867 prefs_register_bool_preference(h225_module, "tp_in_tree",
868 "Display tunnelled protocols inside H.225.0 tree",
869 "ON - display tunnelled protocols inside H.225.0 tree, OFF - display tunnelled protocols in root tree after H.225.0",
872 register_dissector(PFNAME, dissect_h225_H323UserInformation, proto_h225);
873 register_dissector("h323ui",dissect_h225_H323UserInformation, proto_h225);
874 h225ras_handle = register_dissector("h225.ras", dissect_h225_h225_RasMessage, proto_h225);
876 nsp_object_dissector_table = register_dissector_table("h225.nsp.object", "H.225 NonStandardParameter Object", proto_h225, FT_STRING, BASE_NONE);
877 nsp_h221_dissector_table = register_dissector_table("h225.nsp.h221", "H.225 NonStandardParameter h221", proto_h225, FT_UINT32, BASE_HEX);
878 tp_dissector_table = register_dissector_table("h225.tp", "H.225 Tunnelled Protocol", proto_h225, FT_STRING, BASE_NONE);
879 gef_name_dissector_table = register_dissector_table("h225.gef.name", "H.225 Generic Extensible Framework Name", proto_h225, FT_STRING, BASE_NONE);
880 gef_content_dissector_table = register_dissector_table("h225.gef.content", "H.225 Generic Extensible Framework Content", proto_h225, FT_STRING, BASE_NONE);
883 ras_calls[i] = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), h225ras_call_hash, h225ras_call_equal);
886 h225_tap = register_tap(PFNAME);
888 register_rtd_table(proto_h225_ras, PFNAME, NUM_RAS_STATS, 1, ras_message_category, h225rassrt_packet, NULL);
890 register_stat_tap_table_ui(&h225_stat_table);
892 oid_add_from_string("Version 1","0.0.8.2250.0.1");
893 oid_add_from_string("Version 2","0.0.8.2250.0.2");
894 oid_add_from_string("Version 3","0.0.8.2250.0.3");
895 oid_add_from_string("Version 4","0.0.8.2250.0.4");
896 oid_add_from_string("Version 5","0.0.8.2250.0.5");
897 oid_add_from_string("Version 6","0.0.8.2250.0.6");
901 /*--- proto_reg_handoff_h225 ---------------------------------------*/
903 proto_reg_handoff_h225(void)
905 static gboolean h225_prefs_initialized = FALSE;
906 static dissector_handle_t q931_tpkt_handle;
907 static guint saved_h225_tls_port;
909 if (!h225_prefs_initialized) {
910 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RAS_RANGE, h225ras_handle);
912 h245_handle = find_dissector("h245");
913 h245dg_handle = find_dissector("h245dg");
914 h4501_handle = find_dissector_add_dependency("h4501", proto_h225);
915 data_handle = find_dissector("data");
916 h225_prefs_initialized = TRUE;
917 q931_tpkt_handle = find_dissector("q931.tpkt");
919 ssl_dissector_delete(saved_h225_tls_port, q931_tpkt_handle);
922 saved_h225_tls_port = h225_tls_port;
923 ssl_dissector_add(saved_h225_tls_port, q931_tpkt_handle);
926 static h225_packet_info* create_h225_packet_info(packet_info *pinfo)
928 h225_packet_info* pi = wmem_new0(pinfo->pool, h225_packet_info);
930 pi->msg_type = H225_OTHERS;
931 pi->cs_type = H225_OTHER;
939 The following function contains the routines for RAS request/response matching.
940 A RAS response matches with a request, if both messages have the same
941 RequestSequenceNumber, belong to the same IP conversation and belong to the same
942 RAS "category" (e.g. Admission, Registration).
944 We use hashtables to access the lists of RAS calls (request/response pairs).
945 We have one hashtable for each RAS category. The hashkeys consist of the
946 non-unique 16-bit RequestSequenceNumber and values representing the conversation.
948 In big capture files, we might get different requests with identical keys.
949 These requests aren't necessarily duplicates. They might be valid new requests.
950 At the moment we just use the timedelta between the last valid and the new request
951 to decide if the new request is a duplicate or not. There might be better ways.
952 Two thresholds are defined below.
954 However the decision is made, another problem arises. We can't just add those
955 requests to our hashtables. Instead we create lists of RAS calls with identical keys.
956 The hashtables for RAS calls contain now pointers to the first RAS call in a list of
957 RAS calls with identical keys.
958 These lists aren't expected to contain more than 3 items and are usually single item
959 lists. So we don't need an expensive but intelligent way to access these lists
960 (e.g. hashtables). Just walk through such a list.
963 #define THRESHOLD_REPEATED_RESPONDED_CALL 300
964 #define THRESHOLD_REPEATED_NOT_RESPONDED_CALL 1800
966 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi)
968 proto_item *hidden_item;
969 conversation_t* conversation = NULL;
970 h225ras_call_info_key h225ras_call_key;
971 h225ras_call_t *h225ras_call = NULL;
975 if(pi->msg_type == H225_RAS && pi->msg_tag < 21) {
976 /* make RAS request/response matching only for tags from 0 to 20 for now */
978 msg_category = pi->msg_tag / 3;
979 if(pi->msg_tag % 3 == 0) { /* Request Message */
980 conversation = find_or_create_conversation(pinfo);
982 /* prepare the key data */
983 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
984 h225ras_call_key.conversation = conversation;
986 /* look up the request */
987 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
989 if (h225ras_call != NULL) {
990 /* We've seen requests with this reqSeqNum, with the same
991 source and destination, before - do we have
992 *this* request already? */
993 /* Walk through list of ras requests with identical keys */
995 if (pinfo->num == h225ras_call->req_num) {
996 /* We have seen this request before -> do nothing */
1000 /* if end of list is reached, exit loop and decide if request is duplicate or not. */
1001 if (h225ras_call->next_call == NULL) {
1002 if ( (pinfo->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0
1003 && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) )
1004 ||(pinfo->num > h225ras_call->req_num && h225ras_call->rsp_num == 0
1005 && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) )
1007 /* if last request has been responded
1008 and this request appears after last response (has bigger frame number)
1009 and last request occurred more than 300 seconds ago,
1010 or if last request hasn't been responded
1011 and this request appears after last request (has bigger frame number)
1012 and last request occurred more than 1800 seconds ago,
1013 we decide that we have a new request */
1014 /* Append new ras call to list */
1015 h225ras_call = append_h225ras_call(h225ras_call, pinfo, &pi->guid, msg_category);
1017 /* No, so it's a duplicate request.
1019 pi->is_duplicate = TRUE;
1020 hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
1021 PROTO_ITEM_SET_HIDDEN(hidden_item);
1025 h225ras_call = h225ras_call->next_call;
1026 } while (h225ras_call != NULL );
1029 h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, &pi->guid, msg_category);
1032 /* add link to response frame, if available */
1033 if(h225ras_call && h225ras_call->rsp_num != 0){
1035 proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num,
1036 "The response to this request is in frame %u",
1037 h225ras_call->rsp_num);
1038 PROTO_ITEM_SET_GENERATED(ti);
1041 /* end of request message handling*/
1043 else { /* Confirm or Reject Message */
1044 conversation = find_conversation_pinfo(pinfo, 0);
1045 if (conversation != NULL) {
1046 /* look only for matching request, if
1047 matching conversation is available. */
1048 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
1049 h225ras_call_key.conversation = conversation;
1050 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
1052 /* find matching ras_call in list of ras calls with identical keys */
1054 if (pinfo->num == h225ras_call->rsp_num) {
1055 /* We have seen this response before -> stop now with matching ras call */
1059 /* Break when list end is reached */
1060 if(h225ras_call->next_call == NULL) {
1063 h225ras_call = h225ras_call->next_call;
1064 } while (h225ras_call != NULL) ;
1066 if (!h225ras_call) {
1070 /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */
1071 if (msg_category == 3 || msg_category == 5) {
1072 pi->guid = h225ras_call->guid;
1073 hidden_item = proto_tree_add_guid(tree, hf_h225_guid, tvb, 0, GUID_LEN, &pi->guid);
1074 PROTO_ITEM_SET_HIDDEN(hidden_item);
1077 if (h225ras_call->rsp_num == 0) {
1078 /* We have not yet seen a response to that call, so
1079 this must be the first response; remember its
1081 h225ras_call->rsp_num = pinfo->num;
1084 /* We have seen a response to this call - but was it
1086 if (h225ras_call->rsp_num != pinfo->num) {
1087 /* No, so it's a duplicate response.
1089 pi->is_duplicate = TRUE;
1090 hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
1091 PROTO_ITEM_SET_HIDDEN(hidden_item);
1095 if(h225ras_call->req_num != 0){
1097 h225ras_call->responded = TRUE;
1098 pi->request_available = TRUE;
1100 /* Indicate the frame to which this is a reply. */
1101 ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num,
1102 "This is a response to a request in frame %u", h225ras_call->req_num);
1103 PROTO_ITEM_SET_GENERATED(ti);
1105 /* Calculate RAS Service Response Time */
1106 nstime_delta(&delta, &pinfo->abs_ts, &h225ras_call->req_time);
1107 pi->delta_time = delta; /* give it to tap */
1109 /* display Ras Service Response Time and make it filterable */
1110 ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time));
1111 PROTO_ITEM_SET_GENERATED(ti);
1120 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1125 * indent-tabs-mode: nil
1128 * vi: set shiftwidth=2 tabstop=8 expandtab:
1129 * :indentSize=2:tabSize=8:noTabs=true: