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__ */