2 * Routines for H.223 packet dissection
3 * Copyright (c) 2004-5 MX Telecom Ltd <richardv@mxtelecom.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/conversation.h>
17 #include <epan/exceptions.h>
18 #include <epan/expert.h>
19 #include <epan/stream.h>
20 #include <epan/golay.h>
21 #include <epan/iax2_codec_type.h>
22 #include <epan/show_exception.h>
23 #include <epan/asn1.h>
24 #include <wsutil/bitswap.h>
25 #include <wsutil/wslog.h>
27 #include "packet-h245.h"
28 #include "packet-iax2.h"
29 #include "packet-h223.h"
31 /* #define DEBUG_H223 */
33 /* debug the mux-pdu defragmentation code. warning: verbose output! */
34 /* #define DEBUG_H223_FRAGMENTATION */
36 #define PROTO_TAG_H223 "H.223"
38 /* Wireshark ID of the H.223 protocol */
39 static int proto_h223
;
40 static int proto_h223_bitswapped
;
42 /* The following hf_* variables are used to hold the Wireshark IDs of
43 * our header fields; they are filled out when we call
44 * proto_register_field_array() in proto_register_h223()
46 /* static int hf_h223_non_h223_data; */
47 static int hf_h223_mux_stuffing_pdu
;
48 static int hf_h223_mux_pdu
;
49 static int hf_h223_mux_header
;
50 static int hf_h223_mux_rawhdr
;
51 static int hf_h223_mux_correctedhdr
;
52 static int hf_h223_mux_mc
;
53 static int hf_h223_mux_mpl
;
54 static int hf_h223_mux_deact
;
55 static int hf_h223_mux_vc
;
56 static int hf_h223_mux_extra
;
57 static int hf_h223_mux_hdlc2
;
58 static int hf_h223_mux_fragments
;
59 static int hf_h223_mux_fragment
;
60 static int hf_h223_mux_fragment_overlap
;
61 static int hf_h223_mux_fragment_overlap_conflict
;
62 static int hf_h223_mux_fragment_multiple_tails
;
63 static int hf_h223_mux_fragment_too_long_fragment
;
64 static int hf_h223_mux_fragment_error
;
65 static int hf_h223_mux_fragment_count
;
66 static int hf_h223_mux_reassembled_in
;
67 static int hf_h223_mux_reassembled_length
;
69 static int hf_h223_al_fragments
;
70 static int hf_h223_al_fragment
;
71 static int hf_h223_al_fragment_overlap
;
72 static int hf_h223_al_fragment_overlap_conflict
;
73 static int hf_h223_al_fragment_multiple_tails
;
74 static int hf_h223_al_fragment_too_long_fragment
;
75 static int hf_h223_al_fragment_error
;
76 static int hf_h223_al_fragment_count
;
77 static int hf_h223_al_reassembled_in
;
78 static int hf_h223_al_reassembled_length
;
80 static int hf_h223_al1
;
81 static int hf_h223_al1_framed
;
82 static int hf_h223_al2
;
83 static int hf_h223_al2_sequenced
;
84 static int hf_h223_al2_unsequenced
;
85 static int hf_h223_al2_seqno
;
86 static int hf_h223_al2_crc
;
87 static int hf_h223_al2_crc_status
;
89 static int hf_h223_al_payload
;
91 /* These are the ids of the subtrees that we may be creating */
93 static int ett_h223_non_h223_data
;
94 static int ett_h223_mux_stuffing_pdu
;
95 static int ett_h223_mux_pdu
;
96 static int ett_h223_mux_header
;
97 static int ett_h223_mux_deact
;
98 static int ett_h223_mux_vc
;
99 static int ett_h223_mux_extra
;
100 static int ett_h223_mux_fragments
;
101 static int ett_h223_mux_fragment
;
102 static int ett_h223_al_fragments
;
103 static int ett_h223_al_fragment
;
104 static int ett_h223_al1
;
105 static int ett_h223_al2
;
106 static int ett_h223_al_payload
;
108 static expert_field ei_h223_al2_crc
;
110 /* These are the handles of our subdissectors */
111 static dissector_handle_t data_handle
;
112 static dissector_handle_t srp_handle
;
113 static dissector_handle_t h223_bitswapped
;
115 static const fragment_items h223_mux_frag_items _U_
= {
116 &ett_h223_mux_fragment
,
117 &ett_h223_mux_fragments
,
118 &hf_h223_mux_fragments
,
119 &hf_h223_mux_fragment
,
120 &hf_h223_mux_fragment_overlap
,
121 &hf_h223_mux_fragment_overlap_conflict
,
122 &hf_h223_mux_fragment_multiple_tails
,
123 &hf_h223_mux_fragment_too_long_fragment
,
124 &hf_h223_mux_fragment_error
,
125 &hf_h223_mux_fragment_count
,
126 &hf_h223_mux_reassembled_in
,
127 &hf_h223_mux_reassembled_length
,
128 /* Reassembled data field */
133 static const fragment_items h223_al_frag_items
= {
134 &ett_h223_al_fragment
,
135 &ett_h223_al_fragments
,
136 &hf_h223_al_fragments
,
137 &hf_h223_al_fragment
,
138 &hf_h223_al_fragment_overlap
,
139 &hf_h223_al_fragment_overlap_conflict
,
140 &hf_h223_al_fragment_multiple_tails
,
141 &hf_h223_al_fragment_too_long_fragment
,
142 &hf_h223_al_fragment_error
,
143 &hf_h223_al_fragment_count
,
144 &hf_h223_al_reassembled_in
,
145 &hf_h223_al_reassembled_length
,
146 /* Reassembled data field */
151 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
152 static uint32_t pdu_offset
;
154 /***************************************************************************
156 * virtual circuit number handling
158 * we have to be able to manage more than one H.223 call at a time,
159 * so have a hash which maps {call,vc} to an integer.
162 typedef struct _h223_call_info h223_call_info
;
165 const h223_call_info
* call
; /* h223 call */
166 uint32_t vc
; /* child circuit */
169 static wmem_map_t
*circuit_chain_hashtable
;
170 static unsigned circuit_chain_count
= 1;
174 circuit_chain_equal(const void *v
, const void *w
)
176 const circuit_chain_key
*v1
= (const circuit_chain_key
*)v
;
177 const circuit_chain_key
*v2
= (const circuit_chain_key
*)w
;
179 result
= ( v1
->call
== v2
->call
&&
180 v1
->vc
== v2
-> vc
);
185 circuit_chain_hash (const void *v
)
187 const circuit_chain_key
*key
= (const circuit_chain_key
*)v
;
188 unsigned hash_val
= (GPOINTER_TO_UINT(key
->call
)) ^ (((uint32_t)key
->vc
) << 16);
193 circuit_chain_lookup(const h223_call_info
* call_info
, uint32_t child_vc
)
195 circuit_chain_key key
, *new_key
;
197 key
.call
= call_info
;
199 circuit_id
= GPOINTER_TO_UINT(wmem_map_lookup( circuit_chain_hashtable
, &key
));
200 if( circuit_id
== 0 ) {
201 new_key
= wmem_new(wmem_file_scope(), circuit_chain_key
);
203 circuit_id
= ++circuit_chain_count
;
204 wmem_map_insert(circuit_chain_hashtable
, new_key
, GUINT_TO_POINTER(circuit_id
));
210 circuit_chain_init(void)
212 circuit_chain_count
= 1;
216 /***************************************************************************
218 * Call information management
222 /* we keep information on each call in an h223_call_info structure
224 * We attach the h223_call_info structures to individual calls with
225 * circuit_add_proto_data().
228 typedef struct _h223_mux_element_listitem h223_mux_element_listitem
;
229 struct _h223_mux_element_listitem
{
230 h223_mux_element
*me
;
231 uint32_t first_frame
;
233 h223_mux_element_listitem
*next
;
236 /* we have this information for each stream */
238 h223_mux_element_listitem
* mux_table
[16];
239 } h223_call_direction_data
;
242 struct _h223_call_info
{
243 /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
244 specified in the annexes
248 /* for H.223 streams over TCP (as opposed to IAX), this
249 stores the source address and port of the first packet spotted,
250 so that we can differentiate directions.
255 h223_call_direction_data direction_data
[2];
258 typedef struct _h223_lc_params_listitem h223_lc_params_listitem
;
259 struct _h223_lc_params_listitem
261 h223_lc_params
*lc_params
;
262 uint32_t first_frame
;
264 h223_lc_params_listitem
*next
;
268 h223_lc_params_listitem
*lc_params
[2];
269 h223_call_info
*call_info
;
273 add_h223_mux_element(h223_call_direction_data
*direct
, uint8_t mc
, h223_mux_element
*me
, uint32_t framenum
)
275 h223_mux_element_listitem
*li
;
276 h223_mux_element_listitem
**old_li_ptr
;
277 h223_mux_element_listitem
*old_li
;
279 DISSECTOR_ASSERT(mc
< 16);
281 li
= wmem_new(wmem_file_scope(), h223_mux_element_listitem
);
282 old_li_ptr
= &(direct
->mux_table
[mc
]);
283 old_li
= *old_li_ptr
;
285 direct
->mux_table
[mc
] = li
;
287 while( old_li
->next
) {
288 old_li_ptr
= &(old_li
->next
);
289 old_li
= *old_li_ptr
;
291 if( framenum
< old_li
->first_frame
|| (framenum
== old_li
->first_frame
&& pdu_offset
< old_li
->pdu_offset
) )
293 else if ( framenum
== old_li
->first_frame
&& pdu_offset
== old_li
->pdu_offset
)
294 *old_li_ptr
= li
; /* replace the tail of the list with the new item, since */
295 /* a single h223 pdu has just set the same MC twice.. */
299 li
->first_frame
= framenum
;
300 li
->pdu_offset
= pdu_offset
;
305 static h223_mux_element
*
306 find_h223_mux_element(h223_call_direction_data
* direct
, uint8_t mc
, uint32_t framenum
, uint32_t 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
)
326 add_h223_lc_params(h223_vc_info
* vc_info
, int direction
, h223_lc_params
*lc_params
, uint32_t framenum
)
328 h223_lc_params_listitem
*li
= wmem_new(wmem_file_scope(), h223_lc_params_listitem
);
329 h223_lc_params_listitem
**old_li_ptr
= &(vc_info
->lc_params
[direction
? 0 : 1]);
330 h223_lc_params_listitem
*old_li
= *old_li_ptr
;
332 vc_info
->lc_params
[direction
? 0 : 1] = li
;
334 while( old_li
->next
) {
335 old_li_ptr
= &(old_li
->next
);
336 old_li
= *old_li_ptr
;
338 if( framenum
< old_li
->first_frame
)
340 else if( framenum
== old_li
->first_frame
)
344 old_li
->last_frame
= framenum
- 1;
347 li
->first_frame
= framenum
;
350 li
->lc_params
= lc_params
;
353 static h223_lc_params
*
354 find_h223_lc_params(h223_vc_info
* vc_info
, int direction
, uint32_t framenum
)
356 h223_lc_params_listitem
* li
= vc_info
->lc_params
[direction
? 0 : 1];
357 while( li
&& li
->next
&& li
->next
->first_frame
<= framenum
)
360 return li
->lc_params
;
366 init_direction_data(h223_call_direction_data
*direct
)
369 h223_mux_element
*mc0_element
;
371 for ( i
= 0; i
< 16; ++i
)
372 direct
->mux_table
[i
] = NULL
;
374 /* set up MC 0 to contain just VC 0 */
375 mc0_element
= wmem_new(wmem_file_scope(), h223_mux_element
);
376 add_h223_mux_element( direct
, 0, mc0_element
, 0 );
377 mc0_element
->sublist
= NULL
;
379 mc0_element
->repeat_count
= 0; /* until closing flag */
380 mc0_element
->next
= NULL
;
384 h223_vc_info_new( h223_call_info
* call_info
)
386 h223_vc_info
*vc_info
= wmem_new(wmem_file_scope(), h223_vc_info
);
387 vc_info
->lc_params
[0] = vc_info
->lc_params
[1] = NULL
;
388 vc_info
->call_info
= call_info
;
393 init_logical_channel( uint32_t start_frame
, h223_call_info
* call_info
, int vc
, int direction
, h223_lc_params
* params
)
395 uint32_t circuit_id
= circuit_chain_lookup(call_info
, vc
);
396 conversation_t
*subcircuit
;
397 h223_vc_info
*vc_info
;
398 subcircuit
= find_conversation_by_id( start_frame
, CONVERSATION_H223
, circuit_id
);
400 if( subcircuit
== NULL
) {
401 subcircuit
= conversation_new_by_id( start_frame
, CONVERSATION_H223
, circuit_id
);
403 ws_debug("%d: Created new circuit %d for call %p VC %d", start_frame
, circuit_id
, call_info
, vc
);
405 vc_info
= h223_vc_info_new( call_info
);
406 conversation_add_proto_data( subcircuit
, proto_h223
, vc_info
);
408 vc_info
= (h223_vc_info
*)conversation_get_proto_data( subcircuit
, proto_h223
);
410 add_h223_lc_params( vc_info
, direction
, params
, start_frame
);
413 /* create a brand-new h223_call_info structure */
414 static h223_call_info
*
415 create_call_info( uint32_t start_frame
)
417 h223_call_info
*datax
;
418 h223_lc_params
*vc0_params
;
420 datax
= wmem_new(wmem_file_scope(), h223_call_info
);
422 /* initialise the call info */
423 init_direction_data(&datax
-> direction_data
[0]);
424 init_direction_data(&datax
-> direction_data
[1]);
426 /* FIXME shouldn't this be figured out dynamically? */
427 datax
-> h223_level
= 2;
429 vc0_params
= wmem_new(wmem_file_scope(), h223_lc_params
);
430 vc0_params
->al_type
= al1Framed
;
431 vc0_params
->al_params
= NULL
;
432 vc0_params
->segmentable
= true;
433 vc0_params
->subdissector
= srp_handle
;
434 init_logical_channel( start_frame
, datax
, 0, P2P_DIR_SENT
, vc0_params
);
435 init_logical_channel( start_frame
, datax
, 0, P2P_DIR_RECV
, vc0_params
);
439 /* find or create call_info struct for calls over circuits (eg, IAX) */
440 static h223_call_info
*
441 find_or_create_call_info_circ(packet_info
* pinfo
, conversation_type ctype
, uint32_t circuit_id
)
443 h223_call_info
*datax
;
444 conversation_t
*circ
= NULL
;
446 if(ctype
!= CONVERSATION_NONE
)
447 circ
= find_conversation_by_id( pinfo
->num
, ctype
, circuit_id
);
451 datax
= (h223_call_info
*)conversation_get_proto_data(circ
, proto_h223
);
453 if( datax
== NULL
) {
454 datax
= create_call_info(pinfo
->num
);
457 ws_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
458 pinfo
->num
, datax
, circ
, type
, circuit_id
);
460 conversation_add_proto_data(circ
, proto_h223
, datax
);
463 /* work out what direction we're really going in */
464 if( pinfo
->p2p_dir
< 0 || pinfo
->p2p_dir
> 1)
465 pinfo
->p2p_dir
= P2P_DIR_SENT
;
470 /* find or create call_info struct for calls over conversations (eg, RTP) */
471 static h223_call_info
*
472 find_or_create_call_info_conv(packet_info
* pinfo
)
474 h223_call_info
*datax
;
475 conversation_t
*conv
;
477 /* assume we're running atop TCP or RTP; use the conversation support */
478 conv
= find_conversation_pinfo(pinfo
, 0 );
480 /* both RTP and TCP track their conversations, so just assert here if
481 * we can't find one */
482 DISSECTOR_ASSERT(conv
);
484 datax
= (h223_call_info
*)conversation_get_proto_data(conv
, proto_h223
);
486 if(datax
== NULL
&& pinfo
->ptype
== PT_UDP
) {
487 conversation_t
*conv2
;
489 /* RTP tracks the two sides of the conversation totally separately;
490 * this messes us up totally.
492 * Look for another converstation, going in the opposite direction.
494 conv2
= find_conversation( pinfo
->num
,
495 &pinfo
->dst
,&pinfo
->src
,
496 conversation_pt_to_conversation_type(pinfo
->ptype
),
497 pinfo
->destport
,pinfo
->srcport
, 0 );
499 datax
= (h223_call_info
*)conversation_get_proto_data(conv2
, proto_h223
);
503 ws_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",
504 pinfo
->num
, conv
, conv2
, datax
, pinfo
->ptype
,
505 pinfo
->dst
.data
[0], pinfo
->dst
.data
[1], pinfo
->dst
.data
[2], pinfo
->dst
.data
[3],
507 pinfo
->src
.data
[0], pinfo
->src
.data
[1], pinfo
->src
.data
[2], pinfo
->src
.data
[3],
510 conversation_add_proto_data(conv
, proto_h223
, datax
);
514 /* we still haven't found any call data - create a new one for this
517 datax
= create_call_info(pinfo
->num
);
520 ws_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
521 pinfo
->num
, datax
, conv
, pinfo
->ptype
,
522 pinfo
->src
.data
[0], pinfo
->src
.data
[1], pinfo
->src
.data
[2], pinfo
->src
.data
[3],
524 pinfo
->dst
.data
[0], pinfo
->dst
.data
[1], pinfo
->dst
.data
[2], pinfo
->dst
.data
[3],
528 conversation_add_proto_data(conv
, proto_h223
, datax
);
529 /* add the source details so we can distinguish directions
531 copy_address_wmem(wmem_file_scope(), &(datax
-> srcaddress
), &(pinfo
->src
));
532 datax
-> srcport
= pinfo
->srcport
;
535 /* work out what direction we're really going in */
536 if( addresses_equal( &(pinfo
->src
), &(datax
->srcaddress
))
537 && pinfo
->srcport
== datax
->srcport
)
538 pinfo
->p2p_dir
= P2P_DIR_SENT
;
540 pinfo
->p2p_dir
= P2P_DIR_RECV
;
545 static h223_call_info
*
546 find_or_create_call_info ( packet_info
* pinfo
, conversation_type ctype
, uint32_t circuit_id
)
548 h223_call_info
*datax
;
550 datax
= find_or_create_call_info_circ(pinfo
, ctype
, circuit_id
);
552 datax
= find_or_create_call_info_conv(pinfo
);
556 /* called from the h245 dissector to handle a MultiplexEntrySend message */
558 h223_set_mc( packet_info
* pinfo
, uint8_t mc
, h223_mux_element
* me
)
560 conversation_t
*circ
= find_conversation_pinfo( pinfo
, 0 );
561 h223_vc_info
* vc_info
;
563 /* if this h245 pdu packet came from an h223 circuit, add the details on
564 * the new mux entry */
566 vc_info
= (h223_vc_info
*)conversation_get_proto_data(circ
, proto_h223
);
568 add_h223_mux_element( &(vc_info
->call_info
->direction_data
[pinfo
->p2p_dir
? 0 : 1]), mc
, me
, pinfo
->num
);
572 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
574 h223_add_lc( packet_info
* pinfo
, uint16_t lc
, h223_lc_params
* params
)
576 conversation_t
*circ
= find_conversation_pinfo( pinfo
, 0 );
577 h223_vc_info
* vc_info
;
579 /* if this h245 pdu packet came from an h223 circuit, add the details on
582 vc_info
= (h223_vc_info
*)conversation_get_proto_data(circ
, proto_h223
);
584 init_logical_channel( pinfo
->num
, vc_info
->call_info
, lc
, pinfo
->p2p_dir
, params
);
588 /************************************************************************************
593 static const uint8_t crctable
[256] = {
594 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
595 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
596 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
597 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
598 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
599 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
600 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
601 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
602 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
603 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
604 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
605 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
606 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
607 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
608 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
609 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
611 static uint8_t h223_al2_crc8bit( tvbuff_t
*tvb
) {
612 uint32_t len
= tvb_reported_length(tvb
) - 1;
613 const uint8_t* datax
= tvb_get_ptr( tvb
, 0, len
);
614 unsigned char crc
= 0;
616 DISSECTOR_ASSERT(tvb_reported_length(tvb
) >= 1);
618 crc
= crctable
[crc
^datax
[pos
++]];
623 dissect_mux_al_pdu( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*vc_tree
,
624 /* circuit_t* vc_circuit, */
625 h223_lc_params
* lc_params
)
627 proto_tree
*al_tree
= NULL
;
628 proto_item
*al_item
, *hidden_item
;
629 proto_tree
*al_subtree
;
630 proto_item
*al_subitem
= NULL
;
631 proto_item
*tmp_item
;
632 tvbuff_t
*next_tvb
= NULL
;
633 dissector_handle_t subdissector
= lc_params
->subdissector
;
634 uint32_t len
= tvb_reported_length(tvb
);
636 uint8_t calc_checksum
;
637 uint8_t real_checksum
;
638 bool al2_sequenced
= false;
641 switch( lc_params
->al_type
) {
644 al_item
= proto_tree_add_none_format(vc_tree
, hf_h223_al1
, tvb
, 0, -1, "H.223 AL1 (%sframed)",
645 (lc_params
->al_type
==al1Framed
)?"":"not ");
646 al_tree
= proto_item_add_subtree (al_item
, ett_h223_al1
);
647 if(lc_params
->al_type
== al1Framed
) {
648 hidden_item
= proto_tree_add_boolean(al_tree
, hf_h223_al1_framed
, tvb
, 0, 1, true );
649 proto_item_set_hidden(hidden_item
);
652 al_subitem
= proto_tree_add_item(al_tree
, hf_h223_al_payload
, next_tvb
, 0, -1, ENC_NA
);
655 case al2WithSequenceNumbers
:
656 al2_sequenced
= true;
658 case al2WithoutSequenceNumbers
:
659 tmp_item
= proto_tree_add_boolean(vc_tree
, hf_h223_al2
, tvb
, 0, 0, true );
661 al_item
= proto_tree_add_item(vc_tree
,
662 al2_sequenced
?hf_h223_al2_sequenced
:hf_h223_al2_unsequenced
,
664 al_tree
= proto_item_add_subtree (al_item
, ett_h223_al2
);
666 proto_item_set_generated(tmp_item
);
668 /* check minimum payload length */
669 if(len
< (al2_sequenced
?2U:1U))
673 if( al2_sequenced
) {
674 proto_tree_add_item(al_tree
, hf_h223_al2_seqno
, tvb
, 0, 1, ENC_LITTLE_ENDIAN
);
678 next_tvb
= tvb_new_subset_length( tvb
, data_start
, len
-1-data_start
);
679 al_subitem
= proto_tree_add_item(al_tree
, hf_h223_al_payload
, next_tvb
, 0, -1, ENC_NA
);
681 calc_checksum
= h223_al2_crc8bit(tvb
);
682 real_checksum
= tvb_get_uint8(tvb
, len
- 1);
684 proto_tree_add_checksum(al_tree
, tvb
, len
- 1, hf_h223_al2_crc
, hf_h223_al2_crc_status
, &ei_h223_al2_crc
, pinfo
, calc_checksum
, ENC_NA
, PROTO_CHECKSUM_VERIFY
);
686 if( calc_checksum
!= real_checksum
) {
687 /* don't pass pdus which fail checksums on to the subdissector */
688 subdissector
= data_handle
;
692 call_dissector(data_handle
, tvb
, pinfo
, vc_tree
);
697 subdissector
= data_handle
;
699 al_subtree
= proto_item_add_subtree(al_subitem
, ett_h223_al_payload
);
700 call_dissector(subdissector
, next_tvb
, pinfo
, al_subtree
);
703 /************************************************************************************
709 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
711 * tvb buffer containing the MUX-PDU fragment
712 * pinfo info on the packet containing the last fragment of the MUX-PDU
713 * pkt_offset offset within the block from the superdissector where the
714 * fragment starts (must increase monotonically for constant pinfo->num)
715 * pdu_tree dissection tree for the PDU; a single item will be added (with
718 * end_of_mux_sdu true if this is a segmentable VC and this is the last
722 dissect_mux_sdu_fragment(tvbuff_t
*volatile next_tvb
, packet_info
*pinfo
,
723 uint32_t pkt_offset
, proto_tree
*pdu_tree
,
724 h223_call_info
* call_info
, uint16_t vc
,
725 bool end_of_mux_sdu
, conversation_type orig_ctype
,
726 uint32_t orig_circuit
)
729 /* update the circuit details before passing to a subdissector */
730 uint32_t circuit_id
= circuit_chain_lookup(call_info
, vc
);
731 conversation_set_elements_by_id(pinfo
, CONVERSATION_H223
, circuit_id
);
733 conversation_t
*subcircuit
= find_conversation_by_id(pinfo
->num
, CONVERSATION_H223
, circuit_id
);
736 h223_vc_info
*vc_info
= NULL
;
737 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
);
742 if( subcircuit
== NULL
) {
743 ws_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo
->num
,
744 circuit_id
, (void *)call_info
, vc
);
746 vc_info
= (h223_vc_info
*)conversation_get_proto_data(subcircuit
, proto_h223
);
747 if( vc_info
!= NULL
) {
748 lc_params
= find_h223_lc_params( vc_info
, pinfo
->p2p_dir
, pinfo
->num
);
753 if( lc_params
!= NULL
) {
754 if( lc_params
->segmentable
&& lc_params
->al_type
!= al1NotFramed
) {
756 stream_pdu_fragment_t
*frag
;
758 substream
= find_stream(subcircuit
,pinfo
->p2p_dir
);
759 if(substream
== NULL
)
760 substream
= stream_new(subcircuit
,pinfo
->p2p_dir
);
761 frag
= stream_find_frag(substream
,pinfo
->num
,pkt_offset
);
765 ws_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
766 pinfo
->num
, orig_circuit
, circuit_id
, pkt_offset
, tvb_reported_length(next_tvb
), end_of_mux_sdu
);
768 frag
= stream_add_frag(substream
,pinfo
->num
,pkt_offset
,
769 next_tvb
,pinfo
,!end_of_mux_sdu
);
772 ws_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
773 pinfo
->num
, orig_circuit
, circuit_id
, pkt_offset
, tvb_reported_length(next_tvb
), end_of_mux_sdu
);
777 next_tvb
= stream_process_reassembled(
779 "Reassembled H.223 AL-PDU",
780 frag
, &h223_al_frag_items
,
785 /* fudge to pass pkt_offset down to add_h223_mux_element,
786 * should it be called */
787 pdu_offset
= pkt_offset
;
788 dissect_mux_al_pdu(next_tvb
, pinfo
, vc_tree
,/* subcircuit,*/ lc_params
);
791 call_dissector(data_handle
,next_tvb
,pinfo
,vc_tree
);
795 /* restore the original circuit details for future PDUs */
797 conversation_set_elements_by_id(pinfo
, orig_ctype
, orig_circuit
);
803 // NOLINTNEXTLINE(misc-no-recursion)
804 mux_element_sublist_size(packet_info
*pinfo
, h223_mux_element
* me
)
806 h223_mux_element
*current_me
= me
->next
;
808 increment_dissection_depth(pinfo
);
809 while ( current_me
) {
810 if ( current_me
->sublist
)
811 length
+= current_me
->repeat_count
* mux_element_sublist_size(pinfo
, current_me
->sublist
);
813 length
+= current_me
->repeat_count
;
814 current_me
= current_me
->next
;
816 decrement_dissection_depth(pinfo
);
818 /* should never happen, but to avoid infinite loops... */
819 DISSECTOR_ASSERT(length
!= 0);
824 /* dissect part of a MUX-PDU payload according to a multiplex list
826 * tvb buffer containing entire mux-pdu payload
827 * pinfo info on the packet containing the last fragment of the MUX-PDU
828 * pkt_offset offset within the block from the superdissector where the
829 * MUX-PDU starts (must increase monotonically for constant
831 * pdu_tree dissection tree for the PDU
832 * call_info data structure for h223 call
834 * offset offset within tvb to start work
835 * endOfMuxSdu true if the end-of-sdu flag was set
838 // NOLINTNEXTLINE(misc-no-recursion)
839 dissect_mux_payload_by_me_list( tvbuff_t
*tvb
, packet_info
*pinfo
,
840 uint32_t pkt_offset
, proto_tree
*pdu_tree
,
841 h223_call_info
* call_info
,
842 h223_mux_element
*me
, uint32_t offset
,
843 bool endOfMuxSdu
, conversation_type ctype
,
846 uint32_t len
= tvb_reported_length(tvb
);
848 uint32_t sublist_len
;
850 increment_dissection_depth(pinfo
);
853 if ( me
->repeat_count
== 0 ) {
854 for(sublist_len
= mux_element_sublist_size(pinfo
, me
->sublist
);
855 offset
+ sublist_len
<= len
;
856 offset
= dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
,
857 call_info
, me
->sublist
, offset
, endOfMuxSdu
,
858 ctype
, circuit_id
) );
860 for(i
= 0; i
< me
->repeat_count
; ++i
)
861 offset
= dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
,
862 call_info
, me
->sublist
, offset
, endOfMuxSdu
,
866 if ( me
->repeat_count
== 0 )
867 frag_len
= len
- offset
;
869 frag_len
= me
->repeat_count
;
872 next_tvb
= tvb_new_subset_length(tvb
, offset
, frag_len
);
873 dissect_mux_sdu_fragment( next_tvb
, pinfo
, pkt_offset
+ offset
, pdu_tree
,
874 call_info
, me
->vc
, (offset
+frag_len
==len
) && endOfMuxSdu
,
881 decrement_dissection_depth(pinfo
);
885 /* dissect the payload of a MUX-PDU
887 * tvb buffer containing entire mux-pdu payload
888 * pinfo info on the packet containing the last fragment of the MUX-PDU
889 * pkt_offset offset within the block from the superdissector where the
890 * MUX-PDU starts (must increase monotonically for constant
892 * pdu_tree dissection tree for the PDU
893 * call_info data structure for h223 call
894 * mc multiplex code for this PDU
895 * endOfMuxSdu true if the end-of-sdu flag was set
898 dissect_mux_payload( tvbuff_t
*tvb
, packet_info
*pinfo
, uint32_t pkt_offset
,
899 proto_tree
*pdu_tree
, h223_call_info
*call_info
,
900 uint8_t mc
, bool endOfMuxSdu
, conversation_type ctype
,
901 uint32_t circuit_id
)
903 uint32_t len
= tvb_reported_length(tvb
);
905 h223_mux_element
* me
= find_h223_mux_element( &(call_info
->direction_data
[pinfo
->p2p_dir
? 0 : 1]), mc
, pinfo
->num
, pkt_offset
);
908 dissect_mux_payload_by_me_list( tvb
, pinfo
, pkt_offset
, pdu_tree
, call_info
, me
, 0, endOfMuxSdu
, ctype
, circuit_id
);
910 /* no entry found in mux-table. ignore packet and dissect as data */
911 proto_tree
*vc_tree
= NULL
;
914 proto_item
*vc_item
= proto_tree_add_item(pdu_tree
, hf_h223_mux_deact
, tvb
, 0, len
, ENC_NA
);
915 vc_tree
= proto_item_add_subtree(vc_item
, ett_h223_mux_deact
);
917 call_dissector(data_handle
,tvb
,pinfo
,vc_tree
);
921 /* dissect a reassembled mux-pdu
923 * tvb buffer containing mux-pdu, including header and closing flag
924 * pinfo packet info for packet containing the end of the mux-pdu
925 * pkt_offset offset within the block from the superdissector where the
926 * MUX-PDU starts (must increase monotonically for constant
928 * h223_tree dissection tree for h223 protocol; a single item will be added
930 * call_info h223 info structure for this h223 call
931 * pdu_no index of this pdu within the call
934 dissect_mux_pdu( tvbuff_t
*tvb
, packet_info
*pinfo
, uint32_t pkt_offset
,
935 proto_tree
*h223_tree
, h223_call_info
*call_info
,
936 conversation_type ctype
, uint32_t circuit_id
)
939 /* actual (as opposed to reported) payload len */
941 uint32_t raw_hdr
= 0, correct_hdr
= 0;
943 uint16_t closing_flag
= 0;
946 bool end_of_mux_sdu
= false;
949 proto_item
*pdu_item
= NULL
;
950 proto_tree
*pdu_tree
= NULL
;
952 #ifdef DEBUG_H223_FRAGMENTATION
953 ws_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
954 pinfo
->num
, pkt_offset
, tvb_reported_length(tvb
));
957 switch(call_info
->h223_level
) {
959 raw_hdr
= tvb_get_uint8(tvb
,0);
960 mc
= (uint8_t)((raw_hdr
>>1) & 0xf);
961 end_of_mux_sdu
= raw_hdr
& 1;
963 /* closing flag is one byte long for h223 level 0, two for level 1 */
964 len
= mpl
= tvb_reported_length_remaining(tvb
, offset
)-(call_info
->h223_level
+1);
966 /* XXX should ignore pdus with incorrect HECs */
970 raw_hdr
= tvb_get_letoh24(tvb
,0);
971 errors
= golay_errors(raw_hdr
);
973 len
= tvb_reported_length_remaining(tvb
,offset
)-2;
976 correct_hdr
= raw_hdr
^ (uint32_t)errors
;
978 mc
= (uint8_t)(correct_hdr
& 0xf);
979 mpl
= (uint8_t)((correct_hdr
>> 4) & 0xff);
981 /* we should never have been called if there's not enough data in
983 DISSECTOR_ASSERT(len
>= mpl
);
985 closing_flag
= tvb_get_ntohs(tvb
,offset
+len
);
986 end_of_mux_sdu
= (closing_flag
==(0xE14D ^ 0xFFFF));
994 /* XXX not implemented */
996 DISSECTOR_ASSERT_NOT_REACHED();
1002 pdu_item
= proto_tree_add_item (h223_tree
, hf_h223_mux_stuffing_pdu
, tvb
, 0, -1, ENC_NA
);
1003 pdu_tree
= proto_item_add_subtree (pdu_item
, ett_h223_mux_stuffing_pdu
);
1005 pdu_item
= proto_tree_add_item (h223_tree
, hf_h223_mux_pdu
, tvb
, 0, -1, ENC_NA
);
1006 pdu_tree
= proto_item_add_subtree (pdu_item
, ett_h223_mux_pdu
);
1011 proto_item
*item
= proto_tree_add_item (pdu_tree
, hf_h223_mux_header
, tvb
, 0, offset
, ENC_NA
);
1012 proto_tree
*hdr_tree
= proto_item_add_subtree (item
, ett_h223_mux_header
);
1014 switch(call_info
->h223_level
) {
1016 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mc
,tvb
,0,1,mc
);
1020 if( errors
== -1 ) {
1021 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1023 "0x%06x (uncorrectable errors)", raw_hdr
);
1025 /* B.3.2.1 Header field */
1027 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1029 "0x%06x (correct)", raw_hdr
);
1031 proto_tree_add_uint_format_value(hdr_tree
, hf_h223_mux_rawhdr
, tvb
,
1033 "0x%06x (errors are 0x%06x)", raw_hdr
, errors
);
1035 item
= proto_tree_add_uint(hdr_tree
,hf_h223_mux_correctedhdr
,tvb
,0,3,
1037 proto_item_set_generated(item
);
1038 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mc
,tvb
,0,1,mc
);
1039 proto_tree_add_uint(hdr_tree
,hf_h223_mux_mpl
,tvb
,0,2,mpl
);
1044 /* XXX not implemented */
1046 DISSECTOR_ASSERT_NOT_REACHED();
1051 pdu_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, len
, mpl
);
1053 dissect_mux_payload(pdu_tvb
,pinfo
,pkt_offset
+offset
,pdu_tree
,call_info
,mc
,end_of_mux_sdu
, ctype
, circuit_id
);
1055 call_dissector(data_handle
,pdu_tvb
,pinfo
,pdu_tree
);
1060 /* any extra data in the PDU, beyond that indictated by the mpl, is
1061 dissected as data. */
1064 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, offset
, len
);
1065 proto_tree
*vc_tree
= NULL
;
1068 proto_item
*vc_item
= proto_tree_add_item(pdu_tree
, hf_h223_mux_extra
, next_tvb
, 0, len
, ENC_NA
);
1069 vc_tree
= proto_item_add_subtree(vc_item
, ett_h223_mux_deact
);
1071 call_dissector(data_handle
,next_tvb
,pinfo
,vc_tree
);
1076 /* add the closing HDLC flag */
1078 proto_tree_add_item(pdu_tree
,hf_h223_mux_hdlc2
,tvb
,offset
,2,ENC_BIG_ENDIAN
);
1082 /************************************************************************************
1084 * MUX-PDU delineation and defragmentation
1087 /* attempt to parse the header of a mux pdu */
1089 attempt_mux_level0_header_parse(uint32_t nbytes _U_
, uint32_t hdr _U_
, uint32_t *minlen _U_
)
1091 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1092 DISSECTOR_ASSERT_NOT_REACHED();
1097 attempt_mux_level1_header_parse(uint32_t nbytes
, uint32_t hdr
, uint32_t *minlen
)
1099 /* this is untested */
1104 /* don't interpret a repeated hdlc as a header */
1108 /* + 1 byte of header and 2 bytes of closing HDLC */
1109 *minlen
= (uint8_t)((hdr
>> 12) & 0xff) + 3;
1114 attempt_mux_level2_3_header_parse(uint32_t nbytes
, uint32_t hdr
, uint32_t *minlen
)
1121 /* + 3 bytes of header and 2 bytes of closing HDLC */
1124 /* bah, we get the header in the wrong order */
1126 ((hdr
& 0xFF0000) >> 16) |
1128 ((hdr
& 0x0000FF) << 16);
1130 errors
= golay_errors(hdr
);
1133 *minlen
+= ((hdr
>> 4) & 0xff);
1139 static bool (* const attempt_mux_header_parse
[])(uint32_t nbytes
, uint32_t header_buf
, uint32_t *minlen
) = {
1140 attempt_mux_level0_header_parse
,
1141 attempt_mux_level1_header_parse
,
1142 attempt_mux_level2_3_header_parse
,
1143 attempt_mux_level2_3_header_parse
1147 h223_mux_check_hdlc(int h223_level
, uint32_t nbytes
, uint32_t tail_buf
)
1151 switch(h223_level
) {
1153 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1154 DISSECTOR_ASSERT_NOT_REACHED();
1158 masked
= tail_buf
& 0xffff;
1159 return nbytes
>= 2 && masked
== 0xE14D;
1162 masked
= tail_buf
& 0xffff;
1163 return nbytes
>= 2 && (masked
== 0xE14D || masked
== (0xE14D ^ 0xFFFF));
1166 DISSECTOR_ASSERT_NOT_REACHED();
1171 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1173 * returns the number of bytes processed, or the negative of the number of
1174 * extra bytes needed, or zero if we don't know yet
1178 dissect_mux_pdu_fragment( tvbuff_t
*tvb
, uint32_t start_offset
,
1179 packet_info
*pinfo
, proto_tree
*h223_tree
,
1180 h223_call_info
*call_info
, conversation_type ctype
,
1181 uint32_t circuit_id
)
1183 tvbuff_t
*volatile next_tvb
;
1184 volatile uint32_t offset
= start_offset
;
1185 bool more_frags
= true;
1187 bool header_parsed
= false;
1188 uint32_t header_buf
= 0, tail_buf
= 0;
1189 uint32_t pdu_minlen
= 0;
1192 #ifdef DEBUG_H223_FRAGMENTATION
1193 ws_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1194 pinfo
->num
,start_offset
, tvb_reported_length_remaining( tvb
, start_offset
));
1197 while( more_frags
&& offset
< tvb_reported_length( tvb
)) {
1198 uint8_t byte
= tvb_get_uint8(tvb
, offset
++);
1200 /* read a byte into the header buf, if necessary */
1201 if((offset
-start_offset
) <= 4) {
1206 /* read the byte into the tail buf */
1210 /* if we haven't parsed the header yet, attempt to do so now */
1212 /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1213 header_parsed
= (attempt_mux_header_parse
[call_info
->h223_level
])
1214 (offset
-start_offset
,header_buf
,&pdu_minlen
);
1216 /* if we have successfully parsed the header, we have sufficient data,
1217 * and we have found the closing hdlc, we are done here */
1218 if(header_parsed
&& (offset
-start_offset
) >= pdu_minlen
) {
1219 if(h223_mux_check_hdlc(call_info
->h223_level
,offset
-start_offset
,tail_buf
)) {
1226 if(pdu_minlen
<= (offset
-start_offset
)) {
1227 /* we haven't found the closing hdlc yet, but we don't know how
1228 * much more we need */
1229 #ifdef DEBUG_H223_FRAGMENTATION
1230 ws_debug("\tBailing, requesting more bytes");
1234 uint32_t needed
= pdu_minlen
-(offset
-start_offset
);
1235 #ifdef DEBUG_H223_FRAGMENTATION
1236 ws_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen
,(offset
-start_offset
),needed
);
1238 return - (int) needed
;
1242 /* create a tvb for the fragment */
1243 next_tvb
= tvb_new_subset_length(tvb
, start_offset
, offset
-start_offset
);
1248 * If it gets an error that means there's no point in dissecting
1249 * any more PDUs, rethrow the exception in question.
1251 * If it gets any other error, report it and continue, as that
1252 * means that PDU got an error, but that doesn't mean we should
1253 * stop dissecting PDUs within this frame or chunk of reassembled
1257 dissect_mux_pdu( next_tvb
, pinfo
, start_offset
, h223_tree
, call_info
, ctype
, circuit_id
);
1259 CATCH_NONFATAL_ERRORS
{
1260 show_exception(tvb
, pinfo
, h223_tree
, EXCEPT_CODE
, GET_MESSAGE
);
1265 return (offset
-start_offset
);
1268 /************************************************************************************
1270 * main dissector entry points
1273 /* dissects PDUs from the tvb
1275 * Updates desegment_offset and desegment_len if the end of the data didn't
1276 * line up with the end of a pdu.
1279 dissect_h223_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, conversation_type ctype
, uint32_t circuit_id
)
1281 proto_tree
*h223_tree
= NULL
;
1282 proto_item
*h223_item
= NULL
;
1283 h223_call_info
*call_info
= NULL
;
1284 uint32_t offset
= 0;
1286 /* set up the protocol and info fields in the summary pane */
1287 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_H223
);
1289 col_clear(pinfo
->cinfo
, COL_INFO
);
1291 /* find or create the call_info for this call */
1292 call_info
= find_or_create_call_info(pinfo
, ctype
, circuit_id
);
1294 /* add the 'h223' tree to the main tree */
1296 h223_item
= proto_tree_add_item (tree
, proto_h223
, tvb
, 0, -1, ENC_NA
);
1297 h223_tree
= proto_item_add_subtree (h223_item
, ett_h223
);
1300 while( offset
< tvb_reported_length( tvb
)) {
1301 int res
= dissect_mux_pdu_fragment( tvb
, offset
, pinfo
,
1302 h223_tree
, call_info
, ctype
, circuit_id
);
1304 /* the end of the tvb held the start of a PDU */
1305 pinfo
->desegment_offset
= offset
;
1307 /* if res != 0, we actually know how much more data we need for a
1310 * However, if we return that, it means that we get called twice
1311 * for the next packet; this makes it hard to tell how far through
1312 * the stream we are and we have to start messing about with
1313 * getting the seqno from the superdissector's private data. So we
1316 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1318 pinfo
-> desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
1321 /* shrink the h223 protocol item such that it only includes the
1322 * bits we dissected */
1323 proto_item_set_len(h223_item
,offset
);
1327 col_set_str(pinfo
->cinfo
, COL_INFO
, "(No complete PDUs)");
1336 dissect_h223_circuit_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1338 iax2_dissector_info_t circuit_info
;
1340 DISSECTOR_ASSERT(data
);
1341 circuit_info
= *((iax2_dissector_info_t
*)data
);
1343 dissect_h223_common(tvb
, pinfo
, tree
, circuit_info
.ctype
, circuit_info
.circuit_id
);
1344 return tvb_captured_length(tvb
);
1348 dissect_h223(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1350 dissect_h223_common(tvb
, pinfo
, tree
, CONVERSATION_NONE
, 0);
1351 return tvb_captured_length(tvb
);
1354 /* H.223 specifies that the least-significant bit is transmitted first;
1355 * however this is at odds with IAX which transmits bytes with the
1356 * first-received bit as the MSB.
1358 * This dissector swaps the ordering of the bits in each byte before using the
1359 * normal entry point.
1362 dissect_h223_bitswapped_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, conversation_type ctype
, uint32_t circuit_id
)
1364 tvbuff_t
*reversed_tvb
;
1368 len
= tvb_reported_length(tvb
);
1369 datax
= (uint8_t *) tvb_memdup(pinfo
->pool
, tvb
, 0, len
);
1370 bitswap_buf_inplace(datax
, len
);
1373 * Add the reversed tvbuff to the list of tvbuffs to which
1374 * the tvbuff we were handed refers, so it'll get
1375 * cleaned up when that tvbuff is cleaned up.
1377 reversed_tvb
= tvb_new_child_real_data(tvb
, datax
,len
,tvb_reported_length(tvb
));
1379 /* Add the reversed data to the data source list. */
1380 add_new_data_source(pinfo
, reversed_tvb
, "Bit-swapped H.223 frame" );
1382 dissect_h223_common(reversed_tvb
,pinfo
,tree
,ctype
,circuit_id
);
1386 dissect_h223_bitswapped_circuit_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1388 iax2_dissector_info_t circuit_info
;
1390 DISSECTOR_ASSERT(data
);
1391 circuit_info
= *((iax2_dissector_info_t
*)data
);
1393 dissect_h223_bitswapped_common(tvb
, pinfo
, tree
, circuit_info
.ctype
, circuit_info
.circuit_id
);
1394 return tvb_captured_length(tvb
);
1398 dissect_h223_bitswapped(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1400 dissect_h223_bitswapped_common(tvb
, pinfo
, tree
, CONVERSATION_NONE
, 0);
1401 return tvb_captured_length(tvb
);
1404 /******************************************************************************/
1407 void proto_register_h223 (void)
1409 /* A header field is something you can search/filter on.
1411 * We create a structure to register our fields. It consists of an
1412 * array of hf_register_info structures, each of which are of the format
1413 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1416 static hf_register_info hf
[] = {
1418 { &hf_h223_non_h223_data
,
1419 { "Non-H.223 data", "h223.non-h223", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1420 "Initial data in stream, not a PDU", HFILL
}},
1423 { &hf_h223_mux_stuffing_pdu
,
1424 { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1425 "Empty PDU used for stuffing when no data available", HFILL
}},
1428 { "H.223 MUX-PDU", "h223.mux", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1431 { &hf_h223_mux_header
,
1432 { "Header", "h223.mux.header", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1433 "H.223 MUX header", HFILL
}},
1435 { &hf_h223_mux_rawhdr
,
1436 { "Raw value", "h223.mux.rawhdr", FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1437 "Raw header bytes", HFILL
}},
1439 { &hf_h223_mux_correctedhdr
,
1440 { "Corrected value", "h223.mux.correctedhdr", FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1441 "Corrected header bytes", HFILL
}},
1444 { "Multiplex Code", "h223.mux.mc", FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
1445 "H.223 MUX multiplex code", HFILL
}},
1448 { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT16
, BASE_DEC
, NULL
, 0xf00f,
1449 "H.223 MUX multiplex Payload Length", HFILL
}},
1451 { &hf_h223_mux_deact
,
1452 { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1453 "mpl refers to an entry in the multiplex table which is not active", HFILL
}},
1456 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1459 { &hf_h223_mux_extra
,
1460 { "Extraneous data", "h223.mux.extra", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1461 "data beyond mpl", HFILL
}},
1463 { &hf_h223_mux_hdlc2
,
1464 { "HDLC flag", "h223.mux.hdlc", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1465 "framing flag", HFILL
}},
1467 /* fields for h.223-mux fragments */
1468 { &hf_h223_mux_fragment_overlap
,
1469 { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1470 "Fragment overlaps with other fragments", HFILL
}},
1472 { &hf_h223_mux_fragment_overlap_conflict
,
1473 { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1474 "Overlapping fragments contained conflicting data", HFILL
}},
1476 { &hf_h223_mux_fragment_multiple_tails
,
1477 { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1478 "Several tails were found when defragmenting the packet", HFILL
}},
1480 { &hf_h223_mux_fragment_too_long_fragment
,
1481 { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1482 "Fragment contained data past end of packet", HFILL
}},
1484 { &hf_h223_mux_fragment_error
,
1485 { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1486 "Defragmentation error due to illegal fragments", HFILL
}},
1488 { &hf_h223_mux_fragment_count
,
1489 { "Fragment count", "h223.mux.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1492 { &hf_h223_mux_fragment
,
1493 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1496 { &hf_h223_mux_fragments
,
1497 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1500 { &hf_h223_mux_reassembled_in
,
1501 { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1502 "This H.223 MUX-PDU packet is reassembled in this frame", HFILL
}},
1504 { &hf_h223_mux_reassembled_length
,
1505 { "Reassembled H.223 MUX-PDU length", "h223.mux.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1506 "The total length of the reassembled payload", HFILL
}},
1508 /* fields for h.223-al fragments */
1509 { &hf_h223_al_fragment_overlap
,
1510 { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1511 "Fragment overlaps with other fragments", HFILL
}},
1513 { &hf_h223_al_fragment_overlap_conflict
,
1514 { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1515 "Overlapping fragments contained conflicting data", HFILL
}},
1517 { &hf_h223_al_fragment_multiple_tails
,
1518 { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1519 "Several tails were found when defragmenting the packet", HFILL
}},
1521 { &hf_h223_al_fragment_too_long_fragment
,
1522 { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1523 "Fragment contained data past end of packet", HFILL
}},
1525 { &hf_h223_al_fragment_error
,
1526 { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1527 "Defragmentation error due to illegal fragments", HFILL
}},
1529 { &hf_h223_al_fragment_count
,
1530 { "Fragment count", "h223.al.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1533 { &hf_h223_al_fragment
,
1534 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1537 { &hf_h223_al_fragments
,
1538 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1541 { &hf_h223_al_reassembled_in
,
1542 { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1543 "This H.223 AL-PDU packet is reassembled in this frame", HFILL
}},
1545 { &hf_h223_al_reassembled_length
,
1546 { "Reassembled H.223 AL-PDU length", "h223.al.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1547 "The total length of the reassembled payload", HFILL
}},
1552 { "H.223 AL1", "h223.al1", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1553 "H.223 AL-PDU using AL1", HFILL
}},
1555 { &hf_h223_al1_framed
,
1556 { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1560 { "H.223 AL2", "h223.al2", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1561 "H.223 AL-PDU using AL2", HFILL
}},
1563 { &hf_h223_al2_sequenced
,
1564 { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1565 "H.223 AL-PDU using AL2 with sequence numbers", HFILL
}},
1567 { &hf_h223_al2_unsequenced
,
1568 { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1569 "H.223 AL-PDU using AL2 without sequence numbers", HFILL
}},
1571 { &hf_h223_al2_seqno
,
1572 { "Sequence Number", "h223.al2.seqno", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1573 "H.223 AL2 sequence number", HFILL
}},
1576 { "CRC", "h223.al2.crc", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1579 { &hf_h223_al2_crc_status
,
1580 { "CRC Status","h223.al2.crc.status", FT_UINT8
, BASE_NONE
, VALS(proto_checksum_vals
), 0x0,
1583 { &hf_h223_al_payload
,
1584 { "H.223 AL Payload", "h223.al.payload", FT_NONE
, BASE_NONE
, NULL
, 0x0,
1585 "H.223 AL-PDU Payload", HFILL
}},
1589 static int *ett
[] = {
1591 &ett_h223_non_h223_data
,
1592 &ett_h223_mux_stuffing_pdu
,
1594 &ett_h223_mux_header
,
1595 &ett_h223_mux_deact
,
1597 &ett_h223_mux_extra
,
1598 &ett_h223_mux_fragments
,
1599 &ett_h223_mux_fragment
,
1600 &ett_h223_al_fragments
,
1601 &ett_h223_al_fragment
,
1604 &ett_h223_al_payload
1607 static ei_register_info ei
[] = {
1608 { &ei_h223_al2_crc
, { "h223.bad_checksum", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
1611 expert_module_t
* expert_h223
;
1614 proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1615 /* Create a H.223 "placeholder" to remove confusion with Decode As" */
1616 proto_h223_bitswapped
=
1617 proto_register_protocol_in_name_only ("ITU-T Recommendation H.223 (Bitswapped)", "H.223 (Bitswapped)", "h223_bitswapped", proto_h223
, FT_PROTOCOL
);
1619 proto_register_field_array (proto_h223
, hf
, array_length (hf
));
1620 proto_register_subtree_array (ett
, array_length (ett
));
1621 expert_h223
= expert_register_protocol(proto_h223
);
1622 expert_register_field_array(expert_h223
, ei
, array_length(ei
));
1624 register_dissector("h223", dissect_h223_circuit_data
, proto_h223
);
1625 h223_bitswapped
= register_dissector("h223_bitswapped", dissect_h223_bitswapped
, proto_h223_bitswapped
);
1627 /* register our init routine to be called at the start of a capture,
1628 to clear out our hash tables etc */
1629 register_init_routine(&circuit_chain_init
);
1631 circuit_chain_hashtable
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), circuit_chain_hash
, circuit_chain_equal
);
1633 h245_set_h223_set_mc_handle( &h223_set_mc
);
1634 h245_set_h223_add_lc_handle( &h223_add_lc
);
1637 void proto_reg_handoff_h223(void)
1639 data_handle
= find_dissector("data");
1640 srp_handle
= find_dissector("srp");
1642 dissector_add_for_decode_as_with_preference("tcp.port", create_dissector_handle( dissect_h223
, proto_h223
));
1643 dissector_add_for_decode_as_with_preference("tcp.port", h223_bitswapped
);
1644 dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped
);
1645 dissector_add_for_decode_as("rtp.pt", h223_bitswapped
);
1646 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_H223_H245
, create_dissector_handle(dissect_h223_bitswapped_circuit_data
, proto_h223_bitswapped
));
1655 * indent-tabs-mode: nil
1658 * ex: set shiftwidth=4 tabstop=8 expandtab:
1659 * :indentSize=4:tabSize=8:noTabs=true: