Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / asn1 / h225 / packet-h225-template.c
blob6beaacc0463fbf106aaf0d66e6bc47e2ac228e40
1 /* packet-h225.c
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
15 * it will go away."
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.
21 #include "config.h"
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>
31 #include <epan/t35.h>
32 #include <epan/tap.h>
33 #include <epan/stat_tap_ui.h>
34 #include <epan/rtd_table.h>
35 #include <epan/tfs.h>
36 #include <wsutil/array.h>
38 #include "packet-frame.h"
39 #include "packet-tpkt.h"
40 #include "packet-per.h"
41 #include "packet-h225.h"
42 #include "packet-h235.h"
43 #include "packet-h245.h"
44 #include "packet-h323.h"
45 #include "packet-q931.h"
46 #include "packet-tls.h"
48 #define PNAME "H323-MESSAGES"
49 #define PSNAME "H.225.0"
50 #define PFNAME "h225"
52 #define UDP_PORT_RAS_RANGE "1718-1719"
53 #define TCP_PORT_CS 1720
54 #define TLS_PORT_CS 1300
56 void proto_register_h225(void);
57 static h225_packet_info* create_h225_packet_info(packet_info *pinfo);
58 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
60 /* Item of ras request list*/
61 typedef struct _h225ras_call_t {
62 uint32_t requestSeqNum;
63 e_guid_t guid;
64 uint32_t req_num; /* frame number request seen */
65 uint32_t rsp_num; /* frame number response seen */
66 nstime_t req_time; /* arrival time of request */
67 bool responded; /* true, if request has been responded */
68 struct _h225ras_call_t *next_call; /* pointer to next ras request with same SequenceNumber and conversation handle */
69 } h225ras_call_t;
72 /* Item of ras-request key list*/
73 typedef struct _h225ras_call_info_key {
74 unsigned reqSeqNum;
75 conversation_t *conversation;
76 } h225ras_call_info_key;
78 /* Global Memory Chunks for lists and Global hash tables*/
80 static wmem_map_t *ras_calls[7];
82 /* functions, needed using ras-request and halfcall matching*/
83 static h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category);
84 static h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category);
85 static h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category);
88 static dissector_handle_t h225ras_handle;
89 static dissector_handle_t data_handle;
90 /* Subdissector tables */
91 static dissector_table_t nsp_object_dissector_table;
92 static dissector_table_t nsp_h221_dissector_table;
93 static dissector_table_t tp_dissector_table;
94 static dissector_table_t gef_name_dissector_table;
95 static dissector_table_t gef_content_dissector_table;
98 static dissector_handle_t h245_handle;
99 static dissector_handle_t h245dg_handle;
100 static dissector_handle_t h4501_handle;
102 static dissector_handle_t nsp_handle;
103 static dissector_handle_t tp_handle;
105 static next_tvb_list_t *h245_list;
106 static next_tvb_list_t *tp_list;
108 /* Initialize the protocol and registered fields */
109 static int h225_tap;
110 static int proto_h225;
112 static int hf_h221Manufacturer;
113 static int hf_h225_ras_req_frame;
114 static int hf_h225_ras_rsp_frame;
115 static int hf_h225_ras_dup;
116 static int hf_h225_ras_deltatime;
117 static int hf_h225_debug_dissector_try_string;
119 #include "packet-h225-hf.c"
121 /* Initialize the subtree pointers */
122 static int ett_h225;
123 #include "packet-h225-ett.c"
125 /* Preferences */
126 static unsigned h225_tls_port = TLS_PORT_CS;
127 static bool h225_reassembly = true;
128 static bool h225_h245_in_tree = true;
129 static bool h225_tp_in_tree = true;
131 /* Global variables */
132 static uint32_t ipv4_address;
133 static ws_in6_addr ipv6_address;
134 static ws_in6_addr ipv6_address_zeros = {{0}};
135 static uint32_t ip_port;
136 static bool contains_faststart;
137 static e_guid_t *call_id_guid;
139 /* NonStandardParameter */
140 static const char *nsiOID;
141 static uint32_t h221NonStandard;
142 static uint32_t t35CountryCode;
143 static uint32_t t35Extension;
144 static uint32_t manufacturerCode;
146 /* TunnelledProtocol */
147 static const char *tpOID;
149 static const value_string ras_message_category[] = {
150 { 0, "Gatekeeper "},
151 { 1, "Registration "},
152 { 2, "UnRegistration"},
153 { 3, "Admission "},
154 { 4, "Bandwidth "},
155 { 5, "Disengage "},
156 { 6, "Location "},
157 { 0, NULL }
160 typedef enum _ras_type {
161 RAS_REQUEST,
162 RAS_CONFIRM,
163 RAS_REJECT,
164 RAS_OTHER
165 }ras_type;
167 typedef enum _ras_category {
168 RAS_GATEKEEPER,
169 RAS_REGISTRATION,
170 RAS_UNREGISTRATION,
171 RAS_ADMISSION,
172 RAS_BANDWIDTH,
173 RAS_DISENGAGE,
174 RAS_LOCATION,
175 RAS_OTHERS
176 }ras_category;
178 #define NUM_RAS_STATS 7
180 static tap_packet_status
181 h225rassrt_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi, tap_flags_t flags _U_)
183 rtd_data_t* rtd_data = (rtd_data_t*)phs;
184 rtd_stat_table* rs = &rtd_data->stat_table;
185 const h225_packet_info *pi=(const h225_packet_info *)phi;
187 ras_type rasmsg_type = RAS_OTHER;
188 ras_category rascategory = RAS_OTHERS;
190 if (pi->msg_type != H225_RAS || pi->msg_tag == -1) {
191 /* No RAS Message or uninitialized msg_tag -> return */
192 return TAP_PACKET_DONT_REDRAW;
195 if (pi->msg_tag < 21) {
196 /* */
197 rascategory = (ras_category)(pi->msg_tag / 3);
198 rasmsg_type = (ras_type)(pi->msg_tag % 3);
200 else {
201 /* No SRT yet (ToDo) */
202 return TAP_PACKET_DONT_REDRAW;
205 switch(rasmsg_type) {
207 case RAS_REQUEST:
208 if(pi->is_duplicate){
209 rs->time_stats[rascategory].req_dup_num++;
211 else {
212 rs->time_stats[rascategory].open_req_num++;
214 break;
216 case RAS_CONFIRM:
217 /* no break - delay stats are identical for Confirm and Reject */
218 case RAS_REJECT:
219 if(pi->is_duplicate){
220 /* Duplicate is ignored */
221 rs->time_stats[rascategory].rsp_dup_num++;
223 else if (!pi->request_available) {
224 /* no request was seen, ignore response */
225 rs->time_stats[rascategory].disc_rsp_num++;
227 else {
228 rs->time_stats[rascategory].open_req_num--;
229 time_stat_update(&(rs->time_stats[rascategory].rtd[0]),&(pi->delta_time), pinfo);
231 break;
233 default:
234 return TAP_PACKET_DONT_REDRAW;
236 return TAP_PACKET_REDRAW;
239 static void h225_set_cs_type(h225_packet_info* h225_pi, h225_cs_type cs_type, bool faststart)
241 if (h225_pi == NULL)
242 return;
244 h225_pi->cs_type = cs_type;
245 /* XXX - Why not always use contains_faststart or h225_pi->is_faststart
246 * There are some UUIEs (e.g., Facility-UUIE) where a fastStart can be
247 * included but the path adding extra to the label has never been used.
248 * Is that an oversight or intentional?
250 if (faststart) {
251 char temp[50];
252 snprintf(temp, 50, "%s OLC (%s)", val_to_str_const(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
253 (void) g_strlcpy(h225_pi->frame_label, temp, 50);
254 } else {
255 snprintf(h225_pi->frame_label, 50, "%s", val_to_str_const(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
259 #include "packet-h225-fn.c"
261 /* Forward declaration we need below */
262 void proto_reg_handoff_h225(void);
265 * Functions needed for Ras-Hash-Table
268 /* compare 2 keys */
269 static int h225ras_call_equal(const void *k1, const void *k2)
271 const h225ras_call_info_key* key1 = (const h225ras_call_info_key*) k1;
272 const h225ras_call_info_key* key2 = (const h225ras_call_info_key*) k2;
274 return (key1->reqSeqNum == key2->reqSeqNum &&
275 key1->conversation == key2->conversation);
278 /* calculate a hash key */
279 static unsigned h225ras_call_hash(const void *k)
281 const h225ras_call_info_key* key = (const h225ras_call_info_key*) k;
283 return key->reqSeqNum + GPOINTER_TO_UINT(key->conversation);
287 h225ras_call_t * find_h225ras_call(h225ras_call_info_key *h225ras_call_key ,int category)
289 h225ras_call_t *h225ras_call = (h225ras_call_t *)wmem_map_lookup(ras_calls[category], h225ras_call_key);
291 return h225ras_call;
294 h225ras_call_t * new_h225ras_call(h225ras_call_info_key *h225ras_call_key, packet_info *pinfo, e_guid_t *guid, int category)
296 h225ras_call_info_key *new_h225ras_call_key;
297 h225ras_call_t *h225ras_call = NULL;
300 /* Prepare the value data.
301 "req_num" and "rsp_num" are frame numbers;
302 frame numbers are 1-origin, so we use 0
303 to mean "we don't yet know in which frame
304 the reply for this call appears". */
305 new_h225ras_call_key = wmem_new(wmem_file_scope(), h225ras_call_info_key);
306 new_h225ras_call_key->reqSeqNum = h225ras_call_key->reqSeqNum;
307 new_h225ras_call_key->conversation = h225ras_call_key->conversation;
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 = h225ras_call_key->reqSeqNum;
312 h225ras_call->responded = false;
313 h225ras_call->next_call = NULL;
314 h225ras_call->req_time=pinfo->abs_ts;
315 h225ras_call->guid=*guid;
316 /* store it */
317 wmem_map_insert(ras_calls[category], new_h225ras_call_key, h225ras_call);
319 return h225ras_call;
322 h225ras_call_t * append_h225ras_call(h225ras_call_t *prev_call, packet_info *pinfo, e_guid_t *guid, int category _U_)
324 h225ras_call_t *h225ras_call = NULL;
326 /* Prepare the value data.
327 "req_num" and "rsp_num" are frame numbers;
328 frame numbers are 1-origin, so we use 0
329 to mean "we don't yet know in which frame
330 the reply for this call appears". */
331 h225ras_call = wmem_new(wmem_file_scope(), h225ras_call_t);
332 h225ras_call->req_num = pinfo->num;
333 h225ras_call->rsp_num = 0;
334 h225ras_call->requestSeqNum = prev_call->requestSeqNum;
335 h225ras_call->responded = false;
336 h225ras_call->next_call = NULL;
337 h225ras_call->req_time=pinfo->abs_ts;
338 h225ras_call->guid=*guid;
340 prev_call->next_call = h225ras_call;
341 return h225ras_call;
344 static void
345 h225_frame_end(void)
347 /* next_tvb pointers are allocated in packet scope, clear it. */
348 h245_list = NULL;
349 tp_list = NULL;
352 static int
353 dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
355 proto_item *it;
356 proto_tree *tr;
357 int offset = 0;
358 h225_packet_info* h225_pi;
360 /* Init struct for collecting h225_packet_info */
361 h225_pi = create_h225_packet_info(pinfo);
362 h225_pi->msg_type = H225_CS;
363 p_add_proto_data(pinfo->pool, pinfo, proto_h225, 0, h225_pi);
365 register_frame_end_routine(pinfo, h225_frame_end);
366 h245_list = next_tvb_list_new(pinfo->pool);
367 tp_list = next_tvb_list_new(pinfo->pool);
369 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
370 col_clear(pinfo->cinfo, COL_INFO);
372 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, -1, PSNAME" CS");
373 tr=proto_item_add_subtree(it, ett_h225);
375 offset = dissect_H323_UserInformation_PDU(tvb, pinfo, tr, NULL);
377 if (h245_list->count){
378 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
379 col_set_fence(pinfo->cinfo, COL_PROTOCOL);
382 next_tvb_call(h245_list, pinfo, tree, h245dg_handle, data_handle);
383 next_tvb_call(tp_list, pinfo, tree, NULL, data_handle);
385 tap_queue_packet(h225_tap, pinfo, h225_pi);
387 return offset;
389 static int
390 dissect_h225_h225_RasMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_){
391 proto_item *it;
392 proto_tree *tr;
393 uint32_t offset=0;
394 h225_packet_info* h225_pi;
396 /* Init struct for collecting h225_packet_info */
397 h225_pi = create_h225_packet_info(pinfo);
398 h225_pi->msg_type = H225_RAS;
399 p_add_proto_data(pinfo->pool, pinfo, proto_h225, 0, h225_pi);
401 register_frame_end_routine(pinfo, h225_frame_end);
402 h245_list = next_tvb_list_new(pinfo->pool);
403 tp_list = next_tvb_list_new(pinfo->pool);
405 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
407 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, offset, -1, PSNAME" RAS");
408 tr=proto_item_add_subtree(it, ett_h225);
410 offset = dissect_RasMessage_PDU(tvb, pinfo, tr, NULL);
412 ras_call_matching(tvb, pinfo, tr, h225_pi);
414 next_tvb_call(h245_list, pinfo, tree, h245dg_handle, data_handle);
415 next_tvb_call(tp_list, pinfo, tree, NULL, data_handle);
417 tap_queue_packet(h225_tap, pinfo, h225_pi);
419 return offset;
423 /* The following values represent the size of their valuestring arrays */
425 #define RAS_MSG_TYPES array_length(h225_RasMessage_vals)
426 #define CS_MSG_TYPES array_length(T_h323_message_body_vals)
428 #define GRJ_REASONS array_length(GatekeeperRejectReason_vals)
429 #define RRJ_REASONS array_length(RegistrationRejectReason_vals)
430 #define URQ_REASONS array_length(UnregRequestReason_vals)
431 #define URJ_REASONS array_length(UnregRejectReason_vals)
432 #define ARJ_REASONS array_length(AdmissionRejectReason_vals)
433 #define BRJ_REASONS array_length(BandRejectReason_vals)
434 #define DRQ_REASONS array_length(DisengageReason_vals)
435 #define DRJ_REASONS array_length(DisengageRejectReason_vals)
436 #define LRJ_REASONS array_length(LocationRejectReason_vals)
437 #define IRQNAK_REASONS array_length(InfoRequestNakReason_vals)
438 #define REL_CMP_REASONS array_length(h225_ReleaseCompleteReason_vals)
439 #define FACILITY_REASONS array_length(FacilityReason_vals)
441 /* TAP STAT INFO */
442 typedef enum
444 MESSAGE_TYPE_COLUMN = 0,
445 COUNT_COLUMN
446 } h225_stat_columns;
448 typedef struct _h225_table_item {
449 unsigned count; /* Message count */
450 unsigned table_idx; /* stat_table index */
451 } h225_table_item_t;
453 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"}};
455 static unsigned ras_msg_idx[RAS_MSG_TYPES];
456 static unsigned cs_msg_idx[CS_MSG_TYPES];
458 static unsigned grj_reason_idx[GRJ_REASONS];
459 static unsigned rrj_reason_idx[RRJ_REASONS];
460 static unsigned urq_reason_idx[URQ_REASONS];
461 static unsigned urj_reason_idx[URJ_REASONS];
462 static unsigned arj_reason_idx[ARJ_REASONS];
463 static unsigned brj_reason_idx[BRJ_REASONS];
464 static unsigned drq_reason_idx[DRQ_REASONS];
465 static unsigned drj_reason_idx[DRJ_REASONS];
466 static unsigned lrj_reason_idx[LRJ_REASONS];
467 static unsigned irqnak_reason_idx[IRQNAK_REASONS];
468 static unsigned rel_cmp_reason_idx[REL_CMP_REASONS];
469 static unsigned facility_reason_idx[FACILITY_REASONS];
471 static unsigned other_idx;
473 static void h225_stat_init(stat_tap_table_ui* new_stat)
475 const char *table_name = "H.225 Messages and Message Reasons";
476 int num_fields = array_length(h225_stat_fields);
477 stat_tap_table *table;
478 int row_idx = 0, msg_idx;
479 stat_tap_table_item_type items[array_length(h225_stat_fields)];
481 table = stat_tap_find_table(new_stat, table_name);
482 if (table) {
483 if (new_stat->stat_tap_reset_table_cb) {
484 new_stat->stat_tap_reset_table_cb(table);
486 return;
489 memset(items, 0x0, sizeof(items));
490 table = stat_tap_init_table(table_name, num_fields, 0, NULL);
491 stat_tap_add_table(new_stat, table);
493 items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING;
494 items[COUNT_COLUMN].type = TABLE_ITEM_UINT;
495 items[COUNT_COLUMN].value.uint_value = 0;
497 /* Add a row for each value type */
499 msg_idx = 0;
502 items[MESSAGE_TYPE_COLUMN].value.string_value =
503 h225_RasMessage_vals[msg_idx].strptr
504 ? h225_RasMessage_vals[msg_idx].strptr
505 : "Unknown RAS message";
506 ras_msg_idx[msg_idx] = row_idx;
508 stat_tap_init_table_row(table, row_idx, num_fields, items);
509 row_idx++;
510 msg_idx++;
511 } while (h225_RasMessage_vals[msg_idx].strptr);
513 msg_idx = 0;
516 items[MESSAGE_TYPE_COLUMN].value.string_value =
517 T_h323_message_body_vals[msg_idx].strptr
518 ? T_h323_message_body_vals[msg_idx].strptr
519 : "Unknown CS message";
520 cs_msg_idx[msg_idx] = row_idx;
522 stat_tap_init_table_row(table, row_idx, num_fields, items);
523 row_idx++;
524 msg_idx++;
525 } while (T_h323_message_body_vals[msg_idx].strptr);
527 msg_idx = 0;
530 items[MESSAGE_TYPE_COLUMN].value.string_value =
531 GatekeeperRejectReason_vals[msg_idx].strptr
532 ? GatekeeperRejectReason_vals[msg_idx].strptr
533 : "Unknown gatekeeper reject reason";
534 grj_reason_idx[msg_idx] = row_idx;
536 stat_tap_init_table_row(table, row_idx, num_fields, items);
537 row_idx++;
538 msg_idx++;
539 } while (GatekeeperRejectReason_vals[msg_idx].strptr);
541 msg_idx = 0;
544 items[MESSAGE_TYPE_COLUMN].value.string_value =
545 RegistrationRejectReason_vals[msg_idx].strptr
546 ? RegistrationRejectReason_vals[msg_idx].strptr
547 : "Unknown registration reject reason";
548 rrj_reason_idx[msg_idx] = row_idx;
550 stat_tap_init_table_row(table, row_idx, num_fields, items);
551 row_idx++;
552 msg_idx++;
553 } while (RegistrationRejectReason_vals[msg_idx].strptr);
555 msg_idx = 0;
558 items[MESSAGE_TYPE_COLUMN].value.string_value =
559 UnregRequestReason_vals[msg_idx].strptr
560 ? UnregRequestReason_vals[msg_idx].strptr
561 : "Unknown unregistration request reason";
562 urq_reason_idx[msg_idx] = row_idx;
564 stat_tap_init_table_row(table, row_idx, num_fields, items);
565 row_idx++;
566 msg_idx++;
567 } while (UnregRequestReason_vals[msg_idx].strptr);
569 msg_idx = 0;
572 items[MESSAGE_TYPE_COLUMN].value.string_value =
573 UnregRejectReason_vals[msg_idx].strptr
574 ? UnregRejectReason_vals[msg_idx].strptr
575 : "Unknown unregistration reject reason";
576 urj_reason_idx[msg_idx] = row_idx;
578 stat_tap_init_table_row(table, row_idx, num_fields, items);
579 row_idx++;
580 msg_idx++;
581 } while (UnregRejectReason_vals[msg_idx].strptr);
583 msg_idx = 0;
586 items[MESSAGE_TYPE_COLUMN].value.string_value =
587 AdmissionRejectReason_vals[msg_idx].strptr
588 ? AdmissionRejectReason_vals[msg_idx].strptr
589 : "Unknown admission reject reason";
590 arj_reason_idx[msg_idx] = row_idx;
592 stat_tap_init_table_row(table, row_idx, num_fields, items);
593 row_idx++;
594 msg_idx++;
595 } while (AdmissionRejectReason_vals[msg_idx].strptr);
597 msg_idx = 0;
600 items[MESSAGE_TYPE_COLUMN].value.string_value =
601 BandRejectReason_vals[msg_idx].strptr
602 ? BandRejectReason_vals[msg_idx].strptr
603 : "Unknown band reject reason";
604 brj_reason_idx[msg_idx] = row_idx;
606 stat_tap_init_table_row(table, row_idx, num_fields, items);
607 row_idx++;
608 msg_idx++;
609 } while (BandRejectReason_vals[msg_idx].strptr);
611 msg_idx = 0;
614 items[MESSAGE_TYPE_COLUMN].value.string_value =
615 DisengageReason_vals[msg_idx].strptr
616 ? DisengageReason_vals[msg_idx].strptr
617 : "Unknown disengage reason";
618 drq_reason_idx[msg_idx] = row_idx;
620 stat_tap_init_table_row(table, row_idx, num_fields, items);
621 row_idx++;
622 msg_idx++;
623 } while (DisengageReason_vals[msg_idx].strptr);
625 msg_idx = 0;
628 items[MESSAGE_TYPE_COLUMN].value.string_value =
629 DisengageRejectReason_vals[msg_idx].strptr
630 ? DisengageRejectReason_vals[msg_idx].strptr
631 : "Unknown disengage reject reason";
632 drj_reason_idx[msg_idx] = row_idx;
634 stat_tap_init_table_row(table, row_idx, num_fields, items);
635 row_idx++;
636 msg_idx++;
637 } while (DisengageRejectReason_vals[msg_idx].strptr);
639 msg_idx = 0;
642 items[MESSAGE_TYPE_COLUMN].value.string_value =
643 LocationRejectReason_vals[msg_idx].strptr
644 ? LocationRejectReason_vals[msg_idx].strptr
645 : "Unknown location reject reason";
646 lrj_reason_idx[msg_idx] = row_idx;
648 stat_tap_init_table_row(table, row_idx, num_fields, items);
649 row_idx++;
650 msg_idx++;
651 } while (LocationRejectReason_vals[msg_idx].strptr);
653 msg_idx = 0;
656 items[MESSAGE_TYPE_COLUMN].value.string_value =
657 InfoRequestNakReason_vals[msg_idx].strptr
658 ? InfoRequestNakReason_vals[msg_idx].strptr
659 : "Unknown info request nak reason";
660 irqnak_reason_idx[msg_idx] = row_idx;
662 stat_tap_init_table_row(table, row_idx, num_fields, items);
663 row_idx++;
664 msg_idx++;
665 } while (InfoRequestNakReason_vals[msg_idx].strptr);
667 msg_idx = 0;
670 items[MESSAGE_TYPE_COLUMN].value.string_value =
671 h225_ReleaseCompleteReason_vals[msg_idx].strptr
672 ? h225_ReleaseCompleteReason_vals[msg_idx].strptr
673 : "Unknown release complete reason";
674 rel_cmp_reason_idx[msg_idx] = row_idx;
676 stat_tap_init_table_row(table, row_idx, num_fields, items);
677 row_idx++;
678 msg_idx++;
679 } while (h225_ReleaseCompleteReason_vals[msg_idx].strptr);
681 msg_idx = 0;
684 items[MESSAGE_TYPE_COLUMN].value.string_value =
685 FacilityReason_vals[msg_idx].strptr
686 ? FacilityReason_vals[msg_idx].strptr
687 : "Unknown facility reason";
688 facility_reason_idx[msg_idx] = row_idx;
690 stat_tap_init_table_row(table, row_idx, num_fields, items);
691 row_idx++;
692 msg_idx++;
693 } while (FacilityReason_vals[msg_idx].strptr);
696 items[MESSAGE_TYPE_COLUMN].value.string_value = "Unknown H.225 message";
697 stat_tap_init_table_row(table, row_idx, num_fields, items);
698 other_idx = row_idx;
701 static tap_packet_status
702 h225_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *hpi_ptr, tap_flags_t flags _U_)
704 stat_data_t* stat_data = (stat_data_t*)tapdata;
705 const h225_packet_info *hpi = (const h225_packet_info *)hpi_ptr;
706 int tag_idx = -1;
707 int reason_idx = -1;
709 if(hpi->msg_tag < 0) { /* uninitialized */
710 return TAP_PACKET_DONT_REDRAW;
713 switch (hpi->msg_type) {
715 case H225_RAS:
716 tag_idx = ras_msg_idx[MIN(hpi->msg_tag, (int)RAS_MSG_TYPES-1)];
718 /* Look for reason tag */
719 if(hpi->reason < 0) { /* uninitialized */
720 break;
723 switch(hpi->msg_tag) {
725 case 2: /* GRJ */
726 reason_idx = grj_reason_idx[MIN(hpi->reason, (int)GRJ_REASONS-1)];
727 break;
728 case 5: /* RRJ */
729 reason_idx = rrj_reason_idx[MIN(hpi->reason, (int)RRJ_REASONS-1)];
730 break;
731 case 6: /* URQ */
732 reason_idx = urq_reason_idx[MIN(hpi->reason, (int)URQ_REASONS-1)];
733 break;
734 case 8: /* URJ */
735 reason_idx = urj_reason_idx[MIN(hpi->reason, (int)URJ_REASONS-1)];
736 break;
737 case 11: /* ARJ */
738 reason_idx = arj_reason_idx[MIN(hpi->reason, (int)ARJ_REASONS-1)];
739 break;
740 case 14: /* BRJ */
741 reason_idx = brj_reason_idx[MIN(hpi->reason, (int)BRJ_REASONS-1)];
742 break;
743 case 15: /* DRQ */
744 reason_idx = drq_reason_idx[MIN(hpi->reason, (int)DRQ_REASONS-1)];
745 break;
746 case 17: /* DRJ */
747 reason_idx = drj_reason_idx[MIN(hpi->reason, (int)DRJ_REASONS-1)];
748 break;
749 case 20: /* LRJ */
750 reason_idx = lrj_reason_idx[MIN(hpi->reason, (int)LRJ_REASONS-1)];
751 break;
752 case 29: /* IRQ Nak */
753 reason_idx = irqnak_reason_idx[MIN(hpi->reason, (int)IRQNAK_REASONS-1)];
754 break;
755 default:
756 /* do nothing */
757 break;
760 break;
762 case H225_CS:
763 tag_idx = cs_msg_idx[MIN(hpi->msg_tag, (int)CS_MSG_TYPES-1)];
765 /* Look for reason tag */
766 if(hpi->reason < 0) { /* uninitialized */
767 break;
770 switch(hpi->msg_tag) {
772 case 5: /* ReleaseComplete */
773 reason_idx = rel_cmp_reason_idx[MIN(hpi->reason, (int)REL_CMP_REASONS-1)];
774 break;
775 case 6: /* Facility */
776 reason_idx = facility_reason_idx[MIN(hpi->reason, (int)FACILITY_REASONS-1)];
777 break;
778 default:
779 /* do nothing */
780 break;
783 break;
785 case H225_OTHERS:
786 default:
787 tag_idx = other_idx;
790 if (tag_idx >= 0) {
791 stat_tap_table*table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0);
792 stat_tap_table_item_type* msg_data = stat_tap_get_field_data(table, tag_idx, COUNT_COLUMN);
793 msg_data->value.uint_value++;
794 stat_tap_set_field_data(table, tag_idx, COUNT_COLUMN, msg_data);
796 if (reason_idx >= 0) {
797 msg_data = stat_tap_get_field_data(table, reason_idx, COUNT_COLUMN);
798 msg_data->value.uint_value++;
799 stat_tap_set_field_data(table, reason_idx, COUNT_COLUMN, msg_data);
802 return TAP_PACKET_REDRAW;
804 return TAP_PACKET_DONT_REDRAW;
807 static void
808 h225_stat_reset(stat_tap_table* table)
810 unsigned element;
811 stat_tap_table_item_type* item_data;
813 for (element = 0; element < table->num_elements; element++)
815 item_data = stat_tap_get_field_data(table, element, COUNT_COLUMN);
816 item_data->value.uint_value = 0;
817 stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data);
821 /*--- proto_register_h225 -------------------------------------------*/
822 void proto_register_h225(void) {
824 /* List of fields */
825 static hf_register_info hf[] = {
826 { &hf_h221Manufacturer,
827 { "H.225 Manufacturer", "h225.Manufacturer", FT_UINT32, BASE_HEX,
828 VALS(H221ManufacturerCode_vals), 0, "h225.H.221 Manufacturer", HFILL }},
830 { &hf_h225_ras_req_frame,
831 { "RAS Request Frame", "h225.ras.reqframe", FT_FRAMENUM, BASE_NONE,
832 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, NULL, HFILL }},
834 { &hf_h225_ras_rsp_frame,
835 { "RAS Response Frame", "h225.ras.rspframe", FT_FRAMENUM, BASE_NONE,
836 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, NULL, HFILL }},
838 { &hf_h225_ras_dup,
839 { "Duplicate RAS Message", "h225.ras.dup", FT_UINT32, BASE_DEC,
840 NULL, 0, NULL, HFILL }},
842 { &hf_h225_ras_deltatime,
843 { "RAS Service Response Time", "h225.ras.timedelta", FT_RELATIVE_TIME, BASE_NONE,
844 NULL, 0, "Timedelta between RAS-Request and RAS-Response", HFILL }},
846 { &hf_h225_debug_dissector_try_string,
847 { "*** DEBUG dissector_try_string", "h225.debug.dissector_try_string", FT_STRING, BASE_NONE,
848 NULL, 0, NULL, HFILL }},
850 #include "packet-h225-hfarr.c"
853 /* List of subtrees */
854 static int *ett[] = {
855 &ett_h225,
856 #include "packet-h225-ettarr.c"
859 static tap_param h225_stat_params[] = {
860 { PARAM_FILTER, "filter", "Filter", NULL, true }
863 static stat_tap_table_ui h225_stat_table = {
864 REGISTER_TELEPHONY_GROUP_UNSORTED,
865 "H.225",
866 PFNAME,
867 "h225,counter",
868 h225_stat_init,
869 h225_stat_packet,
870 h225_stat_reset,
871 NULL,
872 NULL,
873 array_length(h225_stat_fields), h225_stat_fields,
874 array_length(h225_stat_params), h225_stat_params,
875 NULL,
879 module_t *h225_module;
880 int i, proto_h225_ras;
882 /* Register protocol */
883 proto_h225 = proto_register_protocol(PNAME, PSNAME, PFNAME);
885 /* Create a "fake" protocol to get proper display strings for SRT dialogs */
886 proto_h225_ras = proto_register_protocol("H.225 RAS", "H.225 RAS", "h225_ras");
888 /* Register fields and subtrees */
889 proto_register_field_array(proto_h225, hf, array_length(hf));
890 proto_register_subtree_array(ett, array_length(ett));
892 h225_module = prefs_register_protocol(proto_h225, proto_reg_handoff_h225);
893 prefs_register_uint_preference(h225_module, "tls.port",
894 "H.225 TLS Port",
895 "H.225 Server TLS Port",
896 10, &h225_tls_port);
897 prefs_register_bool_preference(h225_module, "reassembly",
898 "Reassemble H.225 messages spanning multiple TCP segments",
899 "Whether the H.225 dissector should reassemble messages spanning multiple TCP segments."
900 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
901 &h225_reassembly);
902 prefs_register_bool_preference(h225_module, "h245_in_tree",
903 "Display tunnelled H.245 inside H.225.0 tree",
904 "ON - display tunnelled H.245 inside H.225.0 tree, OFF - display tunnelled H.245 in root tree after H.225.0",
905 &h225_h245_in_tree);
906 prefs_register_bool_preference(h225_module, "tp_in_tree",
907 "Display tunnelled protocols inside H.225.0 tree",
908 "ON - display tunnelled protocols inside H.225.0 tree, OFF - display tunnelled protocols in root tree after H.225.0",
909 &h225_tp_in_tree);
911 register_dissector(PFNAME, dissect_h225_H323UserInformation, proto_h225);
912 register_dissector("h323ui",dissect_h225_H323UserInformation, proto_h225);
913 h225ras_handle = register_dissector("h225.ras", dissect_h225_h225_RasMessage, proto_h225);
915 nsp_object_dissector_table = register_dissector_table("h225.nsp.object", "H.225 NonStandardParameter Object", proto_h225, FT_STRING, STRING_CASE_SENSITIVE);
916 nsp_h221_dissector_table = register_dissector_table("h225.nsp.h221", "H.225 NonStandardParameter h221", proto_h225, FT_UINT32, BASE_HEX);
917 tp_dissector_table = register_dissector_table("h225.tp", "H.225 Tunnelled Protocol", proto_h225, FT_STRING, STRING_CASE_SENSITIVE);
918 gef_name_dissector_table = register_dissector_table("h225.gef.name", "H.225 Generic Extensible Framework Name", proto_h225, FT_STRING, STRING_CASE_SENSITIVE);
919 gef_content_dissector_table = register_dissector_table("h225.gef.content", "H.225 Generic Extensible Framework Content", proto_h225, FT_STRING, STRING_CASE_SENSITIVE);
921 for(i=0;i<7;i++) {
922 ras_calls[i] = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), h225ras_call_hash, h225ras_call_equal);
925 h225_tap = register_tap(PFNAME);
927 register_rtd_table(proto_h225_ras, PFNAME, NUM_RAS_STATS, 1, ras_message_category, h225rassrt_packet, NULL);
929 register_stat_tap_table_ui(&h225_stat_table);
931 oid_add_from_string("Version 1","0.0.8.2250.0.1");
932 oid_add_from_string("Version 2","0.0.8.2250.0.2");
933 oid_add_from_string("Version 3","0.0.8.2250.0.3");
934 oid_add_from_string("Version 4","0.0.8.2250.0.4");
935 oid_add_from_string("Version 5","0.0.8.2250.0.5");
936 oid_add_from_string("Version 6","0.0.8.2250.0.6");
940 /*--- proto_reg_handoff_h225 ---------------------------------------*/
941 void
942 proto_reg_handoff_h225(void)
944 static bool h225_prefs_initialized = false;
945 static dissector_handle_t q931_tpkt_handle;
946 static unsigned saved_h225_tls_port;
948 if (!h225_prefs_initialized) {
949 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RAS_RANGE, h225ras_handle);
951 h245_handle = find_dissector("h245");
952 h245dg_handle = find_dissector("h245dg");
953 h4501_handle = find_dissector_add_dependency("h4501", proto_h225);
954 data_handle = find_dissector("data");
955 h225_prefs_initialized = true;
956 q931_tpkt_handle = find_dissector("q931.tpkt");
957 } else {
958 ssl_dissector_delete(saved_h225_tls_port, q931_tpkt_handle);
961 saved_h225_tls_port = h225_tls_port;
962 ssl_dissector_add(saved_h225_tls_port, q931_tpkt_handle);
965 static h225_packet_info* create_h225_packet_info(packet_info *pinfo)
967 h225_packet_info* pi = wmem_new0(pinfo->pool, h225_packet_info);
969 pi->msg_type = H225_OTHERS;
970 pi->cs_type = H225_OTHER;
971 pi->msg_tag = -1;
972 pi->reason = -1;
974 return pi;
978 The following function contains the routines for RAS request/response matching.
979 A RAS response matches with a request, if both messages have the same
980 RequestSequenceNumber, belong to the same IP conversation and belong to the same
981 RAS "category" (e.g. Admission, Registration).
983 We use hashtables to access the lists of RAS calls (request/response pairs).
984 We have one hashtable for each RAS category. The hashkeys consist of the
985 non-unique 16-bit RequestSequenceNumber and values representing the conversation.
987 In big capture files, we might get different requests with identical keys.
988 These requests aren't necessarily duplicates. They might be valid new requests.
989 At the moment we just use the timedelta between the last valid and the new request
990 to decide if the new request is a duplicate or not. There might be better ways.
991 Two thresholds are defined below.
993 However the decision is made, another problem arises. We can't just add those
994 requests to our hashtables. Instead we create lists of RAS calls with identical keys.
995 The hashtables for RAS calls contain now pointers to the first RAS call in a list of
996 RAS calls with identical keys.
997 These lists aren't expected to contain more than 3 items and are usually single item
998 lists. So we don't need an expensive but intelligent way to access these lists
999 (e.g. hashtables). Just walk through such a list.
1002 #define THRESHOLD_REPEATED_RESPONDED_CALL 300
1003 #define THRESHOLD_REPEATED_NOT_RESPONDED_CALL 1800
1005 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi)
1007 proto_item *hidden_item;
1008 conversation_t* conversation = NULL;
1009 h225ras_call_info_key h225ras_call_key;
1010 h225ras_call_t *h225ras_call = NULL;
1011 nstime_t delta;
1012 unsigned msg_category;
1014 if(pi->msg_type == H225_RAS && pi->msg_tag < 21) {
1015 /* make RAS request/response matching only for tags from 0 to 20 for now */
1017 msg_category = pi->msg_tag / 3;
1018 if(pi->msg_tag % 3 == 0) { /* Request Message */
1019 conversation = find_or_create_conversation(pinfo);
1021 /* prepare the key data */
1022 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
1023 h225ras_call_key.conversation = conversation;
1025 /* look up the request */
1026 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
1028 if (h225ras_call != NULL) {
1029 /* We've seen requests with this reqSeqNum, with the same
1030 source and destination, before - do we have
1031 *this* request already? */
1032 /* Walk through list of ras requests with identical keys */
1033 do {
1034 if (pinfo->num == h225ras_call->req_num) {
1035 /* We have seen this request before -> do nothing */
1036 break;
1039 /* if end of list is reached, exit loop and decide if request is duplicate or not. */
1040 if (h225ras_call->next_call == NULL) {
1041 if ( (pinfo->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0
1042 && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) )
1043 ||(pinfo->num > h225ras_call->req_num && h225ras_call->rsp_num == 0
1044 && pinfo->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) )
1046 /* if last request has been responded
1047 and this request appears after last response (has bigger frame number)
1048 and last request occurred more than 300 seconds ago,
1049 or if last request hasn't been responded
1050 and this request appears after last request (has bigger frame number)
1051 and last request occurred more than 1800 seconds ago,
1052 we decide that we have a new request */
1053 /* Append new ras call to list */
1054 h225ras_call = append_h225ras_call(h225ras_call, pinfo, &pi->guid, msg_category);
1055 } else {
1056 /* No, so it's a duplicate request.
1057 Mark it as such. */
1058 pi->is_duplicate = true;
1059 hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
1060 proto_item_set_hidden(hidden_item);
1062 break;
1064 h225ras_call = h225ras_call->next_call;
1065 } while (h225ras_call != NULL );
1067 else {
1068 h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, &pi->guid, msg_category);
1071 /* add link to response frame, if available */
1072 if(h225ras_call && h225ras_call->rsp_num != 0){
1073 proto_item *ti =
1074 proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num,
1075 "The response to this request is in frame %u",
1076 h225ras_call->rsp_num);
1077 proto_item_set_generated(ti);
1080 /* end of request message handling*/
1082 else { /* Confirm or Reject Message */
1083 conversation = find_conversation_pinfo(pinfo, 0);
1084 if (conversation != NULL) {
1085 /* look only for matching request, if
1086 matching conversation is available. */
1087 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
1088 h225ras_call_key.conversation = conversation;
1089 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
1090 if(h225ras_call) {
1091 /* find matching ras_call in list of ras calls with identical keys */
1092 do {
1093 if (pinfo->num == h225ras_call->rsp_num) {
1094 /* We have seen this response before -> stop now with matching ras call */
1095 break;
1098 /* Break when list end is reached */
1099 if(h225ras_call->next_call == NULL) {
1100 break;
1102 h225ras_call = h225ras_call->next_call;
1103 } while (h225ras_call != NULL) ;
1105 if (!h225ras_call) {
1106 return;
1109 /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */
1110 if (msg_category == 3 || msg_category == 5) {
1111 pi->guid = h225ras_call->guid;
1112 hidden_item = proto_tree_add_guid(tree, hf_h225_guid, tvb, 0, GUID_LEN, &pi->guid);
1113 proto_item_set_hidden(hidden_item);
1116 if (h225ras_call->rsp_num == 0) {
1117 /* We have not yet seen a response to that call, so
1118 this must be the first response; remember its
1119 frame number. */
1120 h225ras_call->rsp_num = pinfo->num;
1122 else {
1123 /* We have seen a response to this call - but was it
1124 *this* response? */
1125 if (h225ras_call->rsp_num != pinfo->num) {
1126 /* No, so it's a duplicate response.
1127 Mark it as such. */
1128 pi->is_duplicate = true;
1129 hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
1130 proto_item_set_hidden(hidden_item);
1134 if(h225ras_call->req_num != 0){
1135 proto_item *ti;
1136 h225ras_call->responded = true;
1137 pi->request_available = true;
1139 /* Indicate the frame to which this is a reply. */
1140 ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num,
1141 "This is a response to a request in frame %u", h225ras_call->req_num);
1142 proto_item_set_generated(ti);
1144 /* Calculate RAS Service Response Time */
1145 nstime_delta(&delta, &pinfo->abs_ts, &h225ras_call->req_time);
1146 pi->delta_time = delta; /* give it to tap */
1148 /* display Ras Service Response Time and make it filterable */
1149 ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time));
1150 proto_item_set_generated(ti);
1159 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1161 * Local Variables:
1162 * c-basic-offset: 2
1163 * tab-width: 8
1164 * indent-tabs-mode: nil
1165 * End:
1167 * vi: set shiftwidth=2 tabstop=8 expandtab:
1168 * :indentSize=2:tabSize=8:noTabs=true: