2 * Routines for H.223 packet dissection
3 * Copyright (c) 2004-5 MX Telecom Ltd <richardv@mxtelecom.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/emem.h>
35 #include <epan/bitswap.h>
36 #include <epan/circuit.h>
37 #include <epan/conversation.h>
38 #include <epan/packet.h>
39 #include <epan/stream.h>
40 #include <epan/reassemble.h>
41 #include <epan/iax2_codec_type.h>
42 #include <epan/dissectors/packet-frame.h>
43 #include <epan/dissectors/packet-h245.h>
45 #include "packet-h223.h"
50 /* #define DEBUG_H223 */
52 /* debug the mux-pdu defragmentation code. warning: verbose output! */
53 /* #define DEBUG_H223_FRAGMENTATION */
55 #define PROTO_TAG_H223 "H223"
57 /* Wireshark ID of the H.223 protocol */
58 static int proto_h223 = -1;
59 static int proto_h223_bitswapped = -1;
61 /* The following hf_* variables are used to hold the Wireshark IDs of
62 * our header fields; they are filled out when we call
63 * proto_register_field_array() in proto_register_h223()
65 static int hf_h223_non_h223_data = -1;
66 static int hf_h223_mux_stuffing_pdu = -1;
67 static int hf_h223_mux_pdu = -1;
68 static int hf_h223_mux_header = -1;
69 static int hf_h223_mux_rawhdr = -1;
70 static int hf_h223_mux_correctedhdr = -1;
71 static int hf_h223_mux_mc = -1;
72 static int hf_h223_mux_mpl = -1;
73 static int hf_h223_mux_deact = -1;
74 static int hf_h223_mux_vc = -1;
75 static int hf_h223_mux_extra = -1;
76 static int hf_h223_mux_hdlc2 = -1;
77 static int hf_h223_mux_fragments = -1;
78 static int hf_h223_mux_fragment = -1;
79 static int hf_h223_mux_fragment_overlap = -1;
80 static int hf_h223_mux_fragment_overlap_conflict = -1;
81 static int hf_h223_mux_fragment_multiple_tails = -1;
82 static int hf_h223_mux_fragment_too_long_fragment = -1;
83 static int hf_h223_mux_fragment_error = -1;
84 static int hf_h223_mux_reassembled_in = -1;
86 static int hf_h223_al_fragments = -1;
87 static int hf_h223_al_fragment = -1;
88 static int hf_h223_al_fragment_overlap = -1;
89 static int hf_h223_al_fragment_overlap_conflict = -1;
90 static int hf_h223_al_fragment_multiple_tails = -1;
91 static int hf_h223_al_fragment_too_long_fragment = -1;
92 static int hf_h223_al_fragment_error = -1;
93 static int hf_h223_al_reassembled_in = -1;
95 static int hf_h223_al1 = -1;
96 static int hf_h223_al1_framed = -1;
97 static int hf_h223_al2 = -1;
98 static int hf_h223_al2_sequenced = -1;
99 static int hf_h223_al2_unsequenced = -1;
100 static int hf_h223_al2_seqno = -1;
101 static int hf_h223_al2_crc = -1;
102 static int hf_h223_al2_crc_bad = -1;
104 static int hf_h223_al_payload = -1;
106 /* These are the ids of the subtrees that we may be creating */
107 static gint ett_h223 = -1;
108 static gint ett_h223_non_h223_data = -1;
109 static gint ett_h223_mux_stuffing_pdu = -1;
110 static gint ett_h223_mux_pdu = -1;
111 static gint ett_h223_mux_header = -1;
112 static gint ett_h223_mux_deact = -1;
113 static gint ett_h223_mux_vc = -1;
114 static gint ett_h223_mux_extra = -1;
115 static gint ett_h223_mux_fragments = -1;
116 static gint ett_h223_mux_fragment = -1;
117 static gint ett_h223_al_fragments = -1;
118 static gint ett_h223_al_fragment = -1;
119 static gint ett_h223_al1 = -1;
120 static gint ett_h223_al2 = -1;
121 static gint ett_h223_al_payload = -1;
123 /* These are the handles of our subdissectors */
124 static dissector_handle_t data_handle=NULL;
125 static dissector_handle_t srp_handle=NULL;
126 static dissector_handle_t h245dg_handle=NULL;
128 static const fragment_items h223_mux_frag_items = {
129 &ett_h223_mux_fragment,
130 &ett_h223_mux_fragments,
131 &hf_h223_mux_fragments,
132 &hf_h223_mux_fragment,
133 &hf_h223_mux_fragment_overlap,
134 &hf_h223_mux_fragment_overlap_conflict,
135 &hf_h223_mux_fragment_multiple_tails,
136 &hf_h223_mux_fragment_too_long_fragment,
137 &hf_h223_mux_fragment_error,
138 &hf_h223_mux_reassembled_in,
142 static const fragment_items h223_al_frag_items = {
143 &ett_h223_al_fragment,
144 &ett_h223_al_fragments,
145 &hf_h223_al_fragments,
146 &hf_h223_al_fragment,
147 &hf_h223_al_fragment_overlap,
148 &hf_h223_al_fragment_overlap_conflict,
149 &hf_h223_al_fragment_multiple_tails,
150 &hf_h223_al_fragment_too_long_fragment,
151 &hf_h223_al_fragment_error,
152 &hf_h223_al_reassembled_in,
156 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
157 static guint32 pdu_offset;
159 /***************************************************************************
161 * virtual circuit number handling
163 * we have to be able to manage more than one H.223 call at a time,
164 * so have a hash which maps {call,vc} to an integer.
167 typedef struct _h223_call_info h223_call_info;
170 const h223_call_info* call; /* h223 call */
171 guint32 vc; /* child circuit */
174 static GHashTable *circuit_chain_hashtable = NULL;
175 static guint circuit_chain_count = 1;
178 static gint circuit_chain_equal(gconstpointer v, gconstpointer w)
180 const circuit_chain_key *v1 = (const circuit_chain_key *)v;
181 const circuit_chain_key *v2 = (const circuit_chain_key *)w;
183 result = ( v1->call == v2->call &&
184 v1->vc == v2 -> vc );
188 static guint circuit_chain_hash (gconstpointer v)
190 const circuit_chain_key *key = (const circuit_chain_key *)v;
191 guint hash_val = ((guint32)(key->call))^(((guint32)key->vc) << 16);
195 static guint32 circuit_chain_lookup(const h223_call_info* call_info,
198 circuit_chain_key key, *new_key;
200 key.call = call_info;
202 circuit_id = GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable, &key ));
203 if( circuit_id == 0 ) {
204 new_key = se_alloc(sizeof(circuit_chain_key));
206 circuit_id = ++circuit_chain_count;
207 g_hash_table_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id));
212 static void circuit_chain_init(void)
214 if (circuit_chain_hashtable)
215 g_hash_table_destroy(circuit_chain_hashtable);
216 circuit_chain_hashtable = g_hash_table_new(circuit_chain_hash, circuit_chain_equal);
217 circuit_chain_count = 1;
221 /***************************************************************************
223 * Call information management
227 /* we keep information on each call in an h223_call_info structure
229 * We attach the h223_call_info structures to individual calls with
230 * circuit_add_proto_data().
233 typedef struct _h223_mux_element_listitem h223_mux_element_listitem;
234 struct _h223_mux_element_listitem {
235 h223_mux_element *me;
238 h223_mux_element_listitem *next;
241 /* we have this information for each stream */
243 h223_mux_element_listitem* mux_table[16];
244 } h223_call_direction_data;
247 struct _h223_call_info {
248 /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
249 specified in the annexes
253 /* for H.223 streams over TCP (as opposed to IAX), this
254 stores the source address and port of the first packet spotted,
255 so that we can differentiate directions.
260 h223_call_direction_data direction_data[2];
263 typedef struct _h223_lc_params_listitem h223_lc_params_listitem;
264 struct _h223_lc_params_listitem
266 h223_lc_params *lc_params;
269 h223_lc_params_listitem *next;
273 h223_lc_params_listitem *lc_params[2];
274 h223_call_info *call_info;
277 static void add_h223_mux_element(h223_call_direction_data *direct, guint8 mc, h223_mux_element *me, guint32 framenum)
279 h223_mux_element_listitem *li;
280 h223_mux_element_listitem **old_li_ptr;
281 h223_mux_element_listitem *old_li;
283 DISSECTOR_ASSERT(mc < 16);
285 li = se_alloc(sizeof(h223_mux_element_listitem));
286 old_li_ptr = &(direct->mux_table[mc]);
287 old_li = *old_li_ptr;
289 direct->mux_table[mc] = li;
291 while( old_li->next ) {
292 old_li_ptr = &(old_li->next);
293 old_li = *old_li_ptr;
295 if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset) )
297 else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset )
298 *old_li_ptr = li; /* replace the tail of the list with the new item, since */
299 /* a single h223 pdu has just set the same MC twice.. */
303 li->first_frame = framenum;
304 li->pdu_offset = pdu_offset;
309 static h223_mux_element* find_h223_mux_element(h223_call_direction_data* direct, guint8 mc, guint32 framenum, guint32 pkt_offset)
311 h223_mux_element_listitem* li;
313 DISSECTOR_ASSERT(mc < 16);
315 li = direct->mux_table[mc];
317 while( li && li->next && li->next->first_frame < framenum )
319 while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset )
328 static void add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, guint32 framenum )
330 h223_lc_params_listitem *li = se_alloc(sizeof(h223_lc_params_listitem));
331 h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction ? 0 : 1]);
332 h223_lc_params_listitem *old_li = *old_li_ptr;
334 vc_info->lc_params[direction ? 0 : 1] = li;
336 while( old_li->next ) {
337 old_li_ptr = &(old_li->next);
338 old_li = *old_li_ptr;
340 if( framenum < old_li->first_frame )
342 else if( framenum == old_li->first_frame )
346 old_li->last_frame = framenum - 1;
349 li->first_frame = framenum;
352 li->lc_params = lc_params;
355 static h223_lc_params* find_h223_lc_params(h223_vc_info* vc_info, int direction, guint32 framenum)
357 h223_lc_params_listitem* li = vc_info->lc_params[direction? 0 : 1];
358 while( li && li->next && li->next->first_frame <= framenum )
361 return li->lc_params;
366 static void init_direction_data(h223_call_direction_data *direct)
369 h223_mux_element *mc0_element;
371 for ( i = 0; i < 16; ++i )
372 direct->mux_table[i] = NULL;
374 /* set up MC 0 to contain just VC 0 */
375 mc0_element = se_alloc(sizeof(h223_mux_element));
376 add_h223_mux_element( direct, 0, mc0_element, 0 );
377 mc0_element->sublist = NULL;
379 mc0_element->repeat_count = 0; /* until closing flag */
380 mc0_element->next = NULL;
383 static h223_vc_info* h223_vc_info_new( h223_call_info* call_info )
385 h223_vc_info *vc_info = se_alloc(sizeof(h223_vc_info));
386 vc_info->lc_params[0] = vc_info->lc_params[1] = NULL;
387 vc_info->call_info = call_info;
391 static void init_logical_channel( guint32 start_frame, h223_call_info* call_info, int vc, int direction, h223_lc_params* params )
393 guint32 circuit_id = circuit_chain_lookup(call_info, vc);
394 circuit_t *subcircuit;
395 h223_vc_info *vc_info;
396 subcircuit = find_circuit( CT_H223, circuit_id, start_frame );
398 if( subcircuit == NULL ) {
399 subcircuit = circuit_new( CT_H223, circuit_id, start_frame );
401 g_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc);
403 vc_info = h223_vc_info_new( call_info );
404 circuit_add_proto_data( subcircuit, proto_h223, vc_info );
406 vc_info = circuit_get_proto_data( subcircuit, proto_h223 );
408 add_h223_lc_params( vc_info, direction, params, start_frame );
411 /* create a brand-new h223_call_info structure */
412 static h223_call_info *create_call_info( guint32 start_frame )
414 h223_call_info *data;
415 h223_lc_params *vc0_params;
417 data = se_alloc(sizeof(h223_call_info));
419 /* initialise the call info */
420 init_direction_data(&data -> direction_data[0]);
421 init_direction_data(&data -> direction_data[1]);
423 /* FIXME shouldn't this be figured out dynamically? */
424 data -> h223_level = 2;
426 vc0_params = se_alloc(sizeof(h223_lc_params));
427 vc0_params->al_type = al1Framed;
428 vc0_params->al_params = NULL;
429 vc0_params->segmentable = TRUE;
430 vc0_params->subdissector = srp_handle;
431 init_logical_channel( start_frame, data, 0, P2P_DIR_SENT, vc0_params );
432 init_logical_channel( start_frame, data, 0, P2P_DIR_RECV, vc0_params );
436 /* find or create call_info struct for calls over circuits (eg, IAX) */
437 static h223_call_info *find_or_create_call_info_circ(packet_info * pinfo)
439 h223_call_info *data;
440 circuit_t *circ = NULL;
442 if(pinfo->ctype != CT_NONE)
443 circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
447 data = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
450 data = create_call_info(pinfo->fd->num);
453 g_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
454 pinfo->fd->num, data, circ, pinfo->ctype, pinfo->circuit_id);
456 circuit_add_proto_data(circ, proto_h223, data);
459 /* work out what direction we're really going in */
460 if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1)
461 pinfo->p2p_dir = P2P_DIR_SENT;
466 /* find or create call_info struct for calls over conversations (eg, RTP) */
467 static h223_call_info *find_or_create_call_info_conv(packet_info * pinfo)
469 h223_call_info *data;
470 conversation_t *conv;
472 /* assume we're running atop TCP or RTP; use the conversation support */
473 conv = find_conversation( pinfo->fd->num,
474 &pinfo->src,&pinfo->dst,
476 pinfo->srcport,pinfo->destport, 0 );
478 /* both RTP and TCP track their conversations, so just assert here if
479 * we can't find one */
480 DISSECTOR_ASSERT(conv);
482 data = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
484 if(data == NULL && pinfo->ptype == PT_UDP ) {
485 conversation_t *conv2;
487 /* RTP tracks the two sides of the conversation totally separately;
488 * this messes us up totally.
490 * Look for another converstation, going in the opposite direction.
492 conv2 = find_conversation( pinfo->fd->num,
493 &pinfo->dst,&pinfo->src,
495 pinfo->destport,pinfo->srcport, 0 );
497 data = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
501 g_debug("%u: Identified conv %p as reverse of conv %p with call %p and type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
502 pinfo->fd->num, conv, conv2, data, pinfo->ptype,
503 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
505 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
508 conversation_add_proto_data(conv, proto_h223, data);
512 /* we still haven't found any call data - create a new one for this
515 data = create_call_info(pinfo->fd->num);
518 g_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
519 pinfo->fd->num, data, conv, pinfo->ptype,
520 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
522 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
526 conversation_add_proto_data(conv, proto_h223, data);
527 /* add the source details so we can distinguish directions
529 COPY_ADDRESS(&(data -> srcaddress), &(pinfo->src));
530 data -> srcport = pinfo->srcport;
533 /* work out what direction we're really going in */
534 if( ADDRESSES_EQUAL( &(pinfo->src), &(data->srcaddress))
535 && pinfo->srcport == data->srcport )
536 pinfo->p2p_dir = P2P_DIR_SENT;
538 pinfo->p2p_dir = P2P_DIR_RECV;
543 static h223_call_info *find_or_create_call_info ( packet_info * pinfo )
545 h223_call_info *data;
547 data = find_or_create_call_info_circ(pinfo);
549 data = find_or_create_call_info_conv(pinfo);
553 /* called from the h245 dissector to handle a MultiplexEntrySend message */
554 static void h223_set_mc( packet_info* pinfo, guint8 mc, h223_mux_element* me )
556 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
557 h223_vc_info* vc_info;
559 /* if this h245 pdu packet came from an h223 circuit, add the details on
560 * the new mux entry */
562 vc_info = circuit_get_proto_data(circ, proto_h223);
563 add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, me, pinfo->fd->num );
567 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
568 static void h223_add_lc( packet_info* pinfo, guint16 lc, h223_lc_params* params )
570 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
571 h223_vc_info* vc_info;
573 /* if this h245 pdu packet came from an h223 circuit, add the details on
576 vc_info = circuit_get_proto_data(circ, proto_h223);
577 init_logical_channel( pinfo->fd->num, vc_info->call_info, lc, pinfo->p2p_dir, params );
581 /************************************************************************************
586 const guint8 crctable[256] = {
587 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
588 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
589 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
590 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
591 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
592 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
593 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
594 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
595 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
596 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
597 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
598 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
599 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
600 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
601 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
602 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
604 static guint8 h223_al2_crc8bit( tvbuff_t *tvb ) {
605 guint32 len = tvb_reported_length(tvb) - 1;
606 const guint8* data = tvb_get_ptr( tvb, 0, len );
607 unsigned char crc = 0;
609 DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
611 crc = crctable[crc^data[pos++]];
615 static void dissect_mux_al_pdu( tvbuff_t *tvb,
618 /* circuit_t* vc_circuit, */
619 h223_lc_params* lc_params )
621 proto_tree *al_tree = NULL;
623 proto_tree *al_subtree;
624 proto_item *al_subitem = NULL;
625 proto_item *tmp_item;
626 tvbuff_t *next_tvb = NULL;
627 dissector_handle_t subdissector = lc_params->subdissector;
628 guint32 len = tvb_reported_length(tvb);
630 guint8 calc_checksum;
631 guint8 real_checksum;
632 gboolean al2_sequenced = FALSE;
635 switch( lc_params->al_type ) {
638 al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)",
639 (lc_params->al_type==al1Framed)?"":"not ");
640 al_tree = proto_item_add_subtree (al_item, ett_h223_al1);
641 if(lc_params->al_type == al1Framed)
642 proto_tree_add_boolean_hidden(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
644 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
647 case al2WithSequenceNumbers:
648 al2_sequenced = TRUE;
650 case al2WithoutSequenceNumbers:
651 tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
653 al_item = proto_tree_add_item(vc_tree,
654 al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
656 al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
658 PROTO_ITEM_SET_GENERATED(tmp_item);
660 /* check minimum payload length */
661 if(len < (al2_sequenced?2U:1U))
665 if( al2_sequenced ) {
666 proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
670 next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
671 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
673 calc_checksum = h223_al2_crc8bit(tvb);
674 real_checksum = tvb_get_guint8(tvb, len - 1);
676 if( calc_checksum == real_checksum ) {
677 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
678 "CRC: 0x%02x (correct)", real_checksum );
680 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
681 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
682 tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
683 PROTO_ITEM_SET_GENERATED(tmp_item);
685 /* don't pass pdus which fail checksums on to the subdissector */
686 subdissector = data_handle;
690 call_dissector(data_handle, tvb, pinfo, vc_tree);
695 subdissector = data_handle;
697 al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
698 call_dissector(subdissector, next_tvb, pinfo, al_subtree);
701 /************************************************************************************
707 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
709 * tvb buffer containing the MUX-PDU fragment
710 * pinfo info on the packet containing the last fragment of the MUX-PDU
711 * pkt_offset offset within the block from the superdissector where the
712 * fragment starts (must increase monotonically for constant pinfo->fd->num)
713 * pdu_tree dissection tree for the PDU; a single item will be added (with
716 * end_of_mux_sdu true if this is a segmentable VC and this is the last
719 static void dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb,
722 proto_tree *pdu_tree,
723 h223_call_info* call_info,
724 guint16 vc, gboolean end_of_mux_sdu)
726 /* update the circuit details before passing to a subdissector */
727 guint32 orig_circuit = pinfo->circuit_id;
728 guint32 orig_ctype = pinfo->ctype;
729 pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
730 pinfo->ctype=CT_H223;
733 circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
734 proto_tree *vc_tree = NULL;
736 h223_vc_info *vc_info = NULL;
737 h223_lc_params *lc_params = NULL;
740 vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
741 vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
744 if( subcircuit == NULL ) {
745 g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
746 pinfo->circuit_id, call_info, vc );
748 vc_info = circuit_get_proto_data(subcircuit, proto_h223);
749 if( vc_info != NULL ) {
750 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
755 if( lc_params != NULL ) {
756 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
758 stream_pdu_fragment_t *frag;
760 substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
761 if(substream == NULL )
762 substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
763 frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
767 g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
768 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
770 frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
771 next_tvb,pinfo,!end_of_mux_sdu);
774 g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
775 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
779 next_tvb = stream_process_reassembled(
781 "Reassembled H.223 AL-PDU",
782 frag, &h223_al_frag_items,
787 /* fudge to pass pkt_offset down to add_h223_mux_element,
788 * should it be called */
789 pdu_offset = pkt_offset;
790 dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
793 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
797 /* restore the original circuit details for future PDUs */
799 pinfo->ctype=orig_ctype;
800 pinfo->circuit_id=orig_circuit;
805 static guint32 mux_element_sublist_size( h223_mux_element* me )
807 h223_mux_element *current_me = me;
809 while ( current_me ) {
810 current_me = current_me->next;
811 if ( current_me->sublist )
812 length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
814 length += current_me->repeat_count;
816 if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
817 DISSECTOR_ASSERT_NOT_REACHED();
823 /* dissect part of a MUX-PDU payload according to a multiplex list
825 * tvb buffer containing entire mux-pdu payload
826 * pinfo info on the packet containing the last fragment of the MUX-PDU
827 * pkt_offset offset within the block from the superdissector where the
828 * MUX-PDU starts (must increase monotonically for constant
830 * pdu_tree dissection tree for the PDU
831 * call_info data structure for h223 call
833 * offset offset within tvb to start work
834 * endOfMuxSdu true if the end-of-sdu flag was set
836 static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
837 proto_tree *pdu_tree,
838 h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu )
840 guint32 len = tvb_reported_length(tvb);
846 if ( me->repeat_count == 0 ) {
847 for(sublist_len = mux_element_sublist_size( me->sublist );
848 offset + sublist_len <= len;
849 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
850 call_info, me->sublist, offset, endOfMuxSdu ) );
852 for(i = 0; i < me->repeat_count; ++i)
853 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
854 call_info, me->sublist, offset, endOfMuxSdu );
857 if ( me->repeat_count == 0 )
858 frag_len = len - offset;
860 frag_len = me->repeat_count;
863 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
864 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
865 call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
874 /* dissect the payload of a MUX-PDU
876 * tvb buffer containing entire mux-pdu payload
877 * pinfo info on the packet containing the last fragment of the MUX-PDU
878 * pkt_offset offset within the block from the superdissector where the
879 * MUX-PDU starts (must increase monotonically for constant
881 * pdu_tree dissection tree for the PDU
882 * call_info data structure for h223 call
883 * mc multiplex code for this PDU
884 * endOfMuxSdu true if the end-of-sdu flag was set
886 static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
887 proto_tree *pdu_tree,
888 h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu )
890 guint32 len = tvb_reported_length(tvb);
892 h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
895 dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
897 /* no entry found in mux-table. ignore packet and dissect as data */
898 proto_tree *vc_tree = NULL;
901 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
902 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
904 call_dissector(data_handle,tvb,pinfo,vc_tree);
908 /* dissect a reassembled mux-pdu
910 * tvb buffer containing mux-pdu, including header and closing flag
911 * pinfo packet info for packet containing the end of the mux-pdu
912 * pkt_offset offset within the block from the superdissector where the
913 * MUX-PDU starts (must increase monotonically for constant
915 * h223_tree dissection tree for h223 protocol; a single item will be added
917 * call_info h223 info structure for this h223 call
918 * pdu_no index of this pdu within the call
920 static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo,
922 proto_tree *h223_tree,
923 h223_call_info *call_info)
926 /* actual (as opposed to reported) payload len */
928 guint32 raw_hdr = 0, correct_hdr = 0;
930 guint16 closing_flag = 0;
933 gboolean end_of_mux_sdu = FALSE;
936 proto_item *pdu_item = NULL;
937 proto_tree *pdu_tree = NULL;
939 #ifdef DEBUG_H223_FRAGMENTATION
940 g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
941 pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
944 switch(call_info->h223_level) {
946 raw_hdr = tvb_get_guint8(tvb,0);
947 mc = (guint8)((raw_hdr>>1) & 0xf);
948 end_of_mux_sdu = raw_hdr & 1;
950 /* closing flag is one byte long for h223 level 0, two for level 1 */
951 len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
953 /* XXX should ignore pdus with incorrect HECs */
957 raw_hdr = tvb_get_letoh24(tvb,0);
958 errors = golay_errors(raw_hdr);
960 len = tvb_length_remaining(tvb,offset)-2;
963 correct_hdr = raw_hdr ^ (guint32)errors;
965 mc = (guint8)(correct_hdr & 0xf);
966 mpl = (guint8)((correct_hdr >> 4) & 0xff);
968 /* we should never have been called if there's not enough data in
970 DISSECTOR_ASSERT(len >= mpl);
972 closing_flag = tvb_get_ntohs(tvb,offset+len);
973 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
981 /* XXX not implemented */
984 DISSECTOR_ASSERT_NOT_REACHED();
990 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
991 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
993 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
994 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
999 proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
1000 proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1002 switch(call_info->h223_level) {
1004 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1008 if( errors == -1 ) {
1009 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1011 "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1014 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1016 "Raw value: 0x%06x (correct)", raw_hdr );
1018 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1020 "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1022 item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1024 PROTO_ITEM_SET_GENERATED(item);
1025 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1026 proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1031 /* XXX not implemented */
1033 DISSECTOR_ASSERT_NOT_REACHED();
1038 pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1040 dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1042 call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1047 /* any extra data in the PDU, beyond that indictated by the mpl, is
1048 dissected as data. */
1051 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1052 proto_tree *vc_tree = NULL;
1055 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1056 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1058 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1063 /* add the closing HDLC flag */
1065 proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1069 /************************************************************************************
1071 * MUX-PDU delineation and defragmentation
1074 /* attempt to parse the header of a mux pdu */
1075 static gboolean attempt_mux_level0_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1077 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1078 DISSECTOR_ASSERT_NOT_REACHED();
1085 static gboolean attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1087 /* this is untested */
1088 DISSECTOR_ASSERT_NOT_REACHED();
1094 /* don't interpret a repeated hdlc as a header */
1098 /* + 1 byte of header and 2 bytes of closing HDLC */
1099 *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1103 static gboolean attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1110 /* + 3 bytes of header and 2 bytes of closing HDLC */
1113 /* bah, we get the header in the wrong order */
1115 ((hdr & 0xFF0000) >> 16) |
1117 ((hdr & 0x0000FF) << 16);
1119 errors = golay_errors(hdr);
1122 *minlen += ((hdr >> 4) & 0xff);
1128 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1129 attempt_mux_level0_header_parse,
1130 attempt_mux_level1_header_parse,
1131 attempt_mux_level2_3_header_parse,
1132 attempt_mux_level2_3_header_parse
1135 static gboolean h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1139 switch(h223_level) {
1141 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1142 DISSECTOR_ASSERT_NOT_REACHED();
1147 masked = tail_buf & 0xffff;
1148 return nbytes >= 2 && masked == 0xE14D;
1151 masked = tail_buf & 0xffff;
1152 return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1155 DISSECTOR_ASSERT_NOT_REACHED();
1160 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1162 * returns the number of bytes processed, or the negative of the number of
1163 * extra bytes needed, or zero if we don't know yet
1166 static gint dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo,
1167 proto_tree *h223_tree,
1168 h223_call_info *call_info)
1170 tvbuff_t *volatile next_tvb;
1171 volatile guint32 offset = start_offset;
1172 gboolean more_frags = TRUE;
1174 gboolean header_parsed = FALSE;
1175 guint32 header_buf = 0, tail_buf = 0;
1176 guint32 pdu_minlen = 0;
1179 #ifdef DEBUG_H223_FRAGMENTATION
1180 g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1181 pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1184 while( more_frags && offset < tvb_reported_length( tvb )) {
1185 guint8 byte = tvb_get_guint8(tvb, offset++);
1187 /* read a byte into the header buf, if necessary */
1188 if((offset-start_offset) <= 4) {
1193 /* read the byte into the tail buf */
1197 /* if we haven't parsed the header yet, attempt to do so now */
1199 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1200 header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1201 (offset-start_offset,header_buf,&pdu_minlen);
1203 /* if we have successfully parsed the header, we have sufficient data,
1204 * and we have found the closing hdlc, we are done here */
1205 if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1206 if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1213 if(pdu_minlen <= (offset-start_offset)) {
1214 /* we haven't found the closing hdlc yet, but we don't know how
1215 * much more we need */
1216 #ifdef DEBUG_H223_FRAGMENTATION
1217 g_debug("\tBailing, requesting more bytes");
1221 guint32 needed = pdu_minlen-(offset-start_offset);
1222 #ifdef DEBUG_H223_FRAGMENTATION
1223 g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1225 return - (gint) needed;
1229 /* create a tvb for the fragment */
1230 next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1231 offset-start_offset);
1234 /* we catch boundserrors on the pdu so that errors on an
1235 * individual pdu don't screw up the whole of the rest of the
1238 dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1241 CATCH2(BoundsError,ReportedBoundsError) {
1242 if (check_col(pinfo->cinfo, COL_INFO))
1243 col_append_str(pinfo->cinfo, COL_INFO,
1244 "[Malformed Packet]");
1245 proto_tree_add_protocol_format(h223_tree, proto_malformed,
1246 tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1251 return (offset-start_offset);
1254 /************************************************************************************
1256 * main dissector entry points
1259 /* dissects PDUs from the tvb
1261 * Updates desegment_offset and desegment_len if the end of the data didn't
1262 * line up with the end of a pdu.
1264 static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1266 proto_tree *h223_tree = NULL;
1267 proto_item *h223_item = NULL;
1268 h223_call_info *call_info = NULL;
1271 /* set up the protocol and info fields in the summary pane */
1272 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1273 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
1275 if (check_col (pinfo->cinfo, COL_INFO))
1276 col_clear (pinfo->cinfo, COL_INFO);
1278 /* find or create the call_info for this call */
1279 call_info = find_or_create_call_info(pinfo);
1281 /* add the 'h223' tree to the main tree */
1283 h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, FALSE);
1284 h223_tree = proto_item_add_subtree (h223_item, ett_h223);
1287 while( offset < tvb_reported_length( tvb )) {
1288 int res = dissect_mux_pdu_fragment( tvb, offset, pinfo,
1289 h223_tree, call_info);
1291 /* the end of the tvb held the start of a PDU */
1292 pinfo->desegment_offset = offset;
1294 /* if res != 0, we actually know how much more data we need for a
1297 * However, if we return that, it means that we get called twice
1298 * for the next packet; this makes it hard to tell how far throught
1299 * the stream we are and we have to start messing about with
1300 * getting the seqno from the superdissector's private data. So we
1303 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1305 pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1308 /* shrink the h223 protocol item such that it only includes the
1309 * bits we dissected */
1310 proto_item_set_len(h223_item,offset);
1314 if(check_col (pinfo->cinfo, COL_INFO))
1315 col_set_str (pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1323 /* H.223 specifies that the least-significant bit is transmitted first;
1324 * however this is at odds with IAX which transmits bytes with the
1325 * first-received bit as the MSB.
1327 * This dissector swaps the ordering of the bits in each byte before using the
1328 * normal entry point.
1330 static void dissect_h223_bitswapped (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1332 tvbuff_t *reversed_tvb;
1337 len = tvb_length(tvb);
1338 data = g_malloc(len);
1339 for( i=0; i<len; i++)
1340 data[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1342 reversed_tvb = tvb_new_real_data(data,len,tvb_reported_length(tvb));
1345 * Add the reversed tvbuff to the list of tvbuffs to which
1346 * the tvbuff we were handed refers, so it'll get
1347 * cleaned up when that tvbuff is cleaned up.
1349 tvb_set_child_real_data_tvbuff(tvb, reversed_tvb);
1352 tvb_set_free_cb(reversed_tvb, g_free);
1354 /* Add the reversed data to the data source list. */
1355 add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1357 dissect_h223(reversed_tvb,pinfo,tree);
1360 /******************************************************************************/
1362 static void h223_init_protocol (void)
1364 circuit_chain_init();
1368 void proto_register_h223 (void)
1370 /* A header field is something you can search/filter on.
1372 * We create a structure to register our fields. It consists of an
1373 * array of hf_register_info structures, each of which are of the format
1374 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1377 static hf_register_info hf[] = {
1378 { &hf_h223_non_h223_data,
1379 { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1380 "Initial data in stream, not a PDU", HFILL }},
1382 { &hf_h223_mux_stuffing_pdu,
1383 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1384 "Empty PDU used for stuffing when no data available", HFILL }},
1387 { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1388 "H.223 MUX-PDU", HFILL }},
1390 { &hf_h223_mux_header,
1391 { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1392 "H.223 MUX header", HFILL }},
1394 { &hf_h223_mux_rawhdr,
1395 { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1396 "Raw header bytes", HFILL }},
1398 { &hf_h223_mux_correctedhdr,
1399 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1400 "Corrected header bytes", HFILL }},
1403 { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1404 "H.223 MUX multiplex code", HFILL }},
1407 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1408 "H.223 MUX multiplex Payload Length", HFILL }},
1410 { &hf_h223_mux_deact,
1411 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1412 "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1415 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1416 "H.223 Virtual Circuit", HFILL }},
1418 { &hf_h223_mux_extra,
1419 { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_DEC, NULL, 0x0,
1420 "data beyond mpl", HFILL }},
1422 { &hf_h223_mux_hdlc2,
1423 { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1424 "framing flag", HFILL }},
1426 /* fields for h.223-mux fragments */
1427 { &hf_h223_mux_fragment_overlap,
1428 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1429 "Fragment overlaps with other fragments", HFILL }},
1431 { &hf_h223_mux_fragment_overlap_conflict,
1432 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1433 "Overlapping fragments contained conflicting data", HFILL }},
1435 { &hf_h223_mux_fragment_multiple_tails,
1436 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1437 "Several tails were found when defragmenting the packet", HFILL }},
1439 { &hf_h223_mux_fragment_too_long_fragment,
1440 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1441 "Fragment contained data past end of packet", HFILL }},
1443 { &hf_h223_mux_fragment_error,
1444 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1445 "Defragmentation error due to illegal fragments", HFILL }},
1447 { &hf_h223_mux_fragment,
1448 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1449 "H.223 MUX-PDU Fragment", HFILL }},
1451 { &hf_h223_mux_fragments,
1452 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1453 "H.223 MUX-PDU Fragments", HFILL }},
1455 { &hf_h223_mux_reassembled_in,
1456 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1457 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1459 /* fields for h.223-al fragments */
1460 { &hf_h223_al_fragment_overlap,
1461 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1462 "Fragment overlaps with other fragments", HFILL }},
1464 { &hf_h223_al_fragment_overlap_conflict,
1465 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1466 "Overlapping fragments contained conflicting data", HFILL }},
1468 { &hf_h223_al_fragment_multiple_tails,
1469 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1470 "Several tails were found when defragmenting the packet", HFILL }},
1472 { &hf_h223_al_fragment_too_long_fragment,
1473 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1474 "Fragment contained data past end of packet", HFILL }},
1476 { &hf_h223_al_fragment_error,
1477 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1478 "Defragmentation error due to illegal fragments", HFILL }},
1480 { &hf_h223_al_fragment,
1481 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1482 "H.223 AL-PDU Fragment", HFILL }},
1484 { &hf_h223_al_fragments,
1485 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1486 "H.223 AL-PDU Fragments", HFILL }},
1488 { &hf_h223_al_reassembled_in,
1489 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1490 "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1495 { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1496 "H.223 AL-PDU using AL1", HFILL }},
1498 { &hf_h223_al1_framed,
1499 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1503 { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1504 "H.223 AL-PDU using AL2", HFILL }},
1506 { &hf_h223_al2_sequenced,
1507 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1508 "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1510 { &hf_h223_al2_unsequenced,
1511 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1512 "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1514 { &hf_h223_al2_seqno,
1515 { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1516 "H.223 AL2 sequence number", HFILL }},
1519 { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1522 { &hf_h223_al2_crc_bad,
1523 { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1526 { &hf_h223_al_payload,
1527 { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1528 "H.223 AL-PDU Payload", HFILL }},
1532 static gint *ett[] = {
1534 &ett_h223_non_h223_data,
1535 &ett_h223_mux_stuffing_pdu,
1537 &ett_h223_mux_header,
1538 &ett_h223_mux_deact,
1540 &ett_h223_mux_extra,
1541 &ett_h223_mux_fragments,
1542 &ett_h223_mux_fragment,
1543 &ett_h223_al_fragments,
1544 &ett_h223_al_fragment,
1547 &ett_h223_al_payload
1550 if (proto_h223 == -1) { /* execute protocol initialization only once */
1552 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1553 proto_h223_bitswapped =
1554 proto_register_protocol ("Bitswapped ITU-T Recommendation H.223", "H.223 (Bitswapped)", "h223_bitswapped");
1556 proto_register_field_array (proto_h223, hf, array_length (hf));
1557 proto_register_subtree_array (ett, array_length (ett));
1558 register_dissector("h223", dissect_h223, proto_h223);
1559 register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped);
1561 /* register our init routine to be called at the start of a capture,
1562 to clear out our hash tables etc */
1563 register_init_routine(&h223_init_protocol);
1566 h245_set_h223_set_mc_handle( &h223_set_mc );
1567 h245_set_h223_add_lc_handle( &h223_add_lc );
1570 void proto_reg_handoff_h223(void)
1572 dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1573 dissector_handle_t h223 = find_dissector("h223");
1574 data_handle = find_dissector("data");
1575 h245dg_handle = find_dissector("h245dg");
1576 srp_handle = find_dissector("srp");
1578 dissector_add_handle("tcp.port", h223);
1579 dissector_add_handle("tcp.port", h223_bitswapped);
1580 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1581 dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1583 /* vim:set ts=8 et: */