Ethereal-dev: [Ethereal-dev] New dissectors: H.223 and friends
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Jeff Snyder <jeff@xxxxxxxxxxxxx>
Date: Fri, 30 Sep 2005 16:15:14 +0100
Hi, I've attached a set of patches (against r16051) that implement dissection of the ITU-T Recommendation H.223, aswell as several associated protocols. These have been developed by myself and Richard van der Hoff at MX Telecom. We would be most greatful if someone could take a look at them and hopefully check them into the svn repository. Could any replies to this mail please be sent to Richard van der Hoff (richardv@xxxxxxxxxxxxx) instead of myself, as I will be leaving this company at the end of today. Finally, here's the list of patches: 00-iax.diff Modifications to the IAX2 dissector so that it offers desegmentation to subdissectors using the same API as TCP offers (pinfo->desegment_len etc) 01-amr.diff Modifications to the AMR dissector to allow AMR IF2 data to be dissected via call_dissector() from packet-h223.c. This patch also causes the AMR dissector to append the frame type string to the info column, so that the info column shows what protocols an H.223 frame contains. 02-h263-data.diff Modifications to packet-h263.c to separate the dissection of h.263 RTP encpasulation from the dissection of the actual h.263 data. The data dissection functions are added as a second dissector. This data-only dissector is used to dissect the video channel in our h.223 streams. As with the AMR modification, this makes the H.263 dissector append to the info column. 03-h245.diff Extensions to the h.245 dissector to extract H.223 Multiplex Code and Logical Channel setup messages, and pass this information to the H.223 dissector. 04-stream.diff A simplified packet reassembly API built on top of fragment_add_seq_next for reassembling fragments that are delivered in-order, where fragments are identified by a framenum and an offset into that frame. Streams are attached to a conversation or a circuit and are unidirectional. 05-plugin-framework.diff Build system stuff for the h223 plugin: confiure.in, Changelog, COPYING, Makefile.am, Makefile.nmake, moduleinfo.h, plugin.c, plus neccesary modifications to plugins/Makefile.{am,nmake} 06-srp.dif A dissector for H.324/SRP and H.324/CCSRL, which runs over H.223 and encapsulates H.245 messages 07-golay.diff Methods used for the checksumming/FEC of H.223 MUX-PDU headers 08-h223.diff The actual H.223 disesctor Thanks, Jeff Snyder -- Jeff Snyder <jeff@xxxxxxxxxxxxx> http://www.mxtelecom.com
--- epan/dissectors/packet-h261.c 2005-09-29 16:07:12.651436752 +0100 +++ epan/dissectors/packet-h261.c 2005-09-29 17:30:14.803034584 +0100 @@ -2,7 +2,7 @@ * * Routines for ITU-T Recommendation H.261 dissection * - * $Id: packet-h261.c,v 1.1.1.2 2005/09/29 13:18:54 jeff Exp $ + * $Id: packet-h261.c,v 1.3 2005/09/29 15:51:25 jeff Exp $ * * Copyright 2000, Philips Electronics N.V. * Andreas Sikkema <h323@xxxxxxxxxx> @@ -43,6 +43,7 @@ #include <string.h> #include <epan/rtp_pt.h> +#include "iax2_codec_type.h" /* H.261 header fields */ static int proto_h261 = -1; @@ -260,4 +261,5 @@ h261_handle = create_dissector_handle(dissect_h261, proto_h261); dissector_add("rtp.pt", PT_H261, h261_handle); + dissector_add("iax2.codec", AST_FORMAT_H261, h261_handle); } --- epan/dissectors/packet-iax2.c 2005-09-29 16:07:12.816411672 +0100 +++ epan/dissectors/packet-iax2.c 2005-09-29 17:30:14.963010264 +0100 @@ -8,7 +8,7 @@ * IAX2 is a VoIP protocol for the open source PBX Asterisk. Please see * http://www.asterisk.org for more information. * - * $Id: packet-iax2.c,v 1.1.1.4 2005/09/29 13:18:54 jeff Exp $ + * $Id: packet-iax2.c,v 1.18 2005/09/29 15:51:25 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -39,6 +39,7 @@ #include <epan/packet.h> #include <epan/to_str.h> #include <epan/emem.h> +#include <epan/reassemble.h> #include "packet-iax2.h" #include <epan/iax2_codec_type.h> @@ -102,6 +103,16 @@ static int hf_iax2_cap_h261 = -1; static int hf_iax2_cap_h263 = -1; +static int hf_iax2_fragments = -1; +static int hf_iax2_fragment = -1; +static int hf_iax2_fragment_overlap = -1; +static int hf_iax2_fragment_overlap_conflict = -1; +static int hf_iax2_fragment_multiple_tails = -1; +static int hf_iax2_fragment_too_long_fragment = -1; +static int hf_iax2_fragment_error = -1; +static int hf_iax2_reassembled_in = -1; + + /* hf_iax2_ies is an array of header fields, one per potential Information * Element. It's done this way (rather than having separate variables for each * IE) to make the dissection of information elements clearer and more @@ -128,6 +139,22 @@ static gint ett_iax2_ie = -1; /* single IE */ static gint ett_iax2_codecs = -1; /* capabilities IE */ static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */ +static gint ett_iax2_fragment = -1; +static gint ett_iax2_fragments = -1; + +static const fragment_items iax2_fragment_items = { + &ett_iax2_fragment, + &ett_iax2_fragments, + &hf_iax2_fragments, + &hf_iax2_fragment, + &hf_iax2_fragment_overlap, + &hf_iax2_fragment_overlap_conflict, + &hf_iax2_fragment_multiple_tails, + &hf_iax2_fragment_too_long_fragment, + &hf_iax2_fragment_error, + &hf_iax2_reassembled_in, + "iax2 fragments" +}; static dissector_handle_t data_handle; @@ -507,6 +534,11 @@ /* ************************************************************************* */ +typedef struct { + guint32 current_frag_id; + guint32 current_frag_bytes; + gboolean in_frag; +} iax_call_dirdata; /* This is our per-call data structure, which is attached to both the * forward and reverse circuits. @@ -538,6 +570,11 @@ /* the absolute start time of the call */ nstime_t start_time; + + GHashTable *fid_table; + GHashTable *fragment_table; + GHashTable *totlen_table; + iax_call_dirdata dirdata[2]; } iax_call_data; static void iax_init_hash( void ) @@ -820,6 +857,11 @@ call -> subdissector = NULL; call -> start_time = pinfo->fd->abs_ts; nstime_delta(&call -> start_time, &call -> start_time, &millisecond); + call -> fid_table = g_hash_table_new(g_direct_hash, g_direct_equal); + call -> totlen_table = g_hash_table_new(g_direct_hash, g_direct_equal); + call -> dirdata[0].in_frag=FALSE; + call -> dirdata[1].in_frag=FALSE; + fragment_table_init(&(call->fragment_table)); iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE); @@ -909,8 +951,8 @@ proto_tree * main_tree); static void dissect_payload(tvbuff_t *tvb, guint32 offset, - packet_info *pinfo, proto_tree *tree, - guint32 ts, gboolean video, + packet_info *pinfo, proto_tree *iax2_tree, + proto_tree *tree, guint32 ts, gboolean video, iax_packet_data *iax_packet); @@ -1468,7 +1510,7 @@ } } - dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE,iax_packet); + dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE,iax_packet); break; case AST_FRAME_VIDEO: @@ -1496,7 +1538,7 @@ col_append_fstr (pinfo->cinfo, COL_INFO, ", Mark" ); - dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet); + dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet); break; @@ -1586,7 +1628,7 @@ scallno, ts, rtp_marker?", Mark":""); - dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet); + dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet); /* next time we come to parse this packet, don't propogate the codec into the * call_data */ @@ -1627,7 +1669,7 @@ /* XXX fix the timestamp logic */ - dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE, iax_packet); + dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet); /* next time we come to parse this packet, don't propogate the codec into the @@ -1637,14 +1679,179 @@ return offset; } +static void process_iax_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + gboolean video, iax_packet_data *iax_packet ) +{ + guint32 codec = iax_packet -> codec; + iax_call_data *iax_call = iax_packet -> call_data; + + if( !video && iax_call && iax_call->subdissector ) { + call_dissector(iax_call->subdissector, tvb, pinfo, tree); + return; + } + + if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, tvb, pinfo, tree )) + return; + + /* we don't know how to dissect our data: dissect it as data */ + call_dissector(data_handle,tvb, pinfo, tree); +} + +static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree, + proto_tree *tree, gboolean video, iax_packet_data *iax_packet ) +{ + + iax_call_data *iax_call = iax_packet -> call_data; + iax_call_dirdata *dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]); + gpointer unused,value; + guint32 fid,frag_len,offset,tot_len,frag_offset,nbytes,deseg_offset; + gint32 old_len; + fragment_data *fd_head; + tvbuff_t *next_tvb; + gboolean complete = FALSE, called_dissector = FALSE, must_desegment = FALSE; + proto_item *frag_tree_item, *iax_tree_item; + + pinfo->desegment_offset = 0; + pinfo->desegment_len = 0; + deseg_offset = 0; + + if((!pinfo->fd->flags.visited && dirdata->in_frag) || + g_hash_table_lookup_extended(iax_call->fid_table, + GUINT_TO_POINTER(pinfo->fd->num), &unused, &value) ) { + /* then we are continuing an already-started pdu */ + frag_len = tvb_reported_length( tvb ); + offset = 0; + tot_len = GPOINTER_TO_UINT(g_hash_table_lookup(iax_call->totlen_table, GUINT_TO_POINTER(fid))); + if(!pinfo->fd->flags.visited) { + fid = dirdata->current_frag_id; + g_hash_table_insert( iax_call->fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid) ); + frag_offset = dirdata->current_frag_bytes; + complete = dirdata->current_frag_bytes > tot_len; + dirdata->current_frag_bytes += frag_len; + } else { + fid = GPOINTER_TO_UINT(value); + // these values are unused by fragmen_add if pinfo->fd->flags.visited + dirdata->current_frag_bytes = 0; + complete = FALSE; + } + + /* fragment_add checks for already-added */ + fd_head = fragment_add( tvb, offset, pinfo, fid, + iax_call->fragment_table, + frag_offset, + frag_len, !complete ); + + if(pinfo->fd->flags.visited) + complete = (fd_head && (pinfo->fd->num == fd_head->reassembled_in)); + + } else { + fid=offset=0; // initialise them here aswell to get rid of compiler warnings + process_iax_pdu(tvb,pinfo,tree,video,iax_packet); + called_dissector = TRUE; + if(pinfo->desegment_len) { + must_desegment = TRUE; + deseg_offset = pinfo->desegment_offset; + } + fd_head = NULL; + } + + /* do we have a completely desegmented datagram? */ + if (fd_head) { + /* we've got sometheing dissectable.. but is this the last segment of it? */ + if(complete) { // this will always be true, since frags are added in seq. + next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); // I don't know what the f*** this line does, so don't ask + add_new_data_source(pinfo, next_tvb, "Reassembled IAX2"); + process_iax_pdu(next_tvb,pinfo,tree,video,iax_packet); + called_dissector = TRUE; + old_len = (gint32)(tvb_reported_length(next_tvb) - tvb_reported_length_remaining(tvb,offset)); + if( pinfo->desegment_len && + pinfo->desegment_offset < old_len ) { + /* + * oops, it wasn't actually complete + */ + fragment_set_partial_reassembly(pinfo, fid, iax_call->fragment_table); + g_hash_table_insert(iax_call->totlen_table, GUINT_TO_POINTER(fid), + GUINT_TO_POINTER(tvb_reported_length(next_tvb) + pinfo->desegment_len) ); + } else { + nbytes = tvb_reported_length( tvb ); + show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item); + iax_tree_item = proto_tree_get_parent( iax2_tree ); + if(iax_tree_item) + iax_tree_item = proto_item_get_parent( iax_tree_item ); + if( frag_tree_item && iax_tree_item ) + proto_tree_move_item( tree, iax_tree_item, frag_tree_item ); + dirdata->in_frag = FALSE; + if( pinfo->desegment_len ) { + /* + * .. but not everything + */ + must_desegment = TRUE; + + // make desegment_offset relative to the tvb + deseg_offset = pinfo->desegment_offset - (tvb_reported_length( next_tvb ) - tvb_reported_length( tvb )); + } + } + } + } + + if(must_desegment) { + fid = pinfo->fd->num; + if(pinfo->fd->flags.visited) { + fd_head = fragment_get( pinfo, fid, iax_call->fragment_table ); + } else { + frag_len = tvb_reported_length_remaining(tvb,deseg_offset); + dirdata->current_frag_id = fid; + dirdata->current_frag_bytes = frag_len; + dirdata->in_frag = TRUE; + offset = deseg_offset; + complete = FALSE; + fd_head = fragment_add(tvb, offset, pinfo, fid, + iax_call->fragment_table, + 0, frag_len, !complete ); + g_hash_table_insert(iax_call->totlen_table, GUINT_TO_POINTER(fid), + GUINT_TO_POINTER( frag_len + pinfo->desegment_len) ); + } + } + + if( !called_dissector || pinfo->desegment_len != 0 ) { + if( fd_head != NULL && fd_head->reassembled_in != 0 && + !(fd_head->flags & FD_PARTIAL_REASSEMBLY) ) { + iax_tree_item = proto_tree_add_uint( tree, hf_iax2_reassembled_in, + tvb, deseg_offset, tvb_reported_length_remaining(tvb,deseg_offset), + fd_head->reassembled_in); + PROTO_ITEM_SET_GENERATED(iax_tree_item); + } else if(fd_head && (fd_head->reassembled_in != 0 || (fd_head->flags & FD_PARTIAL_REASSEMBLY)) ) { + // this fragment is never reassembled + proto_tree_add_text( tree, tvb, deseg_offset, -1, + "IAX2 fragment, unfinished"); + } + + if( pinfo->desegment_offset == 0 ) { + if (check_col(pinfo->cinfo, COL_PROTOCOL)){ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2"); + } + if (check_col(pinfo->cinfo, COL_INFO)){ + col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]"); + } + } + nbytes = tvb_reported_length_remaining( tvb, deseg_offset ); + } + + pinfo->can_desegment = 0; + pinfo->desegment_offset = 0; + pinfo->desegment_len = 0; +} + static void dissect_payload(tvbuff_t *tvb, guint32 offset, - packet_info *pinfo, proto_tree *tree, - guint32 ts, gboolean video, + packet_info *pinfo, proto_tree *iax2_tree, + proto_tree *tree, guint32 ts, gboolean video, iax_packet_data *iax_packet) { gboolean out_of_order = FALSE; tvbuff_t *sub_tvb; guint32 codec = iax_packet -> codec; + guint32 nbytes; iax_call_data *iax_call = iax_packet -> call_data; /* keep compiler quiet */ @@ -1674,17 +1881,12 @@ } } + nbytes = tvb_reported_length(sub_tvb); + proto_tree_add_text( iax2_tree, sub_tvb, 0, -1, + "IAX2 payload (%u byte%s)", nbytes, + plurality( nbytes, "", "s" )); /* pass the rest of the block to a subdissector */ - if( !video && iax_call && iax_call->subdissector ) { - call_dissector(iax_call->subdissector,sub_tvb, pinfo, tree); - return; - } - - if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, sub_tvb, pinfo, tree )) - return; - - /* we don't know how to dissect our data: dissect it as data */ - call_dissector(data_handle,sub_tvb, pinfo, tree); + desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet ); } /* @@ -2158,7 +2360,45 @@ {&hf_iax2_cap_h263, {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32, TFS(&supported_strings), AST_FORMAT_H263, - "H.263 video", HFILL }} + "H.263 video", HFILL }}, + + /* reassembly stuff */ + {&hf_iax2_fragments, + {"IAX2 Fragments", "iax2.fragments", FT_NONE, BASE_NONE, NULL, 0x0, + "IAX2 Fragments", HFILL }}, + + {&hf_iax2_fragment, + {"IAX2 Fragment data", "iax2.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "IAX2 Fragment data", HFILL }}, + + {&hf_iax2_fragment_overlap, + {"Fragment overlap", "iax2.fragment.overlap", FT_BOOLEAN, BASE_NONE, + NULL, 0x0, "Fragment overlaps with other fragments", HFILL }}, + + {&hf_iax2_fragment_overlap_conflict, + {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Overlapping fragments contained conflicting data", HFILL }}, + + {&hf_iax2_fragment_multiple_tails, + {"Multiple tail fragments found", "iax2.fragment.multipletails", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Several tails were found when defragmenting the packet", HFILL }}, + + {&hf_iax2_fragment_too_long_fragment, + {"Fragment too long", "iax2.fragment.toolongfragment", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Fragment contained data past end of packet", HFILL }}, + + {&hf_iax2_fragment_error, + {"Defragmentation error", "iax2.fragment.error", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Defragmentation error due to illegal fragments", HFILL }}, + + {&hf_iax2_reassembled_in, + {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This IAX2 packet is reassembled in this frame", HFILL }} }; static gint *ett[] = { @@ -2167,7 +2407,9 @@ &ett_iax2_type, &ett_iax2_ie, &ett_iax2_codecs, - &ett_iax2_ies_apparent_addr + &ett_iax2_ies_apparent_addr, + &ett_iax2_fragment, + &ett_iax2_fragments }; /* initialise the hf_iax2_ies[] array to -1 */ @@ -2205,4 +2447,7 @@ * Local Variables: * c-basic-offset: 2 * End: + * + * .. And for vim: + * vim:set ts=8 sts=2 sw=2 noet: */
--- epan/Makefile.common 2005-09-29 16:07:07.439229128 +0100 +++ epan/Makefile.common 2005-09-29 17:30:10.987614616 +0100 @@ -3,7 +3,7 @@ # a) common to both files and # b) portable between both files # -# $Id: Makefile.common,v 1.1.1.8 2005/09/29 13:18:52 jeff Exp $ +# $Id: Makefile.common,v 1.9 2005/09/29 15:51:24 jeff Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -76,6 +76,7 @@ stat_cmd_args.c \ stats_tree.c \ strutil.c \ + stream.c \ t35.c \ tap.c \ timestamp.c \ @@ -165,6 +166,7 @@ stat_cmd_args.h \ stats_tree.h \ stats_tree_priv.h \ + stream.h \ strutil.h \ t35.h \ tap.h \ --- epan/packet.c 2005-09-29 16:07:08.172117712 +0100 +++ epan/packet.c 2005-09-29 17:30:11.603520984 +0100 @@ -1,7 +1,7 @@ /* packet.c * Routines for packet disassembly * - * $Id: packet.c,v 1.1.1.7 2005/09/29 13:18:53 jeff Exp $ + * $Id: packet.c,v 1.7 2005/09/29 15:51:24 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -54,6 +54,7 @@ #include "emem.h" #include <epan/reassemble.h> +#include <epan/stream.h> static gint proto_malformed = -1; static dissector_handle_t frame_handle = NULL; @@ -146,6 +147,9 @@ may free up space for fragments, which they find by using the data structures that "reassemble_init()" frees. */ reassemble_init(); + + /* Initialise the stream-handling tables */ + stream_init(); } void --- epan/stream.c 1970-01-01 01:00:00.000000000 +0100 +++ epan/stream.c 2005-07-27 23:47:55.000000000 +0100 @@ -0,0 +1,533 @@ +/* stream.c + * + * Definititions for handling circuit-switched protocols + * which are handled as streams, and don't have lengths + * and IDs such as are required for reassemble.h + * + * $Id: stream.c,v 1.9 2005/07/27 22:47:55 richardv Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> +#include <epan/reassemble.h> +#include <epan/stream.h> +#include <epan/tvbuff.h> + +/* number of streams to allocate memory for at once */ +#define MEMCHUNK_STREAM_COUNT 20 + +/* ditto pdus */ +#define MEMCHUNK_PDU_COUNT 100 + +/* ditto fragments */ +#define MEMCHUNK_FRAGMENT_COUNT 100 + + +typedef struct { + fragment_data *fd_head; /* the reassembled data, NULL + * until we add the last fragment */ + guint32 pdu_number; /* Number of this PDU within the stream */ + + /* id of this pdu (globally unique) */ + guint32 id; +} stream_pdu_t; + + +struct stream_pdu_fragment +{ + guint32 len; /* the length of this fragment */ + stream_pdu_t *pdu; + gboolean final_fragment; +}; + +struct stream { + /* the key used to add this stream to stream_hash */ + struct stream_key *key; + + /* pdu to add the next fragment to, or NULL if we need to start + * a new PDU. + */ + stream_pdu_t *current_pdu; + + /* number of PDUs added to this stream so far */ + guint32 pdu_counter; + + /* the framenumber and offset of the last fragment added; + used for sanity-checking */ + guint32 lastfrag_framenum; + guint32 lastfrag_offset; +}; + + +/***************************************************************************** + * + * Stream hash + */ + +/* key */ +typedef struct stream_key { + /* streams can be attached to circuits or conversations, and we note + that here */ + gboolean is_circuit; + union { + const struct circuit *circuit; + const struct conversation *conv; + } circ; + int p2p_dir; +} stream_key_t; + + +/* hash func */ +guint stream_hash_func(gconstpointer k) +{ + const stream_key_t *key = (const stream_key_t *)k; + + /* is_circuit is redundant to the circuit/conversation pointer */ + return ((guint)key->circ.circuit) ^ key->p2p_dir; +} + +/* compare func */ +gboolean stream_compare_func(gconstpointer a, + gconstpointer b) +{ + const stream_key_t *key1 = (const stream_key_t *)a; + const stream_key_t *key2 = (const stream_key_t *)b; + if( key1 -> p2p_dir != key2 -> p2p_dir || + key1-> is_circuit != key2 -> is_circuit ) + return FALSE; + + if( key1 -> is_circuit ) + return (key1 -> circ.circuit == key2 -> circ.circuit ); + else + return (key1 -> circ.conv == key2 -> circ.conv ); +} + +/* value destroy func */ +void stream_value_destroy_func(gpointer v) +{ + stream_t *val = (stream_t *)v; + + /* this is only called when the entire hash (and hence the entire + * "streams" GMemChunk is being freed, so there is no need to free + * v. + */ +} + +/* memory pools */ +static GMemChunk *stream_keys = NULL; +static GMemChunk *streams = NULL; + + +/* the hash table */ +static GHashTable *stream_hash; + + +/* init/reset function, call from stream_init() */ +static void init_stream_hash( void ) { + if( stream_hash != NULL ) { + g_hash_table_destroy( stream_hash ); + stream_hash = NULL; + } + + if( stream_keys != NULL ) { + g_mem_chunk_destroy( stream_keys ); + stream_keys = NULL; + } + + if( streams != NULL ) { + g_mem_chunk_destroy( streams ); + streams = NULL; + } + + streams = g_mem_chunk_create(stream_t, + MEMCHUNK_STREAM_COUNT, + G_ALLOC_ONLY); + + stream_keys = g_mem_chunk_create(stream_key_t, + MEMCHUNK_STREAM_COUNT, + G_ALLOC_ONLY); + + stream_hash = g_hash_table_new_full(stream_hash_func, + stream_compare_func, + NULL, + stream_value_destroy_func); +} + + +/* lookup function, returns null if not found */ +static stream_t *stream_hash_lookup_circ( const struct circuit *circuit, int p2p_dir ) +{ + stream_key_t key = {TRUE,{circuit}, p2p_dir}; + return (stream_t *)g_hash_table_lookup(stream_hash, &key); +} + +static stream_t *stream_hash_lookup_conv( const struct conversation *conv, int p2p_dir ) +{ + stream_key_t key = {FALSE,{NULL}, p2p_dir}; + key.circ.conv = conv; + return (stream_t *)g_hash_table_lookup(stream_hash, &key); +} + + +static stream_t *new_stream( stream_key_t *key ) +{ + stream_t *val; + + val = g_mem_chunk_alloc(streams); + val -> key = key; + val -> pdu_counter = 0; + val -> current_pdu = NULL; + val -> lastfrag_framenum = 0; + val -> lastfrag_offset = 0; + g_hash_table_insert(stream_hash, key, val); + + return val; +} + + +/* insert function */ +static stream_t *stream_hash_insert_circ( const struct circuit *circuit, int p2p_dir ) +{ + stream_key_t *key; + + key = g_mem_chunk_alloc(stream_keys); + key->is_circuit = TRUE; + key->circ.circuit = circuit; + key->p2p_dir = p2p_dir; + + return new_stream(key); +} + +static stream_t *stream_hash_insert_conv( const struct conversation *conv, int p2p_dir ) +{ + stream_key_t *key; + + key = g_mem_chunk_alloc(stream_keys); + key->is_circuit = FALSE; + key->circ.conv = conv; + key->p2p_dir = p2p_dir; + + return new_stream(key); +} + + +/****************************************************************************** + * + * PDU data + */ +static GMemChunk *pdus = NULL; + +/* pdu counter, for generating unique pdu ids */ +static guint32 pdu_counter; + + +static void stream_init_pdu_data(void) +{ + if( pdus != NULL ) { + g_mem_chunk_destroy( pdus ); + pdus = NULL; + } + + pdus = g_mem_chunk_create(stream_pdu_t, + MEMCHUNK_PDU_COUNT, + G_ALLOC_ONLY); + pdu_counter = 0; +} + + +/* new pdu in this stream */ +static stream_pdu_t *stream_new_pdu(stream_t *stream) +{ + stream_pdu_t *pdu; + pdu = g_mem_chunk_alloc(pdus); + pdu -> fd_head = NULL; + pdu -> pdu_number = stream -> pdu_counter++; + pdu -> id = pdu_counter++; + return pdu; +} + +/***************************************************************************** + * + * fragment hash + */ + +/* key */ +typedef struct fragment_key { + const stream_t *stream; + guint32 framenum; + guint32 offset; +} fragment_key_t; + + +/* hash func */ +guint fragment_hash_func(gconstpointer k) +{ + const fragment_key_t *key = (const fragment_key_t *)k; + return ((guint)key->stream) + ((guint)key -> framenum) + ((guint)key->offset); +} + +/* compare func */ +gboolean fragment_compare_func(gconstpointer a, + gconstpointer b) +{ + const fragment_key_t *key1 = (const fragment_key_t *)a; + const fragment_key_t *key2 = (const fragment_key_t *)b; + return (key1 -> stream == key2 -> stream && + key1 -> framenum == key2 -> framenum && + key1 -> offset == key2 -> offset ); +} + +/* memory pools */ +static GMemChunk *fragment_keys = NULL; +static GMemChunk *fragment_vals = NULL; + +/* the hash table */ +static GHashTable *fragment_hash; + + +/* init/reset function, call from stream_init() */ +static void init_fragment_hash( void ) { + if( fragment_hash != NULL ) { + g_hash_table_destroy( fragment_hash ); + fragment_hash = NULL; + } + + if( fragment_vals != NULL ) { + g_mem_chunk_destroy( fragment_vals ); + fragment_vals = NULL; + } + + if( fragment_keys != NULL ) { + g_mem_chunk_destroy( fragment_keys ); + fragment_keys = NULL; + } + + fragment_keys = g_mem_chunk_create(fragment_key_t, + MEMCHUNK_FRAGMENT_COUNT, + G_ALLOC_ONLY); + + fragment_vals = g_mem_chunk_create(stream_pdu_fragment_t, + MEMCHUNK_FRAGMENT_COUNT, + G_ALLOC_ONLY); + + fragment_hash = g_hash_table_new(fragment_hash_func, + fragment_compare_func); +} + + +/* lookup function, returns null if not found */ +static stream_pdu_fragment_t *fragment_hash_lookup( const stream_t *stream, guint32 framenum, guint32 offset ) +{ + fragment_key_t key = {stream, framenum, offset}; + stream_pdu_fragment_t *val = g_hash_table_lookup(fragment_hash, &key); + + return val; +} + + +/* insert function */ +static stream_pdu_fragment_t *fragment_hash_insert( const stream_t *stream, guint32 framenum, guint32 offset, + guint32 length) +{ + fragment_key_t *key; + stream_pdu_fragment_t *val; + + key = g_mem_chunk_alloc(fragment_keys); + key->stream = stream; + key->framenum = framenum; + key->offset = offset; + + val = g_mem_chunk_alloc(fragment_vals); + val->len = length; + val->pdu = NULL; + val->final_fragment = FALSE; + + g_hash_table_insert(fragment_hash, key, val); + return val; +} + +/*****************************************************************************/ + +/* fragmentation hash tables */ +static GHashTable *stream_fragment_table = NULL; +static GHashTable *stream_reassembled_table = NULL; + +/* Initialise a new stream. Call this when you first identify a distinct + * stream. */ +stream_t *stream_new_circ ( const struct circuit *circuit, int p2p_dir ) +{ + stream_t * stream; + + /* we don't want to replace the previous data if we get called twice on the + same circuit, so do a lookup first */ + stream = stream_hash_lookup_circ(circuit, p2p_dir); + g_assert( stream == NULL ); + + stream = stream_hash_insert_circ(circuit, p2p_dir); + + return stream; +} + +stream_t *stream_new_conv ( const struct conversation *conv, int p2p_dir ) +{ + stream_t * stream; + + /* we don't want to replace the previous data if we get called twice on the + same conversation, so do a lookup first */ + stream = stream_hash_lookup_conv(conv, p2p_dir); + g_assert( stream == NULL ); + + stream = stream_hash_insert_conv(conv, p2p_dir); + return stream; +} + + + + +/* retrieve a previously-created stream. + * + * Returns null if no matching stream was found. + */ +stream_t *find_stream_circ ( const struct circuit *circuit, int p2p_dir ) +{ + return stream_hash_lookup_circ(circuit,p2p_dir); +} +stream_t *find_stream_conv ( const struct conversation *conv, int p2p_dir ) +{ + return stream_hash_lookup_conv(conv,p2p_dir); +} + + +/* initialise the stream routines */ +void stream_init( void ) +{ + init_stream_hash(); + init_fragment_hash(); + stream_init_pdu_data(); + + fragment_table_init(&stream_fragment_table); + reassembled_table_init(&stream_reassembled_table); +} + + + + +/*****************************************************************************/ + +stream_pdu_fragment_t *stream_find_frag( stream_t *stream, guint32 framenum, guint32 offset ) +{ + return fragment_hash_lookup( stream, framenum, offset ); +} + +stream_pdu_fragment_t *stream_add_frag( stream_t *stream, guint32 framenum, guint32 offset, + tvbuff_t *tvb, packet_info *pinfo, gboolean more_frags ) +{ + fragment_data *fd_head; + stream_pdu_t *pdu; + stream_pdu_fragment_t *frag_data; + guint8 *datacopy; + + g_assert(stream); + + /* check that this fragment is at the end of the stream */ + g_assert( framenum > stream->lastfrag_framenum || + (framenum == stream->lastfrag_framenum && offset > stream->lastfrag_offset)); + + + pdu = stream->current_pdu; + if( pdu == NULL ) { + /* start a new pdu */ + pdu = stream->current_pdu = stream_new_pdu(stream); + } + + /* add it to the reassembly tables */ + fd_head = fragment_add_seq_next(tvb, 0, pinfo, pdu->id, + stream_fragment_table, stream_reassembled_table, + tvb_reported_length(tvb), more_frags); + /* add it to our hash */ + frag_data = fragment_hash_insert( stream, framenum, offset, tvb_reported_length(tvb)); + frag_data -> pdu = pdu; + + if( fd_head != NULL ) { + /* if this was the last fragment, update the pdu data. + */ + pdu -> fd_head = fd_head; + + /* start a new pdu next time */ + stream->current_pdu = NULL; + + frag_data -> final_fragment = TRUE; + } + + /* stashing the framenum and offset permit future sanity checks */ + stream -> lastfrag_framenum = framenum; + stream -> lastfrag_offset = offset; + + return frag_data; +} + + +tvbuff_t *stream_process_reassembled( + tvbuff_t *tvb, int offset, packet_info *pinfo, + char *name, const stream_pdu_fragment_t *frag, + const struct _fragment_items *fit, + gboolean *update_col_infop, proto_tree *tree) +{ + stream_pdu_t *pdu; + g_assert(frag); + pdu = frag->pdu; + + /* we handle non-terminal fragments ourselves, because + reassemble.c messes them up */ + if(!frag->final_fragment) { + if (pdu->fd_head != NULL && fit->hf_reassembled_in != NULL) { + proto_tree_add_uint(tree, + *(fit->hf_reassembled_in), tvb, + 0, 0, pdu->fd_head->reassembled_in); + } + return NULL; + } + + return process_reassembled_data(tvb, offset, pinfo, name, pdu->fd_head, + fit, update_col_infop, tree); +} + +guint32 stream_get_frag_length( const stream_pdu_fragment_t *frag) +{ + g_assert( frag ); + return frag->len; +} + +fragment_data *stream_get_frag_data( const stream_pdu_fragment_t *frag) +{ + g_assert( frag ); + return frag->pdu->fd_head; +} + +guint32 stream_get_pdu_no( const stream_pdu_fragment_t *frag) +{ + g_assert( frag ); + return frag->pdu->pdu_number; +} --- epan/stream.h 1970-01-01 01:00:00.000000000 +0100 +++ epan/stream.h 2005-07-27 23:47:55.000000000 +0100 @@ -0,0 +1,137 @@ +/* stream.h + * + * Definititions for handling circuit-switched protocols + * which are handled as streams, and don't have lengths + * and IDs such as are required for reassemble.h + * + * $Id: stream.h,v 1.10 2005/07/27 22:47:55 richardv Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef stream_h +#define stream_h + +#include <epan/tvbuff.h> + +struct _fragment_items; + +/* A stream represents the concept of an arbitrary stream of data, + divided up into frames for transmission, where the frames have + little or no correspondence to the PDUs of the protocol being + streamed, and those PDUs are just delineated by a magic number. + + For example, we stream H.223 over IAX2. IAX2 has no concept of + H.223 PDUs and just divides the H.223 stream into 160-byte + frames. H.223 PDUs are delineated by two-byte magic numbers (which + may, of course, straddle an IAX2 frame boundary). + + Essentially we act as a wrapper to reassemble.h, by making up + PDU ids and keeping some additional data on fragments to allow the + PDUs to be defragmented again. +*/ + + +/* A stream_t represents a stream. There might be one or two streams + in a circuit, depending on whether that circuit is mono- or bi-directional. +*/ +typedef struct stream stream_t; + +/* Fragments in a PDU are represented using a stream_pdu_fragment_t, + and placed in a linked-list with other fragments in the PDU. + + (They're also placed in a hash so we can find them again later) +*/ +typedef struct stream_pdu_fragment stream_pdu_fragment_t; + + +struct circuit; +struct conversation; + +/* initialise a new stream. Call this when you first identify a distinct + * stream. The circit pointer is just used as a key to look up the stream. */ +stream_t *stream_new_circ ( const struct circuit *circuit, int p2p_dir ); +stream_t *stream_new_conv ( const struct conversation *conv, int p2p_dir ); + +/* retrieve a previously-created stream. + * + * Returns null if no matching stream was found. + */ +stream_t *find_stream_circ ( const struct circuit *circuit, int p2p_dir ); +stream_t *find_stream_conv ( const struct conversation *conv, int p2p_dir ); + + + +/* see if we've seen this fragment before. + + The framenum and offset are just hash keys, so can be any values unique + to this frame, but the idea is that you use the number of the frame being + disassembled, and the byte-offset within that frame. +*/ +stream_pdu_fragment_t *stream_find_frag( stream_t *stream, guint32 framenum, guint32 offset ); + +/* add a new fragment to the fragment tables for the stream. The framenum and + * offset are keys allowing future access with stream_find_frag(), tvb is the + * fragment to be added, and pinfo is the information for the frame containing + * this fragment. more_frags should be set if this is the final fragment in the + * PDU. + * + * * the fragment must be later in the stream than any previous fragment + * (ie, framenum.offset must be greater than those passed on the previous + * call) + * + * This essentially means that you can only add fragments on the first pass + * through the stream. + */ +stream_pdu_fragment_t *stream_add_frag( stream_t *stream, guint32 framenum, guint32 offset, + tvbuff_t *tvb, packet_info *pinfo, gboolean more_frags ); + +/* Get the length of a fragment previously found by stream_find_frag(). + */ +guint32 stream_get_frag_length( const stream_pdu_fragment_t *frag); + +/* Get a handle on the top of the chain of fragment_datas underlying this PDU + * frag can be any fragment within a PDU, and it will always return the head of + * the chain + * + * Returns NULL until the last fragment is added. + */ +struct _fragment_data *stream_get_frag_data( const stream_pdu_fragment_t *frag); + +/* + * Process reassembled data; if this is the last fragment, put the fragment + * information into the protocol tree, and construct a tvbuff with the + * reassembled data, otherwise just put a "reassembled in" item into the + * protocol tree. + */ +tvbuff_t *stream_process_reassembled( + tvbuff_t *tvb, int offset, packet_info *pinfo, + char *name, const stream_pdu_fragment_t *frag, + const struct _fragment_items *fit, + gboolean *update_col_infop, proto_tree *tree); + +/* Get the PDU number. PDUs are numbered from zero within a stream. + * frag can be any fragment within a PDU. + */ +guint32 stream_get_pdu_no( const stream_pdu_fragment_t *frag); + +/* initialise the stream routines */ +void stream_init( void ); + +#endif
--- epan/dissectors/packet-h263.c 2005-09-29 16:07:12.675433104 +0100 +++ epan/dissectors/packet-h263.c 2005-09-29 17:30:14.807033976 +0100 @@ -5,7 +5,7 @@ * Copyright 2003 Niklas Ögren <niklas.ogren@xxxxx> * Seven Levels Consultants AB * - * $Id: packet-h263.c,v 1.1.1.3 2005/09/29 13:18:54 jeff Exp $ + * $Id: packet-h263.c,v 1.3 2005/09/29 15:51:25 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -47,8 +47,11 @@ #include <epan/rtp_pt.h> #include <epan/iax2_codec_type.h> +static void dissect_h263_data( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ); + /* H.263 header fields */ static int proto_h263 = -1; +static int proto_h263_data = -1; /* Mode A header */ static int hf_h263_ftype = -1; @@ -87,6 +90,7 @@ static int hf_h263_optional_advanced_prediction_mode = -1; static int hf_h263_PB_frames_mode = -1; static int hf_h263_data = -1; +static int hf_h263_payload = -1; /* Source format types */ #define SRCFORMAT_FORB 0 /* forbidden */ @@ -128,33 +132,30 @@ dissect_h263( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti = NULL; - proto_item *h263_payload_item = NULL; proto_tree *h263_tree = NULL; - proto_tree *h263_payload_tree = NULL; unsigned int offset = 0; unsigned int h263_version = 0; - guint32 data; - guint8 octet; + tvbuff_t *next_tvb; h263_version = (tvb_get_guint8( tvb, offset ) & 0xc0 ) >> 6; if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) { - col_set_str( pinfo->cinfo, COL_PROTOCOL, "H.263" ); + col_set_str( pinfo->cinfo, COL_PROTOCOL, "H.263 " ); } if( h263_version == 0x00) { if ( check_col( pinfo->cinfo, COL_INFO) ) { - col_append_str( pinfo->cinfo, COL_INFO, " MODE A"); + col_append_str( pinfo->cinfo, COL_INFO, "MODE A "); } } else if( h263_version == 0x02) { if ( check_col( pinfo->cinfo, COL_INFO) ) { - col_append_str( pinfo->cinfo, COL_INFO, " MODE B"); + col_append_str( pinfo->cinfo, COL_INFO, "MODE B "); } } else if( h263_version == 0x03) { if ( check_col( pinfo->cinfo, COL_INFO) ) { - col_append_str( pinfo->cinfo, COL_INFO, " MODE C"); + col_append_str( pinfo->cinfo, COL_INFO, "MODE C "); } } @@ -272,14 +273,38 @@ } /* end not mode a */ /* The rest of the packet is the H.263 stream */ - h263_payload_item = proto_tree_add_text(h263_tree,tvb,offset,-1,"H263 Payload"); + next_tvb = tvb_new_subset( tvb, offset, tvb_length(tvb) - offset, tvb_reported_length(tvb) - offset); + dissect_h263_data( next_tvb, pinfo, h263_tree ); + + } +} + + +static void dissect_h263_data( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) +{ + guint offset = 0; + proto_item *h263_payload_item = NULL; + proto_tree *h263_payload_tree = NULL; + guint32 data; + guint8 octet; + + if ( check_col( pinfo->cinfo, COL_INFO) ) { + col_append_str( pinfo->cinfo, COL_INFO, "H263 payload "); + } + + if( tree ) { + h263_payload_item = proto_tree_add_item( tree, hf_h263_payload, tvb, offset, -1, FALSE ); h263_payload_tree = proto_item_add_subtree( h263_payload_item, ett_h263_payload ); + } - /* Check for PSC, PSC is a word of 22 bits. Its value is 0000 0000 0000 0000' 1000 00xx xxxx xxxx. */ - data = tvb_get_ntohl(tvb, offset); - - if (( data & 0xffff8000) == 0x00008000 ) { /* PSC or Group of Block Start Code (GBSC) found */ - if (( data & 0xfffffc00) == 0x00008000 ) { /* PSC found */ + /* Check for PSC, PSC is a word of 22 bits. Its value is 0000 0000 0000 0000' 1000 00xx xxxx xxxx. */ + data = tvb_get_ntohl(tvb, offset); + + if (( data & 0xffff8000) == 0x00008000 ) { /* PSC or Group of Block Start Code (GBSC) found */ + if (( data & 0xfffffc00) == 0x00008000 ) { /* PSC found */ + if ( check_col( pinfo->cinfo, COL_INFO) ) + col_append_str( pinfo->cinfo, COL_INFO, "(PSC) "); + if( tree ) { proto_tree_add_uint(h263_payload_tree, hf_h263_psc,tvb, offset,3,data); offset = offset + 2; proto_tree_add_uint(h263_payload_tree, hf_h263_TR,tvb, offset,2,data); @@ -313,9 +338,11 @@ /* Bit 13: Optional PB-frames mode (see Annex G), "0" normal I- or P-picture, "1" PB-frame.*/ proto_tree_add_item( h263_payload_tree, hf_h263_PB_frames_mode, tvb, offset, 1, FALSE ); } - }else{ - if ((data & 0x00007c00)!= 0) { /* GBSC found */ - + } + }else if ((data & 0x00007c00)!= 0) { /* GBSC found */ + if ( check_col( pinfo->cinfo, COL_INFO) ) + col_append_str( pinfo->cinfo, COL_INFO, "(GBSC) "); + if( tree ) { /* Group of Block Start Code (GBSC) (17 bits) * A word of 17 bits. Its value is 0000 0000 0000 0000 1. GOB start codes may be byte aligned. This * can be achieved by inserting GSTUF before the start code such that the first bit of the start code is @@ -324,11 +351,11 @@ */ proto_tree_add_uint(h263_payload_tree, hf_h263_gbsc,tvb, offset,3,data); offset = offset + 2; - } - } - } - proto_tree_add_item( h263_payload_tree, hf_h263_data, tvb, offset, -1, FALSE ); + } + } } + if( tree ) + proto_tree_add_item( h263_payload_tree, hf_h263_data, tvb, offset, -1, FALSE ); } void @@ -589,6 +616,18 @@ } }, { + &hf_h263_payload, + { + "H.263 payload", + "h263.payload", + FT_NONE, + BASE_NONE, + NULL, + 0x0, + "The actual H.263 data", HFILL + } + }, + { &hf_h263_data, { "H.263 stream", @@ -755,9 +794,12 @@ proto_h263 = proto_register_protocol("ITU-T Recommendation H.263 RTP Payload header (RFC2190)", "H.263", "h263"); + proto_h263_data = proto_register_protocol("ITU-T Recommendation H.263", + "H.263 data", "h263data"); proto_register_field_array(proto_h263, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); register_dissector("h263", dissect_h263, proto_h263); + register_dissector("h263data", dissect_h263_data, proto_h263_data); } void
--- epan/dissectors/packet-amr.c 2005-09-29 16:07:09.478919048 +0100 +++ epan/dissectors/packet-amr.c 2005-09-30 15:54:58.090310528 +0100 @@ -2,7 +2,7 @@ * Routines for AMR dissection * Copyright 2005, Anders Broman <anders.broman[at]ericsson.com> * - * $Id: packet-amr.c,v 1.1.1.3 2005/09/29 13:18:53 jeff Exp $ + * $Id: packet-amr.c,v 1.6 2005/09/30 14:53:23 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -163,7 +163,7 @@ static void dissect_amr_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){ - int offset =0; + int offset =0, i; guint8 octet; proto_tree_add_item(tree, hf_amr_if2_ft, tvb, offset, 1, FALSE); @@ -178,6 +178,12 @@ return; proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data"); + for(i=0;amr_codec_mode_request_vals[i].value != 0 || amr_codec_mode_request_vals[i].strptr != NULL;++i) { + if(amr_codec_mode_request_vals[i].value == octet) + break; + } + if(amr_codec_mode_request_vals[i].strptr && check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", amr_codec_mode_request_vals[i].strptr ); } /* Code to actually dissect the packets */ @@ -451,6 +457,8 @@ "Type of AMR encoding of the payload", &amr_encoding_type, encoding_types, FALSE); + register_dissector("amr_if1", dissect_amr_if1, proto_amr); + register_dissector("amr_if2", dissect_amr_if2, proto_amr); }
--- asn1/h245/h245.cnf 2005-09-29 16:07:04.043745320 +0100 +++ asn1/h245/h245.cnf 2005-09-29 17:30:08.694963152 +0100 @@ -1,6 +1,6 @@ # H.245 conformation file # Copyright 2005 Anders Broman anders.broman[at]ericsson.com -# $Id: h245.cnf,v 1.1.1.3 2005/09/29 13:18:51 jeff Exp $ +# $Id: h245.cnf,v 1.6 2005/09/29 15:51:24 jeff Exp $ #---------------------------------------------------------------------------------------- #.EXPORTS #---------------------------------------------------------------------------------------- @@ -12,6 +12,233 @@ OpenLogicalChannel #---------------------------------------------------------------------------------------- +#.FN_BODY MultiplexEntryDescriptor + /*MultiplexEntryDescriptor*/ + h223_me = NULL; + h223_mc = 0; +%(DEFAULT_BODY)s + if(h223_set_mc_handle) + (*h223_set_mc_handle)(pinfo, h223_mc, h223_me); + /* stuff */ +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS MultiplexTableEntryNumber + VAL_PTR = &value +#.FN_BODY MultiplexTableEntryNumber + guint32 value; +%(DEFAULT_BODY)s + h223_mc = value & 0xf; +#.END +#---------------------------------------------------------------------------------------- +#.FN_BODY MultiplexEntryDescriptor/elementList + /* create a h223_mux_element to hold onto the head of the list, since + * h223_me will track the tail */ + h223_mux_element dummy_me; + h223_me = &dummy_me; +%(DEFAULT_BODY)s + /* set h223_me to the head of the list for MEDescriptor to pick up */ + h223_me = dummy_me.next; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR MultiplexElement + /*MultiplexElement*/ + h223_mux_element* me = se_alloc(sizeof(h223_mux_element)); + h223_me->next = me; + h223_me = me; + h223_me->next = NULL; +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS MultiplexElement/type/logicalChannelNumber + VAL_PTR = &value +#.FN_BODY MultiplexElement/type/logicalChannelNumber + /*MultiplexElement/type/logicalChannelNumber*/ + guint32 value; +%(DEFAULT_BODY)s + h223_me->sublist = NULL; + h223_me->vc = value & 0xffff; +#.END +#---------------------------------------------------------------------------------------- +#.FN_BODY MultiplexElement/type/subElementList + h223_mux_element dummy_me, *parent_me = h223_me; + h223_me = &dummy_me; +%(DEFAULT_BODY)s + parent_me->sublist = dummy_me.next; + h223_me = parent_me; + h223_me->vc = 0; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR MultiplexElement/repeatCount/untilClosingFlag + h223_me->repeat_count = 0; +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS MultiplexElement/repeatCount/finite + VAL_PTR = &value +#.FN_BODY MultiplexElement/repeatCount/finite + guint32 value; +%(DEFAULT_BODY)s + h223_me->repeat_count = value & 0xffff; +#.END +#---------------------------------------------------------------------------------------- +# OpenLogicalChannel .FN_FTR is also declared, line 460ish +#.FN_BODY OpenLogicalChannel + h223_fw_lc_num = 0; + h223_lc_params_temp = NULL; +%(DEFAULT_BODY)s + if(h223_fw_lc_num != 0 && h223_fw_lc_params) { + h223_pending_olc *pending = se_alloc(sizeof(h223_pending_olc)); + pending->fw_channel_params = h223_fw_lc_params; + pending->rev_channel_params = h223_rev_lc_params; + gint32 temp = h223_fw_lc_num; + g_hash_table_insert(h223_pending_olc_reqs[pinfo->p2p_dir], GINT_TO_POINTER(temp), pending); + } +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS LogicalChannelNumber + VAL_PTR = &value +#.FN_BODY LogicalChannelNumber + guint32 value; +%(DEFAULT_BODY)s + h245_lc_temp = value & 0xfff; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR OpenLogicalChannel/forwardLogicalChannelNumber + h223_fw_lc_num = h245_lc_temp; +#.END +#---------------------------------------------------------------------------------------- +#.FN_BODY OpenLogicalChannel/forwardLogicalChannelParameters + h245_lc_dissector = NULL; +%(DEFAULT_BODY)s + if(h223_lc_params_temp && h245_lc_dissector) + h223_lc_params_temp->subdissector = h245_lc_dissector; + else if(h223_lc_params_temp) + h223_lc_params_temp->subdissector = data_handle; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters + h223_fw_lc_params = se_alloc(sizeof(h223_lc_params)); + h223_fw_lc_params->al_type = al_nonStandard; + h223_fw_lc_params->al_params = NULL; + h223_fw_lc_params->segmentable = 0; + h223_fw_lc_params->subdissector = NULL; + h223_lc_params_temp = h223_fw_lc_params; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters + h223_rev_lc_params = se_alloc(sizeof(h223_lc_params)); + h223_rev_lc_params->al_type = al_nonStandard; + h223_rev_lc_params->al_params = NULL; + h223_rev_lc_params->segmentable = 0; + h223_rev_lc_params->subdissector = NULL; + h223_lc_params_temp = h223_rev_lc_params; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al1Framed + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1Framed; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al1NotFramed + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1NotFramed; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al2WithoutSequenceNumbers + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2WithoutSequenceNumbers; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al2WithSequenceNumbers + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2WithSequenceNumbers; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al3 + if(h223_lc_params_temp) { + h223_lc_params_temp->al_type = al3; + h223_lc_params_temp->al_params = se_alloc(sizeof(h223_al3_params)); + } +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS Al3/controlFieldOctets + VAL_PTR = &value +#.FN_BODY Al3/controlFieldOctets + guint32 value; +%(DEFAULT_BODY)s + if(h223_lc_params_temp && h223_lc_params_temp->al_params) + ((h223_al3_params*)h223_lc_params_temp->al_params)->control_field_octets = value & 3 ; +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS Al3/sendBufferSize + VAL_PTR = &value +#.FN_BODY Al3/sendBufferSize + guint32 value; +%(DEFAULT_BODY)s + if(h223_lc_params_temp && h223_lc_params_temp->al_params) + ((h223_al3_params*)h223_lc_params_temp->al_params)->send_buffer_size = value & 0xfffff; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al1M + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1M; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al2M + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2M; +#.END +#---------------------------------------------------------------------------------------- +#.FN_HDR H223LogicalChannelParameters/adaptationLayerType/al3M + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al3M; +#.END +#---------------------------------------------------------------------------------------- +#.FN_PARS H223LogicalChannelParameters/segmentableFlag + VAL_PTR = &value +#.FN_BODY H223LogicalChannelParameters/segmentableFlag + guint32 value; +%(DEFAULT_BODY)s + if(h223_lc_params_temp) + h223_lc_params_temp->segmentable = value & 1; +#.END +#---------------------------------------------------------------------------------------- +# OpenLogicalChannelAck .FN_FTR is also declared, line 460ish +#.FN_BODY OpenLogicalChannelAck + h223_fw_lc_num = 0; + h223_rev_lc_num = 0; +%(DEFAULT_BODY)s + guint32 temp = h223_fw_lc_num; + int p2p_dir = pinfo->p2p_dir; + if(pinfo->p2p_dir == P2P_DIR_SENT) + pinfo->p2p_dir = P2P_DIR_RECV; + else + pinfo->p2p_dir = P2P_DIR_SENT; + h223_pending_olc *pend = g_hash_table_lookup( h223_pending_olc_reqs[pinfo->p2p_dir], GINT_TO_POINTER(temp) ); + if (pend) { + DISSECTOR_ASSERT( ( h223_rev_lc_num && pend->rev_channel_params) + || (!h223_rev_lc_num && !pend->rev_channel_params) ); + if(h223_add_lc_handle) { + (*h223_add_lc_handle)( pinfo, h223_fw_lc_num, pend->fw_channel_params ); + if(h223_rev_lc_num) + (*h223_add_lc_handle)( pinfo, h223_rev_lc_num, pend->rev_channel_params ); + } + } else { + /* we missed the OpenLogicalChannel packet */ + } + pinfo->p2p_dir = p2p_dir; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR OpenLogicalChannelAck/forwardLogicalChannelNumber + h223_fw_lc_num = h245_lc_temp; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR OpenLogicalChannelAck/reverseLogicalChannelParamaters/reverseLogicalChannelNumber + h223_rev_lc_num = h245_lc_temp; +#.END +#---------------------------------------------------------------------------------------- +#.FN_FTR H263VideoCapability + h245_lc_dissector = h263_handle; +#.END +#---------------------------------------------------------------------------------------- #.FN_BODY RequestMessage VAL_PTR = &value guint32 value; @@ -231,11 +458,13 @@ h245_pi->msg_type = H245_TermCapSetRls; #.END #---------------------------------------------------------------------------------------- +# OpenLogicalChannel .FN_BODY is also declared, line 70ish #.FN_FTR OpenLogicalChannel if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; #.END #---------------------------------------------------------------------------------------- +# OpenLogicalChannelAck .FN_BODY is also declared, line 200ish #.FN_FTR OpenLogicalChannelAck h245_pi->msg_type = H245_OpenLogChnAck; @@ -243,6 +472,9 @@ #---------------------------------------------------------------------------------------- #.FN_PARS CapabilityIdentifier/standard FN_VARIANT = _str VAL_PTR = &standard_oid_str +#.FN_FTR CapabilityIdentifier/standard + if(!h245_lc_dissector && strcmp(standard_oid_str,"0.0.8.245.1.1.1") == 0) + h245_lc_dissector = amr_handle; #.END #---------------------------------------------------------------------------------------- #.FN_HDR GenericMessage/subMessageIdentifer @@ -501,9 +733,13 @@ MulticastAddress/iP6Address MIP6Address NonStandardIdentifier/h221NonStandard H221NonStandardID +OpenLogicalChannel/forwardLogicalChannelNumber OLC_fw_lcn +OpenLogicalChannelAck/forwardLogicalChannelNumber OLC_ack_fw_lcn OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters OLC_forw_multiplexParameters OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters OLC_rev_multiplexParameters OpenLogicalChannel/reverseLogicalChannelParameters OLC_reverseLogicalChannelParameters +OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters OLC_fw_h223_params +OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters OLC_rev_h223_params OpenLogicalChannelAck/reverseLogicalChannelParameters OLC_ack_reverseLogicalChannelParameters CloseLogicalChannel/reason Clc_reason VCCapability/availableBitRates/type Avb_type @@ -518,6 +754,7 @@ FECData/rfc2733/mode FECdata_mode FECMode/rfc2733Mode/mode FEC_mode IS11172AudioMode/multichannelType IS11172_multichannelType +MultiplexElement/repeatCount/finite ME_finiteRepeatCount MultiplexElement/repeatCount ME_repeatCount FECCapability/rfc2733 FECC_rfc2733 RequestModeAck/response Req_mode_ack_response @@ -685,7 +922,7 @@ NewATMVCCommand/aal/aal1/errorCorrection/errorCorrectionOnly errorCorrectionOnlyFlag NewATMVCIndication/aal/aal1/errorCorrection/errorCorrectionOnly errorCorrectionOnlyFlag UserInputCapability/extendedAlphanumeric extendedAlphanumericFlag -MultiplexElement/repeatCount/finite finite_1_65535 +MultiplexElement/repeatCount/finite me_repeatCount_finite MiscellaneousCommand/type/videoFastUpdateMB/firstMB firstMB_1_8192 MiscellaneousIndication/type/videoNotDecodedMBs/firstMB firstMB_1_8192 H261VideoCapability/cifMPI cifMPI_1_4 @@ -745,8 +982,10 @@ FECData/rfc2733/mode fec_data_mode V76LogicalChannelParameters/mode v76_mode OpenLogicalChannelAck/reverseLogicalChannelParameters/multiplexParameters olc_ack_multiplexParameters -OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters olc_rev_multiplexParameter +OpenLogicalChannel/forwardLogicalChannelNumber olc_fw_lcn +OpenLogicalChannelAck/forwardLogicalChannelNumber olc_ack_fw_lcn OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters olc_forw_multiplexParameters +OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters olc_rev_multiplexParameter IS11172AudioMode/multichannelType is11172multichannelType IS13818AudioMode/multichannelType is13818MultichannelType CloseLogicalChannel/reason clc_reason @@ -774,6 +1013,20 @@ CommunicationModeTableEntry/mediaChannel cm_mediaChannel CommunicationModeTableEntry/mediaControlChannel cm_mediaControlChannel +OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters olc_rev_h223_params +OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters olc_fw_h223_params + +H223LogicalChannelParameters/adaptationLayerType/al1Framed h223_al_type_al1Framed +H223LogicalChannelParameters/adaptationLayerType/al1NotFramed h223_al_type_al1NotFramed +H223LogicalChannelParameters/adaptationLayerType/al2WithoutSequenceNumbers h223_al_type_al2WithoutSequenceNumbers +H223LogicalChannelParameters/adaptationLayerType/al2WithSequenceNumbers h223_al_type_al2WithSequenceNumbers +H223LogicalChannelParameters/adaptationLayerType/al3 h223_al_type_al3 +Al3/sendBufferSize al3_sendBufferSize +H223LogicalChannelParameters/adaptationLayerType/al1M h223_al_type_al1M +H223LogicalChannelParameters/adaptationLayerType/al2M h223_al_type_al2M +H223LogicalChannelParameters/adaptationLayerType/al3M h223_al_type_al3M +H223LogicalChannelParameters/segmentableFlag h223_lc_segmentableFlag + #---------------------------------------------------------------------------------------- #.TYPE_ATTR UnicastAddress/iPAddress/network TYPE = FT_IPv4 DISPLAY = BASE_NONE STRINGS = NULL @@ -788,4 +1041,6 @@ #---------------------------------------------------------------------------------------- #.FIELD_ATTR AlternativeCapabilitySet/_item NAME = "alternativeCapability" + #---------------------------------------------------------------------------------------- +# vim:set ts=4 sts=2 sw=2: --- asn1/h245/packet-h245-template.c 2005-09-29 16:07:04.050744256 +0100 +++ asn1/h245/packet-h245-template.c 2005-09-30 15:08:16.432227296 +0100 @@ -2,7 +2,7 @@ * Routines for h245 packet dissection * Copyright 2004, Anders Broman <anders.broman@xxxxxxxxxxxx> * - * $Id: packet-h245-template.c,v 1.1.1.3 2005/09/29 13:18:51 jeff Exp $ + * $Id: packet-h245-template.c,v 1.9 2005/09/30 11:04:10 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -53,6 +53,7 @@ #include "packet-rtp.h" #include "packet-rtcp.h" #include "packet-ber.h" +#include <epan/emem.h> #define PNAME "MULTIMEDIA-SYSTEM-CONTROL" #define PSNAME "H.245" @@ -66,6 +67,8 @@ static dissector_handle_t data_handle; static dissector_handle_t h245_handle; static dissector_handle_t MultimediaSystemControlMessage_handle; +static dissector_handle_t h263_handle = NULL; +static dissector_handle_t amr_handle = NULL; static void reset_h245_packet_info(h245_packet_info *pi); static int hf_h245_pdu_type = -1; @@ -221,6 +224,53 @@ { 3267, "RFC 3267 - Adaptive Multi-Rate (AMR) and Adaptive Multi-Rate Wideband (AMR-WB)" }, { 0, NULL } }; + +/* h223 multiplex codes */ +static h223_set_mc_handle_t h223_set_mc_handle = NULL; +h223_mux_element *h223_me=NULL; +guint8 h223_mc=0; +void h245_set_h223_set_mc_handle( h223_set_mc_handle_t handle ) +{ + h223_set_mc_handle = handle; +} + +/* h223 logical channels */ +typedef struct { + h223_lc_params *fw_channel_params; + h223_lc_params *rev_channel_params; +} h223_pending_olc; + +static GHashTable* h223_pending_olc_reqs[] = { NULL, NULL }; +static dissector_handle_t h245_lc_dissector; +static guint16 h245_lc_temp; +static guint16 h223_fw_lc_num; +static guint16 h223_rev_lc_num; +static h223_lc_params *h223_lc_params_temp; +static h223_lc_params *h223_fw_lc_params; +static h223_lc_params *h223_rev_lc_params; +static h223_add_lc_handle_t h223_add_lc_handle = NULL; + +static void h223_lc_init_dir( int dir ) +{ + if ( h223_pending_olc_reqs[dir] ) + g_hash_table_destroy( h223_pending_olc_reqs[dir] ); + h223_pending_olc_reqs[dir] = g_hash_table_new( g_direct_hash, g_direct_equal ); +} + +static void h223_lc_init() +{ + h223_lc_init_dir( P2P_DIR_SENT ); + h223_lc_init_dir( P2P_DIR_RECV ); + h223_lc_params_temp = NULL; + h245_lc_dissector = NULL; + h223_fw_lc_num = 0; +} + +void h245_set_h223_add_lc_handle( h223_add_lc_handle_t handle ) +{ + h223_add_lc_handle = handle; +} + /* Initialize the protocol and registered fields */ int proto_h245 = -1; #include "packet-h245-hf.c" @@ -348,12 +398,16 @@ rtp_handle = find_dissector("rtp"); rtcp_handle = find_dissector("rtcp"); data_handle = find_dissector("data"); + h263_handle = find_dissector("h263data"); + amr_handle = find_dissector("amr_if2"); h245_handle=create_dissector_handle(dissect_h245, proto_h245); dissector_add_handle("tcp.port", h245_handle); MultimediaSystemControlMessage_handle=create_dissector_handle(dissect_h245_h245, proto_h245); dissector_add_handle("udp.port", MultimediaSystemControlMessage_handle); + + h223_lc_init(); } static void reset_h245_packet_info(h245_packet_info *pi) --- asn1/h245/packet-h245-template.h 2005-09-29 16:07:04.051744104 +0100 +++ asn1/h245/packet-h245-template.h 2005-09-29 17:30:08.696962848 +0100 @@ -2,7 +2,7 @@ * Routines for h245 packet dissection * Copyright 2005, Anders Broman <anders.broman@xxxxxxxxxxxx> * - * $Id: packet-h245-template.h,v 1.1.1.2 2005/09/29 13:18:51 jeff Exp $ + * $Id: packet-h245-template.h,v 1.5 2005/09/29 15:51:24 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -49,8 +49,77 @@ gchar comment[50]; /* the Frame Comment used by graph_analysis, what is a message desc */ } h245_packet_info; +/* + * h223 LC info + */ + +typedef enum { + al_nonStandard, + al1Framed, + al1NotFramed, + al2WithoutSequenceNumbers, + al2WithSequenceNumbers, + al3, + /*...*/ + // al?M: unimplemented annex C adaptation layers + al1M, + al2M, + al3M +} h223_al_type; + +typedef struct { + guint8 control_field_octets; + guint32 send_buffer_size; +} h223_al3_params; + +typedef struct { + h223_al_type al_type; + gpointer al_params; + gboolean segmentable; + dissector_handle_t subdissector; +} h223_lc_params; + +typedef enum { + nonStandardDataType, + nullData, + videoData, + audioData, + data, + encryptionData, + /*...,*/ + h235Control, + h235Media, + multiplexedStream, + redundancyEncoding, + multiplePayloadStream, + fec +} h245_lc_data_type_enum; + +typedef struct { + h245_lc_data_type_enum data_type; + gpointer params; +} h245_lc_data_type; + +/* + * h223 MUX info + */ + +typedef struct _h223_mux_element h223_mux_element; +struct _h223_mux_element { + h223_mux_element* sublist; /* if NULL, use vc instead */ + guint16 vc; + guint16 repeat_count; /* 0 == untilClosingFlag */ + h223_mux_element* next; +}; + +#include <epan/packet_info.h> +typedef void (*h223_set_mc_handle_t) ( packet_info* pinfo, guint8 mc, h223_mux_element* me ); +extern void h245_set_h223_set_mc_handle( h223_set_mc_handle_t handle ); + +typedef void (*h223_add_lc_handle_t) ( packet_info* pinfo, guint16 lc, h223_lc_params* params ); +extern void h245_set_h223_add_lc_handle( h223_add_lc_handle_t handle ); -#include "packet-h245-exp.h"*/ +#include "packet-h245-exp.h" void dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, char *codec_str); --- epan/dissectors/packet-h245.c 2005-09-29 16:07:12.567449520 +0100 +++ epan/dissectors/packet-h245.c 2005-09-30 15:08:18.131968896 +0100 @@ -1,6 +1,6 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Ethereal dissector compiler */ -/* .\packet-h245.c */ +/* ./packet-h245.c */ /* ../../tools/asn2eth.py -X -e -p h245 -c h245.cnf -s packet-h245-template h245.asn */ /* Input file: packet-h245-template.c */ @@ -9,7 +9,7 @@ * Routines for h245 packet dissection * Copyright 2004, Anders Broman <anders.broman@xxxxxxxxxxxx> * - * $Id: packet-h245.c,v 1.1.1.4 2005/09/29 13:18:54 jeff Exp $ + * $Id: packet-h245.c,v 1.10 2005/09/30 11:04:10 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -60,6 +60,7 @@ #include "packet-rtp.h" #include "packet-rtcp.h" #include "packet-ber.h" +#include <epan/emem.h> #define PNAME "MULTIMEDIA-SYSTEM-CONTROL" #define PSNAME "H.245" @@ -73,6 +74,8 @@ static dissector_handle_t data_handle; static dissector_handle_t h245_handle; static dissector_handle_t MultimediaSystemControlMessage_handle; +static dissector_handle_t h263_handle = NULL; +static dissector_handle_t amr_handle = NULL; static void reset_h245_packet_info(h245_packet_info *pi); static int hf_h245_pdu_type = -1; @@ -228,6 +231,53 @@ { 3267, "RFC 3267 - Adaptive Multi-Rate (AMR) and Adaptive Multi-Rate Wideband (AMR-WB)" }, { 0, NULL } }; + +/* h223 multiplex codes */ +static h223_set_mc_handle_t h223_set_mc_handle = NULL; +h223_mux_element *h223_me=NULL; +guint8 h223_mc=0; +void h245_set_h223_set_mc_handle( h223_set_mc_handle_t handle ) +{ + h223_set_mc_handle = handle; +} + +/* h223 logical channels */ +typedef struct { + h223_lc_params *fw_channel_params; + h223_lc_params *rev_channel_params; +} h223_pending_olc; + +static GHashTable* h223_pending_olc_reqs[] = { NULL, NULL }; +static dissector_handle_t h245_lc_dissector; +static guint16 h245_lc_temp; +static guint16 h223_fw_lc_num; +static guint16 h223_rev_lc_num; +static h223_lc_params *h223_lc_params_temp; +static h223_lc_params *h223_fw_lc_params; +static h223_lc_params *h223_rev_lc_params; +static h223_add_lc_handle_t h223_add_lc_handle = NULL; + +static void h223_lc_init_dir( int dir ) +{ + if ( h223_pending_olc_reqs[dir] ) + g_hash_table_destroy( h223_pending_olc_reqs[dir] ); + h223_pending_olc_reqs[dir] = g_hash_table_new( g_direct_hash, g_direct_equal ); +} + +static void h223_lc_init() +{ + h223_lc_init_dir( P2P_DIR_SENT ); + h223_lc_init_dir( P2P_DIR_RECV ); + h223_lc_params_temp = NULL; + h245_lc_dissector = NULL; + h223_fw_lc_num = 0; +} + +void h245_set_h223_add_lc_handle( h223_add_lc_handle_t handle ) +{ + h223_add_lc_handle = handle; +} + /* Initialize the protocol and registered fields */ int proto_h245 = -1; @@ -913,19 +963,20 @@ static int hf_h245_separateStreamBool = -1; /* T_separateStream */ static int hf_h245_separatePort = -1; /* BOOLEAN */ static int hf_h245_samePortBool = -1; /* BOOLEAN */ -static int hf_h245_forwardLogicalChannelNumber = -1; /* LogicalChannelNumber */ +static int hf_h245_olc_fw_lcn = -1; /* OLC_fw_lcn */ static int hf_h245_forwardLogicalChannelParameters = -1; /* T_forwardLogicalChannelParameters */ static int hf_h245_portNumber = -1; /* INTEGER_0_65535 */ static int hf_h245_dataType = -1; /* DataType */ static int hf_h245_olc_forw_multiplexParameters = -1; /* OLC_forw_multiplexParameters */ static int hf_h245_h222LogicalChannelParameters = -1; /* H222LogicalChannelParameters */ -static int hf_h245_h223LogicalChannelParameters = -1; /* H223LogicalChannelParameters */ +static int hf_h245_olc_fw_h223_params = -1; /* OLC_fw_h223_params */ static int hf_h245_v76LogicalChannelParameters = -1; /* V76LogicalChannelParameters */ static int hf_h245_h2250LogicalChannelParameters = -1; /* H2250LogicalChannelParameters */ static int hf_h245_forwardLogicalChannelDependency = -1; /* LogicalChannelNumber */ static int hf_h245_replacementFor = -1; /* LogicalChannelNumber */ static int hf_h245_reverseLogicalChannelParameters = -1; /* OLC_reverseLogicalChannelParameters */ static int hf_h245_olc_rev_multiplexParameter = -1; /* OLC_rev_multiplexParameters */ +static int hf_h245_olc_rev_h223_params = -1; /* OLC_rev_h223_params */ static int hf_h245_reverseLogicalChannelDependency = -1; /* LogicalChannelNumber */ static int hf_h245_separateStack = -1; /* NetworkAccessParameters */ static int hf_h245_encryptionSync = -1; /* EncryptionSync */ @@ -965,17 +1016,17 @@ static int hf_h245_programDescriptors = -1; /* OCTET_STRING */ static int hf_h245_streamDescriptors = -1; /* OCTET_STRING */ static int hf_h245_adaptationLayerType = -1; /* T_adaptationLayerType */ -static int hf_h245_al1Framed = -1; /* NULL */ -static int hf_h245_al1NotFramed = -1; /* NULL */ -static int hf_h245_al2WithoutSequenceNumbers = -1; /* NULL */ -static int hf_h245_al2WithSequenceNumbers = -1; /* NULL */ -static int hf_h245_al3 = -1; /* Al3 */ -static int hf_h245_al1M = -1; /* H223AL1MParameters */ -static int hf_h245_al2M = -1; /* H223AL2MParameters */ -static int hf_h245_al3M = -1; /* H223AL3MParameters */ -static int hf_h245_segmentableFlag = -1; /* BOOLEAN */ -static int hf_h245_controlFieldOctets = -1; /* INTEGER_0_2 */ -static int hf_h245_sendBufferSize = -1; /* INTEGER_0_16777215 */ +static int hf_h245_h223_al_type_al1Framed = -1; /* T_al1Framed */ +static int hf_h245_h223_al_type_al1NotFramed = -1; /* T_al1NotFramed */ +static int hf_h245_h223_al_type_al2WithoutSequenceNumbers = -1; /* T_al2WithoutSequenceNumbers */ +static int hf_h245_h223_al_type_al2WithSequenceNumbers = -1; /* T_al2WithSequenceNumbers */ +static int hf_h245_h223_al_type_al3 = -1; /* T_al3 */ +static int hf_h245_h223_al_type_al1M = -1; /* T_al1M */ +static int hf_h245_h223_al_type_al2M = -1; /* T_al2M */ +static int hf_h245_h223_al_type_al3M = -1; /* T_al3M */ +static int hf_h245_h223_lc_segmentableFlag = -1; /* T_segmentableFlag */ +static int hf_h245_controlFieldOctets = -1; /* T_controlFieldOctets */ +static int hf_h245_al3_sendBufferSize = -1; /* T_sendBufferSize */ static int hf_h245_transferMode = -1; /* T_transferMode */ static int hf_h245_framed = -1; /* NULL */ static int hf_h245_unframed = -1; /* NULL */ @@ -1005,6 +1056,7 @@ static int hf_h245_numberOfRetransmissions = -1; /* T_numberOfRetransmissions */ static int hf_h245_finite = -1; /* INTEGER_0_16 */ static int hf_h245_infinite = -1; /* NULL */ +static int hf_h245_sendBufferSize = -1; /* INTEGER_0_16777215 */ static int hf_h245_hdlcParameters = -1; /* V76HDLCParameters */ static int hf_h245_suspendResume = -1; /* T_suspendResume */ static int hf_h245_noSuspendResume = -1; /* NULL */ @@ -1088,11 +1140,13 @@ static int hf_h245_escrowentry_item = -1; /* EscrowData */ static int hf_h245_escrowID = -1; /* OBJECT_IDENTIFIER */ static int hf_h245_escrowValue = -1; /* BIT_STRING_SIZE_1_65535 */ +static int hf_h245_olc_ack_fw_lcn = -1; /* OLC_ack_fw_lcn */ static int hf_h245_olc_ack_reverseLogicalChannelParameters = -1; /* OLC_ack_reverseLogicalChannelParameters */ static int hf_h245_reverseLogicalChannelNumber = -1; /* LogicalChannelNumber */ static int hf_h245_olc_ack_multiplexParameters = -1; /* T_multiplexParameters */ static int hf_h245_forwardMultiplexAckParameters = -1; /* T_forwardMultiplexAckParameters */ static int hf_h245_h2250LogicalChannelAckParameters = -1; /* H2250LogicalChannelAckParameters */ +static int hf_h245_forwardLogicalChannelNumber = -1; /* LogicalChannelNumber */ static int hf_h245_olc_rej_cause = -1; /* OpenLogicalChannelRejectCause */ static int hf_h245_unsuitableReverseParameters = -1; /* NULL */ static int hf_h245_dataTypeNotSupported = -1; /* NULL */ @@ -1125,15 +1179,15 @@ static int hf_h245_multiplexEntryDescriptors = -1; /* SET_SIZE_1_15_OF_MultiplexEntryDescriptor */ static int hf_h245_multiplexEntryDescriptors_item = -1; /* MultiplexEntryDescriptor */ static int hf_h245_multiplexTableEntryNumber = -1; /* MultiplexTableEntryNumber */ -static int hf_h245_elementList = -1; /* SEQUENCE_SIZE_1_256_OF_MultiplexElement */ +static int hf_h245_elementList = -1; /* T_elementList */ static int hf_h245_elementList_item = -1; /* MultiplexElement */ static int hf_h245_me_type = -1; /* Me_type */ -static int hf_h245_logicalChannelNum = -1; /* INTEGER_0_65535 */ -static int hf_h245_subElementList = -1; /* SEQUENCE_SIZE_2_255_OF_MultiplexElement */ +static int hf_h245_logicalChannelNum = -1; /* T_logicalChannelNumber */ +static int hf_h245_subElementList = -1; /* T_subElementList */ static int hf_h245_subElementList_item = -1; /* MultiplexElement */ static int hf_h245_me_repeatCount = -1; /* ME_repeatCount */ -static int hf_h245_finite_1_65535 = -1; /* INTEGER_1_65535 */ -static int hf_h245_untilClosingFlag = -1; /* NULL */ +static int hf_h245_me_repeatCount_finite = -1; /* ME_finiteRepeatCount */ +static int hf_h245_untilClosingFlag = -1; /* T_untilClosingFlag */ static int hf_h245_multiplexTableEntryNumbers = -1; /* SET_SIZE_1_15_OF_MultiplexTableEntryNumber */ static int hf_h245_multiplexTableEntryNumber_item = -1; /* MultiplexTableEntryNumber */ static int hf_h245_rejectionDescriptions1 = -1; /* SET_SIZE_1_15_OF_MultiplexEntryRejectionDescriptions */ @@ -1182,6 +1236,15 @@ static int hf_h245_rfc2733Mode = -1; /* T_rfc2733Mode */ static int hf_h245_fec_mode = -1; /* FEC_mode */ static int hf_h245_adaptationLayer = -1; /* AdaptationLayerType */ +static int hf_h245_al1Framed = -1; /* NULL */ +static int hf_h245_al1NotFramed = -1; /* NULL */ +static int hf_h245_al2WithoutSequenceNumbers = -1; /* NULL */ +static int hf_h245_al2WithSequenceNumbers = -1; /* NULL */ +static int hf_h245_al3 = -1; /* Al3 */ +static int hf_h245_al1M = -1; /* H223AL1MParameters */ +static int hf_h245_al2M = -1; /* H223AL2MParameters */ +static int hf_h245_al3M = -1; /* H223AL3MParameters */ +static int hf_h245_segmentableFlag = -1; /* BOOLEAN */ static int hf_h245_redundancyEncodingMode = -1; /* RedundancyEncodingMode */ static int hf_h245_secondaryEncoding = -1; /* T_secondaryEncoding */ static int hf_h245_h261VideoMode = -1; /* H261VideoMode */ @@ -1834,10 +1897,10 @@ static gint ett_h245_MultiplexEntrySend = -1; static gint ett_h245_SET_SIZE_1_15_OF_MultiplexEntryDescriptor = -1; static gint ett_h245_MultiplexEntryDescriptor = -1; -static gint ett_h245_SEQUENCE_SIZE_1_256_OF_MultiplexElement = -1; +static gint ett_h245_T_elementList = -1; static gint ett_h245_MultiplexElement = -1; static gint ett_h245_Me_type = -1; -static gint ett_h245_SEQUENCE_SIZE_2_255_OF_MultiplexElement = -1; +static gint ett_h245_T_subElementList = -1; static gint ett_h245_ME_repeatCount = -1; static gint ett_h245_MultiplexEntrySendAck = -1; static gint ett_h245_SET_SIZE_1_15_OF_MultiplexTableEntryNumber = -1; @@ -3154,9 +3217,6 @@ static int dissect_audioHeaderPresent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_audioHeaderPresent); } -static int dissect_segmentableFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_segmentableFlag); -} static int dissect_alsduSplitting(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_alsduSplitting); } @@ -3175,6 +3235,9 @@ static int dissect_flowControlToZero(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_flowControlToZero); } +static int dissect_segmentableFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_segmentableFlag); +} static int dissect_multiplexCapabilityBool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_BOOLEAN(tvb, offset, pinfo, tree, hf_h245_multiplexCapabilityBool); } @@ -3279,9 +3342,6 @@ static int dissect_multicast_IPv6_tsapIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_INTEGER_0_65535(tvb, offset, pinfo, tree, hf_h245_multicast_IPv6_tsapIdentifier); } -static int dissect_logicalChannelNum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_INTEGER_0_65535(tvb, offset, pinfo, tree, hf_h245_logicalChannelNum); -} static int dissect_requestedInterval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_INTEGER_0_65535(tvb, offset, pinfo, tree, hf_h245_requestedInterval); } @@ -3325,9 +3385,6 @@ static int dissect_higherBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_INTEGER_1_65535(tvb, offset, pinfo, tree, hf_h245_higherBitRate); } -static int dissect_finite_1_65535(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_INTEGER_1_65535(tvb, offset, pinfo, tree, hf_h245_finite_1_65535); -} static int dissect_maxNumberOfAdditionalConnections(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_INTEGER_1_65535(tvb, offset, pinfo, tree, hf_h245_maxNumberOfAdditionalConnections); } @@ -3779,18 +3836,6 @@ static int dissect_nullData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_nullData); } -static int dissect_al1Framed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al1Framed); -} -static int dissect_al1NotFramed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al1NotFramed); -} -static int dissect_al2WithoutSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al2WithoutSequenceNumbers); -} -static int dissect_al2WithSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al2WithSequenceNumbers); -} static int dissect_framed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_framed); } @@ -3926,9 +3971,6 @@ static int dissect_normal(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_normal); } -static int dissect_untilClosingFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_untilClosingFlag); -} static int dissect_unspecifiedCause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_unspecifiedCause); } @@ -3950,6 +3992,18 @@ static int dissect_requestDenied(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_requestDenied); } +static int dissect_al1Framed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al1Framed); +} +static int dissect_al1NotFramed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al1NotFramed); +} +static int dissect_al2WithoutSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al2WithoutSequenceNumbers); +} +static int dissect_al2WithSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_al2WithSequenceNumbers); +} static int dissect_qcif(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_NULL(tvb, offset, pinfo, tree, hf_h245_qcif); } @@ -5222,6 +5276,8 @@ dissect_h245_T_standard(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { offset = dissect_per_object_identifier_str(tvb, offset, pinfo, tree, hf_index, &standard_oid_str); + if(!h245_lc_dissector && strcmp(standard_oid_str,"0.0.8.245.1.1.1") == 0) + h245_lc_dissector = amr_handle; return offset; } static int dissect_standardOid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -7358,6 +7414,7 @@ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_H263VideoCapability, H263VideoCapability_sequence); + h245_lc_dissector = h263_handle; return offset; } static int dissect_h263VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -8500,14 +8557,14 @@ static int dissect_h245_LogicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, - 1U, 65535U, NULL, NULL, FALSE); + 1U, 65535U, &value, NULL, FALSE); + + h245_lc_temp = value & 0xfff; return offset; } -static int dissect_forwardLogicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_forwardLogicalChannelNumber); -} static int dissect_forwardLogicalChannelDependency(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_forwardLogicalChannelDependency); } @@ -8520,6 +8577,9 @@ static int dissect_reverseLogicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_reverseLogicalChannelNumber); } +static int dissect_forwardLogicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_forwardLogicalChannelNumber); +} static int dissect_logicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { return dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_logicalChannelNumber); } @@ -8543,6 +8603,19 @@ } + +static int +dissect_h245_OLC_fw_lcn(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + offset = dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_index); + + h223_fw_lc_num = h245_lc_temp; + return offset; +} +static int dissect_olc_fw_lcn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_OLC_fw_lcn(tvb, offset, pinfo, tree, hf_h245_olc_fw_lcn); +} + + static const value_string h245_EncryptionMode_vals[] = { { 0, "nonStandard" }, { 1, "h233Encryption" }, @@ -8976,20 +9049,97 @@ static int -dissect_h245_INTEGER_0_2(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { +dissect_h245_T_al1Framed(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1Framed; + offset = dissect_per_null(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al1Framed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al1Framed(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al1Framed); +} + + + +static int +dissect_h245_T_al1NotFramed(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1NotFramed; + offset = dissect_per_null(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al1NotFramed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al1NotFramed(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al1NotFramed); +} + + + +static int +dissect_h245_T_al2WithoutSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2WithoutSequenceNumbers; + offset = dissect_per_null(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al2WithoutSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al2WithoutSequenceNumbers(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al2WithoutSequenceNumbers); +} + + + +static int +dissect_h245_T_al2WithSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2WithSequenceNumbers; + offset = dissect_per_null(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al2WithSequenceNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al2WithSequenceNumbers(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al2WithSequenceNumbers); +} + + + +static int +dissect_h245_T_controlFieldOctets(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, - 0U, 2U, NULL, NULL, FALSE); + 0U, 2U, &value, NULL, FALSE); + + if(h223_lc_params_temp && h223_lc_params_temp->al_params) + ((h223_al3_params*)h223_lc_params_temp->al_params)->control_field_octets = value & 3 ; return offset; } static int dissect_controlFieldOctets(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_INTEGER_0_2(tvb, offset, pinfo, tree, hf_h245_controlFieldOctets); + return dissect_h245_T_controlFieldOctets(tvb, offset, pinfo, tree, hf_h245_controlFieldOctets); +} + + + +static int +dissect_h245_T_sendBufferSize(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; + offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, + 0U, 16777215U, &value, NULL, FALSE); + + if(h223_lc_params_temp && h223_lc_params_temp->al_params) + ((h223_al3_params*)h223_lc_params_temp->al_params)->send_buffer_size = value & 0xfffff; + + return offset; +} +static int dissect_al3_sendBufferSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_sendBufferSize(tvb, offset, pinfo, tree, hf_h245_al3_sendBufferSize); } static const per_sequence_t Al3_sequence[] = { { "controlFieldOctets" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_controlFieldOctets }, - { "sendBufferSize" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_sendBufferSize }, + { "sendBufferSize" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_al3_sendBufferSize }, { NULL, 0, 0, NULL } }; @@ -9005,6 +9155,22 @@ } + +static int +dissect_h245_T_al3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) { + h223_lc_params_temp->al_type = al3; + h223_lc_params_temp->al_params = se_alloc(sizeof(h223_al3_params)); + } + offset = dissect_h245_Al3(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al3(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al3); +} + + static const value_string h245_T_transferMode_vals[] = { { 0, "framed" }, { 1, "unframed" }, @@ -9215,6 +9381,20 @@ } + +static int +dissect_h245_T_al1M(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al1M; + offset = dissect_h245_H223AL1MParameters(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al1M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al1M(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al1M); +} + + static const value_string h245_AL2HeaderFEC_vals[] = { { 0, "sebch16-5" }, { 1, "golay24-12" }, @@ -9258,6 +9438,20 @@ } + +static int +dissect_h245_T_al2M(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al2M; + offset = dissect_h245_H223AL2MParameters(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al2M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al2M(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al2M); +} + + static const value_string h245_T_headerFormat_vals[] = { { 0, "sebch16-7" }, { 1, "golay24-12" }, @@ -9342,6 +9536,20 @@ } + +static int +dissect_h245_T_al3M(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + if(h223_lc_params_temp) + h223_lc_params_temp->al_type = al3M; + offset = dissect_h245_H223AL3MParameters(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_h223_al_type_al3M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_al3M(tvb, offset, pinfo, tree, hf_h245_h223_al_type_al3M); +} + + static const value_string h245_T_adaptationLayerType_vals[] = { { 0, "nonStandard" }, { 1, "al1Framed" }, @@ -9357,14 +9565,14 @@ static const per_choice_t T_adaptationLayerType_choice[] = { { 0, "nonStandard" , ASN1_EXTENSION_ROOT , dissect_nonStandard }, - { 1, "al1Framed" , ASN1_EXTENSION_ROOT , dissect_al1Framed }, - { 2, "al1NotFramed" , ASN1_EXTENSION_ROOT , dissect_al1NotFramed }, - { 3, "al2WithoutSequenceNumbers" , ASN1_EXTENSION_ROOT , dissect_al2WithoutSequenceNumbers }, - { 4, "al2WithSequenceNumbers" , ASN1_EXTENSION_ROOT , dissect_al2WithSequenceNumbers }, - { 5, "al3" , ASN1_EXTENSION_ROOT , dissect_al3 }, - { 6, "al1M" , ASN1_NOT_EXTENSION_ROOT, dissect_al1M }, - { 7, "al2M" , ASN1_NOT_EXTENSION_ROOT, dissect_al2M }, - { 8, "al3M" , ASN1_NOT_EXTENSION_ROOT, dissect_al3M }, + { 1, "al1Framed" , ASN1_EXTENSION_ROOT , dissect_h223_al_type_al1Framed }, + { 2, "al1NotFramed" , ASN1_EXTENSION_ROOT , dissect_h223_al_type_al1NotFramed }, + { 3, "al2WithoutSequenceNumbers" , ASN1_EXTENSION_ROOT , dissect_h223_al_type_al2WithoutSequenceNumbers }, + { 4, "al2WithSequenceNumbers" , ASN1_EXTENSION_ROOT , dissect_h223_al_type_al2WithSequenceNumbers }, + { 5, "al3" , ASN1_EXTENSION_ROOT , dissect_h223_al_type_al3 }, + { 6, "al1M" , ASN1_NOT_EXTENSION_ROOT, dissect_h223_al_type_al1M }, + { 7, "al2M" , ASN1_NOT_EXTENSION_ROOT, dissect_h223_al_type_al2M }, + { 8, "al3M" , ASN1_NOT_EXTENSION_ROOT, dissect_h223_al_type_al3M }, { 0, NULL, 0, NULL } }; @@ -9381,9 +9589,26 @@ } + +static int +dissect_h245_T_segmentableFlag(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; + offset = dissect_per_boolean(tvb, offset, pinfo, tree, hf_index, + &value, NULL); + + if(h223_lc_params_temp) + h223_lc_params_temp->segmentable = value & 1; + + return offset; +} +static int dissect_h223_lc_segmentableFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_segmentableFlag(tvb, offset, pinfo, tree, hf_h245_h223_lc_segmentableFlag); +} + + static const per_sequence_t H223LogicalChannelParameters_sequence[] = { { "adaptationLayerType" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_adaptationLayerType }, - { "segmentableFlag" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_segmentableFlag }, + { "segmentableFlag" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_h223_lc_segmentableFlag }, { NULL, 0, 0, NULL } }; @@ -9394,8 +9619,23 @@ return offset; } -static int dissect_h223LogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_H223LogicalChannelParameters(tvb, offset, pinfo, tree, hf_h245_h223LogicalChannelParameters); + + + +static int +dissect_h245_OLC_fw_h223_params(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h223_fw_lc_params = se_alloc(sizeof(h223_lc_params)); + h223_fw_lc_params->al_type = al_nonStandard; + h223_fw_lc_params->al_params = NULL; + h223_fw_lc_params->segmentable = 0; + h223_fw_lc_params->subdissector = NULL; + h223_lc_params_temp = h223_fw_lc_params; + offset = dissect_h245_H223LogicalChannelParameters(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_olc_fw_h223_params(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_OLC_fw_h223_params(tvb, offset, pinfo, tree, hf_h245_olc_fw_h223_params); } @@ -10102,7 +10342,7 @@ static const per_choice_t OLC_forw_multiplexParameters_choice[] = { { 0, "h222LogicalChannelParameters", ASN1_EXTENSION_ROOT , dissect_h222LogicalChannelParameters }, - { 1, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT , dissect_h223LogicalChannelParameters }, + { 1, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT , dissect_olc_fw_h223_params }, { 2, "v76LogicalChannelParameters" , ASN1_EXTENSION_ROOT , dissect_v76LogicalChannelParameters }, { 3, "h2250LogicalChannelParameters", ASN1_NOT_EXTENSION_ROOT, dissect_h2250LogicalChannelParameters }, { 4, "none" , ASN1_NOT_EXTENSION_ROOT, dissect_none }, @@ -10133,9 +10373,15 @@ static int dissect_h245_T_forwardLogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h245_lc_dissector = NULL; offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_T_forwardLogicalChannelParameters, T_forwardLogicalChannelParameters_sequence); + if(h223_lc_params_temp && h245_lc_dissector) + h223_lc_params_temp->subdissector = h245_lc_dissector; + else if(h223_lc_params_temp) + h223_lc_params_temp->subdissector = data_handle; + return offset; } static int dissect_forwardLogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -10143,6 +10389,24 @@ } + +static int +dissect_h245_OLC_rev_h223_params(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h223_rev_lc_params = se_alloc(sizeof(h223_lc_params)); + h223_rev_lc_params->al_type = al_nonStandard; + h223_rev_lc_params->al_params = NULL; + h223_rev_lc_params->segmentable = 0; + h223_rev_lc_params->subdissector = NULL; + h223_lc_params_temp = h223_rev_lc_params; + offset = dissect_h245_H223LogicalChannelParameters(tvb, offset, pinfo, tree, hf_index); + + return offset; +} +static int dissect_olc_rev_h223_params(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_OLC_rev_h223_params(tvb, offset, pinfo, tree, hf_h245_olc_rev_h223_params); +} + + static const value_string h245_OLC_rev_multiplexParameters_vals[] = { { 0, "h223LogicalChannelParameters" }, { 1, "v76LogicalChannelParameters" }, @@ -10151,7 +10415,7 @@ }; static const per_choice_t OLC_rev_multiplexParameters_choice[] = { - { 0, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT , dissect_h223LogicalChannelParameters }, + { 0, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT , dissect_olc_rev_h223_params }, { 1, "v76LogicalChannelParameters" , ASN1_EXTENSION_ROOT , dissect_v76LogicalChannelParameters }, { 2, "h2250LogicalChannelParameters", ASN1_NOT_EXTENSION_ROOT, dissect_h2250LogicalChannelParameters }, { 0, NULL, 0, NULL } @@ -10432,7 +10696,7 @@ static const per_sequence_t OpenLogicalChannel_sequence[] = { - { "forwardLogicalChannelNumber" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_forwardLogicalChannelNumber }, + { "forwardLogicalChannelNumber" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_olc_fw_lcn }, { "forwardLogicalChannelParameters", ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_forwardLogicalChannelParameters }, { "reverseLogicalChannelParameters", ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_reverseLogicalChannelParameters }, { "separateStack" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_separateStack }, @@ -10442,9 +10706,19 @@ int dissect_h245_OpenLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h223_fw_lc_num = 0; + h223_lc_params_temp = NULL; offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence); + if(h223_fw_lc_num != 0 && h223_fw_lc_params) { + h223_pending_olc *pending = se_alloc(sizeof(h223_pending_olc)); + pending->fw_channel_params = h223_fw_lc_params; + pending->rev_channel_params = h223_rev_lc_params; + gint32 temp = h223_fw_lc_num; + g_hash_table_insert(h223_pending_olc_reqs[pinfo->p2p_dir], GINT_TO_POINTER(temp), pending); + } + if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn; return offset; @@ -10578,8 +10852,11 @@ static int dissect_h245_MultiplexTableEntryNumber(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, - 1U, 15U, NULL, NULL, FALSE); + 1U, 15U, &value, NULL, FALSE); + + h223_mc = value & 0xf; return offset; } @@ -10594,20 +10871,44 @@ } -static const per_sequence_t SEQUENCE_SIZE_2_255_OF_MultiplexElement_sequence_of[1] = { + +static int +dissect_h245_T_logicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + /*MultiplexElement/type/logicalChannelNumber*/ + guint32 value; + offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, + 0U, 65535U, &value, NULL, FALSE); + + h223_me->sublist = NULL; + h223_me->vc = value & 0xffff; + + return offset; +} +static int dissect_logicalChannelNum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_logicalChannelNumber(tvb, offset, pinfo, tree, hf_h245_logicalChannelNum); +} + + +static const per_sequence_t T_subElementList_sequence_of[1] = { { "" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_subElementList_item }, }; static int -dissect_h245_SEQUENCE_SIZE_2_255_OF_MultiplexElement(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { +dissect_h245_T_subElementList(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h223_mux_element dummy_me, *parent_me = h223_me; + h223_me = &dummy_me; offset = dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_index, - ett_h245_SEQUENCE_SIZE_2_255_OF_MultiplexElement, SEQUENCE_SIZE_2_255_OF_MultiplexElement_sequence_of, + ett_h245_T_subElementList, T_subElementList_sequence_of, 2, 255); + parent_me->sublist = dummy_me.next; + h223_me = parent_me; + h223_me->vc = 0; + return offset; } static int dissect_subElementList(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_SEQUENCE_SIZE_2_255_OF_MultiplexElement(tvb, offset, pinfo, tree, hf_h245_subElementList); + return dissect_h245_T_subElementList(tvb, offset, pinfo, tree, hf_h245_subElementList); } @@ -10636,6 +10937,35 @@ } + +static int +dissect_h245_ME_finiteRepeatCount(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + guint32 value; + offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index, + 1U, 65535U, &value, NULL, FALSE); + + h223_me->repeat_count = value & 0xffff; + + return offset; +} +static int dissect_me_repeatCount_finite(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_ME_finiteRepeatCount(tvb, offset, pinfo, tree, hf_h245_me_repeatCount_finite); +} + + + +static int +dissect_h245_T_untilClosingFlag(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + offset = dissect_per_null(tvb, offset, pinfo, tree, hf_index); + + h223_me->repeat_count = 0; + return offset; +} +static int dissect_untilClosingFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_T_untilClosingFlag(tvb, offset, pinfo, tree, hf_h245_untilClosingFlag); +} + + static const value_string h245_ME_repeatCount_vals[] = { { 0, "finite" }, { 1, "untilClosingFlag" }, @@ -10643,7 +10973,7 @@ }; static const per_choice_t ME_repeatCount_choice[] = { - { 0, "finite" , ASN1_NO_EXTENSIONS , dissect_finite_1_65535 }, + { 0, "finite" , ASN1_NO_EXTENSIONS , dissect_me_repeatCount_finite }, { 1, "untilClosingFlag" , ASN1_NO_EXTENSIONS , dissect_untilClosingFlag }, { 0, NULL, 0, NULL } }; @@ -10669,6 +10999,11 @@ static int dissect_h245_MultiplexElement(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + /*MultiplexElement*/ + h223_mux_element* me = se_alloc(sizeof(h223_mux_element)); + h223_me->next = me; + h223_me = me; + h223_me->next = NULL; offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_MultiplexElement, MultiplexElement_sequence); @@ -10676,20 +11011,27 @@ } -static const per_sequence_t SEQUENCE_SIZE_1_256_OF_MultiplexElement_sequence_of[1] = { +static const per_sequence_t T_elementList_sequence_of[1] = { { "" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_elementList_item }, }; static int -dissect_h245_SEQUENCE_SIZE_1_256_OF_MultiplexElement(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { +dissect_h245_T_elementList(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + /* create a h223_mux_element to hold onto the head of the list, since + * h223_me will track the tail */ + h223_mux_element dummy_me; + h223_me = &dummy_me; offset = dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_index, - ett_h245_SEQUENCE_SIZE_1_256_OF_MultiplexElement, SEQUENCE_SIZE_1_256_OF_MultiplexElement_sequence_of, + ett_h245_T_elementList, T_elementList_sequence_of, 1, 256); + /* set h223_me to the head of the list for MEDescriptor to pick up */ + h223_me = dummy_me.next; + return offset; } static int dissect_elementList(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - return dissect_h245_SEQUENCE_SIZE_1_256_OF_MultiplexElement(tvb, offset, pinfo, tree, hf_h245_elementList); + return dissect_h245_T_elementList(tvb, offset, pinfo, tree, hf_h245_elementList); } @@ -10701,9 +11043,16 @@ static int dissect_h245_MultiplexEntryDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + /*MultiplexEntryDescriptor*/ + h223_me = NULL; + h223_mc = 0; offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_MultiplexEntryDescriptor, MultiplexEntryDescriptor_sequence); + if(h223_set_mc_handle) + (*h223_set_mc_handle)(pinfo, h223_mc, h223_me); + /* stuff */ + return offset; } static int dissect_multiplexEntryDescriptors_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -12825,6 +13174,19 @@ } + +static int +dissect_h245_OLC_ack_fw_lcn(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + offset = dissect_h245_LogicalChannelNumber(tvb, offset, pinfo, tree, hf_index); + + h223_fw_lc_num = h245_lc_temp; + return offset; +} +static int dissect_olc_ack_fw_lcn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + return dissect_h245_OLC_ack_fw_lcn(tvb, offset, pinfo, tree, hf_h245_olc_ack_fw_lcn); +} + + static const value_string h245_T_multiplexParameters_vals[] = { { 0, "h222LogicalChannelParameters" }, { 1, "h2250LogicalChannelParameters" }, @@ -12978,7 +13340,7 @@ static const per_sequence_t OpenLogicalChannelAck_sequence[] = { - { "forwardLogicalChannelNumber" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_forwardLogicalChannelNumber }, + { "forwardLogicalChannelNumber" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_olc_ack_fw_lcn }, { "reverseLogicalChannelParameters", ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_olc_ack_reverseLogicalChannelParameters }, { "separateStack" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_separateStack }, { "forwardMultiplexAckParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_forwardMultiplexAckParameters }, @@ -12988,9 +13350,31 @@ static int dissect_h245_OpenLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) { + h223_fw_lc_num = 0; + h223_rev_lc_num = 0; offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index, ett_h245_OpenLogicalChannelAck, OpenLogicalChannelAck_sequence); + guint32 temp = h223_fw_lc_num; + int p2p_dir = pinfo->p2p_dir; + if(pinfo->p2p_dir == P2P_DIR_SENT) + pinfo->p2p_dir = P2P_DIR_RECV; + else + pinfo->p2p_dir = P2P_DIR_SENT; + h223_pending_olc *pend = g_hash_table_lookup( h223_pending_olc_reqs[pinfo->p2p_dir], GINT_TO_POINTER(temp) ); + if (pend) { + DISSECTOR_ASSERT( ( h223_rev_lc_num && pend->rev_channel_params) + || (!h223_rev_lc_num && !pend->rev_channel_params) ); + if(h223_add_lc_handle) { + (*h223_add_lc_handle)( pinfo, h223_fw_lc_num, pend->fw_channel_params ); + if(h223_rev_lc_num) + (*h223_add_lc_handle)( pinfo, h223_rev_lc_num, pend->rev_channel_params ); + } + } else { + /* we missed the OpenLogicalChannel packet */ + } + pinfo->p2p_dir = p2p_dir; + h245_pi->msg_type = H245_OpenLogChnAck; return offset; @@ -19652,10 +20036,10 @@ { "samePort", "h245.samePort", FT_BOOLEAN, 8, NULL, 0, "FECCapability/rfc2733/separateStream/samePort", HFILL }}, - { &hf_h245_forwardLogicalChannelNumber, + { &hf_h245_olc_fw_lcn, { "forwardLogicalChannelNumber", "h245.forwardLogicalChannelNumber", FT_UINT32, BASE_DEC, NULL, 0, - "", HFILL }}, + "OpenLogicalChannel/forwardLogicalChannelNumber", HFILL }}, { &hf_h245_forwardLogicalChannelParameters, { "forwardLogicalChannelParameters", "h245.forwardLogicalChannelParameters", FT_NONE, BASE_NONE, NULL, 0, @@ -19676,10 +20060,10 @@ { "h222LogicalChannelParameters", "h245.h222LogicalChannelParameters", FT_NONE, BASE_NONE, NULL, 0, "", HFILL }}, - { &hf_h245_h223LogicalChannelParameters, + { &hf_h245_olc_fw_h223_params, { "h223LogicalChannelParameters", "h245.h223LogicalChannelParameters", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, + "OpenLogicalChannel/forwardLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters", HFILL }}, { &hf_h245_v76LogicalChannelParameters, { "v76LogicalChannelParameters", "h245.v76LogicalChannelParameters", FT_NONE, BASE_NONE, NULL, 0, @@ -19704,6 +20088,10 @@ { "multiplexParameters", "h245.multiplexParameters", FT_UINT32, BASE_DEC, VALS(h245_OLC_rev_multiplexParameters_vals), 0, "OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters", HFILL }}, + { &hf_h245_olc_rev_h223_params, + { "h223LogicalChannelParameters", "h245.h223LogicalChannelParameters", + FT_NONE, BASE_NONE, NULL, 0, + "OpenLogicalChannel/reverseLogicalChannelParameters/multiplexParameters/h223LogicalChannelParameters", HFILL }}, { &hf_h245_reverseLogicalChannelDependency, { "reverseLogicalChannelDependency", "h245.reverseLogicalChannelDependency", FT_UINT32, BASE_DEC, NULL, 0, @@ -19860,50 +20248,50 @@ { "adaptationLayerType", "h245.adaptationLayerType", FT_UINT32, BASE_DEC, VALS(h245_T_adaptationLayerType_vals), 0, "H223LogicalChannelParameters/adaptationLayerType", HFILL }}, - { &hf_h245_al1Framed, + { &hf_h245_h223_al_type_al1Framed, { "al1Framed", "h245.al1Framed", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al1NotFramed, + "H223LogicalChannelParameters/adaptationLayerType/al1Framed", HFILL }}, + { &hf_h245_h223_al_type_al1NotFramed, { "al1NotFramed", "h245.al1NotFramed", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al2WithoutSequenceNumbers, + "H223LogicalChannelParameters/adaptationLayerType/al1NotFramed", HFILL }}, + { &hf_h245_h223_al_type_al2WithoutSequenceNumbers, { "al2WithoutSequenceNumbers", "h245.al2WithoutSequenceNumbers", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al2WithSequenceNumbers, + "H223LogicalChannelParameters/adaptationLayerType/al2WithoutSequenceNumbers", HFILL }}, + { &hf_h245_h223_al_type_al2WithSequenceNumbers, { "al2WithSequenceNumbers", "h245.al2WithSequenceNumbers", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al3, + "H223LogicalChannelParameters/adaptationLayerType/al2WithSequenceNumbers", HFILL }}, + { &hf_h245_h223_al_type_al3, { "al3", "h245.al3", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al1M, + "H223LogicalChannelParameters/adaptationLayerType/al3", HFILL }}, + { &hf_h245_h223_al_type_al1M, { "al1M", "h245.al1M", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al2M, + "H223LogicalChannelParameters/adaptationLayerType/al1M", HFILL }}, + { &hf_h245_h223_al_type_al2M, { "al2M", "h245.al2M", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_al3M, + "H223LogicalChannelParameters/adaptationLayerType/al2M", HFILL }}, + { &hf_h245_h223_al_type_al3M, { "al3M", "h245.al3M", FT_NONE, BASE_NONE, NULL, 0, - "", HFILL }}, - { &hf_h245_segmentableFlag, + "H223LogicalChannelParameters/adaptationLayerType/al3M", HFILL }}, + { &hf_h245_h223_lc_segmentableFlag, { "segmentableFlag", "h245.segmentableFlag", FT_BOOLEAN, 8, NULL, 0, - "", HFILL }}, + "H223LogicalChannelParameters/segmentableFlag", HFILL }}, { &hf_h245_controlFieldOctets, { "controlFieldOctets", "h245.controlFieldOctets", FT_UINT32, BASE_DEC, NULL, 0, "Al3/controlFieldOctets", HFILL }}, - { &hf_h245_sendBufferSize, + { &hf_h245_al3_sendBufferSize, { "sendBufferSize", "h245.sendBufferSize", FT_UINT32, BASE_DEC, NULL, 0, - "", HFILL }}, + "Al3/sendBufferSize", HFILL }}, { &hf_h245_transferMode, { "transferMode", "h245.transferMode", FT_UINT32, BASE_DEC, VALS(h245_T_transferMode_vals), 0, @@ -20020,6 +20408,10 @@ { "infinite", "h245.infinite", FT_NONE, BASE_NONE, NULL, 0, "H223AnnexCArqParameters/numberOfRetransmissions/infinite", HFILL }}, + { &hf_h245_sendBufferSize, + { "sendBufferSize", "h245.sendBufferSize", + FT_UINT32, BASE_DEC, NULL, 0, + "H223AnnexCArqParameters/sendBufferSize", HFILL }}, { &hf_h245_hdlcParameters, { "hdlcParameters", "h245.hdlcParameters", FT_NONE, BASE_NONE, NULL, 0, @@ -20352,6 +20744,10 @@ { "escrowValue", "h245.escrowValue", FT_BYTES, BASE_HEX, NULL, 0, "EscrowData/escrowValue", HFILL }}, + { &hf_h245_olc_ack_fw_lcn, + { "forwardLogicalChannelNumber", "h245.forwardLogicalChannelNumber", + FT_UINT32, BASE_DEC, NULL, 0, + "OpenLogicalChannelAck/forwardLogicalChannelNumber", HFILL }}, { &hf_h245_olc_ack_reverseLogicalChannelParameters, { "reverseLogicalChannelParameters", "h245.reverseLogicalChannelParameters", FT_NONE, BASE_NONE, NULL, 0, @@ -20372,6 +20768,10 @@ { "h2250LogicalChannelAckParameters", "h245.h2250LogicalChannelAckParameters", FT_NONE, BASE_NONE, NULL, 0, "OpenLogicalChannelAck/forwardMultiplexAckParameters/h2250LogicalChannelAckParameters", HFILL }}, + { &hf_h245_forwardLogicalChannelNumber, + { "forwardLogicalChannelNumber", "h245.forwardLogicalChannelNumber", + FT_UINT32, BASE_DEC, NULL, 0, + "", HFILL }}, { &hf_h245_olc_rej_cause, { "cause", "h245.cause", FT_UINT32, BASE_DEC, VALS(h245_OpenLogicalChannelRejectCause_vals), 0, @@ -20528,7 +20928,7 @@ { "repeatCount", "h245.repeatCount", FT_UINT32, BASE_DEC, VALS(h245_ME_repeatCount_vals), 0, "MultiplexElement/repeatCount", HFILL }}, - { &hf_h245_finite_1_65535, + { &hf_h245_me_repeatCount_finite, { "finite", "h245.finite", FT_UINT32, BASE_DEC, NULL, 0, "MultiplexElement/repeatCount/finite", HFILL }}, @@ -20728,6 +21128,42 @@ { "adaptationLayerType", "h245.adaptationLayerType", FT_UINT32, BASE_DEC, VALS(h245_AdaptationLayerType_vals), 0, "H223ModeParameters/adaptationLayerType", HFILL }}, + { &hf_h245_al1Framed, + { "al1Framed", "h245.al1Framed", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al1Framed", HFILL }}, + { &hf_h245_al1NotFramed, + { "al1NotFramed", "h245.al1NotFramed", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al1NotFramed", HFILL }}, + { &hf_h245_al2WithoutSequenceNumbers, + { "al2WithoutSequenceNumbers", "h245.al2WithoutSequenceNumbers", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al2WithoutSequenceNumbers", HFILL }}, + { &hf_h245_al2WithSequenceNumbers, + { "al2WithSequenceNumbers", "h245.al2WithSequenceNumbers", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al2WithSequenceNumbers", HFILL }}, + { &hf_h245_al3, + { "al3", "h245.al3", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al3", HFILL }}, + { &hf_h245_al1M, + { "al1M", "h245.al1M", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al1M", HFILL }}, + { &hf_h245_al2M, + { "al2M", "h245.al2M", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al2M", HFILL }}, + { &hf_h245_al3M, + { "al3M", "h245.al3M", + FT_NONE, BASE_NONE, NULL, 0, + "H223ModeParameters/adaptationLayerType/al3M", HFILL }}, + { &hf_h245_segmentableFlag, + { "segmentableFlag", "h245.segmentableFlag", + FT_BOOLEAN, 8, NULL, 0, + "H223ModeParameters/segmentableFlag", HFILL }}, { &hf_h245_redundancyEncodingMode, { "redundancyEncodingMode", "h245.redundancyEncodingMode", FT_NONE, BASE_NONE, NULL, 0, @@ -22544,10 +22980,10 @@ &ett_h245_MultiplexEntrySend, &ett_h245_SET_SIZE_1_15_OF_MultiplexEntryDescriptor, &ett_h245_MultiplexEntryDescriptor, - &ett_h245_SEQUENCE_SIZE_1_256_OF_MultiplexElement, + &ett_h245_T_elementList, &ett_h245_MultiplexElement, &ett_h245_Me_type, - &ett_h245_SEQUENCE_SIZE_2_255_OF_MultiplexElement, + &ett_h245_T_subElementList, &ett_h245_ME_repeatCount, &ett_h245_MultiplexEntrySendAck, &ett_h245_SET_SIZE_1_15_OF_MultiplexTableEntryNumber, @@ -22816,12 +23252,16 @@ rtp_handle = find_dissector("rtp"); rtcp_handle = find_dissector("rtcp"); data_handle = find_dissector("data"); + h263_handle = find_dissector("h263data"); + amr_handle = find_dissector("amr_if2"); h245_handle=create_dissector_handle(dissect_h245, proto_h245); dissector_add_handle("tcp.port", h245_handle); MultimediaSystemControlMessage_handle=create_dissector_handle(dissect_h245_h245, proto_h245); dissector_add_handle("udp.port", MultimediaSystemControlMessage_handle); + + h223_lc_init(); } static void reset_h245_packet_info(h245_packet_info *pi) --- epan/dissectors/packet-h245.h 2005-09-29 16:07:12.590446024 +0100 +++ epan/dissectors/packet-h245.h 2005-09-29 17:30:14.766040208 +0100 @@ -9,7 +9,7 @@ * Routines for h245 packet dissection * Copyright 2005, Anders Broman <anders.broman@xxxxxxxxxxxx> * - * $Id: packet-h245.h,v 1.1.1.3 2005/09/29 13:18:54 jeff Exp $ + * $Id: packet-h245.h,v 1.8 2005/09/29 15:51:25 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -56,6 +56,75 @@ gchar comment[50]; /* the Frame Comment used by graph_analysis, what is a message desc */ } h245_packet_info; +/* + * h223 LC info + */ + +typedef enum { + al_nonStandard, + al1Framed, + al1NotFramed, + al2WithoutSequenceNumbers, + al2WithSequenceNumbers, + al3, + /*...*/ + // al?M: unimplemented annex C adaptation layers + al1M, + al2M, + al3M +} h223_al_type; + +typedef struct { + guint8 control_field_octets; + guint32 send_buffer_size; +} h223_al3_params; + +typedef struct { + h223_al_type al_type; + gpointer al_params; + gboolean segmentable; + dissector_handle_t subdissector; +} h223_lc_params; + +typedef enum { + nonStandardDataType, + nullData, + videoData, + audioData, + data, + encryptionData, + /*...,*/ + h235Control, + h235Media, + multiplexedStream, + redundancyEncoding, + multiplePayloadStream, + fec +} h245_lc_data_type_enum; + +typedef struct { + h245_lc_data_type_enum data_type; + gpointer params; +} h245_lc_data_type; + +/* + * h223 MUX info + */ + +typedef struct _h223_mux_element h223_mux_element; +struct _h223_mux_element { + h223_mux_element* sublist; /* if NULL, use vc instead */ + guint16 vc; + guint16 repeat_count; /* 0 == untilClosingFlag */ + h223_mux_element* next; +}; + +#include <epan/packet_info.h> +typedef void (*h223_set_mc_handle_t) ( packet_info* pinfo, guint8 mc, h223_mux_element* me ); +extern void h245_set_h223_set_mc_handle( h223_set_mc_handle_t handle ); + +typedef void (*h223_add_lc_handle_t) ( packet_info* pinfo, guint16 lc, h223_lc_params* params ); +extern void h245_set_h223_add_lc_handle( h223_add_lc_handle_t handle ); /*--- Included file: packet-h245-exp.h ---*/
--- plugins/h223/packet-srp.c 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/packet-srp.c 2005-07-05 06:27:45.000000000 +0100 @@ -0,0 +1,242 @@ +/* packet-srp.c + * Routines for H.324/SRP dissection + * 2004 Richard van der Hoff <richardv@xxxxxxxxxxxxx> + * + * $Id: packet-srp.c,v 1.2 2005/07/05 05:27:45 richardv Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gmodule.h> +#include <glib.h> +#include <epan/bitswap.h> +#include <epan/circuit.h> +#include <epan/packet.h> +#include <epan/stream.h> +#include <epan/reassemble.h> +#include <epan/crc16.h> + +#include "packet-srp.h" + +/* Ethereal ID of the protocols */ +static int proto_srp = -1; +static int proto_ccsrl = -1; + +/* The following hf_* variables are used to hold the ethereal IDs of + * our header fields; they are filled out when we call + * proto_register_field_array() in proto_register_srp() + */ +static int hf_srp_header = -1; +static int hf_srp_seqno = -1; +static int hf_srp_crc = -1; +static int hf_srp_crc_bad = -1; +static int hf_ccsrl_ls = -1; + +/* These are the ids of the subtrees that we may be creating */ +static gint ett_srp = -1; +static gint ett_ccsrl = -1; + +static dissector_handle_t data_handle=NULL; +static dissector_handle_t ccsrl_handle=NULL; +static dissector_handle_t h245dg_handle=NULL; + +/*****************************************************************************/ +#define SRP_SRP_COMMAND 249 +#define SRP_SRP_RESPONSE 251 +#define SRP_NSRP_RESPONSE 247 + +static const value_string srp_frame_types[] = { + {SRP_SRP_COMMAND, "SRP command"}, + {SRP_SRP_RESPONSE, "SRP response"}, + {SRP_NSRP_RESPONSE, "NSRP response"}, + {0,NULL} +}; + +static const value_string ccsrl_ls_vals[] = { + {0xFF, "Yes"}, + {0x00, "No"}, + {0,NULL} +}; + +/*****************************************************************************/ + +static void dissect_ccsrl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + proto_item *ccsrl_item; + proto_tree *ccsrl_tree=NULL; + guint8 lastseg = tvb_get_guint8(tvb,0); + tvbuff_t *next_tvb; + + /* add the 'ccsrl' tree to the main tree */ + if (tree) { + ccsrl_item = proto_tree_add_item (tree, proto_ccsrl, tvb, 0, -1, FALSE); + ccsrl_tree = proto_item_add_subtree (ccsrl_item, ett_ccsrl); + proto_tree_add_uint(ccsrl_tree,hf_ccsrl_ls,tvb,0,1,lastseg); + } + + /* XXX add support for reassembly of fragments */ + + /* XXX currently, we always dissect as H245. It's not necessarily + that though. + */ + next_tvb = tvb_new_subset(tvb, 1, -1, -1 ); + call_dissector( h245dg_handle, next_tvb, pinfo, ccsrl_tree ); +} + +static void dissect_srp_command(tvbuff_t * tvb, packet_info * pinfo, proto_tree * srp_tree) +{ + tvbuff_t *next_tvb; + guint payload_len; + + if( srp_tree ) + proto_tree_add_item(srp_tree,hf_srp_seqno,tvb,1,1,FALSE); + + payload_len = tvb_reported_length_remaining(tvb,4); + next_tvb = tvb_new_subset(tvb, 2, payload_len, payload_len ); + + /* XXX currently, we always dissect as CCSRL. It's only that in + * H324/Annex C though. + */ + call_dissector(ccsrl_handle, next_tvb, pinfo, srp_tree ); +} + +static void dissect_srp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + proto_item *srp_item = NULL; + proto_tree *srp_tree = NULL; + + guint8 header = tvb_get_guint8(tvb,0); + + /* add the 'srp' tree to the main tree */ + if (tree) { + srp_item = proto_tree_add_item (tree, proto_srp, tvb, 0, -1, FALSE); + srp_tree = proto_item_add_subtree (srp_item, ett_srp); + proto_tree_add_uint(srp_tree,hf_srp_header,tvb,0,1,header); + } + + switch( header ) { + case SRP_SRP_COMMAND: + dissect_srp_command(tvb,pinfo,srp_tree); + break; + + case SRP_SRP_RESPONSE: + break; + + case SRP_NSRP_RESPONSE: + if( srp_tree ) + proto_tree_add_item(srp_tree,hf_srp_seqno,tvb,1,1,FALSE); + break; + + default: + break; + } + + if( srp_tree ) { + guint16 crc, calc_crc; + guint crc_offset = tvb_reported_length(tvb)-2; + crc = tvb_get_letohs(tvb,-2); + + /* crc includes the header */ + calc_crc = crc16_ccitt_tvb(tvb,crc_offset); + + if( crc == calc_crc ) { + proto_tree_add_uint_format(srp_tree, hf_srp_crc, tvb, + crc_offset, 2, crc, + "CRC: 0x%04x (correct)", crc); + } else { + proto_tree_add_boolean_hidden(srp_tree, hf_srp_crc_bad, tvb, + crc_offset, 2, TRUE); + proto_tree_add_uint_format(srp_tree, hf_srp_crc, tvb, + crc_offset, 2, crc, + "CRC: 0x%04x (incorrect, should be 0x%04x)", + crc, + calc_crc); + } + } + +} + +void proto_register_ccsrl (void) +{ + static hf_register_info hf[] = { + { &hf_ccsrl_ls, + { "Last Segment","ccsrl.ls",FT_UINT8, BASE_HEX, ccsrl_ls_vals, 0x0, + "Last segment indicator", HFILL}}, + }; + + static gint *ett[] = { + &ett_ccsrl, + }; + + if (proto_ccsrl == -1) { /* execute protocol initialization only once */ + proto_ccsrl = + proto_register_protocol ("H.324/CCSRL", "CCSRL", "ccsrl"); + + proto_register_field_array (proto_ccsrl, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + register_dissector("ccsrl", dissect_ccsrl, proto_ccsrl); + } +} + +void proto_register_srp (void) +{ + static hf_register_info hf[] = { + {&hf_srp_header, + { "Header", "srp.header", FT_UINT8, BASE_DEC, srp_frame_types, 0x0, + "SRP header octet", HFILL }}, + {&hf_srp_seqno, + { "Sequence Number", "srp.seqno", FT_UINT8, BASE_DEC, NULL, 0x0, + "Sequence Number", HFILL }}, + {&hf_srp_crc, + { "CRC", "srp.crc", FT_UINT16, BASE_HEX, NULL, 0x0, + "CRC", HFILL }}, + { &hf_srp_crc_bad, + { "Bad CRC","srp.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + }; + + static gint *ett[] = { + &ett_srp, + }; + + if (proto_srp == -1) { /* execute protocol initialization only once */ + proto_srp = + proto_register_protocol ("H.324/SRP", "SRP", "srp"); + + proto_register_field_array (proto_srp, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + register_dissector("srp", dissect_srp, proto_srp); + + /* register our init routine to be called at the start of a capture, + to clear out our hash tables etc */ + // register_init_routine(&srp_init_protocol); + + } +} + + +void proto_reg_handoff_srp(void) { + data_handle = find_dissector("data"); + ccsrl_handle = find_dissector("ccsrl"); + h245dg_handle = find_dissector("h245dg"); +} --- plugins/h223/packet-srp.h 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/packet-srp.h 2004-05-18 16:10:49.000000000 +0100 @@ -0,0 +1,33 @@ +/* $Id: packet-srp.h,v 1.1 2004/05/18 15:10:49 richardv Exp $ + * + * H.324/SRP dissection + * + * 2004 Richard van der Hoff <richardv@xxxxxxxxxxxxx> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_SRP_H__ +#define __PACKET_SRP_H__ + +void proto_register_srp (void); +void proto_register_ccsrl (void); +void proto_reg_handoff_srp(void); + +#endif /* __PACKET_SRP_H__ */
--- configure.in 2005-09-29 16:07:01.958062392 +0100 +++ configure.in 2005-09-29 17:30:06.807250128 +0100 @@ -1,4 +1,4 @@ -# $Id: configure.in,v 1.1.1.9 2005/09/29 13:18:51 jeff Exp $ +# $Id: configure.in,v 1.9 2005/09/29 15:51:24 jeff Exp $ # AC_INIT(cfile.h) @@ -1238,6 +1238,7 @@ plugins/enttec/Makefile plugins/giop/Makefile plugins/gryphon/Makefile + plugins/h223/Makefile plugins/irda/Makefile plugins/lwres/Makefile plugins/mate/Makefile --- plugins/h223/AUTHORS 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/AUTHORS 2004-04-15 15:07:43.000000000 +0100 @@ -0,0 +1,4 @@ +Author : +Richard van der Hoff <richardv@xxxxxxxxxxxxx> + + --- plugins/h223/ChangeLog 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/ChangeLog 2004-04-15 15:07:43.000000000 +0100 @@ -0,0 +1,5 @@ +2004-04-14 Richard van der Hoff <richardv@xxxxxxxxxxxxx> + + * initial version + + --- plugins/h223/COPYING 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/COPYING 2004-04-15 15:07:43.000000000 +0100 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. --- plugins/h223/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/Makefile.am 2004-05-24 12:38:55.000000000 +0100 @@ -0,0 +1,52 @@ +# Makefile.am +# Automake file for Ethereal/H223 +# +# $Id: Makefile.am,v 1.3 2004/05/24 11:38:55 richardv Exp $ +# +# Ethereal - Network traffic analyzer +# By Gerald Combs <gerald@xxxxxxxxxxxx> +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +INCLUDES = -I$(top_srcdir) + +plugindir = @plugindir@ + +plugin_LTLIBRARIES = h223.la +h223_la_SOURCES = \ + golay.h \ + golay.c \ + moduleinfo.h \ + packet-h223.c \ + packet-h223.h \ + packet-srp.c \ + packet-srp.h \ + plugin.c + +h223_la_LDFLAGS = -module -avoid-version + +# Libs must be cleared, or else libtool won't create a shared module. +# If your module needs to be linked against any particular libraries, +# add them here. +LIBS = + +CLEANFILES = \ + h223 \ + *~ + +EXTRA_DIST = \ + Makefile.nmake --- plugins/h223/Makefile.nmake 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/Makefile.nmake 2004-05-24 12:38:55.000000000 +0100 @@ -0,0 +1,21 @@ +# +# $Id: Makefile.nmake,v 1.4 2004/05/24 11:38:55 richardv Exp $ +# + +include ..\..\config.nmake + +############### no need to modify below this line ######### + +CFLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \ + /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS) + +OBJECTS=packet-h223.obj packet-srp.obj plugin.obj golay.obj + +h223.dll h223.exp h223.lib : $(OBJECTS) ..\plugin_api.obj + link -dll /out:h223.dll $(OBJECTS) ..\plugin_api.obj \ + $(GLIB_LIBS) + +clean: + rm -f $(OBJECTS) h223.dll h223.exp h223.lib $(PDB_FILE) + +distclean: clean --- plugins/h223/moduleinfo.h 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/moduleinfo.h 2004-04-15 15:07:43.000000000 +0100 @@ -0,0 +1,18 @@ +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "h223" + + +#ifdef VERSION +#undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.0.1" + + --- plugins/h223/plugin.c 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/plugin.c 2005-07-05 06:28:02.000000000 +0100 @@ -0,0 +1,51 @@ +/* $Id: plugin.c,v 1.2 2005/07/05 05:28:02 richardv Exp $ + * + * Routines for H.223 packet dissection + * Copyright (c) 2005 MX Telecom Ltd <richardv@xxxxxxxxxxxxx> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gmodule.h> +#include <glib.h> +#include "moduleinfo.h" + +#include "packet-h223.h" +#include "packet-srp.h" + +#ifndef ENABLE_STATIC +G_MODULE_EXPORT const gchar version[] = VERSION; + +G_MODULE_EXPORT void plugin_register(void) +{ + /* register the new protocol, protocol fields, and subtrees */ + proto_register_h223(); + proto_register_srp(); + proto_register_ccsrl(); +} + +G_MODULE_EXPORT void plugin_reg_handoff(void){ + proto_reg_handoff_h223(); + proto_reg_handoff_srp(); +} +#endif --- plugins/Makefile.am 2005-09-29 16:07:20.009318184 +0100 +++ plugins/Makefile.am 2005-09-29 17:30:21.047085344 +0100 @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.1.1.6 2005/09/29 13:18:56 jeff Exp $ +# $Id: Makefile.am,v 1.7 2005/09/29 15:51:26 jeff Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -31,6 +31,7 @@ enttec \ giop \ gryphon \ + h223 \ irda \ lwres \ mate \ --- plugins/Makefile.nmake 2005-09-29 16:07:20.050311952 +0100 +++ plugins/Makefile.nmake 2005-09-29 17:30:21.061083216 +0100 @@ -1,5 +1,5 @@ # -# $Id: Makefile.nmake,v 1.1.1.6 2005/09/29 13:18:56 jeff Exp $ +# $Id: Makefile.nmake,v 1.7 2005/09/29 15:51:26 jeff Exp $ # include ..\config.nmake @@ -77,6 +77,11 @@ $(MAKE) /$(MAKEFLAGS) -f Makefile.nmake cd .. +h223:: + cd h223 + $(MAKE) /$(MAKEFLAGS) -f Makefile.nmake + cd .. + irda:: cd irda $(MAKE) /$(MAKEFLAGS) -f Makefile.nmake
--- plugins/h223/golay.c 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/golay.c 2004-05-24 12:38:55.000000000 +0100 @@ -0,0 +1,257 @@ +/* $Id: golay.c,v 1.2 2004/05/24 11:38:55 richardv Exp $ + * + * Provides routines for encoding and decoding the extended Golay + * (24,12,8) code. + * + * This implementation will detect up to 4 errors in a codeword (without + * being able to correct them); it will correct up to 3 errors. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <glib.h> +#include "golay.h" + + +/* Encoding matrix, H + + These entries are formed from the matrix specified in H.223/B.3.2.1.3; + it's first transposed so we have: + + [P1 ] [111110010010] [MC1 ] + [P2 ] [011111001001] [MC2 ] + [P3 ] [110001110110] [MC3 ] + [P4 ] [011000111011] [MC4 ] + [P5 ] [110010001111] [MPL1] + [P6 ] = [100111010101] [MPL2] + [P7 ] [101101111000] [MPL3] + [P8 ] [010110111100] [MPL4] + [P9 ] [001011011110] [MPL5] + [P10] [000101101111] [MPL6] + [P11] [111100100101] [MPL7] + [P12] [101011100011] [MPL8] + + So according to the equation, P1 = MC1+MC2+MC3+MC4+MPL1+MPL4+MPL7 + + Looking down the first column, we see that if MC1 is set, we toggle bits + 1,3,5,6,7,11,12 of the parity: in binary, 110001110101 = 0xE3A + + Similarly, to calculate the inverse, we read across the top of the table and + see that P1 is affected by bits MC1,MC2,MC3,MC4,MPL1,MPL4,MPL7: in binary, + 111110010010 = 0x49F. + + I've seen cunning implementations of this which only use one table. That + technique doesn't seem to work with these numbers though. +*/ + +static const guint golay_encode_matrix[12] = { + 0xC75, + 0x49F, + 0xD4B, + 0x6E3, + 0x9B3, + 0xB66, + 0xECC, + 0x1ED, + 0x3DA, + 0x7B4, + 0xB1D, + 0xE3A, +}; + +static const guint golay_decode_matrix[12] = { + 0x49F, + 0x93E, + 0x6E3, + 0xDC6, + 0xF13, + 0xAB9, + 0x1ED, + 0x3DA, + 0x7B4, + 0xF68, + 0xA4F, + 0xC75, +}; + + + +/* Function to compute the Hamming weight of a 12-bit integer */ +static guint weight12(guint vector) +{ + guint w=0; + guint i; + for( i=0; i<12; i++ ) + if( vector & 1<<i ) + w++; + return w; +} + +/* returns the golay coding of the given 12-bit word */ +static guint golay_coding(guint w) +{ + guint out=0; + guint i; + + for( i = 0; i<12; i++ ) { + if( w & 1<<i ) + out ^= golay_encode_matrix[i]; + } + return out; +} + +/* encodes a 12-bit word to a 24-bit codeword */ +guint32 golay_encode(guint w) +{ + return ((guint32)w) | ((guint32)golay_coding(w))<<12; +} + + + +/* returns the golay coding of the given 12-bit word */ +static guint golay_decoding(guint w) +{ + guint out=0; + guint i; + + for( i = 0; i<12; i++ ) { + if( w & 1<<(i) ) + out ^= golay_decode_matrix[i]; + } + return out; +} + + +/* return a mask showing the bits which are in error in a received + * 24-bit codeword, or -1 if 4 errors were detected. + */ +gint32 golay_errors(guint32 codeword) +{ + guint received_data, received_parity; + guint syndrome; + guint w,i; + guint inv_syndrome = 0; + + received_parity = (guint)(codeword>>12); + received_data = (guint)codeword & 0xfff; + + /* We use the C notation ^ for XOR to represent addition modulo 2. + * + * Model the received codeword (r) as the transmitted codeword (u) + * plus an error vector (e). + * + * r = e ^ u + * + * Then we calculate a syndrome (s): + * + * s = r * H, where H = [ P ], where I12 is the identity matrix + * [ I12 ] + * + * (In other words, we calculate the parity check for the received + * data bits, and add them to the received parity bits) + */ + + syndrome = received_parity ^ (golay_coding(received_data)); + w = weight12(syndrome); + + /* + * The properties of the golay code are such that the Hamming distance (ie, + * the minimum distance between codewords) is 8; that means that one bit of + * error in the data bits will cause 7 errors in the parity bits. + * + * In particular, if we find 3 or fewer errors in the parity bits, either: + * - there are no errors in the data bits, or + * - there are at least 5 errors in the data bits + * we hope for the former (we don't profess to deal with the + * latter). + */ + if( w <= 3 ) { + return ((gint32) syndrome)<<12; + } + + /* the next thing to try is one error in the data bits. + * we try each bit in turn and see if an error in that bit would have given + * us anything like the parity bits we got. At this point, we tolerate two + * errors in the parity bits, but three or more errors would give a total + * error weight of 4 or more, which means it's actually uncorrectable or + * closer to another codeword. */ + + for( i = 0; i<12; i++ ) { + guint error = 1<<i; + guint coding_error = golay_encode_matrix[i]; + if( weight12(syndrome^coding_error) <= 2 ) { + return (gint32)((((guint32)(syndrome^coding_error))<<12) | (guint32)error) ; + } + } + + /* okay then, let's see whether the parity bits are error free, and all the + * errors are in the data bits. model this as follows: + * + * [r | pr] = [u | pu] + [e | 0] + * + * pr = pu + * pu = H * u => u = H' * pu = H' * pr , where H' is inverse of H + * + * we already have s = H*r + pr, so pr = s - H*r = s ^ H*r + * e = u ^ r + * = (H' * ( s ^ H*r )) ^ r + * = H'*s ^ r ^ r + * = H'*s + * + * Once again, we accept up to three error bits... + */ + + inv_syndrome = golay_decoding(syndrome); + w = weight12(inv_syndrome); + if( w <=3 ) { + return (gint32)inv_syndrome; + } + + /* Final shot: try with 2 errors in the data bits, and 1 in the parity + * bits; as before we try each of the bits in the parity in turn */ + for( i = 0; i<12; i++ ) { + guint error = 1<<i; + guint coding_error = golay_decode_matrix[i]; + if( weight12(inv_syndrome^coding_error) <= 2 ) { + guint32 error_word = ((guint32)(inv_syndrome^coding_error)) | ((guint32)error)<<12; + return (gint32)error_word; + } + } + + /* uncorrectable error */ + return -1; +} + + + +/* decode a received codeword. Up to 3 errors are corrected for; 4 + errors are detected as uncorrectable (return -1); 5 or more errors + cause an incorrect correction. +*/ +gint golay_decode(guint32 w) +{ + guint data = (guint)w & 0xfff; + gint32 errors = golay_errors(w); + guint data_errors; + + if( errors == -1 ) + return -1; + data_errors = (guint)errors & 0xfff; + return (gint)(data ^ data_errors); +} --- plugins/h223/golay.h 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/golay.h 2004-05-24 12:38:55.000000000 +0100 @@ -0,0 +1,49 @@ +/* $Id: golay.h,v 1.1 2004/05/24 11:38:55 richardv Exp $ + * + * Provides routines for encoding and decoding the extended Golay + * (24,12,8) code. + * + * This implementation will detect up to 4 errors in a codeword (without + * being able to correct them); it will correct up to 3 errors. + * + * We use guint32s to hold the 24-bit codewords, with the data part in + * the bottom 12 bits and the parity in bits 12-23. + * + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __GOLAY_H__ +#define __GOLAY_H__ + +/* encodes a 12-bit word to a 24-bit codeword + */ +guint32 golay_encode(guint w); + +/* return a mask showing the bits which are in error in a received + * 24-bit codeword, or -1 if 4 errors were detected. + */ +gint32 golay_errors(guint32 codeword); + +/* decode a received codeword. Up to 3 errors are corrected for; 4 + errors are detected as uncorrectable (return -1); 5 or more errors + cause an incorrect correction. +*/ +gint golay_decode(guint32 w); + +#endif
--- epan/address.h 2005-09-29 16:07:07.482222592 +0100 +++ epan/address.h 2005-09-29 17:30:11.279570232 +0100 @@ -2,7 +2,7 @@ * Definitions for structures storing addresses, and for the type of * variables holding port-type values * - * $Id: address.h,v 1.1.1.4 2005/09/29 13:18:52 jeff Exp $ + * $Id: address.h,v 1.5 2005/09/29 15:51:24 jeff Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> @@ -126,7 +126,8 @@ CT_ISDN, /* ISDN channel number */ CT_X25, /* X.25 logical channel number */ CT_ISUP, /* ISDN User Part CIC */ - CT_IAX2 /* IAX2 call id */ + CT_IAX2, /* IAX2 call id */ + CT_H223 /* H.223 logical channel number */ /* Could also have ATM VPI/VCI pairs */ } circuit_type; --- plugins/h223/packet-h223.c 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/packet-h223.c 2005-09-30 11:46:09.459807328 +0100 @@ -0,0 +1,1423 @@ +/* packet-h223.c + * Routines for H.223 packet dissection + * Copyright (c) 2004-5 MX Telecom Ltd <richardv@xxxxxxxxxxxxx> + * + * $Id: packet-h223.c,v 1.34 2005/09/30 10:40:16 jeff Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <execinfo.h> + +#include <gmodule.h> +#include <glib.h> +#include <epan/emem.h> +#include <epan/bitswap.h> +#include <epan/circuit.h> +#include <epan/conversation.h> +#include <epan/packet.h> +#include <epan/stream.h> +#include <epan/reassemble.h> +#include <epan/iax2_codec_type.h> +#include <epan/dissectors/packet-frame.h> +#include <epan/dissectors/packet-h245.h> + +#include "packet-h223.h" +#include "golay.h" + +#include <string.h> + +#define PROTO_TAG_H223 "H223" + +/* Ethereal ID of the H.223 protocol */ +static int proto_h223 = -1; + +/* The following hf_* variables are used to hold the ethereal IDs of + * our header fields; they are filled out when we call + * proto_register_field_array() in proto_register_h223() + */ +static int hf_h223_non_h223_data = -1; +static int hf_h223_mux_stuffing_pdu = -1; +static int hf_h223_mux_pdu = -1; +static int hf_h223_mux_header = -1; +static int hf_h223_mux_rawhdr = -1; +static int hf_h223_mux_correctedhdr = -1; +static int hf_h223_mux_mc = -1; +static int hf_h223_mux_mpl = -1; +static int hf_h223_mux_deact = -1; +static int hf_h223_mux_vc = -1; +static int hf_h223_mux_extra = -1; +static int hf_h223_mux_hdlc2 = -1; +static int hf_h223_mux_fragments = -1; +static int hf_h223_mux_fragment = -1; +static int hf_h223_mux_fragment_overlap = -1; +static int hf_h223_mux_fragment_overlap_conflict = -1; +static int hf_h223_mux_fragment_multiple_tails = -1; +static int hf_h223_mux_fragment_too_long_fragment = -1; +static int hf_h223_mux_fragment_error = -1; +static int hf_h223_mux_reassembled_in = -1; + +static int hf_h223_al_fragments = -1; +static int hf_h223_al_fragment = -1; +static int hf_h223_al_fragment_overlap = -1; +static int hf_h223_al_fragment_overlap_conflict = -1; +static int hf_h223_al_fragment_multiple_tails = -1; +static int hf_h223_al_fragment_too_long_fragment = -1; +static int hf_h223_al_fragment_error = -1; +static int hf_h223_al_reassembled_in = -1; + +static int hf_h223_al1 = -1; +static int hf_h223_al1_framed = -1; +static int hf_h223_al2 = -1; +static int hf_h223_al2_sequenced = -1; +static int hf_h223_al2_seqno = -1; +static int hf_h223_al2_crc = -1; +static int hf_h223_al2_crc_bad = -1; + +static int hf_h223_al_payload = -1; + +/* These are the ids of the subtrees that we may be creating */ +static gint ett_h223 = -1; +static gint ett_h223_non_h223_data = -1; +static gint ett_h223_mux_stuffing_pdu = -1; +static gint ett_h223_mux_pdu = -1; +static gint ett_h223_mux_header = -1; +static gint ett_h223_mux_deact = -1; +static gint ett_h223_mux_vc = -1; +static gint ett_h223_mux_extra = -1; +static gint ett_h223_mux_fragments = -1; +static gint ett_h223_mux_fragment = -1; +static gint ett_h223_al_fragments = -1; +static gint ett_h223_al_fragment = -1; +static gint ett_h223_al1 = -1; +static gint ett_h223_al2 = -1; +static gint ett_h223_al_payload = -1; + +/* These are the handles of our subdissectors */ +static dissector_handle_t data_handle=NULL; +static dissector_handle_t srp_handle=NULL; +static dissector_handle_t h245dg_handle=NULL; + +static const fragment_items h223_mux_frag_items = { + &ett_h223_mux_fragment, + &ett_h223_mux_fragments, + &hf_h223_mux_fragments, + &hf_h223_mux_fragment, + &hf_h223_mux_fragment_overlap, + &hf_h223_mux_fragment_overlap_conflict, + &hf_h223_mux_fragment_multiple_tails, + &hf_h223_mux_fragment_too_long_fragment, + &hf_h223_mux_fragment_error, + &hf_h223_mux_reassembled_in, + "fragments" +}; + +static const fragment_items h223_al_frag_items = { + &ett_h223_al_fragment, + &ett_h223_al_fragments, + &hf_h223_al_fragments, + &hf_h223_al_fragment, + &hf_h223_al_fragment_overlap, + &hf_h223_al_fragment_overlap_conflict, + &hf_h223_al_fragment_multiple_tails, + &hf_h223_al_fragment_too_long_fragment, + &hf_h223_al_fragment_error, + &hf_h223_al_reassembled_in, + "fragments" +}; + +static guint32 pdu_offset; // offset of the last pdu to start being dissected in the last packet to start being dissected + +/*************************************************************************** + * + * virtual circuit number handling + * + * we have to be able to manage more than one H.223 call at a time, + * so have a hash which maps {call,vc} to an integer. + */ + +typedef struct _h223_call_info h223_call_info; + +typedef struct { + const h223_call_info* call; /* h223 call */ + guint32 vc; /* child circuit */ +} circuit_chain_key; + +static GHashTable *circuit_chain_hashtable = NULL; +static guint circuit_chain_count = 1; + +/* Hash Functions */ +static gint circuit_chain_equal(gconstpointer v, gconstpointer w) +{ + const circuit_chain_key *v1 = (const circuit_chain_key *)v; + const circuit_chain_key *v2 = (const circuit_chain_key *)w; + gint result; + result = ( v1->call == v2->call && + v1->vc == v2 -> vc ); + return result;; +} + +static guint circuit_chain_hash (gconstpointer v) +{ + const circuit_chain_key *key = (const circuit_chain_key *)v; + guint hash_val = ((guint32)(key->call))^(((guint32)key->vc) << 16); + return hash_val; +} + +static guint32 circuit_chain_lookup(const h223_call_info* call_info, + guint32 child_vc) +{ + circuit_chain_key key, *new_key; + guint32 circuit_id; + key.call = call_info; + key.vc = child_vc; + circuit_id = GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable, &key )); + if( circuit_id == 0 ) { + new_key = se_alloc(sizeof(circuit_chain_key)); + *new_key = key; + circuit_id = ++circuit_chain_count; + g_hash_table_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id)); + } + return circuit_id; +} + +static void circuit_chain_init(void) +{ + if (circuit_chain_hashtable) + g_hash_table_destroy(circuit_chain_hashtable); + circuit_chain_hashtable = g_hash_table_new(circuit_chain_hash, circuit_chain_equal); + circuit_chain_count = 1; +} + + +/*************************************************************************** + * + * Call information management + * + */ + +/* we keep information on each call in an h223_call_info structure + * + * We attach the h223_call_info structures to individual calls with + * circuit_add_proto_data(). +*/ + +typedef struct _h223_mux_element_listitem h223_mux_element_listitem; +struct _h223_mux_element_listitem { + h223_mux_element *me; + guint32 first_frame; + guint32 pdu_offset; + h223_mux_element_listitem *next; +}; + +/* we have this information for each stream */ +typedef struct { + gboolean current_pdu_header_parsed; + + guint32 current_pdu_minlen; + guint32 current_pdu_read; + + guint32 header_buf; + guint32 tail_buf; + + gboolean first_pdu; + + h223_mux_element_listitem* mux_table[16]; +} h223_call_direction_data; + + +struct _h223_call_info { + /* H.223 specifies that the least-significant bit is transmitted first; + however this is at odds with IAX which transmits the MSB first, so + in general, all of our bytes are reversed. */ + gboolean bitswapped; + + /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols + specified in the annexes + */ + int h223_level; + + /* for H.223 streams over TCP (as opposed to IAX), this + stores the source address and port of the first packet spotted, + so that we can differentiate directions. + */ + address srcaddress; + guint32 srcport; + + h223_call_direction_data direction_data[2]; +}; + +typedef struct _h223_lc_params_listitem h223_lc_params_listitem; +struct _h223_lc_params_listitem +{ + h223_lc_params *lc_params; + guint32 first_frame; + guint32 last_frame; + h223_lc_params_listitem *next; +}; + +typedef struct { + h223_lc_params_listitem *lc_params[2]; + h223_call_info *call_info; +} h223_vc_info; + +static void add_h223_mux_element(h223_call_direction_data *direct, guint8 mc, h223_mux_element *me, guint32 framenum) +{ + h223_mux_element_listitem *li = se_alloc(sizeof(h223_mux_element_listitem)); + h223_mux_element_listitem **old_li_ptr = &(direct->mux_table[mc]); + h223_mux_element_listitem *old_li = *old_li_ptr; + if( !old_li ) { + direct->mux_table[mc] = li; + } else { + while( old_li->next ) { + old_li_ptr = &(old_li->next); + old_li = *old_li_ptr; + } + if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset) ) + return; + else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset ) + *old_li_ptr = li; // replace the tail of the list with the new item, since + // a single h223 pdu has just set the same MC twice.. + else + old_li->next = li; + } + li->first_frame = framenum; + li->pdu_offset = pdu_offset; + li->next = 0; + li->me = me; +} + +static h223_mux_element* find_h223_mux_element(h223_call_direction_data* direct, guint8 mc, guint32 framenum) +{ + h223_mux_element_listitem* li = direct->mux_table[mc]; + while( li && li->next && li->next->first_frame < framenum ) + li = li->next; + while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pdu_offset ) + li = li->next; + if( li ) { + return li->me; + } else { + return NULL; + } +} + +static void add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, guint32 framenum ) +{ + h223_lc_params_listitem *li = se_alloc(sizeof(h223_lc_params_listitem)); + h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction]); + h223_lc_params_listitem *old_li = *old_li_ptr; + if( !old_li ) { + vc_info->lc_params[direction] = li; + } else { + while( old_li->next ) { + old_li_ptr = &(old_li->next); + old_li = *old_li_ptr; + } + if( framenum < old_li->first_frame ) + return; + else if( framenum == old_li->first_frame ) + *old_li_ptr = li; + else { + old_li->next = li; + old_li->last_frame = framenum - 1; + } + } + li->first_frame = framenum; + li->last_frame = 0; + li->next = 0; + li->lc_params = lc_params; +} + +static h223_lc_params* find_h223_lc_params(h223_vc_info* vc_info, int direction, guint32 framenum) +{ + h223_lc_params_listitem* li = vc_info->lc_params[direction]; + while( li && li->next && li->next->first_frame <= framenum ) + li = li->next; + if( li ) + return li->lc_params; + else + return NULL; +} + +static void init_direction_data(h223_call_direction_data *direct) +{ + int i; + + direct -> first_pdu = TRUE; + + for ( i = 0; i < 16; ++i ) + direct->mux_table[i] = NULL; + + /* set up MC 0 to contain just VC 0 */ + h223_mux_element *mc0_element = se_alloc(sizeof(h223_mux_element)); + add_h223_mux_element( direct, 0, mc0_element, 0 ); + mc0_element->sublist = NULL; + mc0_element->vc = 0; + mc0_element->repeat_count = 0; /* until closing flag */ + mc0_element->next = NULL; +} + +static h223_vc_info* h223_vc_info_new( h223_call_info* call_info ) +{ + h223_vc_info *vc_info = se_alloc(sizeof(h223_vc_info)); + vc_info->lc_params[0] = vc_info->lc_params[1] = NULL; + vc_info->call_info = call_info; + return vc_info; +} + +static void init_logical_channel( packet_info* pinfo, h223_call_info* call_info, int vc, int direction, h223_lc_params* params ) +{ + guint32 circuit_id = circuit_chain_lookup(call_info, vc); + circuit_t *subcircuit; + h223_vc_info *vc_info; + subcircuit = find_circuit( CT_H223, circuit_id, pinfo->fd->num ); + + if( subcircuit == NULL ) { + subcircuit = circuit_new( CT_H223, circuit_id, pinfo->fd->num ); + vc_info = h223_vc_info_new( call_info ); + circuit_add_proto_data( subcircuit, proto_h223, vc_info ); + } else { + vc_info = circuit_get_proto_data( subcircuit, proto_h223 ); + } + add_h223_lc_params( vc_info, direction, params, pinfo->fd->num ); +} + +static void init_control_channels( packet_info* pinfo, h223_call_info* call_info ) +{ + h223_lc_params *vc0_params = se_alloc(sizeof(h223_lc_params)); + vc0_params->al_type = al1Framed; + vc0_params->al_params = NULL; + vc0_params->segmentable = TRUE; + vc0_params->subdissector = srp_handle; + init_logical_channel( pinfo, call_info, 0, P2P_DIR_SENT, vc0_params ); + init_logical_channel( pinfo, call_info, 0, P2P_DIR_RECV, vc0_params ); +} + +static h223_call_info *find_or_create_call_info ( packet_info * pinfo ) +{ + circuit_t *circ; + conversation_t *conv = NULL; + h223_call_info *data; + + // look for a circuit (eg, IAX call) first + circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num ); + if( circ == NULL ) { + // assume we're running atop TCP; use the converstion support + conv = find_conversation( pinfo->fd->num, + &pinfo->src,&pinfo->dst, + pinfo->ptype, + pinfo->srcport,pinfo->destport, 0 ); + if( conv == NULL ) { + conv = conversation_new( pinfo->fd->num, + &pinfo->src,&pinfo->dst, + pinfo->ptype, + pinfo->srcport,pinfo->destport, 0 ); + } + + } + + if( circ ) + data = (h223_call_info *)circuit_get_proto_data(circ, proto_h223); + else + data = (h223_call_info *)conversation_get_proto_data(conv, proto_h223); + + if( data == NULL ) { + data = se_alloc(sizeof(h223_call_info)); + + if( circ ) { + circuit_add_proto_data(circ, proto_h223, data); + + /* circuit-switched H.223 conversations are bitswapped */ + data -> bitswapped = TRUE; + } else { + conversation_add_proto_data(conv, proto_h223, data); + /* add the source details so we can distinguish directions + * in future */ + COPY_ADDRESS(&(data -> srcaddress), &(pinfo->src)); + data -> srcport = pinfo->srcport; + + /* packet-switched H.223 conversations are NOT bitswapped */ + data -> bitswapped = FALSE; + } + + /* initialise the call info */ + init_direction_data(&data -> direction_data[0]); + init_direction_data(&data -> direction_data[1]); + + /* FIXME shouldn't this be figured out dynamically? */ + data -> h223_level = 2; + + init_control_channels( pinfo, data ); + } + + /* work out what direction we're really going in */ + if( circ ) { + if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1) + pinfo->p2p_dir = P2P_DIR_SENT; + } else { + if( ADDRESSES_EQUAL( &(pinfo->src), &(data->srcaddress)) + && pinfo->srcport == data->srcport ) + pinfo->p2p_dir = P2P_DIR_SENT; + else + pinfo->p2p_dir = P2P_DIR_RECV; + } + + return data; +} + +void h223_set_mc( packet_info* pinfo, guint8 mc, h223_mux_element* me ) +{ + circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num ); + h223_vc_info* vc_info; + g_assert( circ ); + vc_info = circuit_get_proto_data(circ, proto_h223); + add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir]), mc, me, pinfo->fd->num ); +} + +void h223_add_lc( packet_info* pinfo, guint16 lc, h223_lc_params* params ) +{ + circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num ); + h223_vc_info* vc_info; + g_assert( circ ); + vc_info = circuit_get_proto_data(circ, proto_h223); + init_logical_channel( pinfo, vc_info->call_info, lc, pinfo->p2p_dir, params ); +} + +/************************************************************************************ + * + * AL-PDU dissection + */ + +char crctable[256] = { + 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, + 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, + 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, + 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, + 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, + 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, + 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, + 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, + 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, + 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, + 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, + 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, + 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, + 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, + 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, + 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf }; + +static guint8 h223_al2_crc8bit( tvbuff_t *tvb ) { + guint32 len = tvb_reported_length(tvb) - 1; + const guint8* data = tvb_get_ptr( tvb, 0, len ); + unsigned char crc = 0; + guint32 pos = 0; + while ( len-- ) + crc = crctable[crc^data[pos++]]; + return crc; +} + +static void dissect_mux_al_pdu( tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *vc_tree, +// circuit_t* vc_circuit, + h223_lc_params* lc_params ) +{ + proto_tree *al_tree = NULL; + proto_item *al_item; + proto_tree *al_subtree; + proto_item *al_subitem = NULL; + tvbuff_t *next_tvb = NULL; + dissector_handle_t subdissector = lc_params->subdissector; + guint32 len = tvb_reported_length(tvb); + gboolean all_done = FALSE; + + guint8 calc_checksum; + guint8 real_checksum; + gboolean al2_sequenced; + + switch( lc_params->al_type ) { + case al1Framed: + case al1NotFramed: + al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)", + (lc_params->al_type==al1Framed)?"":"not "); + al_tree = proto_item_add_subtree (al_item, ett_h223_al1); + if(lc_params->al_type == al1Framed) + proto_tree_add_boolean_hidden(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE ); + next_tvb = tvb; + break; + case al2WithoutSequenceNumbers: + case al2WithSequenceNumbers: + if( lc_params->al_type == al2WithoutSequenceNumbers ) { + next_tvb = tvb_new_subset( tvb, 0, len-1, len-1 ); + al2_sequenced = FALSE; + } else { + next_tvb = tvb_new_subset( tvb, 1, len-2, len-2 ); + al2_sequenced = TRUE; + } + + al_item = proto_tree_add_none_format(vc_tree, hf_h223_al2, tvb, 0, -1, "H223 AL2 (with%s sequence numbers)", + al2_sequenced?"":"out" ); + al_tree = proto_item_add_subtree (al_item, ett_h223_al2); + + if( al2_sequenced ) { + proto_tree_add_boolean_hidden(al_tree, hf_h223_al2_sequenced, tvb, 0, 1, TRUE ); + proto_tree_add_uint_format(al_tree, hf_h223_al2_seqno, tvb, 0, 1, tvb_get_guint8( tvb, 0 ), + "Sequence number: %u", tvb_get_guint8( tvb, 0 ) ); + } + + calc_checksum = h223_al2_crc8bit(tvb); + real_checksum = tvb_get_guint8(tvb, len - 1); + if( calc_checksum == real_checksum ) { + al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE); + proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum, + "CRC: 0x%02x (correct)", real_checksum ); + } else { + call_dissector(data_handle, tvb, pinfo, al_tree); + proto_tree_add_boolean_hidden( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE ); + proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum, + "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum ); + all_done = TRUE; + } + break; + default: + break; + } + + if (!subdissector) + subdissector = data_handle; + + if(next_tvb && al_tree && !al_subitem && !all_done) + al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE); + + if(next_tvb && al_subitem && !all_done) { + al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload); + call_dissector(subdissector, next_tvb, pinfo, al_subtree); + } else if ( !all_done ) + call_dissector(data_handle, tvb, pinfo, vc_tree); +} + +/************************************************************************************ + * + * MUX-PDU dissection + */ + + +/* dissect a fragment of a MUX-PDU which belongs to a particular VC + * + * tvb buffer containing the whole MUX-PDU + * offset offset within the MUX-PDU of this fragment + * pinfo info on the packet containing the last fragment of the MUX-PDU + * pkt_offset offset within that packet of the start of the final fragment of + * the MUX_PDU + * pdu_tree dissection tree for the PDU; a single item will be added (with + * its own subtree) + * vc VC for this SDU + * frag_len length of the MUX-SDU fragment + * end_of_mux_sdu true if this is a segmentable VC and this is the last + * fragment in an SDU + */ +static void dissect_mux_sdu_fragment(tvbuff_t *tvb, guint32 offset, + packet_info *pinfo, + guint32 pkt_offset, + proto_tree *pdu_tree, + h223_call_info* call_info, + guint16 vc, gint frag_len, gboolean end_of_mux_sdu) +{ + /* update the circuit details before passing to a subdissector */ + guint32 orig_circuit = pinfo->circuit_id; + guint32 orig_ctype = pinfo->ctype; + pinfo->circuit_id=circuit_chain_lookup(call_info, vc); + pinfo->ctype=CT_H223; + + TRY { + tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len); + circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num); + dissector_handle_t subdissector = NULL; + proto_tree *vc_tree = NULL; + proto_item *vc_item; + h223_vc_info *vc_info = NULL; + h223_lc_params *lc_params = NULL; + gboolean stuffing = ( vc == 0 && frag_len == 0 ); + + if(pdu_tree && !stuffing) { + vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, frag_len, vc); + vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc); + } + + if( stuffing ) { + next_tvb = NULL; + subdissector = data_handle; + } else if( subcircuit == NULL ) { + g_message( "Frame %d: no subcircuit id %d found for circuit %d id %d, vc %d", pinfo->fd->num, + pinfo->circuit_id, orig_ctype, orig_circuit, vc ); + subdissector = data_handle; + } else { + vc_info = circuit_get_proto_data(subcircuit, proto_h223); + if( vc_info != NULL ) { + lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num ); + } + if( lc_params == NULL ) { + subdissector = data_handle; + } else { + if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) { + stream_t *substream; + stream_pdu_fragment_t *frag; + + substream = find_stream_circ(subcircuit,pinfo->p2p_dir); + if(substream == NULL ) + substream = stream_new_circ(subcircuit,pinfo->p2p_dir); + frag = stream_find_frag(substream,pinfo->fd->num,offset+pkt_offset); + if(frag == NULL ) { + frag = stream_add_frag(substream,pinfo->fd->num,offset+pkt_offset, + next_tvb,pinfo,!end_of_mux_sdu); + } + next_tvb = stream_process_reassembled( + next_tvb, 0, pinfo, + "Reassembled H.223 AL-PDU", + frag, &h223_al_frag_items, + NULL, vc_tree); + } + } + } + + if(next_tvb) { + if(lc_params) + dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params ); + else + call_dissector(subdissector,next_tvb,pinfo,vc_tree); + } + } + + /* restore the original circuit details for future PDUs */ + FINALLY { + pinfo->ctype=orig_ctype; + pinfo->circuit_id=orig_circuit; + } + ENDTRY; +} + +static guint32 mux_element_sublist_size( h223_mux_element* me ) +{ + h223_mux_element *current_me = me; + guint32 length = 0; + while ( current_me ) { + current_me = current_me->next; + if ( current_me->sublist ) + length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist ); + else + length += current_me->repeat_count; + } + if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */ + DISSECTOR_ASSERT_NOT_REACHED(); + length = 1; + } + return length; +} + +static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset, proto_tree *pdu_tree, + h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu ) +{ + guint32 len = tvb_reported_length(tvb); + guint32 frag_len; + guint32 sublist_len; + int i; + while ( me ) { + if ( me->sublist ) { + if ( me->repeat_count == 0 ) { + for(sublist_len = mux_element_sublist_size( me->sublist ); + offset + sublist_len <= len; + offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, + call_info, me->sublist, offset, endOfMuxSdu ) ); + } else { + for(i = 0; i < me->repeat_count; ++i) + offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, + call_info, me->sublist, offset, endOfMuxSdu ); + } + } else { + if ( me->repeat_count == 0 ) + frag_len = len - offset; + else + frag_len = me->repeat_count; + dissect_mux_sdu_fragment( tvb, offset, pinfo, pkt_offset, pdu_tree, + call_info, me->vc, frag_len, (offset+frag_len==len) && endOfMuxSdu); + offset += frag_len; + } + me = me->next; + } + return offset; +} + +/* dissect the payload of a MUX-PDU */ +static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset, proto_tree *pdu_tree, + h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu ) +{ + guint32 len = tvb_reported_length(tvb); + + h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir]), mc, pinfo->fd->num ); + + if( me ) { + dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu ); + } else { + /* no entry found in mux-table. ignore packet and dissect as data */ + proto_tree *vc_tree = NULL; + + if(pdu_tree) { + proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE); + vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact); + } + call_dissector(data_handle,tvb,pinfo,vc_tree); + } +} + +/* dissect a reassembled mux-pdu + * + * tvb buffer containing mux-pdu, including header and closing flag + * pinfo packet info for packet containing the end of the mux-pdu + * pkt_offset offset within that packet of the start of the last fragment + * h223_tree dissection tree for h223 protocol; a single item will be added + * (with a sub-tree) + * call_info h223 info structure for this h223 call + * pdu_no index of this pdu within the call + */ +static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo, + guint32 pkt_offset, + proto_tree *h223_tree, + h223_call_info *call_info) +{ + guint32 offset = 0; + /* actual (as opposed to reported) payload len */ + guint32 len; + guint32 raw_hdr = 0, correct_hdr = 0; + gint32 errors = 0; + guint16 closing_flag = 0; + guint8 mc = 0; + guint8 mpl = 0; + gboolean end_of_mux_sdu = FALSE; + tvbuff_t *pdu_tvb; + + proto_item *pdu_item = NULL; + proto_tree *pdu_tree = NULL; + + switch(call_info->h223_level) { + case 0: case 1: + raw_hdr = tvb_get_guint8(tvb,0); + mc = (guint8)((raw_hdr>>1) & 0xf); + end_of_mux_sdu = raw_hdr & 1; + offset++; + /* closing flag is one byte long for h223 level 0, two for level 1 */ + len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1); + + /* XXX should ignore pdus with incorrect HECs */ + break; + + case 2: + raw_hdr = tvb_get_letoh24(tvb,0); + errors = golay_errors(raw_hdr); + correct_hdr = ((errors == -1) ? raw_hdr : raw_hdr ^ (guint32)errors); + + mc = (guint8)(correct_hdr & 0xf); + mpl = (guint8)((correct_hdr >> 4) & 0xff); + + offset += 3; + len = tvb_length_remaining(tvb,offset)-2; + closing_flag = tvb_get_ntohs(tvb,offset+len); + end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF)); + break; + + case 3: + /* XXX not implemented */ + default: + len=0; + DISSECTOR_ASSERT_NOT_REACHED(); + } + + + if( h223_tree ) { + if( mpl == 0 ) { + pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE); + pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu); + } else { + pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE); + pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu); + } + } + + if( pdu_tree ) { + proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE); + proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header); + + switch(call_info->h223_level) { + case 0: case 1: + proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc); + break; + + case 2: + if( errors == -1 ) { + proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb, + 0, 3, raw_hdr, + "Raw value: 0x%06x (uncorrectable errors)", raw_hdr ); + } else if( errors == 0 ) { + proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb, + 0, 3, raw_hdr, + "Raw value: 0x%06x (correct)", raw_hdr ); + } else { + proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb, + 0, 3, raw_hdr, + "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors ); + } + item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3, + correct_hdr); + PROTO_ITEM_SET_GENERATED(item); + + proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc); + proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl); + break; + + case 3: + /* XXX not implemented */ + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + } + + pdu_tvb = tvb_new_subset(tvb, offset, len, mpl); + dissect_mux_payload(pdu_tvb,pinfo,offset+pkt_offset,pdu_tree,call_info,mc,end_of_mux_sdu); + offset += mpl; + + /* any extra data in the PDU, beyond that indictated by the mpl, is + dissected as data. */ + len -= mpl; + if( len > 0 ) { + tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len); + proto_tree *vc_tree = NULL; + + if( pdu_tree ) { + proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE); + vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact); + } + call_dissector(data_handle,next_tvb,pinfo,vc_tree); + + offset += len; + } + + /* add the closing HDLC flag */ + if( pdu_tree ) + proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE); +} + + +/************************************************************************************ + * + * MUX-PDU delineation and defragmentation + */ + +/* attempt to parse the header of a mux pdu */ +static void attempt_mux_level0_header_parse(h223_call_direction_data *dirdata) +{ + /* level 0 isn't byte-aligned, so is a complete pain to implement */ + DISSECTOR_ASSERT_NOT_REACHED(); + dirdata = dirdata; +} + +static void attempt_mux_level1_header_parse(h223_call_direction_data *dirdata) +{ + guint32 hdr; + + if(dirdata->current_pdu_read != 2) + return; + + hdr = dirdata->header_buf & 0xffff; + /* don't interpret a repeated hdlc as a header */ + if(hdr == 0xE14D) + return; + + /* + 1 byte of header and 2 bytes of closing HDLC */ + dirdata -> current_pdu_minlen = (guint8)((hdr >> 12) & 0xff) + 3; + dirdata -> current_pdu_header_parsed = TRUE; +} + +static void attempt_mux_level2_3_header_parse(h223_call_direction_data *dirdata) +{ + guint32 hdr; + gint32 errors; + + if(dirdata->current_pdu_read != 3) + return; + + /* + 3 bytes of header and 2 bytes of closing HDLC */ + dirdata -> current_pdu_minlen = 5; + + hdr = dirdata->header_buf; + hdr = + ((hdr & 0xFF0000) >> 16) | + (hdr & 0x00FF00) | + ((hdr & 0x0000FF) << 16); + + errors = golay_errors(hdr); + if(errors != -1) { + hdr ^= errors; + dirdata -> current_pdu_minlen += ((hdr >> 4) & 0xff); + } + + dirdata -> current_pdu_header_parsed = TRUE; +} + +static void (* const attempt_mux_header_parse[])(h223_call_direction_data *dirdata) = { + attempt_mux_level0_header_parse, + attempt_mux_level1_header_parse, + attempt_mux_level2_3_header_parse, + attempt_mux_level2_3_header_parse +}; + +static gboolean h223_mux_check_hdlc(int h223_level, h223_call_direction_data *dirdata) +{ + guint32 masked; + + switch(h223_level) { + case 0: + /* level 0 isn't byte-aligned, so is a complete pain to implement */ + DISSECTOR_ASSERT_NOT_REACHED(); + return FALSE; + break; + + case 1: + masked = dirdata->tail_buf & 0xffff; + return masked == 0xE14D; + + case 2: case 3: + masked = dirdata->tail_buf & 0xffff; + return masked == 0xE14D || masked == (0xE14D ^ 0xFFFF); + + default: + DISSECTOR_ASSERT_NOT_REACHED(); + return FALSE; + } +} + +/* read a pdu (or the end of a pdu) from the tvb, and dissect it + * + * returns an offset to the next byte + * + * *pdu_found is set TRUE if a pdu was found, or FALSE if we reached the + * end of the tvb without completing one. + */ + +static guint32 dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo, + guint32* pkt_offset, + proto_tree *tree, + proto_tree **h223_tree_p, + h223_call_info *call_info, + gboolean *pdu_found) +{ + proto_item *h223_item = NULL; + proto_tree *volatile h223_tree = *h223_tree_p; + tvbuff_t *volatile next_tvb; + volatile guint32 offset = start_offset; + gboolean more_frags = TRUE; + h223_call_direction_data *dirdata = &call_info -> direction_data[pinfo->p2p_dir]; + + dirdata -> current_pdu_read = 0; + dirdata -> current_pdu_minlen = 0; + dirdata -> current_pdu_header_parsed = FALSE; + + while( more_frags && offset < tvb_reported_length( tvb )) { + guint8 byte = tvb_get_guint8(tvb, offset++); + dirdata -> current_pdu_read++; + + /* read a byte into the header buf, if necessary */ + if(dirdata -> current_pdu_read <= 4) { + dirdata -> header_buf <<= 8; + dirdata -> header_buf |= byte; + } + + /* read the byte into the tail buf */ + dirdata -> tail_buf <<= 8; + dirdata -> tail_buf |= byte; + + /* if we haven't parsed the header yet, attempt to do so now */ + if(!dirdata -> current_pdu_header_parsed) + /* this sets current_pdu_header parsed if current_pdu_read == 3 */ + (attempt_mux_header_parse[call_info->h223_level])(dirdata); + + if(dirdata -> current_pdu_read >= dirdata -> current_pdu_minlen) { + if(h223_mux_check_hdlc(call_info->h223_level,dirdata)) { + dirdata -> current_pdu_minlen = 0; + dirdata -> current_pdu_read = 0; + dirdata -> current_pdu_header_parsed = FALSE; + more_frags = FALSE; + } + } + } + + if( more_frags ) { + /* offset = tvb_reported length now */ + pinfo->desegment_offset = offset - dirdata->current_pdu_read; + if(dirdata->current_pdu_read > dirdata->current_pdu_minlen) + pinfo->desegment_len = 1; + else + pinfo->desegment_len = dirdata->current_pdu_minlen - dirdata->current_pdu_read; + return offset; + } + + if(!*h223_tree_p) { + /* add the 'h223' tree to the main tree */ + if (tree) { + h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, FALSE); + h223_tree = proto_item_add_subtree (h223_item, ett_h223); + *h223_tree_p = h223_tree; + } + } + *pdu_found = TRUE; + + /* create a tvb for the fragment */ + next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset, + offset-start_offset); + + + *pkt_offset += tvb_reported_length( next_tvb ); + + /* the first PDU isn't real H.223 data. */ + if( dirdata->first_pdu ) { + dirdata->first_pdu = FALSE; + proto_tree *pdu_tree = NULL; + if( h223_tree ) { + proto_item *pdu_item = proto_tree_add_item (h223_tree, hf_h223_non_h223_data, tvb, 0, -1, FALSE); + pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_non_h223_data); + } + call_dissector(data_handle,tvb, pinfo, pdu_tree); + return offset; + } + + /* we catch boundserrors on the pdu so that errors on an + * individual pdu don't screw up the whole of the rest of the + * stream */ + pdu_offset = *pkt_offset - tvb_reported_length( next_tvb ); + TRY { + dissect_mux_pdu( next_tvb, pinfo, *pkt_offset - tvb_reported_length( next_tvb ), h223_tree, call_info); + } + + CATCH2(BoundsError,ReportedBoundsError) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_str(pinfo->cinfo, COL_INFO, + "[Malformed Packet]"); + proto_tree_add_protocol_format(h223_tree, proto_malformed, + tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto); + } + + ENDTRY; + + return offset; +} + +/************************************************************************************ + * + * main dissector entry point + */ + +static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + proto_tree *h223_tree = NULL; + h223_call_info *call_info = NULL; + guint32 offset = 0; + + /* pkt_offset becomes different from offset if we reassemble a pdu: + * + * before: offset = a, pkt_offset = b + * offset = dissect_h223_mux_pdu_fragment(ending fragment, offset, &pkt_offset) + * after: offset = a + sizeof(ending frament), pkt_offset = b + sizeof(reassembled pdu) + * + * This lets us get a value "pkt_offset + offset_into_pdu" which will never decrease + * as we walk through a packet + */ + guint32 pkt_offset = 0; + gboolean pdu_found = FALSE; + + if (check_col (pinfo->cinfo, COL_INFO)) + col_clear (pinfo->cinfo, COL_INFO); + + + /* find or create the call_info for this call */ + call_info = find_or_create_call_info(pinfo); + + /* we may need to reverse the bit ordering before we go any further. */ + if( call_info -> bitswapped ) { + tvbuff_t *reversed_tvb; + guint8 *data; + guint len; + guint i; + + len = tvb_length(tvb); + data = g_malloc(len); + for( i=0; i<len; i++) + data[i]=BIT_SWAP(tvb_get_guint8(tvb,i)); + + + reversed_tvb = tvb_new_real_data(data,len,tvb_reported_length(tvb)); + + /* + * Add the reversed tvbuff to the list of tvbuffs to which + * the tvbuff we were handed refers, so it'll get + * cleaned up when that tvbuff is cleaned up. + */ + tvb_set_child_real_data_tvbuff(tvb, reversed_tvb); + + + /* Add a freer */ + tvb_set_free_cb(reversed_tvb, g_free); + + /* Add the reversed data to the data source list. */ + add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" ); + + tvb = reversed_tvb; + } + + while( offset < tvb_reported_length( tvb )) { + gboolean pdu_found_this_fragment = FALSE; + offset = dissect_mux_pdu_fragment( tvb, offset, pinfo, &pkt_offset, tree, + &h223_tree, call_info, + &pdu_found_this_fragment ); + if( pdu_found_this_fragment ) + pdu_found = TRUE; + } + + if( !pdu_found && check_col (pinfo->cinfo, COL_INFO)) + col_set_str (pinfo->cinfo, COL_INFO, "(No complete PDUs)"); + + /* set up the protocol and info fields in the summary pane */ + if (check_col (pinfo->cinfo, COL_PROTOCOL)) + col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223); +} + +static void h223_init_protocol (void) +{ + circuit_chain_init(); +} + + +void proto_register_h223 (void) +{ + /* A header field is something you can search/filter on. + * + * We create a structure to register our fields. It consists of an + * array of hf_register_info structures, each of which are of the format + * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. + */ + + static hf_register_info hf[] = { + { &hf_h223_non_h223_data, + { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0, + "Initial data in stream, not a PDU", HFILL }}, + + { &hf_h223_mux_stuffing_pdu, + { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0, + "Empty PDU used for stuffing when no data available", HFILL }}, + + { &hf_h223_mux_pdu, + { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 MUX-PDU", HFILL }}, + + { &hf_h223_mux_header, + { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 MUX header", HFILL }}, + + { &hf_h223_mux_rawhdr, + { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0, + "Raw header bytes", HFILL }}, + + { &hf_h223_mux_correctedhdr, + { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0, + "Corrected header bytes", HFILL }}, + + { &hf_h223_mux_mc, + { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0, + "H.223 MUX multiplex code", HFILL }}, + + { &hf_h223_mux_mpl, + { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0, + "H.223 MUX multiplex Payload Length", HFILL }}, + + { &hf_h223_mux_deact, + { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0, + "mpl refers to an entry in the multiplex table which is not active", HFILL }}, + + { &hf_h223_mux_vc, + { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0, + "H.223 Virtual Circuit", HFILL }}, + + { &hf_h223_mux_extra, + { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_DEC, NULL, 0x0, + "data beyond mpl", HFILL }}, + + { &hf_h223_mux_hdlc2, + { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0, + "framing flag", HFILL }}, + + /* fields for h.223-mux fragments */ + { &hf_h223_mux_fragment_overlap, + { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Fragment overlaps with other fragments", HFILL }}, + + { &hf_h223_mux_fragment_overlap_conflict, + { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Overlapping fragments contained conflicting data", HFILL }}, + + { &hf_h223_mux_fragment_multiple_tails, + { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Several tails were found when defragmenting the packet", HFILL }}, + + { &hf_h223_mux_fragment_too_long_fragment, + { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Fragment contained data past end of packet", HFILL }}, + + { &hf_h223_mux_fragment_error, + { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Defragmentation error due to illegal fragments", HFILL }}, + + { &hf_h223_mux_fragment, + { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "H.223 MUX-PDU Fragment", HFILL }}, + + { &hf_h223_mux_fragments, + { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 MUX-PDU Fragments", HFILL }}, + + { &hf_h223_mux_reassembled_in, + { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }}, + + /* fields for h.223-al fragments */ + { &hf_h223_al_fragment_overlap, + { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Fragment overlaps with other fragments", HFILL }}, + + { &hf_h223_al_fragment_overlap_conflict, + { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Overlapping fragments contained conflicting data", HFILL }}, + + { &hf_h223_al_fragment_multiple_tails, + { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Several tails were found when defragmenting the packet", HFILL }}, + + { &hf_h223_al_fragment_too_long_fragment, + { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Fragment contained data past end of packet", HFILL }}, + + { &hf_h223_al_fragment_error, + { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Defragmentation error due to illegal fragments", HFILL }}, + + { &hf_h223_al_fragment, + { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "H.223 AL-PDU Fragment", HFILL }}, + + { &hf_h223_al_fragments, + { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 AL-PDU Fragments", HFILL }}, + + { &hf_h223_al_reassembled_in, + { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This H.223 AL-PDU packet is reassembled in this frame", HFILL }}, + + /* h223-als */ + + { &hf_h223_al1, + { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 AL-PDU using AL1", HFILL }}, + + { &hf_h223_al1_framed, + { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + { &hf_h223_al2, + { "H.223 AL2", "h223.al2", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 AL-PDU using AL2", HFILL }}, + + { &hf_h223_al2_sequenced, + { "H.223 AL2 sequenced", "h223.al2.sequenced", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + { &hf_h223_al2_seqno, + { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0, + "H.223 AL2 sequence number", HFILL }}, + + { &hf_h223_al2_crc, + { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0, + "CRC", HFILL }}, + + { &hf_h223_al2_crc_bad, + { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + { &hf_h223_al_payload, + { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0, + "H.223 AL-PDU Payload", HFILL }}, + + }; + + static gint *ett[] = { + &ett_h223, + &ett_h223_non_h223_data, + &ett_h223_mux_stuffing_pdu, + &ett_h223_mux_pdu, + &ett_h223_mux_header, + &ett_h223_mux_deact, + &ett_h223_mux_vc, + &ett_h223_mux_extra, + &ett_h223_mux_fragments, + &ett_h223_mux_fragment, + &ett_h223_al_fragments, + &ett_h223_al_fragment, + &ett_h223_al1, + &ett_h223_al2, + &ett_h223_al_payload + }; + + if (proto_h223 == -1) { /* execute protocol initialization only once */ + proto_h223 = + proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223"); + + proto_register_field_array (proto_h223, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + register_dissector("h223", dissect_h223, proto_h223); + + /* register our init routine to be called at the start of a capture, + to clear out our hash tables etc */ + register_init_routine(&h223_init_protocol); + } + + h245_set_h223_set_mc_handle( &h223_set_mc ); + h245_set_h223_add_lc_handle( &h223_add_lc ); +} + +void proto_reg_handoff_h223(void) +{ + dissector_handle_t h223 = find_dissector("h223"); + data_handle = find_dissector("data"); + h245dg_handle = find_dissector("h245dg"); + srp_handle = find_dissector("srp"); + + dissector_add_handle("tcp.port", h223); + dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223); +} +/* vim:set ts=8 et: */ --- plugins/h223/packet-h223.h 1970-01-01 01:00:00.000000000 +0100 +++ plugins/h223/packet-h223.h 2005-08-23 16:57:38.000000000 +0100 @@ -0,0 +1,31 @@ +/* $Id: packet-h223.h,v 1.3 2005/08/23 15:57:38 jeff Exp $ + * + * Routines for H.223 packet dissection + * 2004 Richard van der Hoff <richardv@xxxxxxxxxxxxx> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_H223_H__ +#define __PACKET_H223_H__ + +void proto_register_h223 (void); +void proto_reg_handoff_h223(void); + +#endif /* __PACKET_H223_H__ */
- Prev by Date: Re: [Ethereal-dev] Interest check: state/event graphs?
- Next by Date: [Ethereal-dev] Enhancement
- Previous by thread: Re: [Ethereal-dev] Interest check: state/event graphs?
- Next by thread: [Ethereal-dev] nettl (HP-UX) patch: uid and pduin/pduout
- Index(es):