Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-h223.c
blob0b46b9f583e1baf55228a904db12cfd223f9864d
1 /* packet-h223.c
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
12 #include "config.h"
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 */
92 static int ett_h223;
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 */
129 NULL,
130 "fragments"
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 */
147 NULL,
148 "fragments"
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;
164 typedef struct {
165 const h223_call_info* call; /* h223 call */
166 uint32_t vc; /* child circuit */
167 } circuit_chain_key;
169 static wmem_map_t *circuit_chain_hashtable;
170 static unsigned circuit_chain_count = 1;
172 /* Hash Functions */
173 static int
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;
178 int result;
179 result = ( v1->call == v2->call &&
180 v1->vc == v2 -> vc );
181 return result;
184 static unsigned
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);
189 return hash_val;
192 static uint32_t
193 circuit_chain_lookup(const h223_call_info* call_info, uint32_t child_vc)
195 circuit_chain_key key, *new_key;
196 uint32_t circuit_id;
197 key.call = call_info;
198 key.vc = child_vc;
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);
202 *new_key = key;
203 circuit_id = ++circuit_chain_count;
204 wmem_map_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id));
206 return circuit_id;
209 static void
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;
232 uint32_t pdu_offset;
233 h223_mux_element_listitem *next;
236 /* we have this information for each stream */
237 typedef struct {
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
246 int h223_level;
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.
252 address srcaddress;
253 uint32_t srcport;
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;
263 uint32_t last_frame;
264 h223_lc_params_listitem *next;
267 typedef struct {
268 h223_lc_params_listitem *lc_params[2];
269 h223_call_info *call_info;
270 } h223_vc_info;
272 static void
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;
284 if( !old_li ) {
285 direct->mux_table[mc] = li;
286 } else {
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) )
292 return;
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.. */
296 else
297 old_li->next = li;
299 li->first_frame = framenum;
300 li->pdu_offset = pdu_offset;
301 li->next = 0;
302 li->me = me;
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 )
315 li = li->next;
316 while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset )
317 li = li->next;
318 if( li ) {
319 return li->me;
320 } else {
321 return NULL;
325 static void
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;
331 if( !old_li ) {
332 vc_info->lc_params[direction ? 0 : 1] = li;
333 } else {
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 )
339 return;
340 else if( framenum == old_li->first_frame )
341 *old_li_ptr = li;
342 else {
343 old_li->next = li;
344 old_li->last_frame = framenum - 1;
347 li->first_frame = framenum;
348 li->last_frame = 0;
349 li->next = 0;
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 )
358 li = li->next;
359 if( li )
360 return li->lc_params;
361 else
362 return NULL;
365 static void
366 init_direction_data(h223_call_direction_data *direct)
368 int i;
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;
378 mc0_element->vc = 0;
379 mc0_element->repeat_count = 0; /* until closing flag */
380 mc0_element->next = NULL;
383 static h223_vc_info*
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;
389 return vc_info;
392 static void
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);
402 #ifdef DEBUG_H223
403 ws_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc);
404 #endif
405 vc_info = h223_vc_info_new( call_info );
406 conversation_add_proto_data( subcircuit, proto_h223, vc_info );
407 } else {
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 );
436 return datax;
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);
448 if(circ == NULL)
449 return NULL;
451 datax = (h223_call_info *)conversation_get_proto_data(circ, proto_h223);
453 if( datax == NULL ) {
454 datax = create_call_info(pinfo->num);
456 #ifdef DEBUG_H223
457 ws_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
458 pinfo->num, datax, circ, type, circuit_id);
459 #endif
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;
467 return datax;
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 );
498 if(conv2 != NULL)
499 datax = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
501 if(datax != NULL) {
502 #ifdef DEBUG_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],
506 pinfo->destport,
507 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
508 pinfo->srcport);
509 #endif
510 conversation_add_proto_data(conv, proto_h223, datax);
514 /* we still haven't found any call data - create a new one for this
515 * conversation */
516 if(datax == NULL) {
517 datax = create_call_info(pinfo->num);
519 #ifdef DEBUG_H223
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],
523 pinfo->srcport,
524 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
525 pinfo->destport);
526 #endif
528 conversation_add_proto_data(conv, proto_h223, datax);
529 /* add the source details so we can distinguish directions
530 * in future */
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;
539 else
540 pinfo->p2p_dir = P2P_DIR_RECV;
542 return datax;
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);
551 if(datax == NULL)
552 datax = find_or_create_call_info_conv(pinfo);
553 return datax;
556 /* called from the h245 dissector to handle a MultiplexEntrySend message */
557 static void
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 */
565 if(circ) {
566 vc_info = (h223_vc_info *)conversation_get_proto_data(circ, proto_h223);
567 if (vc_info != NULL)
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 */
573 static void
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
580 * the new channel */
581 if(circ) {
582 vc_info = (h223_vc_info *)conversation_get_proto_data(circ, proto_h223);
583 if (vc_info != NULL)
584 init_logical_channel( pinfo->num, vc_info->call_info, lc, pinfo->p2p_dir, params );
588 /************************************************************************************
590 * AL-PDU dissection
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;
615 uint32_t pos = 0;
616 DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
617 while ( len-- )
618 crc = crctable[crc^datax[pos++]];
619 return crc;
622 static void
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;
639 int data_start;
641 switch( lc_params->al_type ) {
642 case al1Framed:
643 case al1NotFramed:
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);
651 next_tvb = tvb;
652 al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, ENC_NA);
653 break;
655 case al2WithSequenceNumbers:
656 al2_sequenced = true;
657 /* fall-through */
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,
663 tvb, 0, -1, ENC_NA);
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))
670 THROW(BoundsError);
672 data_start = 0;
673 if( al2_sequenced ) {
674 proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, ENC_LITTLE_ENDIAN);
675 data_start++;
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;
690 break;
691 default:
692 call_dissector(data_handle, tvb, pinfo, vc_tree);
693 return;
696 if (!subdissector)
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 /************************************************************************************
705 * MUX-PDU dissection
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
716 * its own subtree)
717 * vc VC for this SDU
718 * end_of_mux_sdu true if this is a segmentable VC and this is the last
719 * fragment in an SDU
721 static void
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)
728 TRY {
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);
734 proto_tree *vc_tree;
735 proto_item *vc_item;
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 );
745 } else {
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 ) {
755 stream_t *substream;
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);
763 if(frag == NULL ) {
764 #ifdef DEBUG_H223
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);
767 #endif
768 frag = stream_add_frag(substream,pinfo->num,pkt_offset,
769 next_tvb,pinfo,!end_of_mux_sdu);
770 } else {
771 #ifdef DEBUG_H223
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);
774 #endif
777 next_tvb = stream_process_reassembled(
778 next_tvb, 0, pinfo,
779 "Reassembled H.223 AL-PDU",
780 frag, &h223_al_frag_items,
781 NULL, vc_tree);
784 if(next_tvb) {
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 );
790 } else {
791 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
795 /* restore the original circuit details for future PDUs */
796 FINALLY {
797 conversation_set_elements_by_id(pinfo, orig_ctype, orig_circuit);
799 ENDTRY;
802 static uint32_t
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;
807 uint32_t length = 0;
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);
812 else
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);
821 return length;
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
830 * pinfo->num)
831 * pdu_tree dissection tree for the PDU
832 * call_info data structure for h223 call
833 * me top of mux list
834 * offset offset within tvb to start work
835 * endOfMuxSdu true if the end-of-sdu flag was set
837 static uint32_t
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,
844 uint32_t circuit_id)
846 uint32_t len = tvb_reported_length(tvb);
847 uint32_t frag_len;
848 uint32_t sublist_len;
849 int i;
850 increment_dissection_depth(pinfo);
851 while ( me ) {
852 if ( me->sublist ) {
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) );
859 } else {
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,
863 ctype, circuit_id);
865 } else {
866 if ( me->repeat_count == 0 )
867 frag_len = len - offset;
868 else
869 frag_len = me->repeat_count;
870 if(frag_len > 0) {
871 tvbuff_t *next_tvb;
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,
875 ctype, circuit_id);
876 offset += frag_len;
879 me = me->next;
881 decrement_dissection_depth(pinfo);
882 return offset;
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
891 * pinfo->num)
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
897 static void
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 );
907 if( me ) {
908 dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu, ctype, circuit_id );
909 } else {
910 /* no entry found in mux-table. ignore packet and dissect as data */
911 proto_tree *vc_tree = NULL;
913 if(pdu_tree) {
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
927 * pinfo->num)
928 * h223_tree dissection tree for h223 protocol; a single item will be added
929 * (with a sub-tree)
930 * call_info h223 info structure for this h223 call
931 * pdu_no index of this pdu within the call
933 static void
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)
938 uint32_t offset = 0;
939 /* actual (as opposed to reported) payload len */
940 uint32_t len;
941 uint32_t raw_hdr = 0, correct_hdr = 0;
942 int32_t errors = 0;
943 uint16_t closing_flag = 0;
944 uint8_t mc = 0;
945 uint8_t mpl = 0;
946 bool end_of_mux_sdu = false;
947 tvbuff_t *pdu_tvb;
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));
955 #endif
957 switch(call_info->h223_level) {
958 case 0: case 1:
959 raw_hdr = tvb_get_uint8(tvb,0);
960 mc = (uint8_t)((raw_hdr>>1) & 0xf);
961 end_of_mux_sdu = raw_hdr & 1;
962 offset++;
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 */
967 break;
969 case 2:
970 raw_hdr = tvb_get_letoh24(tvb,0);
971 errors = golay_errors(raw_hdr);
972 offset += 3;
973 len = tvb_reported_length_remaining(tvb,offset)-2;
975 if(errors != -1) {
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
982 * available. */
983 DISSECTOR_ASSERT(len >= mpl);
985 closing_flag = tvb_get_ntohs(tvb,offset+len);
986 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
987 } else {
988 mc = 0;
989 mpl = len;
991 break;
993 case 3:
994 /* XXX not implemented */
995 default:
996 DISSECTOR_ASSERT_NOT_REACHED();
1000 if( h223_tree ) {
1001 if( mpl == 0 ) {
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);
1004 } else {
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);
1010 if( pdu_tree ) {
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) {
1015 case 0: case 1:
1016 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1017 break;
1019 case 2:
1020 if( errors == -1 ) {
1021 proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb,
1022 0, 3, raw_hdr,
1023 "0x%06x (uncorrectable errors)", raw_hdr );
1024 } else {
1025 /* B.3.2.1 Header field */
1026 if( errors == 0 ) {
1027 proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb,
1028 0, 3, raw_hdr,
1029 "0x%06x (correct)", raw_hdr );
1030 } else {
1031 proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb,
1032 0, 3, raw_hdr,
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,
1036 correct_hdr);
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);
1041 break;
1043 case 3:
1044 /* XXX not implemented */
1045 default:
1046 DISSECTOR_ASSERT_NOT_REACHED();
1050 if(mpl > 0) {
1051 pdu_tvb = tvb_new_subset_length_caplen(tvb, offset, len, mpl);
1052 if(errors != -1) {
1053 dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu, ctype, circuit_id);
1054 } else {
1055 call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1057 offset += mpl;
1060 /* any extra data in the PDU, beyond that indictated by the mpl, is
1061 dissected as data. */
1062 len -= mpl;
1063 if( len > 0 ) {
1064 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, len);
1065 proto_tree *vc_tree = NULL;
1067 if( pdu_tree ) {
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);
1073 offset += len;
1076 /* add the closing HDLC flag */
1077 if( pdu_tree )
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 */
1088 static bool
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();
1093 return false;
1096 static bool
1097 attempt_mux_level1_header_parse(uint32_t nbytes, uint32_t hdr, uint32_t *minlen )
1099 /* this is untested */
1100 if(nbytes < 2)
1101 return false;
1103 hdr &= 0xffff;
1104 /* don't interpret a repeated hdlc as a header */
1105 if(hdr == 0xE14D)
1106 return false;
1108 /* + 1 byte of header and 2 bytes of closing HDLC */
1109 *minlen = (uint8_t)((hdr >> 12) & 0xff) + 3;
1110 return true;
1113 static bool
1114 attempt_mux_level2_3_header_parse(uint32_t nbytes, uint32_t hdr, uint32_t *minlen)
1116 int32_t errors;
1118 if(nbytes < 3)
1119 return false;
1121 /* + 3 bytes of header and 2 bytes of closing HDLC */
1122 *minlen = 5;
1124 /* bah, we get the header in the wrong order */
1125 hdr =
1126 ((hdr & 0xFF0000) >> 16) |
1127 (hdr & 0x00FF00) |
1128 ((hdr & 0x0000FF) << 16);
1130 errors = golay_errors(hdr);
1131 if(errors != -1) {
1132 hdr ^= errors;
1133 *minlen += ((hdr >> 4) & 0xff);
1136 return true;
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
1146 static bool
1147 h223_mux_check_hdlc(int h223_level, uint32_t nbytes, uint32_t tail_buf)
1149 uint32_t masked;
1151 switch(h223_level) {
1152 case 0:
1153 /* level 0 isn't byte-aligned, so is a complete pain to implement */
1154 DISSECTOR_ASSERT_NOT_REACHED();
1155 return false;
1157 case 1:
1158 masked = tail_buf & 0xffff;
1159 return nbytes >= 2 && masked == 0xE14D;
1161 case 2: case 3:
1162 masked = tail_buf & 0xffff;
1163 return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1165 default:
1166 DISSECTOR_ASSERT_NOT_REACHED();
1167 return false;
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
1177 static int
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 ));
1195 #endif
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) {
1202 header_buf <<= 8;
1203 header_buf |= byte;
1206 /* read the byte into the tail buf */
1207 tail_buf <<= 8;
1208 tail_buf |= byte;
1210 /* if we haven't parsed the header yet, attempt to do so now */
1211 if(!header_parsed)
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)) {
1220 more_frags = false;
1225 if( more_frags ) {
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");
1231 #endif
1232 return 0;
1233 } else {
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);
1237 #endif
1238 return - (int) needed;
1242 /* create a tvb for the fragment */
1243 next_tvb = tvb_new_subset_length(tvb, start_offset, offset-start_offset);
1246 * Dissect the PDU.
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
1254 * data.
1256 TRY {
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);
1263 ENDTRY;
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.
1278 static void
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 */
1295 if (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);
1303 if(res <= 0) {
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
1308 * PDU.
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
1314 * don't do that.
1316 * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1318 pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1320 if(h223_item) {
1321 /* shrink the h223 protocol item such that it only includes the
1322 * bits we dissected */
1323 proto_item_set_len(h223_item,offset);
1326 if(offset == 0) {
1327 col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1329 return;
1331 offset += res;
1335 static int
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);
1347 static int
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.
1361 static void
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;
1365 uint8_t *datax;
1366 unsigned len;
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);
1385 static int
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);
1397 static int
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[] = {
1417 #if 0
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 }},
1421 #endif
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 }},
1427 { &hf_h223_mux_pdu,
1428 { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1429 NULL, HFILL }},
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 }},
1443 { &hf_h223_mux_mc,
1444 { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0f,
1445 "H.223 MUX multiplex code", HFILL }},
1447 { &hf_h223_mux_mpl,
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 }},
1455 { &hf_h223_mux_vc,
1456 { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1457 NULL, HFILL }},
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,
1490 NULL, HFILL }},
1492 { &hf_h223_mux_fragment,
1493 { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1494 NULL, HFILL }},
1496 { &hf_h223_mux_fragments,
1497 { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1498 NULL, HFILL }},
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,
1531 NULL, HFILL }},
1533 { &hf_h223_al_fragment,
1534 { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1535 NULL, HFILL }},
1537 { &hf_h223_al_fragments,
1538 { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1539 NULL, HFILL }},
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 }},
1549 /* h223-als */
1551 { &hf_h223_al1,
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,
1557 NULL, HFILL }},
1559 { &hf_h223_al2,
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 }},
1575 { &hf_h223_al2_crc,
1576 { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1577 NULL, HFILL }},
1579 { &hf_h223_al2_crc_status,
1580 { "CRC Status","h223.al2.crc.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
1581 NULL, HFILL }},
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[] = {
1590 &ett_h223,
1591 &ett_h223_non_h223_data,
1592 &ett_h223_mux_stuffing_pdu,
1593 &ett_h223_mux_pdu,
1594 &ett_h223_mux_header,
1595 &ett_h223_mux_deact,
1596 &ett_h223_mux_vc,
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,
1602 &ett_h223_al1,
1603 &ett_h223_al2,
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;
1613 proto_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));
1650 * Editor modelines
1652 * Local Variables:
1653 * c-basic-offset: 4
1654 * tab-width: 8
1655 * indent-tabs-mode: nil
1656 * End:
1658 * ex: set shiftwidth=4 tabstop=8 expandtab:
1659 * :indentSize=4:tabSize=8:noTabs=true: