2 * Routines for h225 packet dissection
3 * Copyright 2005, Anders Broman <anders.broman@ericsson.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * To quote the author of the previous H323/H225/H245 dissector:
26 * "This is a complete replacement of the previous limitied dissector
27 * that Ronnie was crazy enough to write by hand. It was a lot of time
28 * to hack it by hand, but it is incomplete and buggy and it is good when
30 * Ronnie did a great job and all the VoIP users had made good use of it!
31 * Credit to Tomas Kukosa for developing the Asn2eth compiler.
40 #include <epan/packet.h>
41 #include <epan/conversation.h>
46 #include <epan/prefs.h>
48 #include "packet-tpkt.h"
49 #include "packet-per.h"
50 #include "packet-h225.h"
52 #include <epan/h225-persistentdata.h>
53 #include "packet-ber.h"
54 #include "packet-h235.h"
55 #include "packet-h245.h"
56 #include "packet-q931.h"
58 /*---------------------------------------------------------------------------*/
59 /* next tvb list - can be moved to some more common file if other dissector needs it */
61 #include <epan/emem.h>
63 typedef struct next_tvb_item {
64 struct next_tvb_item *next;
65 struct next_tvb_item *previous;
66 dissector_handle_t handle;
72 next_tvb_item_t *first;
73 next_tvb_item_t *last;
77 void next_tvb_init(next_tvb_list_t *list);
78 void next_tvb_add(next_tvb_list_t *list, tvbuff_t *tvb, proto_tree *tree, dissector_handle_t handle);
79 void next_tvb_call(next_tvb_list_t *list, packet_info *pinfo, proto_tree *tree, dissector_handle_t handle, dissector_handle_t data_handle);
81 void next_tvb_init(next_tvb_list_t *list) {
87 void next_tvb_add(next_tvb_list_t *list, tvbuff_t *tvb, proto_tree *tree, dissector_handle_t handle) {
88 next_tvb_item_t *item;
90 item = ep_alloc(sizeof(next_tvb_item_t));
92 item->handle = handle;
97 list->last->next = item;
102 item->previous = list->last;
107 void next_tvb_call(next_tvb_list_t *list, packet_info *pinfo, proto_tree *tree, dissector_handle_t handle, dissector_handle_t data_handle) {
108 next_tvb_item_t *item;
112 if (item->tvb && tvb_length(item->tvb)) {
113 call_dissector((item->handle) ? item->handle : ((handle) ? handle : data_handle), item->tvb, pinfo, (item->tree) ? item->tree : tree);
119 /*---------------------------------------------------------------------------*/
121 #define PNAME "H323-MESSAGES"
122 #define PSNAME "H.225.0"
123 #define PFNAME "h225"
125 #define UDP_PORT_RAS1 1718
126 #define UDP_PORT_RAS2 1719
127 #define TCP_PORT_CS 1720
129 static void reset_h225_packet_info(h225_packet_info *pi);
130 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
131 static int dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
133 static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H225 messaages per packet */
134 static int pi_current=0;
135 h225_packet_info *h225_pi=NULL;
137 static dissector_handle_t h225ras_handle;
138 static dissector_handle_t H323UserInformation_handle;
139 static dissector_handle_t data_handle;
140 /* Subdissector tables */
141 static dissector_table_t nsp_object_dissector_table;
142 static dissector_table_t nsp_h221_dissector_table;
143 static dissector_table_t tp_dissector_table;
146 static dissector_handle_t h245_handle=NULL;
147 static dissector_handle_t h245dg_handle=NULL;
148 static dissector_handle_t h4501_handle=NULL;
150 static dissector_handle_t nsp_handle;
151 static dissector_handle_t tp_handle;
153 static next_tvb_list_t h245_list;
154 static next_tvb_list_t tp_list;
156 /* Initialize the protocol and registered fields */
157 static int h225_tap = -1;
158 static int proto_h225 = -1;
160 static int hf_h225_H323_UserInformation = -1;
161 static int hf_h225_RasMessage = -1;
162 static int hf_h221Manufacturer = -1;
163 static int hf_h225_ras_req_frame = -1;
164 static int hf_h225_ras_rsp_frame = -1;
165 static int hf_h225_ras_dup = -1;
166 static int hf_h225_ras_deltatime = -1;
167 static int hf_h225_fastStart_item_length = -1;
169 #include "packet-h225-hf.c"
171 /* Initialize the subtree pointers */
172 static gint ett_h225 = -1;
173 #include "packet-h225-ett.c"
176 static gboolean h225_reassembly = TRUE;
177 static gboolean h225_h245_in_tree = TRUE;
178 static gboolean h225_tp_in_tree = TRUE;
180 /* Global variables */
181 static guint32 ipv4_address;
182 static guint32 ipv4_port;
183 guint32 T38_manufacturer_code;
185 static gboolean contains_faststart = FALSE;
187 /* NonStandardParameter */
188 static const char *nsiOID;
189 static guint32 h221NonStandard;
190 static guint32 t35CountryCode;
191 static guint32 t35Extension;
192 static guint32 manufacturerCode;
194 /* TunnelledProtocol */
195 static const char *tpOID;
197 #include "packet-h225-fn.c"
201 dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
211 h225_pi=&pi_arr[pi_current];
213 /* Init struct for collecting h225_packet_info */
214 reset_h225_packet_info(h225_pi);
215 h225_pi->msg_type = H225_CS;
217 next_tvb_init(&h245_list);
218 next_tvb_init(&tp_list);
220 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
221 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
223 if (check_col(pinfo->cinfo, COL_INFO)){
224 col_clear(pinfo->cinfo, COL_INFO);
227 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, tvb_length(tvb), PSNAME" CS");
228 tr=proto_item_add_subtree(it, ett_h225);
230 per_aligment_type_callback(TRUE);
231 offset = dissect_h225_H323_UserInformation(tvb, offset,pinfo, tr, hf_h225_H323_UserInformation);
233 if (h245_list.count && check_col(pinfo->cinfo, COL_PROTOCOL)){
234 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
235 col_set_fence(pinfo->cinfo, COL_PROTOCOL);
238 next_tvb_call(&h245_list, pinfo, tree, h245dg_handle, data_handle);
239 next_tvb_call(&tp_list, pinfo, tree, NULL, data_handle);
241 tap_queue_packet(h225_tap, pinfo, h225_pi);
246 dissect_h225_h225_RasMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){
255 h225_pi=&pi_arr[pi_current];
257 /* Init struct for collecting h225_packet_info */
258 reset_h225_packet_info(h225_pi);
259 h225_pi->msg_type = H225_RAS;
261 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
262 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
265 it=proto_tree_add_protocol_format(tree, proto_h225, tvb, offset, tvb_length(tvb), PSNAME" RAS");
266 tr=proto_item_add_subtree(it, ett_h225);
268 per_aligment_type_callback(TRUE);
269 offset = dissect_h225_RasMessage(tvb, 0, pinfo,tr, hf_h225_RasMessage );
271 ras_call_matching(tvb, pinfo, tr, h225_pi);
273 tap_queue_packet(h225_tap, pinfo, h225_pi);
278 /*--- proto_register_h225 -------------------------------------------*/
279 void proto_register_h225(void) {
282 static hf_register_info hf[] = {
283 { &hf_h225_H323_UserInformation,
284 { "H323_UserInformation", "h225.H323_UserInformation", FT_NONE, BASE_NONE,
285 NULL, 0, "H323_UserInformation sequence", HFILL }},
286 { &hf_h225_RasMessage,
287 { "RasMessage", "h225.RasMessage", FT_UINT32, BASE_DEC,
288 VALS(RasMessage_vals), 0, "RasMessage choice", HFILL }},
289 { &hf_h221Manufacturer,
290 { "H.221 Manufacturer", "h221.Manufacturer", FT_UINT32, BASE_HEX,
291 VALS(H221ManufacturerCode_vals), 0, "H.221 Manufacturer", HFILL }},
292 { &hf_h225_ras_req_frame,
293 { "RAS Request Frame", "h225.ras.reqframe", FT_FRAMENUM, BASE_NONE,
294 NULL, 0, "RAS Request Frame", HFILL }},
295 { &hf_h225_ras_rsp_frame,
296 { "RAS Response Frame", "h225.ras.rspframe", FT_FRAMENUM, BASE_NONE,
297 NULL, 0, "RAS Response Frame", HFILL }},
299 { "Duplicate RAS Message", "h225.ras.dup", FT_UINT32, BASE_DEC,
300 NULL, 0, "Duplicate RAS Message", HFILL }},
301 { &hf_h225_ras_deltatime,
302 { "RAS Service Response Time", "h225.ras.timedelta", FT_RELATIVE_TIME, BASE_NONE,
303 NULL, 0, "Timedelta between RAS-Request and RAS-Response", HFILL }},
304 { &hf_h225_fastStart_item_length,
305 { "fastStart item length", "h225.fastStart_item_length", FT_UINT32, BASE_DEC,
306 NULL, 0, "fastStart item length", HFILL }},
308 #include "packet-h225-hfarr.c"
311 /* List of subtrees */
312 static gint *ett[] = {
314 #include "packet-h225-ettarr.c"
316 module_t *h225_module;
318 /* Register protocol */
319 proto_h225 = proto_register_protocol(PNAME, PSNAME, PFNAME);
320 /* Register fields and subtrees */
321 proto_register_field_array(proto_h225, hf, array_length(hf));
322 proto_register_subtree_array(ett, array_length(ett));
324 h225_module = prefs_register_protocol(proto_h225, NULL);
325 prefs_register_bool_preference(h225_module, "reassembly",
326 "Reassemble H.225 messages spanning multiple TCP segments",
327 "Whether the H.225 dissector should reassemble messages spanning multiple TCP segments."
328 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
330 prefs_register_bool_preference(h225_module, "h245_in_tree",
331 "Display tunnelled H.245 inside H.225.0 tree",
332 "ON - display tunnelled H.245 inside H.225.0 tree, OFF - display tunnelled H.245 in root tree after H.225.0",
334 prefs_register_bool_preference(h225_module, "tp_in_tree",
335 "Display tunnelled protocols inside H.225.0 tree",
336 "ON - display tunnelled protocols inside H.225.0 tree, OFF - display tunnelled protocols in root tree after H.225.0",
339 new_register_dissector("h225", dissect_h225_H323UserInformation, proto_h225);
340 new_register_dissector("h323ui",dissect_h225_H323UserInformation, proto_h225);
342 nsp_object_dissector_table = register_dissector_table("h225.nsp.object", "H.225 NonStandardParameter (object)", FT_STRING, BASE_NONE);
343 nsp_h221_dissector_table = register_dissector_table("h225.nsp.h221", "H.225 NonStandardParameter (h221)", FT_UINT32, BASE_HEX);
344 tp_dissector_table = register_dissector_table("h225.tp", "H.225 TunnelledProtocol", FT_STRING, BASE_NONE);
346 register_init_routine(&h225_init_routine);
347 h225_tap = register_tap("h225");
348 register_ber_oid_name("0.0.8.2250.0.2","itu-t(0) recommendation(0) h(8) h225-0(2250) version(0) 2");
349 register_ber_oid_name("0.0.8.2250.0.4","itu-t(0) recommendation(0) h(8) h225-0(2250) version(0) 4");
355 /*--- proto_reg_handoff_h225 ---------------------------------------*/
357 proto_reg_handoff_h225(void)
359 h225ras_handle=new_create_dissector_handle(dissect_h225_h225_RasMessage, proto_h225);
360 H323UserInformation_handle=find_dissector("h323ui");
362 h245_handle = find_dissector("h245");
363 h245dg_handle = find_dissector("h245dg");
364 h4501_handle = find_dissector("h4501");
365 data_handle = find_dissector("data");
367 dissector_add("udp.port", UDP_PORT_RAS1, h225ras_handle);
368 dissector_add("udp.port", UDP_PORT_RAS2, h225ras_handle);
372 static void reset_h225_packet_info(h225_packet_info *pi)
378 pi->msg_type = H225_OTHERS;
379 pi->cs_type = H225_OTHER;
382 pi->requestSeqNum = 0;
383 memset(&pi->guid,0,sizeof pi->guid);
384 pi->is_duplicate = FALSE;
385 pi->request_available = FALSE;
386 pi->is_faststart = FALSE;
388 pi->is_h245Tunneling = FALSE;
389 pi->h245_address = 0;
391 pi->frame_label[0] = '\0';
392 pi->dialedDigits[0] = '\0';
393 pi->is_destinationInfo = FALSE;
397 The following function contains the routines for RAS request/response matching.
398 A RAS response matches with a request, if both messages have the same
399 RequestSequenceNumber, belong to the same IP conversation and belong to the same
400 RAS "category" (e.g. Admission, Registration).
402 We use hashtables to access the lists of RAS calls (request/response pairs).
403 We have one hashtable for each RAS category. The hashkeys consist of the
404 non-unique 16-bit RequestSequenceNumber and values representing the conversation.
406 In big capture files, we might get different requests with identical keys.
407 These requests aren't necessarily duplicates. They might be valid new requests.
408 At the moment we just use the timedelta between the last valid and the new request
409 to decide if the new request is a duplicate or not. There might be better ways.
410 Two thresholds are defined below.
412 However the decision is made, another problem arises. We can't just add those
413 requests to our hashtables. Instead we create lists of RAS calls with identical keys.
414 The hashtables for RAS calls contain now pointers to the first RAS call in a list of
415 RAS calls with identical keys.
416 These lists aren't expected to contain more than 3 items and are usually single item
417 lists. So we don't need an expensive but intelligent way to access these lists
418 (e.g. hashtables). Just walk through such a list.
421 #define THRESHOLD_REPEATED_RESPONDED_CALL 300
422 #define THRESHOLD_REPEATED_NOT_RESPONDED_CALL 1800
424 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi)
426 conversation_t* conversation = NULL;
427 h225ras_call_info_key h225ras_call_key;
428 h225ras_call_t *h225ras_call = NULL;
432 if(pi->msg_type == H225_RAS && pi->msg_tag < 21) {
433 /* make RAS request/response matching only for tags from 0 to 20 for now */
435 msg_category = pi->msg_tag / 3;
436 if(pi->msg_tag % 3 == 0) { /* Request Message */
437 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
438 &pinfo->dst, pinfo->ptype, pinfo->srcport,
441 if (conversation == NULL) {
442 /* It's not part of any conversation - create a new one. */
443 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
444 &pinfo->dst, pinfo->ptype, pinfo->srcport,
449 /* prepare the key data */
450 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
451 h225ras_call_key.conversation = conversation;
453 /* look up the request */
454 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
456 if (h225ras_call != NULL) {
457 /* We've seen requests with this reqSeqNum, with the same
458 source and destination, before - do we have
459 *this* request already? */
460 /* Walk through list of ras requests with identical keys */
462 if (pinfo->fd->num == h225ras_call->req_num) {
463 /* We have seen this request before -> do nothing */
467 /* if end of list is reached, exit loop and decide if request is duplicate or not. */
468 if (h225ras_call->next_call == NULL) {
469 if ( (pinfo->fd->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0
470 && pinfo->fd->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) )
471 ||(pinfo->fd->num > h225ras_call->req_num && h225ras_call->rsp_num == 0
472 && pinfo->fd->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) )
474 /* if last request has been responded
475 and this request appears after last response (has bigger frame number)
476 and last request occured more than 300 seconds ago,
477 or if last request hasn't been responded
478 and this request appears after last request (has bigger frame number)
479 and last request occured more than 1800 seconds ago,
480 we decide that we have a new request */
481 /* Append new ras call to list */
482 h225ras_call = append_h225ras_call(h225ras_call, pinfo, &pi->guid, msg_category);
484 /* No, so it's a duplicate request.
486 pi->is_duplicate = TRUE;
487 proto_tree_add_uint_hidden(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
491 h225ras_call = h225ras_call->next_call;
492 } while (h225ras_call != NULL );
495 h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, &pi->guid, msg_category);
498 /* add link to response frame, if available */
499 if(h225ras_call->rsp_num != 0){
501 proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num,
502 "The response to this request is in frame %u",
503 h225ras_call->rsp_num);
504 PROTO_ITEM_SET_GENERATED(ti);
507 /* end of request message handling*/
509 else { /* Confirm or Reject Message */
510 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
511 &pinfo->dst, pinfo->ptype, pinfo->srcport,
513 if (conversation != NULL) {
514 /* look only for matching request, if
515 matching conversation is available. */
516 h225ras_call_key.reqSeqNum = pi->requestSeqNum;
517 h225ras_call_key.conversation = conversation;
518 h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
520 /* find matching ras_call in list of ras calls with identical keys */
522 if (pinfo->fd->num == h225ras_call->rsp_num) {
523 /* We have seen this response before -> stop now with matching ras call */
527 /* Break when list end is reached */
528 if(h225ras_call->next_call == NULL) {
531 h225ras_call = h225ras_call->next_call;
532 } while (h225ras_call != NULL) ;
534 /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */
535 if (msg_category == 3 || msg_category == 5) {
536 pi->guid = h225ras_call->guid;
537 proto_tree_add_guid_hidden(tree, hf_h225_guid, tvb, 0, GUID_LEN, &pi->guid);
540 if (h225ras_call->rsp_num == 0) {
541 /* We have not yet seen a response to that call, so
542 this must be the first response; remember its
544 h225ras_call->rsp_num = pinfo->fd->num;
547 /* We have seen a response to this call - but was it
549 if (h225ras_call->rsp_num != pinfo->fd->num) {
550 /* No, so it's a duplicate response.
552 pi->is_duplicate = TRUE;
553 proto_tree_add_uint_hidden(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
557 if(h225ras_call->req_num != 0){
559 h225ras_call->responded = TRUE;
560 pi->request_available = TRUE;
562 /* Indicate the frame to which this is a reply. */
563 ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num,
564 "This is a response to a request in frame %u", h225ras_call->req_num);
565 PROTO_ITEM_SET_GENERATED(ti);
567 /* Calculate RAS Service Response Time */
568 nstime_delta(&delta, &pinfo->fd->abs_ts, &h225ras_call->req_time);
569 pi->delta_time = delta; /* give it to tap */
571 /* display Ras Service Response Time and make it filterable */
572 ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time));
573 PROTO_ITEM_SET_GENERATED(ti);