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.
31 #include <epan/emem.h>
32 #include <epan/bitswap.h>
33 #include <epan/circuit.h>
34 #include <epan/conversation.h>
35 #include <epan/packet.h>
36 #include <epan/stream.h>
37 #include <epan/reassemble.h>
38 #include <epan/golay.h>
39 #include <epan/iax2_codec_type.h>
40 #include <epan/dissectors/packet-frame.h>
41 #include <epan/asn1.h>
42 #include <epan/dissectors/packet-h245.h>
44 #include "packet-h223.h"
48 /* #define DEBUG_H223 */
50 /* debug the mux-pdu defragmentation code. warning: verbose output! */
51 /* #define DEBUG_H223_FRAGMENTATION */
53 #define PROTO_TAG_H223 "H223"
55 /* Wireshark ID of the H.223 protocol */
56 static int proto_h223 = -1;
58 /* The following hf_* variables are used to hold the Wireshark IDs of
59 * our header fields; they are filled out when we call
60 * proto_register_field_array() in proto_register_h223()
62 static int hf_h223_non_h223_data = -1;
63 static int hf_h223_mux_stuffing_pdu = -1;
64 static int hf_h223_mux_pdu = -1;
65 static int hf_h223_mux_header = -1;
66 static int hf_h223_mux_rawhdr = -1;
67 static int hf_h223_mux_correctedhdr = -1;
68 static int hf_h223_mux_mc = -1;
69 static int hf_h223_mux_mpl = -1;
70 static int hf_h223_mux_deact = -1;
71 static int hf_h223_mux_vc = -1;
72 static int hf_h223_mux_extra = -1;
73 static int hf_h223_mux_hdlc2 = -1;
74 static int hf_h223_mux_fragments = -1;
75 static int hf_h223_mux_fragment = -1;
76 static int hf_h223_mux_fragment_overlap = -1;
77 static int hf_h223_mux_fragment_overlap_conflict = -1;
78 static int hf_h223_mux_fragment_multiple_tails = -1;
79 static int hf_h223_mux_fragment_too_long_fragment = -1;
80 static int hf_h223_mux_fragment_error = -1;
81 static int hf_h223_mux_fragment_count = -1;
82 static int hf_h223_mux_reassembled_in = -1;
83 static int hf_h223_mux_reassembled_length = -1;
85 static int hf_h223_al_fragments = -1;
86 static int hf_h223_al_fragment = -1;
87 static int hf_h223_al_fragment_overlap = -1;
88 static int hf_h223_al_fragment_overlap_conflict = -1;
89 static int hf_h223_al_fragment_multiple_tails = -1;
90 static int hf_h223_al_fragment_too_long_fragment = -1;
91 static int hf_h223_al_fragment_error = -1;
92 static int hf_h223_al_fragment_count = -1;
93 static int hf_h223_al_reassembled_in = -1;
94 static int hf_h223_al_reassembled_length = -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_fragment_count,
139 &hf_h223_mux_reassembled_in,
140 &hf_h223_mux_reassembled_length,
144 static const fragment_items h223_al_frag_items = {
145 &ett_h223_al_fragment,
146 &ett_h223_al_fragments,
147 &hf_h223_al_fragments,
148 &hf_h223_al_fragment,
149 &hf_h223_al_fragment_overlap,
150 &hf_h223_al_fragment_overlap_conflict,
151 &hf_h223_al_fragment_multiple_tails,
152 &hf_h223_al_fragment_too_long_fragment,
153 &hf_h223_al_fragment_error,
154 &hf_h223_al_fragment_count,
155 &hf_h223_al_reassembled_in,
156 &hf_h223_al_reassembled_length,
160 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
161 static guint32 pdu_offset;
163 /***************************************************************************
165 * virtual circuit number handling
167 * we have to be able to manage more than one H.223 call at a time,
168 * so have a hash which maps {call,vc} to an integer.
171 typedef struct _h223_call_info h223_call_info;
174 const h223_call_info* call; /* h223 call */
175 guint32 vc; /* child circuit */
178 static GHashTable *circuit_chain_hashtable = NULL;
179 static guint circuit_chain_count = 1;
183 circuit_chain_equal(gconstpointer v, gconstpointer w)
185 const circuit_chain_key *v1 = (const circuit_chain_key *)v;
186 const circuit_chain_key *v2 = (const circuit_chain_key *)w;
188 result = ( v1->call == v2->call &&
189 v1->vc == v2 -> vc );
194 circuit_chain_hash (gconstpointer v)
196 const circuit_chain_key *key = (const circuit_chain_key *)v;
197 guint hash_val = ((guint32)(unsigned long)(key->call))^(((guint32)key->vc) << 16);
202 circuit_chain_lookup(const h223_call_info* call_info, guint32 child_vc)
204 circuit_chain_key key, *new_key;
206 key.call = call_info;
208 circuit_id = GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable, &key ));
209 if( circuit_id == 0 ) {
210 new_key = se_alloc(sizeof(circuit_chain_key));
212 circuit_id = ++circuit_chain_count;
213 g_hash_table_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id));
219 circuit_chain_init(void)
221 if (circuit_chain_hashtable)
222 g_hash_table_destroy(circuit_chain_hashtable);
223 circuit_chain_hashtable = g_hash_table_new(circuit_chain_hash, circuit_chain_equal);
224 circuit_chain_count = 1;
228 /***************************************************************************
230 * Call information management
234 /* we keep information on each call in an h223_call_info structure
236 * We attach the h223_call_info structures to individual calls with
237 * circuit_add_proto_data().
240 typedef struct _h223_mux_element_listitem h223_mux_element_listitem;
241 struct _h223_mux_element_listitem {
242 h223_mux_element *me;
245 h223_mux_element_listitem *next;
248 /* we have this information for each stream */
250 h223_mux_element_listitem* mux_table[16];
251 } h223_call_direction_data;
254 struct _h223_call_info {
255 /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
256 specified in the annexes
260 /* for H.223 streams over TCP (as opposed to IAX), this
261 stores the source address and port of the first packet spotted,
262 so that we can differentiate directions.
267 h223_call_direction_data direction_data[2];
270 typedef struct _h223_lc_params_listitem h223_lc_params_listitem;
271 struct _h223_lc_params_listitem
273 h223_lc_params *lc_params;
276 h223_lc_params_listitem *next;
280 h223_lc_params_listitem *lc_params[2];
281 h223_call_info *call_info;
285 add_h223_mux_element(h223_call_direction_data *direct, guint8 mc, h223_mux_element *me, guint32 framenum)
287 h223_mux_element_listitem *li;
288 h223_mux_element_listitem **old_li_ptr;
289 h223_mux_element_listitem *old_li;
291 DISSECTOR_ASSERT(mc < 16);
293 li = se_alloc(sizeof(h223_mux_element_listitem));
294 old_li_ptr = &(direct->mux_table[mc]);
295 old_li = *old_li_ptr;
297 direct->mux_table[mc] = li;
299 while( old_li->next ) {
300 old_li_ptr = &(old_li->next);
301 old_li = *old_li_ptr;
303 if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset) )
305 else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset )
306 *old_li_ptr = li; /* replace the tail of the list with the new item, since */
307 /* a single h223 pdu has just set the same MC twice.. */
311 li->first_frame = framenum;
312 li->pdu_offset = pdu_offset;
317 static h223_mux_element*
318 find_h223_mux_element(h223_call_direction_data* direct, guint8 mc, guint32 framenum, guint32 pkt_offset)
320 h223_mux_element_listitem* li;
322 DISSECTOR_ASSERT(mc < 16);
324 li = direct->mux_table[mc];
326 while( li && li->next && li->next->first_frame < framenum )
328 while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset )
338 add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, guint32 framenum )
340 h223_lc_params_listitem *li = se_alloc(sizeof(h223_lc_params_listitem));
341 h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction ? 0 : 1]);
342 h223_lc_params_listitem *old_li = *old_li_ptr;
344 vc_info->lc_params[direction ? 0 : 1] = li;
346 while( old_li->next ) {
347 old_li_ptr = &(old_li->next);
348 old_li = *old_li_ptr;
350 if( framenum < old_li->first_frame )
352 else if( framenum == old_li->first_frame )
356 old_li->last_frame = framenum - 1;
359 li->first_frame = framenum;
362 li->lc_params = lc_params;
365 static h223_lc_params*
366 find_h223_lc_params(h223_vc_info* vc_info, int direction, guint32 framenum)
368 h223_lc_params_listitem* li = vc_info->lc_params[direction? 0 : 1];
369 while( li && li->next && li->next->first_frame <= framenum )
372 return li->lc_params;
378 init_direction_data(h223_call_direction_data *direct)
381 h223_mux_element *mc0_element;
383 for ( i = 0; i < 16; ++i )
384 direct->mux_table[i] = NULL;
386 /* set up MC 0 to contain just VC 0 */
387 mc0_element = se_alloc(sizeof(h223_mux_element));
388 add_h223_mux_element( direct, 0, mc0_element, 0 );
389 mc0_element->sublist = NULL;
391 mc0_element->repeat_count = 0; /* until closing flag */
392 mc0_element->next = NULL;
396 h223_vc_info_new( h223_call_info* call_info )
398 h223_vc_info *vc_info = se_alloc(sizeof(h223_vc_info));
399 vc_info->lc_params[0] = vc_info->lc_params[1] = NULL;
400 vc_info->call_info = call_info;
405 init_logical_channel( guint32 start_frame, h223_call_info* call_info, int vc, int direction, h223_lc_params* params )
407 guint32 circuit_id = circuit_chain_lookup(call_info, vc);
408 circuit_t *subcircuit;
409 h223_vc_info *vc_info;
410 subcircuit = find_circuit( CT_H223, circuit_id, start_frame );
412 if( subcircuit == NULL ) {
413 subcircuit = circuit_new( CT_H223, circuit_id, start_frame );
415 g_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc);
417 vc_info = h223_vc_info_new( call_info );
418 circuit_add_proto_data( subcircuit, proto_h223, vc_info );
420 vc_info = circuit_get_proto_data( subcircuit, proto_h223 );
422 add_h223_lc_params( vc_info, direction, params, start_frame );
425 /* create a brand-new h223_call_info structure */
426 static h223_call_info *
427 create_call_info( guint32 start_frame )
429 h223_call_info *datax;
430 h223_lc_params *vc0_params;
432 datax = se_alloc(sizeof(h223_call_info));
434 /* initialise the call info */
435 init_direction_data(&datax -> direction_data[0]);
436 init_direction_data(&datax -> direction_data[1]);
438 /* FIXME shouldn't this be figured out dynamically? */
439 datax -> h223_level = 2;
441 vc0_params = se_alloc(sizeof(h223_lc_params));
442 vc0_params->al_type = al1Framed;
443 vc0_params->al_params = NULL;
444 vc0_params->segmentable = TRUE;
445 vc0_params->subdissector = srp_handle;
446 init_logical_channel( start_frame, datax, 0, P2P_DIR_SENT, vc0_params );
447 init_logical_channel( start_frame, datax, 0, P2P_DIR_RECV, vc0_params );
451 /* find or create call_info struct for calls over circuits (eg, IAX) */
452 static h223_call_info *
453 find_or_create_call_info_circ(packet_info * pinfo)
455 h223_call_info *datax;
456 circuit_t *circ = NULL;
458 if(pinfo->ctype != CT_NONE)
459 circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
463 datax = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
465 if( datax == NULL ) {
466 datax = create_call_info(pinfo->fd->num);
469 g_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
470 pinfo->fd->num, datax, circ, pinfo->ctype, pinfo->circuit_id);
472 circuit_add_proto_data(circ, proto_h223, datax);
475 /* work out what direction we're really going in */
476 if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1)
477 pinfo->p2p_dir = P2P_DIR_SENT;
482 /* find or create call_info struct for calls over conversations (eg, RTP) */
483 static h223_call_info *
484 find_or_create_call_info_conv(packet_info * pinfo)
486 h223_call_info *datax;
487 conversation_t *conv;
489 /* assume we're running atop TCP or RTP; use the conversation support */
490 conv = find_conversation( pinfo->fd->num,
491 &pinfo->src,&pinfo->dst,
493 pinfo->srcport,pinfo->destport, 0 );
495 /* both RTP and TCP track their conversations, so just assert here if
496 * we can't find one */
497 DISSECTOR_ASSERT(conv);
499 datax = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
501 if(datax == NULL && pinfo->ptype == PT_UDP ) {
502 conversation_t *conv2;
504 /* RTP tracks the two sides of the conversation totally separately;
505 * this messes us up totally.
507 * Look for another converstation, going in the opposite direction.
509 conv2 = find_conversation( pinfo->fd->num,
510 &pinfo->dst,&pinfo->src,
512 pinfo->destport,pinfo->srcport, 0 );
514 datax = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
518 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",
519 pinfo->fd->num, conv, conv2, datax, pinfo->ptype,
520 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
522 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
525 conversation_add_proto_data(conv, proto_h223, datax);
529 /* we still haven't found any call data - create a new one for this
532 datax = create_call_info(pinfo->fd->num);
535 g_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
536 pinfo->fd->num, datax, conv, pinfo->ptype,
537 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
539 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
543 conversation_add_proto_data(conv, proto_h223, datax);
544 /* add the source details so we can distinguish directions
546 COPY_ADDRESS(&(datax -> srcaddress), &(pinfo->src));
547 datax -> srcport = pinfo->srcport;
550 /* work out what direction we're really going in */
551 if( ADDRESSES_EQUAL( &(pinfo->src), &(datax->srcaddress))
552 && pinfo->srcport == datax->srcport )
553 pinfo->p2p_dir = P2P_DIR_SENT;
555 pinfo->p2p_dir = P2P_DIR_RECV;
560 static h223_call_info *
561 find_or_create_call_info ( packet_info * pinfo )
563 h223_call_info *datax;
565 datax = find_or_create_call_info_circ(pinfo);
567 datax = find_or_create_call_info_conv(pinfo);
571 /* called from the h245 dissector to handle a MultiplexEntrySend message */
573 h223_set_mc( packet_info* pinfo, guint8 mc, h223_mux_element* me )
575 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
576 h223_vc_info* vc_info;
578 /* if this h245 pdu packet came from an h223 circuit, add the details on
579 * the new mux entry */
581 vc_info = circuit_get_proto_data(circ, proto_h223);
582 add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, me, pinfo->fd->num );
586 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
588 h223_add_lc( packet_info* pinfo, guint16 lc, h223_lc_params* params )
590 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
591 h223_vc_info* vc_info;
593 /* if this h245 pdu packet came from an h223 circuit, add the details on
596 vc_info = circuit_get_proto_data(circ, proto_h223);
597 init_logical_channel( pinfo->fd->num, vc_info->call_info, lc, pinfo->p2p_dir, params );
601 /************************************************************************************
606 static const guint8 crctable[256] = {
607 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
608 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
609 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
610 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
611 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
612 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
613 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
614 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
615 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
616 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
617 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
618 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
619 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
620 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
621 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
622 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
624 static guint8 h223_al2_crc8bit( tvbuff_t *tvb ) {
625 guint32 len = tvb_reported_length(tvb) - 1;
626 const guint8* datax = tvb_get_ptr( tvb, 0, len );
627 unsigned char crc = 0;
629 DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
631 crc = crctable[crc^datax[pos++]];
636 dissect_mux_al_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *vc_tree,
637 /* circuit_t* vc_circuit, */
638 h223_lc_params* lc_params )
640 proto_tree *al_tree = NULL;
641 proto_item *al_item, *hidden_item;
642 proto_tree *al_subtree;
643 proto_item *al_subitem = NULL;
644 proto_item *tmp_item;
645 tvbuff_t *next_tvb = NULL;
646 dissector_handle_t subdissector = lc_params->subdissector;
647 guint32 len = tvb_reported_length(tvb);
649 guint8 calc_checksum;
650 guint8 real_checksum;
651 gboolean al2_sequenced = FALSE;
654 switch( lc_params->al_type ) {
657 al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)",
658 (lc_params->al_type==al1Framed)?"":"not ");
659 al_tree = proto_item_add_subtree (al_item, ett_h223_al1);
660 if(lc_params->al_type == al1Framed) {
661 hidden_item = proto_tree_add_boolean(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
662 PROTO_ITEM_SET_HIDDEN(hidden_item);
665 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
668 case al2WithSequenceNumbers:
669 al2_sequenced = TRUE;
671 case al2WithoutSequenceNumbers:
672 tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
674 al_item = proto_tree_add_item(vc_tree,
675 al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
677 al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
679 PROTO_ITEM_SET_GENERATED(tmp_item);
681 /* check minimum payload length */
682 if(len < (al2_sequenced?2U:1U))
686 if( al2_sequenced ) {
687 proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
691 next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
692 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
694 calc_checksum = h223_al2_crc8bit(tvb);
695 real_checksum = tvb_get_guint8(tvb, len - 1);
697 if( calc_checksum == real_checksum ) {
698 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
699 "CRC: 0x%02x (correct)", real_checksum );
701 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
702 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
703 tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
704 PROTO_ITEM_SET_GENERATED(tmp_item);
706 /* don't pass pdus which fail checksums on to the subdissector */
707 subdissector = data_handle;
711 call_dissector(data_handle, tvb, pinfo, vc_tree);
716 subdissector = data_handle;
718 al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
719 call_dissector(subdissector, next_tvb, pinfo, al_subtree);
722 /************************************************************************************
728 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
730 * tvb buffer containing the MUX-PDU fragment
731 * pinfo info on the packet containing the last fragment of the MUX-PDU
732 * pkt_offset offset within the block from the superdissector where the
733 * fragment starts (must increase monotonically for constant pinfo->fd->num)
734 * pdu_tree dissection tree for the PDU; a single item will be added (with
737 * end_of_mux_sdu true if this is a segmentable VC and this is the last
741 dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb, packet_info *pinfo,
742 guint32 pkt_offset, proto_tree *pdu_tree,
743 h223_call_info* call_info, guint16 vc,
744 gboolean end_of_mux_sdu)
746 /* update the circuit details before passing to a subdissector */
747 guint32 orig_circuit = pinfo->circuit_id;
748 guint32 orig_ctype = pinfo->ctype;
749 pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
750 pinfo->ctype=CT_H223;
753 circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
754 proto_tree *vc_tree = NULL;
756 h223_vc_info *vc_info = NULL;
757 h223_lc_params *lc_params = NULL;
760 vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
761 vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
764 if( subcircuit == NULL ) {
765 g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
766 pinfo->circuit_id, (void *)call_info, vc );
768 vc_info = circuit_get_proto_data(subcircuit, proto_h223);
769 if( vc_info != NULL ) {
770 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
775 if( lc_params != NULL ) {
776 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
778 stream_pdu_fragment_t *frag;
780 substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
781 if(substream == NULL )
782 substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
783 frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
787 g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
788 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
790 frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
791 next_tvb,pinfo,!end_of_mux_sdu);
794 g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
795 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
799 next_tvb = stream_process_reassembled(
801 "Reassembled H.223 AL-PDU",
802 frag, &h223_al_frag_items,
807 /* fudge to pass pkt_offset down to add_h223_mux_element,
808 * should it be called */
809 pdu_offset = pkt_offset;
810 dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
813 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
817 /* restore the original circuit details for future PDUs */
819 pinfo->ctype=orig_ctype;
820 pinfo->circuit_id=orig_circuit;
826 mux_element_sublist_size( h223_mux_element* me )
828 h223_mux_element *current_me = me;
830 while ( current_me ) {
831 current_me = current_me->next;
832 if ( current_me->sublist )
833 length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
835 length += current_me->repeat_count;
837 if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
838 DISSECTOR_ASSERT_NOT_REACHED();
844 /* dissect part of a MUX-PDU payload according to a multiplex list
846 * tvb buffer containing entire mux-pdu payload
847 * pinfo info on the packet containing the last fragment of the MUX-PDU
848 * pkt_offset offset within the block from the superdissector where the
849 * MUX-PDU starts (must increase monotonically for constant
851 * pdu_tree dissection tree for the PDU
852 * call_info data structure for h223 call
854 * offset offset within tvb to start work
855 * endOfMuxSdu true if the end-of-sdu flag was set
858 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo,
859 guint32 pkt_offset, proto_tree *pdu_tree,
860 h223_call_info* call_info,
861 h223_mux_element *me, guint32 offset,
862 gboolean endOfMuxSdu )
864 guint32 len = tvb_reported_length(tvb);
870 if ( me->repeat_count == 0 ) {
871 for(sublist_len = mux_element_sublist_size( me->sublist );
872 offset + sublist_len <= len;
873 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
874 call_info, me->sublist, offset, endOfMuxSdu ) );
876 for(i = 0; i < me->repeat_count; ++i)
877 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
878 call_info, me->sublist, offset, endOfMuxSdu );
881 if ( me->repeat_count == 0 )
882 frag_len = len - offset;
884 frag_len = me->repeat_count;
887 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
888 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
889 call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
898 /* dissect the payload of a MUX-PDU
900 * tvb buffer containing entire mux-pdu payload
901 * pinfo info on the packet containing the last fragment of the MUX-PDU
902 * pkt_offset offset within the block from the superdissector where the
903 * MUX-PDU starts (must increase monotonically for constant
905 * pdu_tree dissection tree for the PDU
906 * call_info data structure for h223 call
907 * mc multiplex code for this PDU
908 * endOfMuxSdu true if the end-of-sdu flag was set
911 dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
912 proto_tree *pdu_tree, h223_call_info *call_info,
913 guint8 mc, gboolean endOfMuxSdu )
915 guint32 len = tvb_reported_length(tvb);
917 h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
920 dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
922 /* no entry found in mux-table. ignore packet and dissect as data */
923 proto_tree *vc_tree = NULL;
926 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
927 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
929 call_dissector(data_handle,tvb,pinfo,vc_tree);
933 /* dissect a reassembled mux-pdu
935 * tvb buffer containing mux-pdu, including header and closing flag
936 * pinfo packet info for packet containing the end of the mux-pdu
937 * pkt_offset offset within the block from the superdissector where the
938 * MUX-PDU starts (must increase monotonically for constant
940 * h223_tree dissection tree for h223 protocol; a single item will be added
942 * call_info h223 info structure for this h223 call
943 * pdu_no index of this pdu within the call
946 dissect_mux_pdu( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
947 proto_tree *h223_tree, h223_call_info *call_info)
950 /* actual (as opposed to reported) payload len */
952 guint32 raw_hdr = 0, correct_hdr = 0;
954 guint16 closing_flag = 0;
957 gboolean end_of_mux_sdu = FALSE;
960 proto_item *pdu_item = NULL;
961 proto_tree *pdu_tree = NULL;
963 #ifdef DEBUG_H223_FRAGMENTATION
964 g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
965 pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
968 switch(call_info->h223_level) {
970 raw_hdr = tvb_get_guint8(tvb,0);
971 mc = (guint8)((raw_hdr>>1) & 0xf);
972 end_of_mux_sdu = raw_hdr & 1;
974 /* closing flag is one byte long for h223 level 0, two for level 1 */
975 len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
977 /* XXX should ignore pdus with incorrect HECs */
981 raw_hdr = tvb_get_letoh24(tvb,0);
982 errors = golay_errors(raw_hdr);
984 len = tvb_length_remaining(tvb,offset)-2;
987 correct_hdr = raw_hdr ^ (guint32)errors;
989 mc = (guint8)(correct_hdr & 0xf);
990 mpl = (guint8)((correct_hdr >> 4) & 0xff);
992 /* we should never have been called if there's not enough data in
994 DISSECTOR_ASSERT(len >= mpl);
996 closing_flag = tvb_get_ntohs(tvb,offset+len);
997 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
1005 /* XXX not implemented */
1007 DISSECTOR_ASSERT_NOT_REACHED();
1013 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
1014 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
1016 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
1017 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
1022 proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
1023 proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1025 switch(call_info->h223_level) {
1027 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1031 if( errors == -1 ) {
1032 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1034 "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1037 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1039 "Raw value: 0x%06x (correct)", raw_hdr );
1041 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1043 "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1045 item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1047 PROTO_ITEM_SET_GENERATED(item);
1048 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1049 proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1054 /* XXX not implemented */
1056 DISSECTOR_ASSERT_NOT_REACHED();
1061 pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1063 dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1065 call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1070 /* any extra data in the PDU, beyond that indictated by the mpl, is
1071 dissected as data. */
1074 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1075 proto_tree *vc_tree = NULL;
1078 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1079 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1081 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1086 /* add the closing HDLC flag */
1088 proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1092 /************************************************************************************
1094 * MUX-PDU delineation and defragmentation
1097 /* attempt to parse the header of a mux pdu */
1099 attempt_mux_level0_header_parse(guint32 nbytes _U_, guint32 hdr _U_, guint32 *minlen _U_)
1101 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1102 DISSECTOR_ASSERT_NOT_REACHED();
1107 attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1109 /* this is untested */
1110 DISSECTOR_ASSERT_NOT_REACHED();
1116 /* don't interpret a repeated hdlc as a header */
1120 /* + 1 byte of header and 2 bytes of closing HDLC */
1121 *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1126 attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1133 /* + 3 bytes of header and 2 bytes of closing HDLC */
1136 /* bah, we get the header in the wrong order */
1138 ((hdr & 0xFF0000) >> 16) |
1140 ((hdr & 0x0000FF) << 16);
1142 errors = golay_errors(hdr);
1145 *minlen += ((hdr >> 4) & 0xff);
1151 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1152 attempt_mux_level0_header_parse,
1153 attempt_mux_level1_header_parse,
1154 attempt_mux_level2_3_header_parse,
1155 attempt_mux_level2_3_header_parse
1159 h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1163 switch(h223_level) {
1165 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1166 DISSECTOR_ASSERT_NOT_REACHED();
1170 masked = tail_buf & 0xffff;
1171 return nbytes >= 2 && masked == 0xE14D;
1174 masked = tail_buf & 0xffff;
1175 return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1178 DISSECTOR_ASSERT_NOT_REACHED();
1183 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1185 * returns the number of bytes processed, or the negative of the number of
1186 * extra bytes needed, or zero if we don't know yet
1190 dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset,
1191 packet_info *pinfo, proto_tree *h223_tree,
1192 h223_call_info *call_info)
1194 tvbuff_t *volatile next_tvb;
1195 volatile guint32 offset = start_offset;
1196 gboolean more_frags = TRUE;
1198 gboolean header_parsed = FALSE;
1199 guint32 header_buf = 0, tail_buf = 0;
1200 guint32 pdu_minlen = 0;
1204 #ifdef DEBUG_H223_FRAGMENTATION
1205 g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1206 pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1209 while( more_frags && offset < tvb_reported_length( tvb )) {
1210 guint8 byte = tvb_get_guint8(tvb, offset++);
1212 /* read a byte into the header buf, if necessary */
1213 if((offset-start_offset) <= 4) {
1218 /* read the byte into the tail buf */
1222 /* if we haven't parsed the header yet, attempt to do so now */
1224 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1225 header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1226 (offset-start_offset,header_buf,&pdu_minlen);
1228 /* if we have successfully parsed the header, we have sufficient data,
1229 * and we have found the closing hdlc, we are done here */
1230 if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1231 if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1238 if(pdu_minlen <= (offset-start_offset)) {
1239 /* we haven't found the closing hdlc yet, but we don't know how
1240 * much more we need */
1241 #ifdef DEBUG_H223_FRAGMENTATION
1242 g_debug("\tBailing, requesting more bytes");
1246 guint32 needed = pdu_minlen-(offset-start_offset);
1247 #ifdef DEBUG_H223_FRAGMENTATION
1248 g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1250 return - (gint) needed;
1254 /* create a tvb for the fragment */
1255 next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1256 offset-start_offset);
1259 /* we catch boundserrors on the pdu so that errors on an
1260 * individual pdu don't screw up the whole of the rest of the
1262 pd_save = pinfo->private_data;
1264 dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1267 CATCH2(BoundsError,ReportedBoundsError) {
1268 /* Restore the private_data structure in case one of the
1269 * called dissectors modified it (and, due to the exception,
1270 * was unable to restore it).
1272 pinfo->private_data = pd_save;
1274 col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1275 proto_tree_add_protocol_format(h223_tree, proto_malformed,
1276 tvb, 0, 0, "[Malformed Packet: %s]",
1277 pinfo->current_proto);
1282 return (offset-start_offset);
1285 /************************************************************************************
1287 * main dissector entry points
1290 /* dissects PDUs from the tvb
1292 * Updates desegment_offset and desegment_len if the end of the data didn't
1293 * line up with the end of a pdu.
1296 dissect_h223 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1298 proto_tree *h223_tree = NULL;
1299 proto_item *h223_item = NULL;
1300 h223_call_info *call_info = NULL;
1303 /* set up the protocol and info fields in the summary pane */
1304 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
1306 col_clear(pinfo->cinfo, COL_INFO);
1308 /* find or create the call_info for this call */
1309 call_info = find_or_create_call_info(pinfo);
1311 /* add the 'h223' tree to the main tree */
1313 h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, FALSE);
1314 h223_tree = proto_item_add_subtree (h223_item, ett_h223);
1317 while( offset < tvb_reported_length( tvb )) {
1318 int res = dissect_mux_pdu_fragment( tvb, offset, pinfo,
1319 h223_tree, call_info);
1321 /* the end of the tvb held the start of a PDU */
1322 pinfo->desegment_offset = offset;
1324 /* if res != 0, we actually know how much more data we need for a
1327 * However, if we return that, it means that we get called twice
1328 * for the next packet; this makes it hard to tell how far throught
1329 * the stream we are and we have to start messing about with
1330 * getting the seqno from the superdissector's private data. So we
1333 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1335 pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1338 /* shrink the h223 protocol item such that it only includes the
1339 * bits we dissected */
1340 proto_item_set_len(h223_item,offset);
1344 col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1352 /* H.223 specifies that the least-significant bit is transmitted first;
1353 * however this is at odds with IAX which transmits bytes with the
1354 * first-received bit as the MSB.
1356 * This dissector swaps the ordering of the bits in each byte before using the
1357 * normal entry point.
1360 dissect_h223_bitswapped (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1362 tvbuff_t *reversed_tvb;
1367 len = tvb_length(tvb);
1368 datax = g_malloc(len);
1369 for( i=0; i<len; i++)
1370 datax[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1373 * Add the reversed tvbuff to the list of tvbuffs to which
1374 * the tvbuff we were handed refers, so it'll get
1375 * cleaned up when that tvbuff is cleaned up.
1377 reversed_tvb = tvb_new_child_real_data(tvb, datax,len,tvb_reported_length(tvb));
1380 tvb_set_free_cb(reversed_tvb, g_free);
1382 /* Add the reversed data to the data source list. */
1383 add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1385 dissect_h223(reversed_tvb,pinfo,tree);
1388 /******************************************************************************/
1391 h223_init_protocol (void)
1393 circuit_chain_init();
1397 void proto_register_h223 (void)
1399 /* A header field is something you can search/filter on.
1401 * We create a structure to register our fields. It consists of an
1402 * array of hf_register_info structures, each of which are of the format
1403 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1406 static hf_register_info hf[] = {
1407 { &hf_h223_non_h223_data,
1408 { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1409 "Initial data in stream, not a PDU", HFILL }},
1411 { &hf_h223_mux_stuffing_pdu,
1412 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1413 "Empty PDU used for stuffing when no data available", HFILL }},
1416 { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1419 { &hf_h223_mux_header,
1420 { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1421 "H.223 MUX header", HFILL }},
1423 { &hf_h223_mux_rawhdr,
1424 { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1425 "Raw header bytes", HFILL }},
1427 { &hf_h223_mux_correctedhdr,
1428 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1429 "Corrected header bytes", HFILL }},
1432 { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1433 "H.223 MUX multiplex code", HFILL }},
1436 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1437 "H.223 MUX multiplex Payload Length", HFILL }},
1439 { &hf_h223_mux_deact,
1440 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1441 "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1444 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1447 { &hf_h223_mux_extra,
1448 { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_NONE, NULL, 0x0,
1449 "data beyond mpl", HFILL }},
1451 { &hf_h223_mux_hdlc2,
1452 { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1453 "framing flag", HFILL }},
1455 /* fields for h.223-mux fragments */
1456 { &hf_h223_mux_fragment_overlap,
1457 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1458 "Fragment overlaps with other fragments", HFILL }},
1460 { &hf_h223_mux_fragment_overlap_conflict,
1461 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1462 "Overlapping fragments contained conflicting data", HFILL }},
1464 { &hf_h223_mux_fragment_multiple_tails,
1465 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1466 "Several tails were found when defragmenting the packet", HFILL }},
1468 { &hf_h223_mux_fragment_too_long_fragment,
1469 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1470 "Fragment contained data past end of packet", HFILL }},
1472 { &hf_h223_mux_fragment_error,
1473 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1474 "Defragmentation error due to illegal fragments", HFILL }},
1476 { &hf_h223_mux_fragment_count,
1477 { "Fragment count", "h223.mux.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
1480 { &hf_h223_mux_fragment,
1481 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1484 { &hf_h223_mux_fragments,
1485 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1488 { &hf_h223_mux_reassembled_in,
1489 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1490 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1492 { &hf_h223_mux_reassembled_length,
1493 { "Reassembled H.223 MUX-PDU length", "h223.mux.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1494 "The total length of the reassembled payload", HFILL }},
1496 /* fields for h.223-al fragments */
1497 { &hf_h223_al_fragment_overlap,
1498 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1499 "Fragment overlaps with other fragments", HFILL }},
1501 { &hf_h223_al_fragment_overlap_conflict,
1502 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1503 "Overlapping fragments contained conflicting data", HFILL }},
1505 { &hf_h223_al_fragment_multiple_tails,
1506 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1507 "Several tails were found when defragmenting the packet", HFILL }},
1509 { &hf_h223_al_fragment_too_long_fragment,
1510 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1511 "Fragment contained data past end of packet", HFILL }},
1513 { &hf_h223_al_fragment_error,
1514 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1515 "Defragmentation error due to illegal fragments", HFILL }},
1517 { &hf_h223_al_fragment_count,
1518 { "Fragment count", "h223.al.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
1521 { &hf_h223_al_fragment,
1522 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1525 { &hf_h223_al_fragments,
1526 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1529 { &hf_h223_al_reassembled_in,
1530 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1531 "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1533 { &hf_h223_al_reassembled_length,
1534 { "Reassembled H.223 AL-PDU length", "h223.al.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1535 "The total length of the reassembled payload", HFILL }},
1540 { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1541 "H.223 AL-PDU using AL1", HFILL }},
1543 { &hf_h223_al1_framed,
1544 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1548 { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1549 "H.223 AL-PDU using AL2", HFILL }},
1551 { &hf_h223_al2_sequenced,
1552 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1553 "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1555 { &hf_h223_al2_unsequenced,
1556 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1557 "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1559 { &hf_h223_al2_seqno,
1560 { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1561 "H.223 AL2 sequence number", HFILL }},
1564 { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1567 { &hf_h223_al2_crc_bad,
1568 { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1571 { &hf_h223_al_payload,
1572 { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1573 "H.223 AL-PDU Payload", HFILL }},
1577 static gint *ett[] = {
1579 &ett_h223_non_h223_data,
1580 &ett_h223_mux_stuffing_pdu,
1582 &ett_h223_mux_header,
1583 &ett_h223_mux_deact,
1585 &ett_h223_mux_extra,
1586 &ett_h223_mux_fragments,
1587 &ett_h223_mux_fragment,
1588 &ett_h223_al_fragments,
1589 &ett_h223_al_fragment,
1592 &ett_h223_al_payload
1596 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1598 proto_register_field_array (proto_h223, hf, array_length (hf));
1599 proto_register_subtree_array (ett, array_length (ett));
1600 register_dissector("h223", dissect_h223, proto_h223);
1601 register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223);
1603 /* register our init routine to be called at the start of a capture,
1604 to clear out our hash tables etc */
1605 register_init_routine(&h223_init_protocol);
1607 h245_set_h223_set_mc_handle( &h223_set_mc );
1608 h245_set_h223_add_lc_handle( &h223_add_lc );
1611 void proto_reg_handoff_h223(void)
1613 dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1614 dissector_handle_t h223 = find_dissector("h223");
1615 data_handle = find_dissector("data");
1616 srp_handle = find_dissector("srp");
1618 dissector_add_handle("tcp.port", h223);
1619 dissector_add_handle("tcp.port", h223_bitswapped);
1620 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1621 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1630 * indent-tabs-mode: nil
1633 * ex: set shiftwidth=4 tabstop=8 expandtab:
1634 * :indentSize=4:tabSize=8:noTabs=true: