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/golay.h>
42 #include <epan/iax2_codec_type.h>
43 #include <epan/dissectors/packet-frame.h>
44 #include <epan/asn1.h>
45 #include <epan/dissectors/packet-h245.h>
47 #include "packet-h223.h"
51 /* #define DEBUG_H223 */
53 /* debug the mux-pdu defragmentation code. warning: verbose output! */
54 /* #define DEBUG_H223_FRAGMENTATION */
56 #define PROTO_TAG_H223 "H223"
58 /* Wireshark ID of the H.223 protocol */
59 static int proto_h223 = -1;
60 static int proto_h223_bitswapped = -1;
62 /* The following hf_* variables are used to hold the Wireshark IDs of
63 * our header fields; they are filled out when we call
64 * proto_register_field_array() in proto_register_h223()
66 static int hf_h223_non_h223_data = -1;
67 static int hf_h223_mux_stuffing_pdu = -1;
68 static int hf_h223_mux_pdu = -1;
69 static int hf_h223_mux_header = -1;
70 static int hf_h223_mux_rawhdr = -1;
71 static int hf_h223_mux_correctedhdr = -1;
72 static int hf_h223_mux_mc = -1;
73 static int hf_h223_mux_mpl = -1;
74 static int hf_h223_mux_deact = -1;
75 static int hf_h223_mux_vc = -1;
76 static int hf_h223_mux_extra = -1;
77 static int hf_h223_mux_hdlc2 = -1;
78 static int hf_h223_mux_fragments = -1;
79 static int hf_h223_mux_fragment = -1;
80 static int hf_h223_mux_fragment_overlap = -1;
81 static int hf_h223_mux_fragment_overlap_conflict = -1;
82 static int hf_h223_mux_fragment_multiple_tails = -1;
83 static int hf_h223_mux_fragment_too_long_fragment = -1;
84 static int hf_h223_mux_fragment_error = -1;
85 static int hf_h223_mux_reassembled_in = -1;
87 static int hf_h223_al_fragments = -1;
88 static int hf_h223_al_fragment = -1;
89 static int hf_h223_al_fragment_overlap = -1;
90 static int hf_h223_al_fragment_overlap_conflict = -1;
91 static int hf_h223_al_fragment_multiple_tails = -1;
92 static int hf_h223_al_fragment_too_long_fragment = -1;
93 static int hf_h223_al_fragment_error = -1;
94 static int hf_h223_al_reassembled_in = -1;
96 static int hf_h223_al1 = -1;
97 static int hf_h223_al1_framed = -1;
98 static int hf_h223_al2 = -1;
99 static int hf_h223_al2_sequenced = -1;
100 static int hf_h223_al2_unsequenced = -1;
101 static int hf_h223_al2_seqno = -1;
102 static int hf_h223_al2_crc = -1;
103 static int hf_h223_al2_crc_bad = -1;
105 static int hf_h223_al_payload = -1;
107 /* These are the ids of the subtrees that we may be creating */
108 static gint ett_h223 = -1;
109 static gint ett_h223_non_h223_data = -1;
110 static gint ett_h223_mux_stuffing_pdu = -1;
111 static gint ett_h223_mux_pdu = -1;
112 static gint ett_h223_mux_header = -1;
113 static gint ett_h223_mux_deact = -1;
114 static gint ett_h223_mux_vc = -1;
115 static gint ett_h223_mux_extra = -1;
116 static gint ett_h223_mux_fragments = -1;
117 static gint ett_h223_mux_fragment = -1;
118 static gint ett_h223_al_fragments = -1;
119 static gint ett_h223_al_fragment = -1;
120 static gint ett_h223_al1 = -1;
121 static gint ett_h223_al2 = -1;
122 static gint ett_h223_al_payload = -1;
124 /* These are the handles of our subdissectors */
125 static dissector_handle_t data_handle;
126 static dissector_handle_t srp_handle;
128 static const fragment_items h223_mux_frag_items _U_ = {
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)(unsigned long)(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 *datax;
415 h223_lc_params *vc0_params;
417 datax = se_alloc(sizeof(h223_call_info));
419 /* initialise the call info */
420 init_direction_data(&datax -> direction_data[0]);
421 init_direction_data(&datax -> direction_data[1]);
423 /* FIXME shouldn't this be figured out dynamically? */
424 datax -> 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, datax, 0, P2P_DIR_SENT, vc0_params );
432 init_logical_channel( start_frame, datax, 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 *datax;
440 circuit_t *circ = NULL;
442 if(pinfo->ctype != CT_NONE)
443 circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
447 datax = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
449 if( datax == NULL ) {
450 datax = 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, datax, circ, pinfo->ctype, pinfo->circuit_id);
456 circuit_add_proto_data(circ, proto_h223, datax);
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 *datax;
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 datax = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
484 if(datax == 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 datax = (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, datax, 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, datax);
512 /* we still haven't found any call data - create a new one for this
515 datax = 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, datax, 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, datax);
527 /* add the source details so we can distinguish directions
529 COPY_ADDRESS(&(datax -> srcaddress), &(pinfo->src));
530 datax -> srcport = pinfo->srcport;
533 /* work out what direction we're really going in */
534 if( ADDRESSES_EQUAL( &(pinfo->src), &(datax->srcaddress))
535 && pinfo->srcport == datax->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 *datax;
547 datax = find_or_create_call_info_circ(pinfo);
549 datax = 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* datax = tvb_get_ptr( tvb, 0, len );
607 unsigned char crc = 0;
609 DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
611 crc = crctable[crc^datax[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;
622 proto_item *al_item, *hidden_item;
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 hidden_item = proto_tree_add_boolean(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
643 PROTO_ITEM_SET_HIDDEN(hidden_item);
646 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
649 case al2WithSequenceNumbers:
650 al2_sequenced = TRUE;
652 case al2WithoutSequenceNumbers:
653 tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
655 al_item = proto_tree_add_item(vc_tree,
656 al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
658 al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
660 PROTO_ITEM_SET_GENERATED(tmp_item);
662 /* check minimum payload length */
663 if(len < (al2_sequenced?2U:1U))
667 if( al2_sequenced ) {
668 proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
672 next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
673 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
675 calc_checksum = h223_al2_crc8bit(tvb);
676 real_checksum = tvb_get_guint8(tvb, len - 1);
678 if( calc_checksum == real_checksum ) {
679 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
680 "CRC: 0x%02x (correct)", real_checksum );
682 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
683 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
684 tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
685 PROTO_ITEM_SET_GENERATED(tmp_item);
687 /* don't pass pdus which fail checksums on to the subdissector */
688 subdissector = data_handle;
692 call_dissector(data_handle, tvb, pinfo, vc_tree);
697 subdissector = data_handle;
699 al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
700 call_dissector(subdissector, next_tvb, pinfo, al_subtree);
703 /************************************************************************************
709 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
711 * tvb buffer containing the MUX-PDU fragment
712 * pinfo info on the packet containing the last fragment of the MUX-PDU
713 * pkt_offset offset within the block from the superdissector where the
714 * fragment starts (must increase monotonically for constant pinfo->fd->num)
715 * pdu_tree dissection tree for the PDU; a single item will be added (with
718 * end_of_mux_sdu true if this is a segmentable VC and this is the last
721 static void dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb,
724 proto_tree *pdu_tree,
725 h223_call_info* call_info,
726 guint16 vc, gboolean end_of_mux_sdu)
728 /* update the circuit details before passing to a subdissector */
729 guint32 orig_circuit = pinfo->circuit_id;
730 guint32 orig_ctype = pinfo->ctype;
731 pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
732 pinfo->ctype=CT_H223;
735 circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
736 proto_tree *vc_tree = NULL;
738 h223_vc_info *vc_info = NULL;
739 h223_lc_params *lc_params = NULL;
742 vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
743 vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
746 if( subcircuit == NULL ) {
747 g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
748 pinfo->circuit_id, (void *)call_info, vc );
750 vc_info = circuit_get_proto_data(subcircuit, proto_h223);
751 if( vc_info != NULL ) {
752 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
757 if( lc_params != NULL ) {
758 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
760 stream_pdu_fragment_t *frag;
762 substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
763 if(substream == NULL )
764 substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
765 frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
769 g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
770 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
772 frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
773 next_tvb,pinfo,!end_of_mux_sdu);
776 g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
777 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
781 next_tvb = stream_process_reassembled(
783 "Reassembled H.223 AL-PDU",
784 frag, &h223_al_frag_items,
789 /* fudge to pass pkt_offset down to add_h223_mux_element,
790 * should it be called */
791 pdu_offset = pkt_offset;
792 dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
795 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
799 /* restore the original circuit details for future PDUs */
801 pinfo->ctype=orig_ctype;
802 pinfo->circuit_id=orig_circuit;
807 static guint32 mux_element_sublist_size( h223_mux_element* me )
809 h223_mux_element *current_me = me;
811 while ( current_me ) {
812 current_me = current_me->next;
813 if ( current_me->sublist )
814 length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
816 length += current_me->repeat_count;
818 if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
819 DISSECTOR_ASSERT_NOT_REACHED();
825 /* dissect part of a MUX-PDU payload according to a multiplex list
827 * tvb buffer containing entire mux-pdu payload
828 * pinfo info on the packet containing the last fragment of the MUX-PDU
829 * pkt_offset offset within the block from the superdissector where the
830 * MUX-PDU starts (must increase monotonically for constant
832 * pdu_tree dissection tree for the PDU
833 * call_info data structure for h223 call
835 * offset offset within tvb to start work
836 * endOfMuxSdu true if the end-of-sdu flag was set
838 static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
839 proto_tree *pdu_tree,
840 h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu )
842 guint32 len = tvb_reported_length(tvb);
848 if ( me->repeat_count == 0 ) {
849 for(sublist_len = mux_element_sublist_size( me->sublist );
850 offset + sublist_len <= len;
851 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
852 call_info, me->sublist, offset, endOfMuxSdu ) );
854 for(i = 0; i < me->repeat_count; ++i)
855 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
856 call_info, me->sublist, offset, endOfMuxSdu );
859 if ( me->repeat_count == 0 )
860 frag_len = len - offset;
862 frag_len = me->repeat_count;
865 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
866 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
867 call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
876 /* dissect the payload of a MUX-PDU
878 * tvb buffer containing entire mux-pdu payload
879 * pinfo info on the packet containing the last fragment of the MUX-PDU
880 * pkt_offset offset within the block from the superdissector where the
881 * MUX-PDU starts (must increase monotonically for constant
883 * pdu_tree dissection tree for the PDU
884 * call_info data structure for h223 call
885 * mc multiplex code for this PDU
886 * endOfMuxSdu true if the end-of-sdu flag was set
888 static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
889 proto_tree *pdu_tree,
890 h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu )
892 guint32 len = tvb_reported_length(tvb);
894 h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
897 dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
899 /* no entry found in mux-table. ignore packet and dissect as data */
900 proto_tree *vc_tree = NULL;
903 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
904 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
906 call_dissector(data_handle,tvb,pinfo,vc_tree);
910 /* dissect a reassembled mux-pdu
912 * tvb buffer containing mux-pdu, including header and closing flag
913 * pinfo packet info for packet containing the end of the mux-pdu
914 * pkt_offset offset within the block from the superdissector where the
915 * MUX-PDU starts (must increase monotonically for constant
917 * h223_tree dissection tree for h223 protocol; a single item will be added
919 * call_info h223 info structure for this h223 call
920 * pdu_no index of this pdu within the call
922 static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo,
924 proto_tree *h223_tree,
925 h223_call_info *call_info)
928 /* actual (as opposed to reported) payload len */
930 guint32 raw_hdr = 0, correct_hdr = 0;
932 guint16 closing_flag = 0;
935 gboolean end_of_mux_sdu = FALSE;
938 proto_item *pdu_item = NULL;
939 proto_tree *pdu_tree = NULL;
941 #ifdef DEBUG_H223_FRAGMENTATION
942 g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
943 pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
946 switch(call_info->h223_level) {
948 raw_hdr = tvb_get_guint8(tvb,0);
949 mc = (guint8)((raw_hdr>>1) & 0xf);
950 end_of_mux_sdu = raw_hdr & 1;
952 /* closing flag is one byte long for h223 level 0, two for level 1 */
953 len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
955 /* XXX should ignore pdus with incorrect HECs */
959 raw_hdr = tvb_get_letoh24(tvb,0);
960 errors = golay_errors(raw_hdr);
962 len = tvb_length_remaining(tvb,offset)-2;
965 correct_hdr = raw_hdr ^ (guint32)errors;
967 mc = (guint8)(correct_hdr & 0xf);
968 mpl = (guint8)((correct_hdr >> 4) & 0xff);
970 /* we should never have been called if there's not enough data in
972 DISSECTOR_ASSERT(len >= mpl);
974 closing_flag = tvb_get_ntohs(tvb,offset+len);
975 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
983 /* XXX not implemented */
986 DISSECTOR_ASSERT_NOT_REACHED();
992 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
993 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
995 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
996 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
1001 proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
1002 proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1004 switch(call_info->h223_level) {
1006 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1010 if( errors == -1 ) {
1011 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1013 "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1016 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1018 "Raw value: 0x%06x (correct)", raw_hdr );
1020 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1022 "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1024 item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1026 PROTO_ITEM_SET_GENERATED(item);
1027 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1028 proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1033 /* XXX not implemented */
1035 DISSECTOR_ASSERT_NOT_REACHED();
1040 pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1042 dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1044 call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1049 /* any extra data in the PDU, beyond that indictated by the mpl, is
1050 dissected as data. */
1053 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1054 proto_tree *vc_tree = NULL;
1057 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1058 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1060 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1065 /* add the closing HDLC flag */
1067 proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1071 /************************************************************************************
1073 * MUX-PDU delineation and defragmentation
1076 /* attempt to parse the header of a mux pdu */
1077 static gboolean attempt_mux_level0_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1079 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1080 DISSECTOR_ASSERT_NOT_REACHED();
1087 static gboolean attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1089 /* this is untested */
1090 DISSECTOR_ASSERT_NOT_REACHED();
1096 /* don't interpret a repeated hdlc as a header */
1100 /* + 1 byte of header and 2 bytes of closing HDLC */
1101 *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1105 static gboolean attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1112 /* + 3 bytes of header and 2 bytes of closing HDLC */
1115 /* bah, we get the header in the wrong order */
1117 ((hdr & 0xFF0000) >> 16) |
1119 ((hdr & 0x0000FF) << 16);
1121 errors = golay_errors(hdr);
1124 *minlen += ((hdr >> 4) & 0xff);
1130 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1131 attempt_mux_level0_header_parse,
1132 attempt_mux_level1_header_parse,
1133 attempt_mux_level2_3_header_parse,
1134 attempt_mux_level2_3_header_parse
1137 static gboolean h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1141 switch(h223_level) {
1143 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1144 DISSECTOR_ASSERT_NOT_REACHED();
1148 masked = tail_buf & 0xffff;
1149 return nbytes >= 2 && masked == 0xE14D;
1152 masked = tail_buf & 0xffff;
1153 return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1156 DISSECTOR_ASSERT_NOT_REACHED();
1161 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1163 * returns the number of bytes processed, or the negative of the number of
1164 * extra bytes needed, or zero if we don't know yet
1167 static gint dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo,
1168 proto_tree *h223_tree,
1169 h223_call_info *call_info)
1171 tvbuff_t *volatile next_tvb;
1172 volatile guint32 offset = start_offset;
1173 gboolean more_frags = TRUE;
1175 gboolean header_parsed = FALSE;
1176 guint32 header_buf = 0, tail_buf = 0;
1177 guint32 pdu_minlen = 0;
1180 #ifdef DEBUG_H223_FRAGMENTATION
1181 g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1182 pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1185 while( more_frags && offset < tvb_reported_length( tvb )) {
1186 guint8 byte = tvb_get_guint8(tvb, offset++);
1188 /* read a byte into the header buf, if necessary */
1189 if((offset-start_offset) <= 4) {
1194 /* read the byte into the tail buf */
1198 /* if we haven't parsed the header yet, attempt to do so now */
1200 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1201 header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1202 (offset-start_offset,header_buf,&pdu_minlen);
1204 /* if we have successfully parsed the header, we have sufficient data,
1205 * and we have found the closing hdlc, we are done here */
1206 if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1207 if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1214 if(pdu_minlen <= (offset-start_offset)) {
1215 /* we haven't found the closing hdlc yet, but we don't know how
1216 * much more we need */
1217 #ifdef DEBUG_H223_FRAGMENTATION
1218 g_debug("\tBailing, requesting more bytes");
1222 guint32 needed = pdu_minlen-(offset-start_offset);
1223 #ifdef DEBUG_H223_FRAGMENTATION
1224 g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1226 return - (gint) needed;
1230 /* create a tvb for the fragment */
1231 next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1232 offset-start_offset);
1235 /* we catch boundserrors on the pdu so that errors on an
1236 * individual pdu don't screw up the whole of the rest of the
1239 dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1242 CATCH2(BoundsError,ReportedBoundsError) {
1243 if (check_col(pinfo->cinfo, COL_INFO))
1244 col_append_str(pinfo->cinfo, COL_INFO,
1245 "[Malformed Packet]");
1246 proto_tree_add_protocol_format(h223_tree, proto_malformed,
1247 tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1252 return (offset-start_offset);
1255 /************************************************************************************
1257 * main dissector entry points
1260 /* dissects PDUs from the tvb
1262 * Updates desegment_offset and desegment_len if the end of the data didn't
1263 * line up with the end of a pdu.
1265 static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1267 proto_tree *h223_tree = NULL;
1268 proto_item *h223_item = NULL;
1269 h223_call_info *call_info = NULL;
1272 /* set up the protocol and info fields in the summary pane */
1273 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1274 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
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 col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1322 /* H.223 specifies that the least-significant bit is transmitted first;
1323 * however this is at odds with IAX which transmits bytes with the
1324 * first-received bit as the MSB.
1326 * This dissector swaps the ordering of the bits in each byte before using the
1327 * normal entry point.
1329 static void dissect_h223_bitswapped (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1331 tvbuff_t *reversed_tvb;
1336 len = tvb_length(tvb);
1337 datax = g_malloc(len);
1338 for( i=0; i<len; i++)
1339 datax[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1342 * Add the reversed tvbuff to the list of tvbuffs to which
1343 * the tvbuff we were handed refers, so it'll get
1344 * cleaned up when that tvbuff is cleaned up.
1346 reversed_tvb = tvb_new_child_real_data(tvb, datax,len,tvb_reported_length(tvb));
1349 tvb_set_free_cb(reversed_tvb, g_free);
1351 /* Add the reversed data to the data source list. */
1352 add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1354 dissect_h223(reversed_tvb,pinfo,tree);
1357 /******************************************************************************/
1359 static void h223_init_protocol (void)
1361 circuit_chain_init();
1365 void proto_register_h223 (void)
1367 /* A header field is something you can search/filter on.
1369 * We create a structure to register our fields. It consists of an
1370 * array of hf_register_info structures, each of which are of the format
1371 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1374 static hf_register_info hf[] = {
1375 { &hf_h223_non_h223_data,
1376 { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1377 "Initial data in stream, not a PDU", HFILL }},
1379 { &hf_h223_mux_stuffing_pdu,
1380 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1381 "Empty PDU used for stuffing when no data available", HFILL }},
1384 { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1387 { &hf_h223_mux_header,
1388 { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1389 "H.223 MUX header", HFILL }},
1391 { &hf_h223_mux_rawhdr,
1392 { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1393 "Raw header bytes", HFILL }},
1395 { &hf_h223_mux_correctedhdr,
1396 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1397 "Corrected header bytes", HFILL }},
1400 { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1401 "H.223 MUX multiplex code", HFILL }},
1404 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1405 "H.223 MUX multiplex Payload Length", HFILL }},
1407 { &hf_h223_mux_deact,
1408 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1409 "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1412 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1413 "H.223 Virtual Circuit", HFILL }},
1415 { &hf_h223_mux_extra,
1416 { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_NONE, NULL, 0x0,
1417 "data beyond mpl", HFILL }},
1419 { &hf_h223_mux_hdlc2,
1420 { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1421 "framing flag", HFILL }},
1423 /* fields for h.223-mux fragments */
1424 { &hf_h223_mux_fragment_overlap,
1425 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1426 "Fragment overlaps with other fragments", HFILL }},
1428 { &hf_h223_mux_fragment_overlap_conflict,
1429 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1430 "Overlapping fragments contained conflicting data", HFILL }},
1432 { &hf_h223_mux_fragment_multiple_tails,
1433 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1434 "Several tails were found when defragmenting the packet", HFILL }},
1436 { &hf_h223_mux_fragment_too_long_fragment,
1437 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1438 "Fragment contained data past end of packet", HFILL }},
1440 { &hf_h223_mux_fragment_error,
1441 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1442 "Defragmentation error due to illegal fragments", HFILL }},
1444 { &hf_h223_mux_fragment,
1445 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1448 { &hf_h223_mux_fragments,
1449 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1452 { &hf_h223_mux_reassembled_in,
1453 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1454 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1456 /* fields for h.223-al fragments */
1457 { &hf_h223_al_fragment_overlap,
1458 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1459 "Fragment overlaps with other fragments", HFILL }},
1461 { &hf_h223_al_fragment_overlap_conflict,
1462 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1463 "Overlapping fragments contained conflicting data", HFILL }},
1465 { &hf_h223_al_fragment_multiple_tails,
1466 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1467 "Several tails were found when defragmenting the packet", HFILL }},
1469 { &hf_h223_al_fragment_too_long_fragment,
1470 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1471 "Fragment contained data past end of packet", HFILL }},
1473 { &hf_h223_al_fragment_error,
1474 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1475 "Defragmentation error due to illegal fragments", HFILL }},
1477 { &hf_h223_al_fragment,
1478 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1481 { &hf_h223_al_fragments,
1482 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1485 { &hf_h223_al_reassembled_in,
1486 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1487 "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1492 { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1493 "H.223 AL-PDU using AL1", HFILL }},
1495 { &hf_h223_al1_framed,
1496 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1500 { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1501 "H.223 AL-PDU using AL2", HFILL }},
1503 { &hf_h223_al2_sequenced,
1504 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1505 "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1507 { &hf_h223_al2_unsequenced,
1508 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1509 "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1511 { &hf_h223_al2_seqno,
1512 { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1513 "H.223 AL2 sequence number", HFILL }},
1516 { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1519 { &hf_h223_al2_crc_bad,
1520 { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1523 { &hf_h223_al_payload,
1524 { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1525 "H.223 AL-PDU Payload", HFILL }},
1529 static gint *ett[] = {
1531 &ett_h223_non_h223_data,
1532 &ett_h223_mux_stuffing_pdu,
1534 &ett_h223_mux_header,
1535 &ett_h223_mux_deact,
1537 &ett_h223_mux_extra,
1538 &ett_h223_mux_fragments,
1539 &ett_h223_mux_fragment,
1540 &ett_h223_al_fragments,
1541 &ett_h223_al_fragment,
1544 &ett_h223_al_payload
1548 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1549 proto_h223_bitswapped =
1550 proto_register_protocol ("Bitswapped ITU-T Recommendation H.223", "H.223 (Bitswapped)", "h223_bitswapped");
1552 proto_register_field_array (proto_h223, hf, array_length (hf));
1553 proto_register_subtree_array (ett, array_length (ett));
1554 register_dissector("h223", dissect_h223, proto_h223);
1555 register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped);
1557 /* register our init routine to be called at the start of a capture,
1558 to clear out our hash tables etc */
1559 register_init_routine(&h223_init_protocol);
1561 h245_set_h223_set_mc_handle( &h223_set_mc );
1562 h245_set_h223_add_lc_handle( &h223_add_lc );
1565 void proto_reg_handoff_h223(void)
1567 dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1568 dissector_handle_t h223 = find_dissector("h223");
1569 data_handle = find_dissector("data");
1570 srp_handle = find_dissector("srp");
1572 dissector_add_handle("tcp.port", h223);
1573 dissector_add_handle("tcp.port", h223_bitswapped);
1574 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1575 dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1577 /* vim:set ts=8 et: */