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;
57 static int proto_h223_bitswapped = -1;
59 /* The following hf_* variables are used to hold the Wireshark IDs of
60 * our header fields; they are filled out when we call
61 * proto_register_field_array() in proto_register_h223()
63 static int hf_h223_non_h223_data = -1;
64 static int hf_h223_mux_stuffing_pdu = -1;
65 static int hf_h223_mux_pdu = -1;
66 static int hf_h223_mux_header = -1;
67 static int hf_h223_mux_rawhdr = -1;
68 static int hf_h223_mux_correctedhdr = -1;
69 static int hf_h223_mux_mc = -1;
70 static int hf_h223_mux_mpl = -1;
71 static int hf_h223_mux_deact = -1;
72 static int hf_h223_mux_vc = -1;
73 static int hf_h223_mux_extra = -1;
74 static int hf_h223_mux_hdlc2 = -1;
75 static int hf_h223_mux_fragments = -1;
76 static int hf_h223_mux_fragment = -1;
77 static int hf_h223_mux_fragment_overlap = -1;
78 static int hf_h223_mux_fragment_overlap_conflict = -1;
79 static int hf_h223_mux_fragment_multiple_tails = -1;
80 static int hf_h223_mux_fragment_too_long_fragment = -1;
81 static int hf_h223_mux_fragment_error = -1;
82 static int hf_h223_mux_reassembled_in = -1;
84 static int hf_h223_al_fragments = -1;
85 static int hf_h223_al_fragment = -1;
86 static int hf_h223_al_fragment_overlap = -1;
87 static int hf_h223_al_fragment_overlap_conflict = -1;
88 static int hf_h223_al_fragment_multiple_tails = -1;
89 static int hf_h223_al_fragment_too_long_fragment = -1;
90 static int hf_h223_al_fragment_error = -1;
91 static int hf_h223_al_reassembled_in = -1;
93 static int hf_h223_al1 = -1;
94 static int hf_h223_al1_framed = -1;
95 static int hf_h223_al2 = -1;
96 static int hf_h223_al2_sequenced = -1;
97 static int hf_h223_al2_unsequenced = -1;
98 static int hf_h223_al2_seqno = -1;
99 static int hf_h223_al2_crc = -1;
100 static int hf_h223_al2_crc_bad = -1;
102 static int hf_h223_al_payload = -1;
104 /* These are the ids of the subtrees that we may be creating */
105 static gint ett_h223 = -1;
106 static gint ett_h223_non_h223_data = -1;
107 static gint ett_h223_mux_stuffing_pdu = -1;
108 static gint ett_h223_mux_pdu = -1;
109 static gint ett_h223_mux_header = -1;
110 static gint ett_h223_mux_deact = -1;
111 static gint ett_h223_mux_vc = -1;
112 static gint ett_h223_mux_extra = -1;
113 static gint ett_h223_mux_fragments = -1;
114 static gint ett_h223_mux_fragment = -1;
115 static gint ett_h223_al_fragments = -1;
116 static gint ett_h223_al_fragment = -1;
117 static gint ett_h223_al1 = -1;
118 static gint ett_h223_al2 = -1;
119 static gint ett_h223_al_payload = -1;
121 /* These are the handles of our subdissectors */
122 static dissector_handle_t data_handle;
123 static dissector_handle_t srp_handle;
125 static const fragment_items h223_mux_frag_items _U_ = {
126 &ett_h223_mux_fragment,
127 &ett_h223_mux_fragments,
128 &hf_h223_mux_fragments,
129 &hf_h223_mux_fragment,
130 &hf_h223_mux_fragment_overlap,
131 &hf_h223_mux_fragment_overlap_conflict,
132 &hf_h223_mux_fragment_multiple_tails,
133 &hf_h223_mux_fragment_too_long_fragment,
134 &hf_h223_mux_fragment_error,
135 &hf_h223_mux_reassembled_in,
139 static const fragment_items h223_al_frag_items = {
140 &ett_h223_al_fragment,
141 &ett_h223_al_fragments,
142 &hf_h223_al_fragments,
143 &hf_h223_al_fragment,
144 &hf_h223_al_fragment_overlap,
145 &hf_h223_al_fragment_overlap_conflict,
146 &hf_h223_al_fragment_multiple_tails,
147 &hf_h223_al_fragment_too_long_fragment,
148 &hf_h223_al_fragment_error,
149 &hf_h223_al_reassembled_in,
153 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
154 static guint32 pdu_offset;
156 /***************************************************************************
158 * virtual circuit number handling
160 * we have to be able to manage more than one H.223 call at a time,
161 * so have a hash which maps {call,vc} to an integer.
164 typedef struct _h223_call_info h223_call_info;
167 const h223_call_info* call; /* h223 call */
168 guint32 vc; /* child circuit */
171 static GHashTable *circuit_chain_hashtable = NULL;
172 static guint circuit_chain_count = 1;
175 static gint circuit_chain_equal(gconstpointer v, gconstpointer w)
177 const circuit_chain_key *v1 = (const circuit_chain_key *)v;
178 const circuit_chain_key *v2 = (const circuit_chain_key *)w;
180 result = ( v1->call == v2->call &&
181 v1->vc == v2 -> vc );
185 static guint circuit_chain_hash (gconstpointer v)
187 const circuit_chain_key *key = (const circuit_chain_key *)v;
188 guint hash_val = ((guint32)(unsigned long)(key->call))^(((guint32)key->vc) << 16);
192 static guint32 circuit_chain_lookup(const h223_call_info* call_info,
195 circuit_chain_key key, *new_key;
197 key.call = call_info;
199 circuit_id = GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable, &key ));
200 if( circuit_id == 0 ) {
201 new_key = se_alloc(sizeof(circuit_chain_key));
203 circuit_id = ++circuit_chain_count;
204 g_hash_table_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id));
209 static void circuit_chain_init(void)
211 if (circuit_chain_hashtable)
212 g_hash_table_destroy(circuit_chain_hashtable);
213 circuit_chain_hashtable = g_hash_table_new(circuit_chain_hash, circuit_chain_equal);
214 circuit_chain_count = 1;
218 /***************************************************************************
220 * Call information management
224 /* we keep information on each call in an h223_call_info structure
226 * We attach the h223_call_info structures to individual calls with
227 * circuit_add_proto_data().
230 typedef struct _h223_mux_element_listitem h223_mux_element_listitem;
231 struct _h223_mux_element_listitem {
232 h223_mux_element *me;
235 h223_mux_element_listitem *next;
238 /* we have this information for each stream */
240 h223_mux_element_listitem* mux_table[16];
241 } h223_call_direction_data;
244 struct _h223_call_info {
245 /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
246 specified in the annexes
250 /* for H.223 streams over TCP (as opposed to IAX), this
251 stores the source address and port of the first packet spotted,
252 so that we can differentiate directions.
257 h223_call_direction_data direction_data[2];
260 typedef struct _h223_lc_params_listitem h223_lc_params_listitem;
261 struct _h223_lc_params_listitem
263 h223_lc_params *lc_params;
266 h223_lc_params_listitem *next;
270 h223_lc_params_listitem *lc_params[2];
271 h223_call_info *call_info;
274 static void add_h223_mux_element(h223_call_direction_data *direct, guint8 mc, h223_mux_element *me, guint32 framenum)
276 h223_mux_element_listitem *li;
277 h223_mux_element_listitem **old_li_ptr;
278 h223_mux_element_listitem *old_li;
280 DISSECTOR_ASSERT(mc < 16);
282 li = se_alloc(sizeof(h223_mux_element_listitem));
283 old_li_ptr = &(direct->mux_table[mc]);
284 old_li = *old_li_ptr;
286 direct->mux_table[mc] = li;
288 while( old_li->next ) {
289 old_li_ptr = &(old_li->next);
290 old_li = *old_li_ptr;
292 if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset) )
294 else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset )
295 *old_li_ptr = li; /* replace the tail of the list with the new item, since */
296 /* a single h223 pdu has just set the same MC twice.. */
300 li->first_frame = framenum;
301 li->pdu_offset = pdu_offset;
306 static h223_mux_element* find_h223_mux_element(h223_call_direction_data* direct, guint8 mc, guint32 framenum, guint32 pkt_offset)
308 h223_mux_element_listitem* li;
310 DISSECTOR_ASSERT(mc < 16);
312 li = direct->mux_table[mc];
314 while( li && li->next && li->next->first_frame < framenum )
316 while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset )
325 static void add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, guint32 framenum )
327 h223_lc_params_listitem *li = se_alloc(sizeof(h223_lc_params_listitem));
328 h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction ? 0 : 1]);
329 h223_lc_params_listitem *old_li = *old_li_ptr;
331 vc_info->lc_params[direction ? 0 : 1] = li;
333 while( old_li->next ) {
334 old_li_ptr = &(old_li->next);
335 old_li = *old_li_ptr;
337 if( framenum < old_li->first_frame )
339 else if( framenum == old_li->first_frame )
343 old_li->last_frame = framenum - 1;
346 li->first_frame = framenum;
349 li->lc_params = lc_params;
352 static h223_lc_params* find_h223_lc_params(h223_vc_info* vc_info, int direction, guint32 framenum)
354 h223_lc_params_listitem* li = vc_info->lc_params[direction? 0 : 1];
355 while( li && li->next && li->next->first_frame <= framenum )
358 return li->lc_params;
363 static void init_direction_data(h223_call_direction_data *direct)
366 h223_mux_element *mc0_element;
368 for ( i = 0; i < 16; ++i )
369 direct->mux_table[i] = NULL;
371 /* set up MC 0 to contain just VC 0 */
372 mc0_element = se_alloc(sizeof(h223_mux_element));
373 add_h223_mux_element( direct, 0, mc0_element, 0 );
374 mc0_element->sublist = NULL;
376 mc0_element->repeat_count = 0; /* until closing flag */
377 mc0_element->next = NULL;
380 static h223_vc_info* h223_vc_info_new( h223_call_info* call_info )
382 h223_vc_info *vc_info = se_alloc(sizeof(h223_vc_info));
383 vc_info->lc_params[0] = vc_info->lc_params[1] = NULL;
384 vc_info->call_info = call_info;
388 static void init_logical_channel( guint32 start_frame, h223_call_info* call_info, int vc, int direction, h223_lc_params* params )
390 guint32 circuit_id = circuit_chain_lookup(call_info, vc);
391 circuit_t *subcircuit;
392 h223_vc_info *vc_info;
393 subcircuit = find_circuit( CT_H223, circuit_id, start_frame );
395 if( subcircuit == NULL ) {
396 subcircuit = circuit_new( CT_H223, circuit_id, start_frame );
398 g_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc);
400 vc_info = h223_vc_info_new( call_info );
401 circuit_add_proto_data( subcircuit, proto_h223, vc_info );
403 vc_info = circuit_get_proto_data( subcircuit, proto_h223 );
405 add_h223_lc_params( vc_info, direction, params, start_frame );
408 /* create a brand-new h223_call_info structure */
409 static h223_call_info *create_call_info( guint32 start_frame )
411 h223_call_info *datax;
412 h223_lc_params *vc0_params;
414 datax = se_alloc(sizeof(h223_call_info));
416 /* initialise the call info */
417 init_direction_data(&datax -> direction_data[0]);
418 init_direction_data(&datax -> direction_data[1]);
420 /* FIXME shouldn't this be figured out dynamically? */
421 datax -> h223_level = 2;
423 vc0_params = se_alloc(sizeof(h223_lc_params));
424 vc0_params->al_type = al1Framed;
425 vc0_params->al_params = NULL;
426 vc0_params->segmentable = TRUE;
427 vc0_params->subdissector = srp_handle;
428 init_logical_channel( start_frame, datax, 0, P2P_DIR_SENT, vc0_params );
429 init_logical_channel( start_frame, datax, 0, P2P_DIR_RECV, vc0_params );
433 /* find or create call_info struct for calls over circuits (eg, IAX) */
434 static h223_call_info *find_or_create_call_info_circ(packet_info * pinfo)
436 h223_call_info *datax;
437 circuit_t *circ = NULL;
439 if(pinfo->ctype != CT_NONE)
440 circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
444 datax = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
446 if( datax == NULL ) {
447 datax = create_call_info(pinfo->fd->num);
450 g_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
451 pinfo->fd->num, datax, circ, pinfo->ctype, pinfo->circuit_id);
453 circuit_add_proto_data(circ, proto_h223, datax);
456 /* work out what direction we're really going in */
457 if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1)
458 pinfo->p2p_dir = P2P_DIR_SENT;
463 /* find or create call_info struct for calls over conversations (eg, RTP) */
464 static h223_call_info *find_or_create_call_info_conv(packet_info * pinfo)
466 h223_call_info *datax;
467 conversation_t *conv;
469 /* assume we're running atop TCP or RTP; use the conversation support */
470 conv = find_conversation( pinfo->fd->num,
471 &pinfo->src,&pinfo->dst,
473 pinfo->srcport,pinfo->destport, 0 );
475 /* both RTP and TCP track their conversations, so just assert here if
476 * we can't find one */
477 DISSECTOR_ASSERT(conv);
479 datax = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
481 if(datax == NULL && pinfo->ptype == PT_UDP ) {
482 conversation_t *conv2;
484 /* RTP tracks the two sides of the conversation totally separately;
485 * this messes us up totally.
487 * Look for another converstation, going in the opposite direction.
489 conv2 = find_conversation( pinfo->fd->num,
490 &pinfo->dst,&pinfo->src,
492 pinfo->destport,pinfo->srcport, 0 );
494 datax = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
498 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",
499 pinfo->fd->num, conv, conv2, datax, pinfo->ptype,
500 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
502 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
505 conversation_add_proto_data(conv, proto_h223, datax);
509 /* we still haven't found any call data - create a new one for this
512 datax = create_call_info(pinfo->fd->num);
515 g_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
516 pinfo->fd->num, datax, conv, pinfo->ptype,
517 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
519 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
523 conversation_add_proto_data(conv, proto_h223, datax);
524 /* add the source details so we can distinguish directions
526 COPY_ADDRESS(&(datax -> srcaddress), &(pinfo->src));
527 datax -> srcport = pinfo->srcport;
530 /* work out what direction we're really going in */
531 if( ADDRESSES_EQUAL( &(pinfo->src), &(datax->srcaddress))
532 && pinfo->srcport == datax->srcport )
533 pinfo->p2p_dir = P2P_DIR_SENT;
535 pinfo->p2p_dir = P2P_DIR_RECV;
540 static h223_call_info *find_or_create_call_info ( packet_info * pinfo )
542 h223_call_info *datax;
544 datax = find_or_create_call_info_circ(pinfo);
546 datax = find_or_create_call_info_conv(pinfo);
550 /* called from the h245 dissector to handle a MultiplexEntrySend message */
551 static void h223_set_mc( packet_info* pinfo, guint8 mc, h223_mux_element* me )
553 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
554 h223_vc_info* vc_info;
556 /* if this h245 pdu packet came from an h223 circuit, add the details on
557 * the new mux entry */
559 vc_info = circuit_get_proto_data(circ, proto_h223);
560 add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, me, pinfo->fd->num );
564 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
565 static void h223_add_lc( packet_info* pinfo, guint16 lc, h223_lc_params* params )
567 circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
568 h223_vc_info* vc_info;
570 /* if this h245 pdu packet came from an h223 circuit, add the details on
573 vc_info = circuit_get_proto_data(circ, proto_h223);
574 init_logical_channel( pinfo->fd->num, vc_info->call_info, lc, pinfo->p2p_dir, params );
578 /************************************************************************************
583 static const guint8 crctable[256] = {
584 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
585 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
586 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
587 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
588 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
589 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
590 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
591 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
592 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
593 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
594 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
595 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
596 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
597 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
598 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
599 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
601 static guint8 h223_al2_crc8bit( tvbuff_t *tvb ) {
602 guint32 len = tvb_reported_length(tvb) - 1;
603 const guint8* datax = tvb_get_ptr( tvb, 0, len );
604 unsigned char crc = 0;
606 DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
608 crc = crctable[crc^datax[pos++]];
612 static void dissect_mux_al_pdu( tvbuff_t *tvb,
615 /* circuit_t* vc_circuit, */
616 h223_lc_params* lc_params )
618 proto_tree *al_tree = NULL;
619 proto_item *al_item, *hidden_item;
620 proto_tree *al_subtree;
621 proto_item *al_subitem = NULL;
622 proto_item *tmp_item;
623 tvbuff_t *next_tvb = NULL;
624 dissector_handle_t subdissector = lc_params->subdissector;
625 guint32 len = tvb_reported_length(tvb);
627 guint8 calc_checksum;
628 guint8 real_checksum;
629 gboolean al2_sequenced = FALSE;
632 switch( lc_params->al_type ) {
635 al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)",
636 (lc_params->al_type==al1Framed)?"":"not ");
637 al_tree = proto_item_add_subtree (al_item, ett_h223_al1);
638 if(lc_params->al_type == al1Framed) {
639 hidden_item = proto_tree_add_boolean(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
640 PROTO_ITEM_SET_HIDDEN(hidden_item);
643 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
646 case al2WithSequenceNumbers:
647 al2_sequenced = TRUE;
649 case al2WithoutSequenceNumbers:
650 tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
652 al_item = proto_tree_add_item(vc_tree,
653 al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
655 al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
657 PROTO_ITEM_SET_GENERATED(tmp_item);
659 /* check minimum payload length */
660 if(len < (al2_sequenced?2U:1U))
664 if( al2_sequenced ) {
665 proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
669 next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
670 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
672 calc_checksum = h223_al2_crc8bit(tvb);
673 real_checksum = tvb_get_guint8(tvb, len - 1);
675 if( calc_checksum == real_checksum ) {
676 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
677 "CRC: 0x%02x (correct)", real_checksum );
679 proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
680 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
681 tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
682 PROTO_ITEM_SET_GENERATED(tmp_item);
684 /* don't pass pdus which fail checksums on to the subdissector */
685 subdissector = data_handle;
689 call_dissector(data_handle, tvb, pinfo, vc_tree);
694 subdissector = data_handle;
696 al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
697 call_dissector(subdissector, next_tvb, pinfo, al_subtree);
700 /************************************************************************************
706 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
708 * tvb buffer containing the MUX-PDU fragment
709 * pinfo info on the packet containing the last fragment of the MUX-PDU
710 * pkt_offset offset within the block from the superdissector where the
711 * fragment starts (must increase monotonically for constant pinfo->fd->num)
712 * pdu_tree dissection tree for the PDU; a single item will be added (with
715 * end_of_mux_sdu true if this is a segmentable VC and this is the last
718 static void dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb,
721 proto_tree *pdu_tree,
722 h223_call_info* call_info,
723 guint16 vc, gboolean end_of_mux_sdu)
725 /* update the circuit details before passing to a subdissector */
726 guint32 orig_circuit = pinfo->circuit_id;
727 guint32 orig_ctype = pinfo->ctype;
728 pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
729 pinfo->ctype=CT_H223;
732 circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
733 proto_tree *vc_tree = NULL;
735 h223_vc_info *vc_info = NULL;
736 h223_lc_params *lc_params = NULL;
739 vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
740 vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
743 if( subcircuit == NULL ) {
744 g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
745 pinfo->circuit_id, (void *)call_info, vc );
747 vc_info = circuit_get_proto_data(subcircuit, proto_h223);
748 if( vc_info != NULL ) {
749 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
754 if( lc_params != NULL ) {
755 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
757 stream_pdu_fragment_t *frag;
759 substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
760 if(substream == NULL )
761 substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
762 frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
766 g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
767 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
769 frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
770 next_tvb,pinfo,!end_of_mux_sdu);
773 g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
774 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
778 next_tvb = stream_process_reassembled(
780 "Reassembled H.223 AL-PDU",
781 frag, &h223_al_frag_items,
786 /* fudge to pass pkt_offset down to add_h223_mux_element,
787 * should it be called */
788 pdu_offset = pkt_offset;
789 dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
792 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
796 /* restore the original circuit details for future PDUs */
798 pinfo->ctype=orig_ctype;
799 pinfo->circuit_id=orig_circuit;
804 static guint32 mux_element_sublist_size( h223_mux_element* me )
806 h223_mux_element *current_me = me;
808 while ( current_me ) {
809 current_me = current_me->next;
810 if ( current_me->sublist )
811 length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
813 length += current_me->repeat_count;
815 if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
816 DISSECTOR_ASSERT_NOT_REACHED();
822 /* dissect part of a MUX-PDU payload according to a multiplex list
824 * tvb buffer containing entire mux-pdu payload
825 * pinfo info on the packet containing the last fragment of the MUX-PDU
826 * pkt_offset offset within the block from the superdissector where the
827 * MUX-PDU starts (must increase monotonically for constant
829 * pdu_tree dissection tree for the PDU
830 * call_info data structure for h223 call
832 * offset offset within tvb to start work
833 * endOfMuxSdu true if the end-of-sdu flag was set
835 static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
836 proto_tree *pdu_tree,
837 h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu )
839 guint32 len = tvb_reported_length(tvb);
845 if ( me->repeat_count == 0 ) {
846 for(sublist_len = mux_element_sublist_size( me->sublist );
847 offset + sublist_len <= len;
848 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
849 call_info, me->sublist, offset, endOfMuxSdu ) );
851 for(i = 0; i < me->repeat_count; ++i)
852 offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
853 call_info, me->sublist, offset, endOfMuxSdu );
856 if ( me->repeat_count == 0 )
857 frag_len = len - offset;
859 frag_len = me->repeat_count;
862 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
863 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
864 call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
873 /* dissect the payload of a MUX-PDU
875 * tvb buffer containing entire mux-pdu payload
876 * pinfo info on the packet containing the last fragment of the MUX-PDU
877 * pkt_offset offset within the block from the superdissector where the
878 * MUX-PDU starts (must increase monotonically for constant
880 * pdu_tree dissection tree for the PDU
881 * call_info data structure for h223 call
882 * mc multiplex code for this PDU
883 * endOfMuxSdu true if the end-of-sdu flag was set
885 static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
886 proto_tree *pdu_tree,
887 h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu )
889 guint32 len = tvb_reported_length(tvb);
891 h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
894 dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
896 /* no entry found in mux-table. ignore packet and dissect as data */
897 proto_tree *vc_tree = NULL;
900 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
901 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
903 call_dissector(data_handle,tvb,pinfo,vc_tree);
907 /* dissect a reassembled mux-pdu
909 * tvb buffer containing mux-pdu, including header and closing flag
910 * pinfo packet info for packet containing the end of the mux-pdu
911 * pkt_offset offset within the block from the superdissector where the
912 * MUX-PDU starts (must increase monotonically for constant
914 * h223_tree dissection tree for h223 protocol; a single item will be added
916 * call_info h223 info structure for this h223 call
917 * pdu_no index of this pdu within the call
919 static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo,
921 proto_tree *h223_tree,
922 h223_call_info *call_info)
925 /* actual (as opposed to reported) payload len */
927 guint32 raw_hdr = 0, correct_hdr = 0;
929 guint16 closing_flag = 0;
932 gboolean end_of_mux_sdu = FALSE;
935 proto_item *pdu_item = NULL;
936 proto_tree *pdu_tree = NULL;
938 #ifdef DEBUG_H223_FRAGMENTATION
939 g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
940 pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
943 switch(call_info->h223_level) {
945 raw_hdr = tvb_get_guint8(tvb,0);
946 mc = (guint8)((raw_hdr>>1) & 0xf);
947 end_of_mux_sdu = raw_hdr & 1;
949 /* closing flag is one byte long for h223 level 0, two for level 1 */
950 len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
952 /* XXX should ignore pdus with incorrect HECs */
956 raw_hdr = tvb_get_letoh24(tvb,0);
957 errors = golay_errors(raw_hdr);
959 len = tvb_length_remaining(tvb,offset)-2;
962 correct_hdr = raw_hdr ^ (guint32)errors;
964 mc = (guint8)(correct_hdr & 0xf);
965 mpl = (guint8)((correct_hdr >> 4) & 0xff);
967 /* we should never have been called if there's not enough data in
969 DISSECTOR_ASSERT(len >= mpl);
971 closing_flag = tvb_get_ntohs(tvb,offset+len);
972 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
980 /* XXX not implemented */
983 DISSECTOR_ASSERT_NOT_REACHED();
989 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
990 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
992 pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
993 pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
998 proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
999 proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1001 switch(call_info->h223_level) {
1003 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1007 if( errors == -1 ) {
1008 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1010 "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1013 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1015 "Raw value: 0x%06x (correct)", raw_hdr );
1017 proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1019 "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1021 item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1023 PROTO_ITEM_SET_GENERATED(item);
1024 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1025 proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1030 /* XXX not implemented */
1032 DISSECTOR_ASSERT_NOT_REACHED();
1037 pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1039 dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1041 call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1046 /* any extra data in the PDU, beyond that indictated by the mpl, is
1047 dissected as data. */
1050 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1051 proto_tree *vc_tree = NULL;
1054 proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1055 vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1057 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1062 /* add the closing HDLC flag */
1064 proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1068 /************************************************************************************
1070 * MUX-PDU delineation and defragmentation
1073 /* attempt to parse the header of a mux pdu */
1074 static gboolean attempt_mux_level0_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1076 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1077 DISSECTOR_ASSERT_NOT_REACHED();
1084 static gboolean attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1086 /* this is untested */
1087 DISSECTOR_ASSERT_NOT_REACHED();
1093 /* don't interpret a repeated hdlc as a header */
1097 /* + 1 byte of header and 2 bytes of closing HDLC */
1098 *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1102 static gboolean attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1109 /* + 3 bytes of header and 2 bytes of closing HDLC */
1112 /* bah, we get the header in the wrong order */
1114 ((hdr & 0xFF0000) >> 16) |
1116 ((hdr & 0x0000FF) << 16);
1118 errors = golay_errors(hdr);
1121 *minlen += ((hdr >> 4) & 0xff);
1127 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1128 attempt_mux_level0_header_parse,
1129 attempt_mux_level1_header_parse,
1130 attempt_mux_level2_3_header_parse,
1131 attempt_mux_level2_3_header_parse
1134 static gboolean h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1138 switch(h223_level) {
1140 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1141 DISSECTOR_ASSERT_NOT_REACHED();
1145 masked = tail_buf & 0xffff;
1146 return nbytes >= 2 && masked == 0xE14D;
1149 masked = tail_buf & 0xffff;
1150 return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1153 DISSECTOR_ASSERT_NOT_REACHED();
1158 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1160 * returns the number of bytes processed, or the negative of the number of
1161 * extra bytes needed, or zero if we don't know yet
1164 static gint dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo,
1165 proto_tree *h223_tree,
1166 h223_call_info *call_info)
1168 tvbuff_t *volatile next_tvb;
1169 volatile guint32 offset = start_offset;
1170 gboolean more_frags = TRUE;
1172 gboolean header_parsed = FALSE;
1173 guint32 header_buf = 0, tail_buf = 0;
1174 guint32 pdu_minlen = 0;
1177 #ifdef DEBUG_H223_FRAGMENTATION
1178 g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1179 pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1182 while( more_frags && offset < tvb_reported_length( tvb )) {
1183 guint8 byte = tvb_get_guint8(tvb, offset++);
1185 /* read a byte into the header buf, if necessary */
1186 if((offset-start_offset) <= 4) {
1191 /* read the byte into the tail buf */
1195 /* if we haven't parsed the header yet, attempt to do so now */
1197 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1198 header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1199 (offset-start_offset,header_buf,&pdu_minlen);
1201 /* if we have successfully parsed the header, we have sufficient data,
1202 * and we have found the closing hdlc, we are done here */
1203 if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1204 if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1211 if(pdu_minlen <= (offset-start_offset)) {
1212 /* we haven't found the closing hdlc yet, but we don't know how
1213 * much more we need */
1214 #ifdef DEBUG_H223_FRAGMENTATION
1215 g_debug("\tBailing, requesting more bytes");
1219 guint32 needed = pdu_minlen-(offset-start_offset);
1220 #ifdef DEBUG_H223_FRAGMENTATION
1221 g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1223 return - (gint) needed;
1227 /* create a tvb for the fragment */
1228 next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1229 offset-start_offset);
1232 /* we catch boundserrors on the pdu so that errors on an
1233 * individual pdu don't screw up the whole of the rest of the
1236 dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1239 CATCH2(BoundsError,ReportedBoundsError) {
1240 col_append_str(pinfo->cinfo, COL_INFO,
1241 "[Malformed Packet]");
1242 proto_tree_add_protocol_format(h223_tree, proto_malformed,
1243 tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1248 return (offset-start_offset);
1251 /************************************************************************************
1253 * main dissector entry points
1256 /* dissects PDUs from the tvb
1258 * Updates desegment_offset and desegment_len if the end of the data didn't
1259 * line up with the end of a pdu.
1261 static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1263 proto_tree *h223_tree = NULL;
1264 proto_item *h223_item = NULL;
1265 h223_call_info *call_info = NULL;
1268 /* set up the protocol and info fields in the summary pane */
1269 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1270 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
1272 col_clear(pinfo->cinfo, COL_INFO);
1274 /* find or create the call_info for this call */
1275 call_info = find_or_create_call_info(pinfo);
1277 /* add the 'h223' tree to the main tree */
1279 h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, FALSE);
1280 h223_tree = proto_item_add_subtree (h223_item, ett_h223);
1283 while( offset < tvb_reported_length( tvb )) {
1284 int res = dissect_mux_pdu_fragment( tvb, offset, pinfo,
1285 h223_tree, call_info);
1287 /* the end of the tvb held the start of a PDU */
1288 pinfo->desegment_offset = offset;
1290 /* if res != 0, we actually know how much more data we need for a
1293 * However, if we return that, it means that we get called twice
1294 * for the next packet; this makes it hard to tell how far throught
1295 * the stream we are and we have to start messing about with
1296 * getting the seqno from the superdissector's private data. So we
1299 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1301 pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1304 /* shrink the h223 protocol item such that it only includes the
1305 * bits we dissected */
1306 proto_item_set_len(h223_item,offset);
1310 col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1318 /* H.223 specifies that the least-significant bit is transmitted first;
1319 * however this is at odds with IAX which transmits bytes with the
1320 * first-received bit as the MSB.
1322 * This dissector swaps the ordering of the bits in each byte before using the
1323 * normal entry point.
1325 static void dissect_h223_bitswapped (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1327 tvbuff_t *reversed_tvb;
1332 len = tvb_length(tvb);
1333 datax = g_malloc(len);
1334 for( i=0; i<len; i++)
1335 datax[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1338 * Add the reversed tvbuff to the list of tvbuffs to which
1339 * the tvbuff we were handed refers, so it'll get
1340 * cleaned up when that tvbuff is cleaned up.
1342 reversed_tvb = tvb_new_child_real_data(tvb, datax,len,tvb_reported_length(tvb));
1345 tvb_set_free_cb(reversed_tvb, g_free);
1347 /* Add the reversed data to the data source list. */
1348 add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1350 dissect_h223(reversed_tvb,pinfo,tree);
1353 /******************************************************************************/
1355 static void h223_init_protocol (void)
1357 circuit_chain_init();
1361 void proto_register_h223 (void)
1363 /* A header field is something you can search/filter on.
1365 * We create a structure to register our fields. It consists of an
1366 * array of hf_register_info structures, each of which are of the format
1367 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1370 static hf_register_info hf[] = {
1371 { &hf_h223_non_h223_data,
1372 { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1373 "Initial data in stream, not a PDU", HFILL }},
1375 { &hf_h223_mux_stuffing_pdu,
1376 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1377 "Empty PDU used for stuffing when no data available", HFILL }},
1380 { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1383 { &hf_h223_mux_header,
1384 { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1385 "H.223 MUX header", HFILL }},
1387 { &hf_h223_mux_rawhdr,
1388 { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1389 "Raw header bytes", HFILL }},
1391 { &hf_h223_mux_correctedhdr,
1392 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1393 "Corrected header bytes", HFILL }},
1396 { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1397 "H.223 MUX multiplex code", HFILL }},
1400 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1401 "H.223 MUX multiplex Payload Length", HFILL }},
1403 { &hf_h223_mux_deact,
1404 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1405 "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1408 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1409 "H.223 Virtual Circuit", HFILL }},
1411 { &hf_h223_mux_extra,
1412 { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_NONE, NULL, 0x0,
1413 "data beyond mpl", HFILL }},
1415 { &hf_h223_mux_hdlc2,
1416 { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1417 "framing flag", HFILL }},
1419 /* fields for h.223-mux fragments */
1420 { &hf_h223_mux_fragment_overlap,
1421 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1422 "Fragment overlaps with other fragments", HFILL }},
1424 { &hf_h223_mux_fragment_overlap_conflict,
1425 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1426 "Overlapping fragments contained conflicting data", HFILL }},
1428 { &hf_h223_mux_fragment_multiple_tails,
1429 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1430 "Several tails were found when defragmenting the packet", HFILL }},
1432 { &hf_h223_mux_fragment_too_long_fragment,
1433 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1434 "Fragment contained data past end of packet", HFILL }},
1436 { &hf_h223_mux_fragment_error,
1437 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1438 "Defragmentation error due to illegal fragments", HFILL }},
1440 { &hf_h223_mux_fragment,
1441 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1444 { &hf_h223_mux_fragments,
1445 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1448 { &hf_h223_mux_reassembled_in,
1449 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1450 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1452 /* fields for h.223-al fragments */
1453 { &hf_h223_al_fragment_overlap,
1454 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1455 "Fragment overlaps with other fragments", HFILL }},
1457 { &hf_h223_al_fragment_overlap_conflict,
1458 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1459 "Overlapping fragments contained conflicting data", HFILL }},
1461 { &hf_h223_al_fragment_multiple_tails,
1462 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1463 "Several tails were found when defragmenting the packet", HFILL }},
1465 { &hf_h223_al_fragment_too_long_fragment,
1466 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1467 "Fragment contained data past end of packet", HFILL }},
1469 { &hf_h223_al_fragment_error,
1470 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1471 "Defragmentation error due to illegal fragments", HFILL }},
1473 { &hf_h223_al_fragment,
1474 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1477 { &hf_h223_al_fragments,
1478 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1481 { &hf_h223_al_reassembled_in,
1482 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1483 "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1488 { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1489 "H.223 AL-PDU using AL1", HFILL }},
1491 { &hf_h223_al1_framed,
1492 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1496 { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1497 "H.223 AL-PDU using AL2", HFILL }},
1499 { &hf_h223_al2_sequenced,
1500 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1501 "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1503 { &hf_h223_al2_unsequenced,
1504 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1505 "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1507 { &hf_h223_al2_seqno,
1508 { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1509 "H.223 AL2 sequence number", HFILL }},
1512 { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1515 { &hf_h223_al2_crc_bad,
1516 { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1519 { &hf_h223_al_payload,
1520 { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1521 "H.223 AL-PDU Payload", HFILL }},
1525 static gint *ett[] = {
1527 &ett_h223_non_h223_data,
1528 &ett_h223_mux_stuffing_pdu,
1530 &ett_h223_mux_header,
1531 &ett_h223_mux_deact,
1533 &ett_h223_mux_extra,
1534 &ett_h223_mux_fragments,
1535 &ett_h223_mux_fragment,
1536 &ett_h223_al_fragments,
1537 &ett_h223_al_fragment,
1540 &ett_h223_al_payload
1544 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1545 proto_h223_bitswapped =
1546 proto_register_protocol ("Bitswapped ITU-T Recommendation H.223", "H.223 (Bitswapped)", "h223_bitswapped");
1548 proto_register_field_array (proto_h223, hf, array_length (hf));
1549 proto_register_subtree_array (ett, array_length (ett));
1550 register_dissector("h223", dissect_h223, proto_h223);
1551 register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped);
1553 /* register our init routine to be called at the start of a capture,
1554 to clear out our hash tables etc */
1555 register_init_routine(&h223_init_protocol);
1557 h245_set_h223_set_mc_handle( &h223_set_mc );
1558 h245_set_h223_add_lc_handle( &h223_add_lc );
1561 void proto_reg_handoff_h223(void)
1563 dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1564 dissector_handle_t h223 = find_dissector("h223");
1565 data_handle = find_dissector("data");
1566 srp_handle = find_dissector("srp");
1568 dissector_add_handle("tcp.port", h223);
1569 dissector_add_handle("tcp.port", h223_bitswapped);
1570 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1571 dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1580 * indent-tabs-mode: nil
1583 * ex: set shiftwidth=4 tabstop=4 expandtab
1584 * :indentSize=4:tabSize=4:noTabs=true: