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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/wmem/wmem.h>
30 #include <epan/bitswap.h>
31 #include <epan/circuit.h>
32 #include <epan/conversation.h>
33 #include <epan/packet.h>
34 #include <epan/exceptions.h>
35 #include <epan/stream.h>
36 #include <epan/reassemble.h>
37 #include <epan/golay.h>
38 #include <epan/iax2_codec_type.h>
39 #include <epan/show_exception.h>
40 #include <epan/asn1.h>
41 #include <epan/dissectors/packet-h245.h>
43 #include "packet-h223.h"
47 /* #define DEBUG_H223 */
49 /* debug the mux-pdu defragmentation code. warning: verbose output! */
50 /* #define DEBUG_H223_FRAGMENTATION */
52 #define PROTO_TAG_H223 "H223"
54 /* Wireshark ID of the H.223 protocol */
55 static int proto_h223
= -1;
57 /* The following hf_* variables are used to hold the Wireshark IDs of
58 * our header fields; they are filled out when we call
59 * proto_register_field_array() in proto_register_h223()
61 /* static int hf_h223_non_h223_data = -1; */
62 static int hf_h223_mux_stuffing_pdu
= -1;
63 static int hf_h223_mux_pdu
= -1;
64 static int hf_h223_mux_header
= -1;
65 static int hf_h223_mux_rawhdr
= -1;
66 static int hf_h223_mux_correctedhdr
= -1;
67 static int hf_h223_mux_mc
= -1;
68 static int hf_h223_mux_mpl
= -1;
69 static int hf_h223_mux_deact
= -1;
70 static int hf_h223_mux_vc
= -1;
71 static int hf_h223_mux_extra
= -1;
72 static int hf_h223_mux_hdlc2
= -1;
73 static int hf_h223_mux_fragments
= -1;
74 static int hf_h223_mux_fragment
= -1;
75 static int hf_h223_mux_fragment_overlap
= -1;
76 static int hf_h223_mux_fragment_overlap_conflict
= -1;
77 static int hf_h223_mux_fragment_multiple_tails
= -1;
78 static int hf_h223_mux_fragment_too_long_fragment
= -1;
79 static int hf_h223_mux_fragment_error
= -1;
80 static int hf_h223_mux_fragment_count
= -1;
81 static int hf_h223_mux_reassembled_in
= -1;
82 static int hf_h223_mux_reassembled_length
= -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_fragment_count
= -1;
92 static int hf_h223_al_reassembled_in
= -1;
93 static int hf_h223_al_reassembled_length
= -1;
95 static int hf_h223_al1
= -1;
96 static int hf_h223_al1_framed
= -1;
97 static int hf_h223_al2
= -1;
98 static int hf_h223_al2_sequenced
= -1;
99 static int hf_h223_al2_unsequenced
= -1;
100 static int hf_h223_al2_seqno
= -1;
101 static int hf_h223_al2_crc
= -1;
102 static int hf_h223_al2_crc_bad
= -1;
104 static int hf_h223_al_payload
= -1;
106 /* These are the ids of the subtrees that we may be creating */
107 static gint ett_h223
= -1;
108 static gint ett_h223_non_h223_data
= -1;
109 static gint ett_h223_mux_stuffing_pdu
= -1;
110 static gint ett_h223_mux_pdu
= -1;
111 static gint ett_h223_mux_header
= -1;
112 static gint ett_h223_mux_deact
= -1;
113 static gint ett_h223_mux_vc
= -1;
114 static gint ett_h223_mux_extra
= -1;
115 static gint ett_h223_mux_fragments
= -1;
116 static gint ett_h223_mux_fragment
= -1;
117 static gint ett_h223_al_fragments
= -1;
118 static gint ett_h223_al_fragment
= -1;
119 static gint ett_h223_al1
= -1;
120 static gint ett_h223_al2
= -1;
121 static gint ett_h223_al_payload
= -1;
123 /* These are the handles of our subdissectors */
124 static dissector_handle_t data_handle
;
125 static dissector_handle_t srp_handle
;
127 static const fragment_items h223_mux_frag_items _U_
= {
128 &ett_h223_mux_fragment
,
129 &ett_h223_mux_fragments
,
130 &hf_h223_mux_fragments
,
131 &hf_h223_mux_fragment
,
132 &hf_h223_mux_fragment_overlap
,
133 &hf_h223_mux_fragment_overlap_conflict
,
134 &hf_h223_mux_fragment_multiple_tails
,
135 &hf_h223_mux_fragment_too_long_fragment
,
136 &hf_h223_mux_fragment_error
,
137 &hf_h223_mux_fragment_count
,
138 &hf_h223_mux_reassembled_in
,
139 &hf_h223_mux_reassembled_length
,
140 /* Reassembled data field */
145 static const fragment_items h223_al_frag_items
= {
146 &ett_h223_al_fragment
,
147 &ett_h223_al_fragments
,
148 &hf_h223_al_fragments
,
149 &hf_h223_al_fragment
,
150 &hf_h223_al_fragment_overlap
,
151 &hf_h223_al_fragment_overlap_conflict
,
152 &hf_h223_al_fragment_multiple_tails
,
153 &hf_h223_al_fragment_too_long_fragment
,
154 &hf_h223_al_fragment_error
,
155 &hf_h223_al_fragment_count
,
156 &hf_h223_al_reassembled_in
,
157 &hf_h223_al_reassembled_length
,
158 /* Reassembled data field */
163 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
164 static guint32 pdu_offset
;
166 /***************************************************************************
168 * virtual circuit number handling
170 * we have to be able to manage more than one H.223 call at a time,
171 * so have a hash which maps {call,vc} to an integer.
174 typedef struct _h223_call_info h223_call_info
;
177 const h223_call_info
* call
; /* h223 call */
178 guint32 vc
; /* child circuit */
181 static GHashTable
*circuit_chain_hashtable
= NULL
;
182 static guint circuit_chain_count
= 1;
186 circuit_chain_equal(gconstpointer v
, gconstpointer w
)
188 const circuit_chain_key
*v1
= (const circuit_chain_key
*)v
;
189 const circuit_chain_key
*v2
= (const circuit_chain_key
*)w
;
191 result
= ( v1
->call
== v2
->call
&&
192 v1
->vc
== v2
-> vc
);
197 circuit_chain_hash (gconstpointer v
)
199 const circuit_chain_key
*key
= (const circuit_chain_key
*)v
;
200 guint hash_val
= ((guint32
)(unsigned long)(key
->call
))^(((guint32
)key
->vc
) << 16);
205 circuit_chain_lookup(const h223_call_info
* call_info
, guint32 child_vc
)
207 circuit_chain_key key
, *new_key
;
209 key
.call
= call_info
;
211 circuit_id
= GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable
, &key
));
212 if( circuit_id
== 0 ) {
213 new_key
= wmem_new(wmem_file_scope(), circuit_chain_key
);
215 circuit_id
= ++circuit_chain_count
;
216 g_hash_table_insert(circuit_chain_hashtable
, new_key
, GUINT_TO_POINTER(circuit_id
));
222 circuit_chain_init(void)
224 if (circuit_chain_hashtable
)
225 g_hash_table_destroy(circuit_chain_hashtable
);
226 circuit_chain_hashtable
= g_hash_table_new(circuit_chain_hash
, circuit_chain_equal
);
227 circuit_chain_count
= 1;
231 /***************************************************************************
233 * Call information management
237 /* we keep information on each call in an h223_call_info structure
239 * We attach the h223_call_info structures to individual calls with
240 * circuit_add_proto_data().
243 typedef struct _h223_mux_element_listitem h223_mux_element_listitem
;
244 struct _h223_mux_element_listitem
{
245 h223_mux_element
*me
;
248 h223_mux_element_listitem
*next
;
251 /* we have this information for each stream */
253 h223_mux_element_listitem
* mux_table
[16];
254 } h223_call_direction_data
;
257 struct _h223_call_info
{
258 /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
259 specified in the annexes
263 /* for H.223 streams over TCP (as opposed to IAX), this
264 stores the source address and port of the first packet spotted,
265 so that we can differentiate directions.
270 h223_call_direction_data direction_data
[2];
273 typedef struct _h223_lc_params_listitem h223_lc_params_listitem
;
274 struct _h223_lc_params_listitem
276 h223_lc_params
*lc_params
;
279 h223_lc_params_listitem
*next
;
283 h223_lc_params_listitem
*lc_params
[2];
284 h223_call_info
*call_info
;
288 add_h223_mux_element(h223_call_direction_data
*direct
, guint8 mc
, h223_mux_element
*me
, guint32 framenum
)
290 h223_mux_element_listitem
*li
;
291 h223_mux_element_listitem
**old_li_ptr
;
292 h223_mux_element_listitem
*old_li
;
294 DISSECTOR_ASSERT(mc
< 16);
296 li
= wmem_new(wmem_file_scope(), h223_mux_element_listitem
);
297 old_li_ptr
= &(direct
->mux_table
[mc
]);
298 old_li
= *old_li_ptr
;
300 direct
->mux_table
[mc
] = li
;
302 while( old_li
->next
) {
303 old_li_ptr
= &(old_li
->next
);
304 old_li
= *old_li_ptr
;
306 if( framenum
< old_li
->first_frame
|| (framenum
== old_li
->first_frame
&& pdu_offset
< old_li
->pdu_offset
) )
308 else if ( framenum
== old_li
->first_frame
&& pdu_offset
== old_li
->pdu_offset
)
309 *old_li_ptr
= li
; /* replace the tail of the list with the new item, since */
310 /* a single h223 pdu has just set the same MC twice.. */
314 li
->first_frame
= framenum
;
315 li
->pdu_offset
= pdu_offset
;
320 static h223_mux_element
*
321 find_h223_mux_element(h223_call_direction_data
* direct
, guint8 mc
, guint32 framenum
, guint32 pkt_offset
)
323 h223_mux_element_listitem
* li
;
325 DISSECTOR_ASSERT(mc
< 16);
327 li
= direct
->mux_table
[mc
];
329 while( li
&& li
->next
&& li
->next
->first_frame
< framenum
)
331 while( li
&& li
->next
&& li
->next
->first_frame
== framenum
&& li
->next
->pdu_offset
< pkt_offset
)
341 add_h223_lc_params(h223_vc_info
* vc_info
, int direction
, h223_lc_params
*lc_params
, guint32 framenum
)
343 h223_lc_params_listitem
*li
= wmem_new(wmem_file_scope(), h223_lc_params_listitem
);
344 h223_lc_params_listitem
**old_li_ptr
= &(vc_info
->lc_params
[direction
? 0 : 1]);
345 h223_lc_params_listitem
*old_li
= *old_li_ptr
;
347 vc_info
->lc_params
[direction
? 0 : 1] = li
;
349 while( old_li
->next
) {
350 old_li_ptr
= &(old_li
->next
);
351 old_li
= *old_li_ptr
;
353 if( framenum
< old_li
->first_frame
)
355 else if( framenum
== old_li
->first_frame
)
359 old_li
->last_frame
= framenum
- 1;
362 li
->first_frame
= framenum
;
365 li
->lc_params
= lc_params
;
368 static h223_lc_params
*
369 find_h223_lc_params(h223_vc_info
* vc_info
, int direction
, guint32 framenum
)
371 h223_lc_params_listitem
* li
= vc_info
->lc_params
[direction
? 0 : 1];
372 while( li
&& li
->next
&& li
->next
->first_frame
<= framenum
)
375 return li
->lc_params
;
381 init_direction_data(h223_call_direction_data
*direct
)
384 h223_mux_element
*mc0_element
;
386 for ( i
= 0; i
< 16; ++i
)
387 direct
->mux_table
[i
] = NULL
;
389 /* set up MC 0 to contain just VC 0 */
390 mc0_element
= wmem_new(wmem_file_scope(), h223_mux_element
);
391 add_h223_mux_element( direct
, 0, mc0_element
, 0 );
392 mc0_element
->sublist
= NULL
;
394 mc0_element
->repeat_count
= 0; /* until closing flag */
395 mc0_element
->next
= NULL
;
399 h223_vc_info_new( h223_call_info
* call_info
)
401 h223_vc_info
*vc_info
= wmem_new(wmem_file_scope(), h223_vc_info
);
402 vc_info
->lc_params
[0] = vc_info
->lc_params
[1] = NULL
;
403 vc_info
->call_info
= call_info
;
408 init_logical_channel( guint32 start_frame
, h223_call_info
* call_info
, int vc
, int direction
, h223_lc_params
* params
)
410 guint32 circuit_id
= circuit_chain_lookup(call_info
, vc
);
411 circuit_t
*subcircuit
;
412 h223_vc_info
*vc_info
;
413 subcircuit
= find_circuit( CT_H223
, circuit_id
, start_frame
);
415 if( subcircuit
== NULL
) {
416 subcircuit
= circuit_new( CT_H223
, circuit_id
, start_frame
);
418 g_debug("%d: Created new circuit %d for call %p VC %d", start_frame
, circuit_id
, call_info
, vc
);
420 vc_info
= h223_vc_info_new( call_info
);
421 circuit_add_proto_data( subcircuit
, proto_h223
, vc_info
);
423 vc_info
= (h223_vc_info
*)circuit_get_proto_data( subcircuit
, proto_h223
);
425 add_h223_lc_params( vc_info
, direction
, params
, start_frame
);
428 /* create a brand-new h223_call_info structure */
429 static h223_call_info
*
430 create_call_info( guint32 start_frame
)
432 h223_call_info
*datax
;
433 h223_lc_params
*vc0_params
;
435 datax
= wmem_new(wmem_file_scope(), h223_call_info
);
437 /* initialise the call info */
438 init_direction_data(&datax
-> direction_data
[0]);
439 init_direction_data(&datax
-> direction_data
[1]);
441 /* FIXME shouldn't this be figured out dynamically? */
442 datax
-> h223_level
= 2;
444 vc0_params
= wmem_new(wmem_file_scope(), h223_lc_params
);
445 vc0_params
->al_type
= al1Framed
;
446 vc0_params
->al_params
= NULL
;
447 vc0_params
->segmentable
= TRUE
;
448 vc0_params
->subdissector
= srp_handle
;
449 init_logical_channel( start_frame
, datax
, 0, P2P_DIR_SENT
, vc0_params
);
450 init_logical_channel( start_frame
, datax
, 0, P2P_DIR_RECV
, vc0_params
);
454 /* find or create call_info struct for calls over circuits (eg, IAX) */
455 static h223_call_info
*
456 find_or_create_call_info_circ(packet_info
* pinfo
)
458 h223_call_info
*datax
;
459 circuit_t
*circ
= NULL
;
461 if(pinfo
->ctype
!= CT_NONE
)
462 circ
= find_circuit( pinfo
->ctype
, pinfo
->circuit_id
, pinfo
->fd
->num
);
466 datax
= (h223_call_info
*)circuit_get_proto_data(circ
, proto_h223
);
468 if( datax
== NULL
) {
469 datax
= create_call_info(pinfo
->fd
->num
);
472 g_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
473 pinfo
->fd
->num
, datax
, circ
, pinfo
->ctype
, pinfo
->circuit_id
);
475 circuit_add_proto_data(circ
, proto_h223
, datax
);
478 /* work out what direction we're really going in */
479 if( pinfo
->p2p_dir
< 0 || pinfo
->p2p_dir
> 1)
480 pinfo
->p2p_dir
= P2P_DIR_SENT
;
485 /* find or create call_info struct for calls over conversations (eg, RTP) */
486 static h223_call_info
*
487 find_or_create_call_info_conv(packet_info
* pinfo
)
489 h223_call_info
*datax
;
490 conversation_t
*conv
;
492 /* assume we're running atop TCP or RTP; use the conversation support */
493 conv
= find_conversation( pinfo
->fd
->num
,
494 &pinfo
->src
,&pinfo
->dst
,
496 pinfo
->srcport
,pinfo
->destport
, 0 );
498 /* both RTP and TCP track their conversations, so just assert here if
499 * we can't find one */
500 DISSECTOR_ASSERT(conv
);
502 datax
= (h223_call_info
*)conversation_get_proto_data(conv
, proto_h223
);
504 if(datax
== NULL
&& pinfo
->ptype
== PT_UDP
) {
505 conversation_t
*conv2
;
507 /* RTP tracks the two sides of the conversation totally separately;
508 * this messes us up totally.
510 * Look for another converstation, going in the opposite direction.
512 conv2
= find_conversation( pinfo
->fd
->num
,
513 &pinfo
->dst
,&pinfo
->src
,
515 pinfo
->destport
,pinfo
->srcport
, 0 );
517 datax
= (h223_call_info
*)conversation_get_proto_data(conv2
, proto_h223
);
521 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",
522 pinfo
->fd
->num
, conv
, conv2
, datax
, pinfo
->ptype
,
523 pinfo
->dst
.data
[0], pinfo
->dst
.data
[1], pinfo
->dst
.data
[2], pinfo
->dst
.data
[3],
525 pinfo
->src
.data
[0], pinfo
->src
.data
[1], pinfo
->src
.data
[2], pinfo
->src
.data
[3],
528 conversation_add_proto_data(conv
, proto_h223
, datax
);
532 /* we still haven't found any call data - create a new one for this
535 datax
= create_call_info(pinfo
->fd
->num
);
538 g_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
539 pinfo
->fd
->num
, datax
, conv
, pinfo
->ptype
,
540 pinfo
->src
.data
[0], pinfo
->src
.data
[1], pinfo
->src
.data
[2], pinfo
->src
.data
[3],
542 pinfo
->dst
.data
[0], pinfo
->dst
.data
[1], pinfo
->dst
.data
[2], pinfo
->dst
.data
[3],
546 conversation_add_proto_data(conv
, proto_h223
, datax
);
547 /* add the source details so we can distinguish directions
549 COPY_ADDRESS(&(datax
-> srcaddress
), &(pinfo
->src
));
550 datax
-> srcport
= pinfo
->srcport
;
553 /* work out what direction we're really going in */
554 if( ADDRESSES_EQUAL( &(pinfo
->src
), &(datax
->srcaddress
))
555 && pinfo
->srcport
== datax
->srcport
)
556 pinfo
->p2p_dir
= P2P_DIR_SENT
;
558 pinfo
->p2p_dir
= P2P_DIR_RECV
;
563 static h223_call_info
*
564 find_or_create_call_info ( packet_info
* pinfo
)
566 h223_call_info
*datax
;
568 datax
= find_or_create_call_info_circ(pinfo
);
570 datax
= find_or_create_call_info_conv(pinfo
);
574 /* called from the h245 dissector to handle a MultiplexEntrySend message */
576 h223_set_mc( packet_info
* pinfo
, guint8 mc
, h223_mux_element
* me
)
578 circuit_t
*circ
= find_circuit( pinfo
->ctype
, pinfo
->circuit_id
, pinfo
->fd
->num
);
579 h223_vc_info
* vc_info
;
581 /* if this h245 pdu packet came from an h223 circuit, add the details on
582 * the new mux entry */
584 vc_info
= (h223_vc_info
*)circuit_get_proto_data(circ
, proto_h223
);
585 add_h223_mux_element( &(vc_info
->call_info
->direction_data
[pinfo
->p2p_dir
? 0 : 1]), mc
, me
, pinfo
->fd
->num
);
589 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
591 h223_add_lc( packet_info
* pinfo
, guint16 lc
, h223_lc_params
* params
)
593 circuit_t
*circ
= find_circuit( pinfo
->ctype
, pinfo
->circuit_id
, pinfo
->fd
->num
);
594 h223_vc_info
* vc_info
;
596 /* if this h245 pdu packet came from an h223 circuit, add the details on
599 vc_info
= (h223_vc_info
*)circuit_get_proto_data(circ
, proto_h223
);
600 init_logical_channel( pinfo
->fd
->num
, vc_info
->call_info
, lc
, pinfo
->p2p_dir
, params
);
604 /************************************************************************************
609 static const guint8 crctable
[256] = {
610 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
611 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
612 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
613 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
614 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
615 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
616 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
617 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
618 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
619 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
620 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
621 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
622 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
623 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
624 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
625 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
627 static guint8
h223_al2_crc8bit( tvbuff_t
*tvb
) {
628 guint32 len
= tvb_reported_length(tvb
) - 1;
629 const guint8
* datax
= tvb_get_ptr( tvb
, 0, len
);
630 unsigned char crc
= 0;
632 DISSECTOR_ASSERT(tvb_reported_length(tvb
) >= 1);
634 crc
= crctable
[crc
^datax
[pos
++]];
639 dissect_mux_al_pdu( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*vc_tree
,
640 /* circuit_t* vc_circuit, */
641 h223_lc_params
* lc_params
)
643 proto_tree
*al_tree
= NULL
;
644 proto_item
*al_item
, *hidden_item
;
645 proto_tree
*al_subtree
;
646 proto_item
*al_subitem
= NULL
;
647 proto_item
*tmp_item
;
648 tvbuff_t
*next_tvb
= NULL
;
649 dissector_handle_t subdissector
= lc_params
->subdissector
;
650 guint32 len
= tvb_reported_length(tvb
);
652 guint8 calc_checksum
;
653 guint8 real_checksum
;
654 gboolean al2_sequenced
= FALSE
;
657 switch( lc_params
->al_type
) {
660 al_item
= proto_tree_add_none_format(vc_tree
, hf_h223_al1
, tvb
, 0, -1, "H.223 AL1 (%sframed)",
661 (lc_params
->al_type
==al1Framed
)?"":"not ");
662 al_tree
= proto_item_add_subtree (al_item
, ett_h223_al1
);
663 if(lc_params
->al_type
== al1Framed
) {
664 hidden_item
= proto_tree_add_boolean(al_tree
, hf_h223_al1_framed
, tvb
, 0, 1, TRUE
);
665 PROTO_ITEM_SET_HIDDEN(hidden_item
);
668 al_subitem
= proto_tree_add_item(al_tree
, hf_h223_al_payload
, next_tvb
, 0, -1, ENC_NA
);
671 case al2WithSequenceNumbers
:
672 al2_sequenced
= TRUE
;
674 case al2WithoutSequenceNumbers
:
675 tmp_item
= proto_tree_add_boolean(vc_tree
, hf_h223_al2
, tvb
, 0, 0, TRUE
);
677 al_item
= proto_tree_add_item(vc_tree
,
678 al2_sequenced
?hf_h223_al2_sequenced
:hf_h223_al2_unsequenced
,
680 al_tree
= proto_item_add_subtree (al_item
, ett_h223_al2
);
682 PROTO_ITEM_SET_GENERATED(tmp_item
);
684 /* check minimum payload length */
685 if(len
< (al2_sequenced
?2U:1U))
689 if( al2_sequenced
) {
690 proto_tree_add_item(al_tree
, hf_h223_al2_seqno
, tvb
, 0, 1, ENC_LITTLE_ENDIAN
);
694 next_tvb
= tvb_new_subset( tvb
, data_start
, len
-1-data_start
, len
-1-data_start
);
695 al_subitem
= proto_tree_add_item(al_tree
, hf_h223_al_payload
, next_tvb
, 0, -1, ENC_NA
);
697 calc_checksum
= h223_al2_crc8bit(tvb
);
698 real_checksum
= tvb_get_guint8(tvb
, len
- 1);
700 if( calc_checksum
== real_checksum
) {
701 proto_tree_add_uint_format_value(al_tree
, hf_h223_al2_crc
, tvb
, len
- 1, 1, real_checksum
,
702 "0x%02x (correct)", real_checksum
);
704 proto_tree_add_uint_format_value(al_tree
, hf_h223_al2_crc
, tvb
, len
- 1, 1, real_checksum
,
705 "0x%02x (incorrect, should be 0x%02x)", real_checksum
, calc_checksum
);
706 tmp_item
= proto_tree_add_boolean( al_tree
, hf_h223_al2_crc_bad
, tvb
, len
- 1, 1, TRUE
);
707 PROTO_ITEM_SET_GENERATED(tmp_item
);
709 /* don't pass pdus which fail checksums on to the subdissector */
710 subdissector
= data_handle
;
714 call_dissector(data_handle
, tvb
, pinfo
, vc_tree
);
719 subdissector
= data_handle
;
721 al_subtree
= proto_item_add_subtree(al_subitem
, ett_h223_al_payload
);
722 call_dissector(subdissector
, next_tvb
, pinfo
, al_subtree
);
725 /************************************************************************************
731 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
733 * tvb buffer containing the MUX-PDU fragment
734 * pinfo info on the packet containing the last fragment of the MUX-PDU
735 * pkt_offset offset within the block from the superdissector where the
736 * fragment starts (must increase monotonically for constant pinfo->fd->num)
737 * pdu_tree dissection tree for the PDU; a single item will be added (with
740 * end_of_mux_sdu true if this is a segmentable VC and this is the last
744 dissect_mux_sdu_fragment(tvbuff_t
*volatile next_tvb
, packet_info
*pinfo
,
745 guint32 pkt_offset
, proto_tree
*pdu_tree
,
746 h223_call_info
* call_info
, guint16 vc
,
747 gboolean end_of_mux_sdu
)
749 /* update the circuit details before passing to a subdissector */
750 guint32 orig_circuit
= pinfo
->circuit_id
;
751 guint32 orig_ctype
= pinfo
->ctype
;
752 pinfo
->circuit_id
=circuit_chain_lookup(call_info
, vc
);
753 pinfo
->ctype
=CT_H223
;
756 circuit_t
*subcircuit
=find_circuit(pinfo
->ctype
,pinfo
->circuit_id
,pinfo
->fd
->num
);
757 proto_tree
*vc_tree
= NULL
;
759 h223_vc_info
*vc_info
= NULL
;
760 h223_lc_params
*lc_params
= NULL
;
763 vc_item
= proto_tree_add_uint(pdu_tree
, hf_h223_mux_vc
, next_tvb
, 0, tvb_reported_length(next_tvb
), vc
);
764 vc_tree
= proto_item_add_subtree (vc_item
, ett_h223_mux_vc
);
767 if( subcircuit
== NULL
) {
768 g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo
->fd
->num
,
769 pinfo
->circuit_id
, (void *)call_info
, vc
);
771 vc_info
= (h223_vc_info
*)circuit_get_proto_data(subcircuit
, proto_h223
);
772 if( vc_info
!= NULL
) {
773 lc_params
= find_h223_lc_params( vc_info
, pinfo
->p2p_dir
, pinfo
->fd
->num
);
778 if( lc_params
!= NULL
) {
779 if( lc_params
->segmentable
&& lc_params
->al_type
!= al1NotFramed
) {
781 stream_pdu_fragment_t
*frag
;
783 substream
= find_stream_circ(subcircuit
,pinfo
->p2p_dir
);
784 if(substream
== NULL
)
785 substream
= stream_new_circ(subcircuit
,pinfo
->p2p_dir
);
786 frag
= stream_find_frag(substream
,pinfo
->fd
->num
,pkt_offset
);
790 g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
791 pinfo
->fd
->num
, orig_circuit
, pinfo
->circuit_id
, pkt_offset
, tvb_reported_length(next_tvb
), end_of_mux_sdu
);
793 frag
= stream_add_frag(substream
,pinfo
->fd
->num
,pkt_offset
,
794 next_tvb
,pinfo
,!end_of_mux_sdu
);
797 g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
798 pinfo
->fd
->num
, orig_circuit
, pinfo
->circuit_id
, pkt_offset
, tvb_reported_length(next_tvb
), end_of_mux_sdu
);
802 next_tvb
= stream_process_reassembled(
804 "Reassembled H.223 AL-PDU",
805 frag
, &h223_al_frag_items
,
810 /* fudge to pass pkt_offset down to add_h223_mux_element,
811 * should it be called */
812 pdu_offset
= pkt_offset
;
813 dissect_mux_al_pdu(next_tvb
, pinfo
, vc_tree
,/* subcircuit,*/ lc_params
);
816 call_dissector(data_handle
,next_tvb
,pinfo
,vc_tree
);
820 /* restore the original circuit details for future PDUs */
822 pinfo
->ctype
=(circuit_type
)orig_ctype
;
823 pinfo
->circuit_id
=orig_circuit
;
829 mux_element_sublist_size( h223_mux_element
* me
)
831 h223_mux_element
*current_me
= me
->next
;
833 while ( current_me
) {
834 if ( current_me
->sublist
)
835 length
+= current_me
->repeat_count
* mux_element_sublist_size( current_me
->sublist
);
837 length
+= current_me
->repeat_count
;
838 current_me
= current_me
->next
;
840 if ( length
== 0 ) { /* should never happen, but to avoid infinite loops... */
841 DISSECTOR_ASSERT_NOT_REACHED();
847 /* dissect part of a MUX-PDU payload according to a multiplex list
849 * tvb buffer containing entire mux-pdu payload
850 * pinfo info on the packet containing the last fragment of the MUX-PDU
851 * pkt_offset offset within the block from the superdissector where the
852 * MUX-PDU starts (must increase monotonically for constant
854 * pdu_tree dissection tree for the PDU
855 * call_info data structure for h223 call
857 * offset offset within tvb to start work
858 * endOfMuxSdu true if the end-of-sdu flag was set
861 dissect_mux_payload_by_me_list( tvbuff_t
*tvb
, packet_info
*pinfo
,
862 guint32 pkt_offset
, proto_tree
*pdu_tree
,
863 h223_call_info
* call_info
,
864 h223_mux_element
*me
, guint32 offset
,
865 gboolean endOfMuxSdu
)
867 guint32 len
= tvb_reported_length(tvb
);
873 if ( me
->repeat_count
== 0 ) {
874 for(sublist_len
= mux_element_sublist_size( me
->sublist
);
875 offset
+ sublist_len
<= len
;
876 offset
= dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
,
877 call_info
, me
->sublist
, offset
, endOfMuxSdu
) );
879 for(i
= 0; i
< me
->repeat_count
; ++i
)
880 offset
= dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
,
881 call_info
, me
->sublist
, offset
, endOfMuxSdu
);
884 if ( me
->repeat_count
== 0 )
885 frag_len
= len
- offset
;
887 frag_len
= me
->repeat_count
;
890 next_tvb
= tvb_new_subset(tvb
, offset
, frag_len
, frag_len
);
891 dissect_mux_sdu_fragment( next_tvb
, pinfo
, pkt_offset
+ offset
, pdu_tree
,
892 call_info
, me
->vc
, (offset
+frag_len
==len
) && endOfMuxSdu
);
901 /* dissect the payload of a MUX-PDU
903 * tvb buffer containing entire mux-pdu payload
904 * pinfo info on the packet containing the last fragment of the MUX-PDU
905 * pkt_offset offset within the block from the superdissector where the
906 * MUX-PDU starts (must increase monotonically for constant
908 * pdu_tree dissection tree for the PDU
909 * call_info data structure for h223 call
910 * mc multiplex code for this PDU
911 * endOfMuxSdu true if the end-of-sdu flag was set
914 dissect_mux_payload( tvbuff_t
*tvb
, packet_info
*pinfo
, guint32 pkt_offset
,
915 proto_tree
*pdu_tree
, h223_call_info
*call_info
,
916 guint8 mc
, gboolean endOfMuxSdu
)
918 guint32 len
= tvb_reported_length(tvb
);
920 h223_mux_element
* me
= find_h223_mux_element( &(call_info
->direction_data
[pinfo
->p2p_dir
? 0 : 1]), mc
, pinfo
->fd
->num
, pkt_offset
);
923 dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
, call_info
, me
, 0, endOfMuxSdu
);
925 /* no entry found in mux-table. ignore packet and dissect as data */
926 proto_tree
*vc_tree
= NULL
;
929 proto_item
*vc_item
= proto_tree_add_item(pdu_tree
, hf_h223_mux_deact
, tvb
, 0, len
, ENC_NA
);
930 vc_tree
= proto_item_add_subtree(vc_item
, ett_h223_mux_deact
);
932 call_dissector(data_handle
,tvb
,pinfo
,vc_tree
);
936 /* dissect a reassembled mux-pdu
938 * tvb buffer containing mux-pdu, including header and closing flag
939 * pinfo packet info for packet containing the end of the mux-pdu
940 * pkt_offset offset within the block from the superdissector where the
941 * MUX-PDU starts (must increase monotonically for constant
943 * h223_tree dissection tree for h223 protocol; a single item will be added
945 * call_info h223 info structure for this h223 call
946 * pdu_no index of this pdu within the call
949 dissect_mux_pdu( tvbuff_t
*tvb
, packet_info
*pinfo
, guint32 pkt_offset
,
950 proto_tree
*h223_tree
, h223_call_info
*call_info
)
953 /* actual (as opposed to reported) payload len */
955 guint32 raw_hdr
= 0, correct_hdr
= 0;
957 guint16 closing_flag
= 0;
960 gboolean end_of_mux_sdu
= FALSE
;
963 proto_item
*pdu_item
= NULL
;
964 proto_tree
*pdu_tree
= NULL
;
966 #ifdef DEBUG_H223_FRAGMENTATION
967 g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
968 pinfo
->fd
->num
, pkt_offset
, tvb_reported_length(tvb
));
971 switch(call_info
->h223_level
) {
973 raw_hdr
= tvb_get_guint8(tvb
,0);
974 mc
= (guint8
)((raw_hdr
>>1) & 0xf);
975 end_of_mux_sdu
= raw_hdr
& 1;
977 /* closing flag is one byte long for h223 level 0, two for level 1 */
978 len
= mpl
= tvb_length_remaining(tvb
, offset
)-(call_info
->h223_level
+1);
980 /* XXX should ignore pdus with incorrect HECs */
984 raw_hdr
= tvb_get_letoh24(tvb
,0);
985 errors
= golay_errors(raw_hdr
);
987 len
= tvb_length_remaining(tvb
,offset
)-2;
990 correct_hdr
= raw_hdr
^ (guint32
)errors
;
992 mc
= (guint8
)(correct_hdr
& 0xf);
993 mpl
= (guint8
)((correct_hdr
>> 4) & 0xff);
995 /* we should never have been called if there's not enough data in
997 DISSECTOR_ASSERT(len
>= mpl
);
999 closing_flag
= tvb_get_ntohs(tvb
,offset
+len
);
1000 end_of_mux_sdu
= (closing_flag
==(0xE14D ^ 0xFFFF));
1008 /* XXX not implemented */
1010 DISSECTOR_ASSERT_NOT_REACHED();
1016 pdu_item
= proto_tree_add_item (h223_tree
, hf_h223_mux_stuffing_pdu
, tvb
, 0, -1, ENC_NA
);
1017 pdu_tree
= proto_item_add_subtree (pdu_item
, ett_h223_mux_stuffing_pdu
);
1019 pdu_item
= proto_tree_add_item (h223_tree
, hf_h223_mux_pdu
, tvb
, 0, -1, ENC_NA
);
1020 pdu_tree
= proto_item_add_subtree (pdu_item
, ett_h223_mux_pdu
);
1025 proto_item
*item
= proto_tree_add_item (pdu_tree
, hf_h223_mux_header
, tvb
, 0, offset
, ENC_NA
);
1026 proto_tree
*hdr_tree
= proto_item_add_subtree (item
, ett_h223_mux_header
);
1028 switch(call_info
->h223_level
) {
1030 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mc
,tvb
,0,1,mc
);
1034 if( errors
== -1 ) {
1035 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1037 "0x%06x (uncorrectable errors)", raw_hdr
);
1040 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1042 "0x%06x (correct)", raw_hdr
);
1044 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1046 "0x%06x (errors are 0x%06x)", raw_hdr
, errors
);
1048 item
= proto_tree_add_uint(hdr_tree
,hf_h223_mux_correctedhdr
,tvb
,0,3,
1050 PROTO_ITEM_SET_GENERATED(item
);
1051 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mc
,tvb
,0,1,mc
);
1052 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mpl
,tvb
,0,2,mpl
);
1057 /* XXX not implemented */
1059 DISSECTOR_ASSERT_NOT_REACHED();
1064 pdu_tvb
= tvb_new_subset(tvb
, offset
, len
, mpl
);
1066 dissect_mux_payload(pdu_tvb
,pinfo
,pkt_offset
+offset
,pdu_tree
,call_info
,mc
,end_of_mux_sdu
);
1068 call_dissector(data_handle
,pdu_tvb
,pinfo
,pdu_tree
);
1073 /* any extra data in the PDU, beyond that indictated by the mpl, is
1074 dissected as data. */
1077 tvbuff_t
*next_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
1078 proto_tree
*vc_tree
= NULL
;
1081 proto_item
*vc_item
= proto_tree_add_item(pdu_tree
, hf_h223_mux_extra
, next_tvb
, 0, len
, ENC_NA
);
1082 vc_tree
= proto_item_add_subtree(vc_item
, ett_h223_mux_deact
);
1084 call_dissector(data_handle
,next_tvb
,pinfo
,vc_tree
);
1089 /* add the closing HDLC flag */
1091 proto_tree_add_item(pdu_tree
,hf_h223_mux_hdlc2
,tvb
,offset
,2,ENC_BIG_ENDIAN
);
1095 /************************************************************************************
1097 * MUX-PDU delineation and defragmentation
1100 /* attempt to parse the header of a mux pdu */
1102 attempt_mux_level0_header_parse(guint32 nbytes _U_
, guint32 hdr _U_
, guint32
*minlen _U_
)
1104 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1105 DISSECTOR_ASSERT_NOT_REACHED();
1110 attempt_mux_level1_header_parse(guint32 nbytes
, guint32 hdr
, guint32
*minlen
)
1112 /* this is untested */
1113 DISSECTOR_ASSERT_NOT_REACHED();
1119 /* don't interpret a repeated hdlc as a header */
1123 /* + 1 byte of header and 2 bytes of closing HDLC */
1124 *minlen
= (guint8
)((hdr
>> 12) & 0xff) + 3;
1129 attempt_mux_level2_3_header_parse(guint32 nbytes
, guint32 hdr
, guint32
*minlen
)
1136 /* + 3 bytes of header and 2 bytes of closing HDLC */
1139 /* bah, we get the header in the wrong order */
1141 ((hdr
& 0xFF0000) >> 16) |
1143 ((hdr
& 0x0000FF) << 16);
1145 errors
= golay_errors(hdr
);
1148 *minlen
+= ((hdr
>> 4) & 0xff);
1154 static gboolean (* const attempt_mux_header_parse
[])(guint32 nbytes
, guint32 header_buf
, guint32
*minlen
) = {
1155 attempt_mux_level0_header_parse
,
1156 attempt_mux_level1_header_parse
,
1157 attempt_mux_level2_3_header_parse
,
1158 attempt_mux_level2_3_header_parse
1162 h223_mux_check_hdlc(int h223_level
, guint32 nbytes
, guint32 tail_buf
)
1166 switch(h223_level
) {
1168 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1169 DISSECTOR_ASSERT_NOT_REACHED();
1173 masked
= tail_buf
& 0xffff;
1174 return nbytes
>= 2 && masked
== 0xE14D;
1177 masked
= tail_buf
& 0xffff;
1178 return nbytes
>= 2 && (masked
== 0xE14D || masked
== (0xE14D ^ 0xFFFF));
1181 DISSECTOR_ASSERT_NOT_REACHED();
1186 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1188 * returns the number of bytes processed, or the negative of the number of
1189 * extra bytes needed, or zero if we don't know yet
1193 dissect_mux_pdu_fragment( tvbuff_t
*tvb
, guint32 start_offset
,
1194 packet_info
*pinfo
, proto_tree
*h223_tree
,
1195 h223_call_info
*call_info
)
1197 tvbuff_t
*volatile next_tvb
;
1198 volatile guint32 offset
= start_offset
;
1199 gboolean more_frags
= TRUE
;
1201 gboolean header_parsed
= FALSE
;
1202 guint32 header_buf
= 0, tail_buf
= 0;
1203 guint32 pdu_minlen
= 0;
1207 #ifdef DEBUG_H223_FRAGMENTATION
1208 g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1209 pinfo
->fd
->num
,start_offset
, tvb_reported_length_remaining( tvb
, start_offset
));
1212 while( more_frags
&& offset
< tvb_reported_length( tvb
)) {
1213 guint8 byte
= tvb_get_guint8(tvb
, offset
++);
1215 /* read a byte into the header buf, if necessary */
1216 if((offset
-start_offset
) <= 4) {
1221 /* read the byte into the tail buf */
1225 /* if we haven't parsed the header yet, attempt to do so now */
1227 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1228 header_parsed
= (attempt_mux_header_parse
[call_info
->h223_level
])
1229 (offset
-start_offset
,header_buf
,&pdu_minlen
);
1231 /* if we have successfully parsed the header, we have sufficient data,
1232 * and we have found the closing hdlc, we are done here */
1233 if(header_parsed
&& (offset
-start_offset
) >= pdu_minlen
) {
1234 if(h223_mux_check_hdlc(call_info
->h223_level
,offset
-start_offset
,tail_buf
)) {
1241 if(pdu_minlen
<= (offset
-start_offset
)) {
1242 /* we haven't found the closing hdlc yet, but we don't know how
1243 * much more we need */
1244 #ifdef DEBUG_H223_FRAGMENTATION
1245 g_debug("\tBailing, requesting more bytes");
1249 guint32 needed
= pdu_minlen
-(offset
-start_offset
);
1250 #ifdef DEBUG_H223_FRAGMENTATION
1251 g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen
,(offset
-start_offset
),needed
);
1253 return - (gint
) needed
;
1257 /* create a tvb for the fragment */
1258 next_tvb
= tvb_new_subset(tvb
, start_offset
, offset
-start_offset
,
1259 offset
-start_offset
);
1264 * If it gets an error that means there's no point in dissecting
1265 * any more PDUs, rethrow the exception in question.
1267 * If it gets any other error, report it and continue, as that
1268 * means that PDU got an error, but that doesn't mean we should
1269 * stop dissecting PDUs within this frame or chunk of reassembled
1272 pd_save
= pinfo
->private_data
;
1274 dissect_mux_pdu( next_tvb
, pinfo
, start_offset
, h223_tree
, call_info
);
1276 CATCH_NONFATAL_ERRORS
{
1277 /* Restore the private_data structure in case one of the
1278 * called dissectors modified it (and, due to the exception,
1279 * was unable to restore it).
1281 pinfo
->private_data
= pd_save
;
1282 show_exception(tvb
, pinfo
, h223_tree
, EXCEPT_CODE
, GET_MESSAGE
);
1287 return (offset
-start_offset
);
1290 /************************************************************************************
1292 * main dissector entry points
1295 /* dissects PDUs from the tvb
1297 * Updates desegment_offset and desegment_len if the end of the data didn't
1298 * line up with the end of a pdu.
1301 dissect_h223 (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1303 proto_tree
*h223_tree
= NULL
;
1304 proto_item
*h223_item
= NULL
;
1305 h223_call_info
*call_info
= NULL
;
1308 /* set up the protocol and info fields in the summary pane */
1309 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_H223
);
1311 col_clear(pinfo
->cinfo
, COL_INFO
);
1313 /* find or create the call_info for this call */
1314 call_info
= find_or_create_call_info(pinfo
);
1316 /* add the 'h223' tree to the main tree */
1318 h223_item
= proto_tree_add_item (tree
, proto_h223
, tvb
, 0, -1, ENC_NA
);
1319 h223_tree
= proto_item_add_subtree (h223_item
, ett_h223
);
1322 while( offset
< tvb_reported_length( tvb
)) {
1323 int res
= dissect_mux_pdu_fragment( tvb
, offset
, pinfo
,
1324 h223_tree
, call_info
);
1326 /* the end of the tvb held the start of a PDU */
1327 pinfo
->desegment_offset
= offset
;
1329 /* if res != 0, we actually know how much more data we need for a
1332 * However, if we return that, it means that we get called twice
1333 * for the next packet; this makes it hard to tell how far throught
1334 * the stream we are and we have to start messing about with
1335 * getting the seqno from the superdissector's private data. So we
1338 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1340 pinfo
-> desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
1343 /* shrink the h223 protocol item such that it only includes the
1344 * bits we dissected */
1345 proto_item_set_len(h223_item
,offset
);
1349 col_set_str(pinfo
->cinfo
, COL_INFO
, "(No complete PDUs)");
1357 /* H.223 specifies that the least-significant bit is transmitted first;
1358 * however this is at odds with IAX which transmits bytes with the
1359 * first-received bit as the MSB.
1361 * This dissector swaps the ordering of the bits in each byte before using the
1362 * normal entry point.
1365 dissect_h223_bitswapped (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1367 tvbuff_t
*reversed_tvb
;
1372 len
= tvb_length(tvb
);
1373 datax
= (guint8
*)wmem_alloc(pinfo
->pool
, len
);
1374 for( i
=0; i
<len
; i
++)
1375 datax
[i
]=BIT_SWAP(tvb_get_guint8(tvb
,i
));
1378 * Add the reversed tvbuff to the list of tvbuffs to which
1379 * the tvbuff we were handed refers, so it'll get
1380 * cleaned up when that tvbuff is cleaned up.
1382 reversed_tvb
= tvb_new_child_real_data(tvb
, datax
,len
,tvb_reported_length(tvb
));
1384 /* Add the reversed data to the data source list. */
1385 add_new_data_source(pinfo
, reversed_tvb
, "Bit-swapped H.223 frame" );
1387 dissect_h223(reversed_tvb
,pinfo
,tree
);
1390 /******************************************************************************/
1393 h223_init_protocol (void)
1395 circuit_chain_init();
1399 void proto_register_h223 (void)
1401 /* A header field is something you can search/filter on.
1403 * We create a structure to register our fields. It consists of an
1404 * array of hf_register_info structures, each of which are of the format
1405 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1408 static hf_register_info hf
[] = {
1410 { &hf_h223_non_h223_data
,
1411 { "Non-H.223 data", "h223.non-h223", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1412 "Initial data in stream, not a PDU", HFILL
}},
1415 { &hf_h223_mux_stuffing_pdu
,
1416 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1417 "Empty PDU used for stuffing when no data available", HFILL
}},
1420 { "H.223 MUX-PDU", "h223.mux", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1423 { &hf_h223_mux_header
,
1424 { "Header", "h223.mux.header", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1425 "H.223 MUX header", HFILL
}},
1427 { &hf_h223_mux_rawhdr
,
1428 { "Raw value", "h223.mux.rawhdr", FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1429 "Raw header bytes", HFILL
}},
1431 { &hf_h223_mux_correctedhdr
,
1432 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1433 "Corrected header bytes", HFILL
}},
1436 { "Multiplex Code", "h223.mux.mc", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1437 "H.223 MUX multiplex code", HFILL
}},
1440 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1441 "H.223 MUX multiplex Payload Length", HFILL
}},
1443 { &hf_h223_mux_deact
,
1444 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1445 "mpl refers to an entry in the multiplex table which is not active", HFILL
}},
1448 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1451 { &hf_h223_mux_extra
,
1452 { "Extraneous data", "h223.mux.extra", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1453 "data beyond mpl", HFILL
}},
1455 { &hf_h223_mux_hdlc2
,
1456 { "HDLC flag", "h223.mux.hdlc", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1457 "framing flag", HFILL
}},
1459 /* fields for h.223-mux fragments */
1460 { &hf_h223_mux_fragment_overlap
,
1461 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1462 "Fragment overlaps with other fragments", HFILL
}},
1464 { &hf_h223_mux_fragment_overlap_conflict
,
1465 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1466 "Overlapping fragments contained conflicting data", HFILL
}},
1468 { &hf_h223_mux_fragment_multiple_tails
,
1469 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1470 "Several tails were found when defragmenting the packet", HFILL
}},
1472 { &hf_h223_mux_fragment_too_long_fragment
,
1473 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1474 "Fragment contained data past end of packet", HFILL
}},
1476 { &hf_h223_mux_fragment_error
,
1477 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1478 "Defragmentation error due to illegal fragments", HFILL
}},
1480 { &hf_h223_mux_fragment_count
,
1481 { "Fragment count", "h223.mux.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1484 { &hf_h223_mux_fragment
,
1485 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1488 { &hf_h223_mux_fragments
,
1489 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1492 { &hf_h223_mux_reassembled_in
,
1493 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1494 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL
}},
1496 { &hf_h223_mux_reassembled_length
,
1497 { "Reassembled H.223 MUX-PDU length", "h223.mux.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1498 "The total length of the reassembled payload", HFILL
}},
1500 /* fields for h.223-al fragments */
1501 { &hf_h223_al_fragment_overlap
,
1502 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1503 "Fragment overlaps with other fragments", HFILL
}},
1505 { &hf_h223_al_fragment_overlap_conflict
,
1506 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1507 "Overlapping fragments contained conflicting data", HFILL
}},
1509 { &hf_h223_al_fragment_multiple_tails
,
1510 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1511 "Several tails were found when defragmenting the packet", HFILL
}},
1513 { &hf_h223_al_fragment_too_long_fragment
,
1514 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1515 "Fragment contained data past end of packet", HFILL
}},
1517 { &hf_h223_al_fragment_error
,
1518 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1519 "Defragmentation error due to illegal fragments", HFILL
}},
1521 { &hf_h223_al_fragment_count
,
1522 { "Fragment count", "h223.al.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1525 { &hf_h223_al_fragment
,
1526 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1529 { &hf_h223_al_fragments
,
1530 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1533 { &hf_h223_al_reassembled_in
,
1534 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1535 "This H.223 AL-PDU packet is reassembled in this frame", HFILL
}},
1537 { &hf_h223_al_reassembled_length
,
1538 { "Reassembled H.223 AL-PDU length", "h223.al.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1539 "The total length of the reassembled payload", HFILL
}},
1544 { "H.223 AL1", "h223.al1", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1545 "H.223 AL-PDU using AL1", HFILL
}},
1547 { &hf_h223_al1_framed
,
1548 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1552 { "H.223 AL2", "h223.al2", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1553 "H.223 AL-PDU using AL2", HFILL
}},
1555 { &hf_h223_al2_sequenced
,
1556 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1557 "H.223 AL-PDU using AL2 with sequence numbers", HFILL
}},
1559 { &hf_h223_al2_unsequenced
,
1560 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1561 "H.223 AL-PDU using AL2 without sequence numbers", HFILL
}},
1563 { &hf_h223_al2_seqno
,
1564 { "Sequence Number", "h223.al2.seqno", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1565 "H.223 AL2 sequence number", HFILL
}},
1568 { "CRC", "h223.al2.crc", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1571 { &hf_h223_al2_crc_bad
,
1572 { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1575 { &hf_h223_al_payload
,
1576 { "H.223 AL Payload", "h223.al.payload", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1577 "H.223 AL-PDU Payload", HFILL
}},
1581 static gint
*ett
[] = {
1583 &ett_h223_non_h223_data
,
1584 &ett_h223_mux_stuffing_pdu
,
1586 &ett_h223_mux_header
,
1587 &ett_h223_mux_deact
,
1589 &ett_h223_mux_extra
,
1590 &ett_h223_mux_fragments
,
1591 &ett_h223_mux_fragment
,
1592 &ett_h223_al_fragments
,
1593 &ett_h223_al_fragment
,
1596 &ett_h223_al_payload
1600 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1602 proto_register_field_array (proto_h223
, hf
, array_length (hf
));
1603 proto_register_subtree_array (ett
, array_length (ett
));
1604 register_dissector("h223", dissect_h223
, proto_h223
);
1605 register_dissector("h223_bitswapped", dissect_h223_bitswapped
, proto_h223
);
1607 /* register our init routine to be called at the start of a capture,
1608 to clear out our hash tables etc */
1609 register_init_routine(&h223_init_protocol
);
1611 h245_set_h223_set_mc_handle( &h223_set_mc
);
1612 h245_set_h223_add_lc_handle( &h223_add_lc
);
1615 void proto_reg_handoff_h223(void)
1617 dissector_handle_t h223_bitswapped
= find_dissector("h223_bitswapped");
1618 dissector_handle_t h223
= find_dissector("h223");
1619 data_handle
= find_dissector("data");
1620 srp_handle
= find_dissector("srp");
1622 dissector_add_handle("tcp.port", h223
);
1623 dissector_add_handle("tcp.port", h223_bitswapped
);
1624 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped
);
1625 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_H223_H245
, h223_bitswapped
);
1634 * indent-tabs-mode: nil
1637 * ex: set shiftwidth=4 tabstop=8 expandtab:
1638 * :indentSize=4:tabSize=8:noTabs=true: