Don't guard col_clear with col_check
[obnox/wireshark/wip.git] / epan / dissectors / packet-h223.c
1 /* packet-h223.c
2  * Routines for H.223 packet dissection
3  * Copyright (c) 2004-5 MX Telecom Ltd <richardv@mxtelecom.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31
32 #include <gmodule.h>
33 #include <glib.h>
34 #include <epan/emem.h>
35 #include <epan/bitswap.h>
36 #include <epan/circuit.h>
37 #include <epan/conversation.h>
38 #include <epan/packet.h>
39 #include <epan/stream.h>
40 #include <epan/reassemble.h>
41 #include <epan/golay.h>
42 #include <epan/iax2_codec_type.h>
43 #include <epan/dissectors/packet-frame.h>
44 #include <epan/asn1.h>
45 #include <epan/dissectors/packet-h245.h>
46
47 #include "packet-h223.h"
48
49 #include <string.h>
50
51 /* #define DEBUG_H223 */
52
53 /* debug the mux-pdu defragmentation code. warning: verbose output! */
54 /* #define DEBUG_H223_FRAGMENTATION */
55
56 #define PROTO_TAG_H223  "H223"
57
58 /* Wireshark ID of the H.223 protocol */
59 static int proto_h223 = -1;
60 static int proto_h223_bitswapped = -1;
61
62 /* The following hf_* variables are used to hold the Wireshark IDs of
63  * our header fields; they are filled out when we call
64  * proto_register_field_array() in proto_register_h223()
65  */
66 static int hf_h223_non_h223_data = -1;
67 static int hf_h223_mux_stuffing_pdu = -1;
68 static int hf_h223_mux_pdu = -1;
69 static int hf_h223_mux_header = -1;
70 static int hf_h223_mux_rawhdr = -1;
71 static int hf_h223_mux_correctedhdr = -1;
72 static int hf_h223_mux_mc = -1;
73 static int hf_h223_mux_mpl = -1;
74 static int hf_h223_mux_deact = -1;
75 static int hf_h223_mux_vc = -1;
76 static int hf_h223_mux_extra = -1;
77 static int hf_h223_mux_hdlc2 = -1;
78 static int hf_h223_mux_fragments = -1;
79 static int hf_h223_mux_fragment = -1;
80 static int hf_h223_mux_fragment_overlap = -1;
81 static int hf_h223_mux_fragment_overlap_conflict = -1;
82 static int hf_h223_mux_fragment_multiple_tails = -1;
83 static int hf_h223_mux_fragment_too_long_fragment = -1;
84 static int hf_h223_mux_fragment_error = -1;
85 static int hf_h223_mux_reassembled_in = -1;
86
87 static int hf_h223_al_fragments = -1;
88 static int hf_h223_al_fragment = -1;
89 static int hf_h223_al_fragment_overlap = -1;
90 static int hf_h223_al_fragment_overlap_conflict = -1;
91 static int hf_h223_al_fragment_multiple_tails = -1;
92 static int hf_h223_al_fragment_too_long_fragment = -1;
93 static int hf_h223_al_fragment_error = -1;
94 static int hf_h223_al_reassembled_in = -1;
95
96 static int hf_h223_al1 = -1;
97 static int hf_h223_al1_framed = -1;
98 static int hf_h223_al2 = -1;
99 static int hf_h223_al2_sequenced = -1;
100 static int hf_h223_al2_unsequenced = -1;
101 static int hf_h223_al2_seqno = -1;
102 static int hf_h223_al2_crc = -1;
103 static int hf_h223_al2_crc_bad = -1;
104
105 static int hf_h223_al_payload = -1;
106
107 /* These are the ids of the subtrees that we may be creating */
108 static gint ett_h223 = -1;
109 static gint ett_h223_non_h223_data = -1;
110 static gint ett_h223_mux_stuffing_pdu = -1;
111 static gint ett_h223_mux_pdu = -1;
112 static gint ett_h223_mux_header = -1;
113 static gint ett_h223_mux_deact = -1;
114 static gint ett_h223_mux_vc = -1;
115 static gint ett_h223_mux_extra = -1;
116 static gint ett_h223_mux_fragments = -1;
117 static gint ett_h223_mux_fragment  = -1;
118 static gint ett_h223_al_fragments = -1;
119 static gint ett_h223_al_fragment  = -1;
120 static gint ett_h223_al1 = -1;
121 static gint ett_h223_al2 = -1;
122 static gint ett_h223_al_payload = -1;
123
124 /* These are the handles of our subdissectors */
125 static dissector_handle_t data_handle;
126 static dissector_handle_t srp_handle;
127
128 static const fragment_items h223_mux_frag_items _U_ = {
129         &ett_h223_mux_fragment,
130         &ett_h223_mux_fragments,
131         &hf_h223_mux_fragments,
132         &hf_h223_mux_fragment,
133         &hf_h223_mux_fragment_overlap,
134         &hf_h223_mux_fragment_overlap_conflict,
135         &hf_h223_mux_fragment_multiple_tails,
136         &hf_h223_mux_fragment_too_long_fragment,
137         &hf_h223_mux_fragment_error,
138         &hf_h223_mux_reassembled_in,
139         "fragments"
140 };
141
142 static const fragment_items h223_al_frag_items = {
143         &ett_h223_al_fragment,
144         &ett_h223_al_fragments,
145         &hf_h223_al_fragments,
146         &hf_h223_al_fragment,
147         &hf_h223_al_fragment_overlap,
148         &hf_h223_al_fragment_overlap_conflict,
149         &hf_h223_al_fragment_multiple_tails,
150         &hf_h223_al_fragment_too_long_fragment,
151         &hf_h223_al_fragment_error,
152         &hf_h223_al_reassembled_in,
153         "fragments"
154 };
155
156 /* this is a fudge to pass pdu_offset into add_h223_mux_element() */
157 static guint32 pdu_offset;
158
159 /***************************************************************************
160  *
161  * virtual circuit number handling
162  *
163  * we have to be able to manage more than one H.223 call at a time,
164  * so have a hash which maps {call,vc} to an integer.
165  */
166
167 typedef struct _h223_call_info h223_call_info;
168
169 typedef struct {
170     const h223_call_info* call; /* h223 call */
171     guint32 vc;                 /* child circuit */
172 } circuit_chain_key;
173
174 static GHashTable *circuit_chain_hashtable = NULL;
175 static guint circuit_chain_count = 1;
176
177 /* Hash Functions */
178 static gint circuit_chain_equal(gconstpointer v, gconstpointer w)
179 {
180     const circuit_chain_key *v1 = (const circuit_chain_key *)v;
181     const circuit_chain_key *v2 = (const circuit_chain_key *)w;
182     gint result;
183     result = ( v1->call == v2->call &&
184                v1->vc == v2 -> vc );
185     return result;
186 }
187
188 static guint circuit_chain_hash (gconstpointer v)
189 {
190     const circuit_chain_key *key = (const circuit_chain_key *)v;
191     guint hash_val = ((guint32)(unsigned long)(key->call))^(((guint32)key->vc) << 16);
192     return hash_val;
193 }
194
195 static guint32 circuit_chain_lookup(const h223_call_info* call_info,
196                                     guint32 child_vc)
197 {
198     circuit_chain_key key, *new_key;
199     guint32 circuit_id;
200     key.call = call_info;
201     key.vc = child_vc;
202     circuit_id = GPOINTER_TO_UINT(g_hash_table_lookup( circuit_chain_hashtable, &key ));
203     if( circuit_id == 0 ) {
204         new_key = se_alloc(sizeof(circuit_chain_key));
205         *new_key = key;
206         circuit_id = ++circuit_chain_count;
207         g_hash_table_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id));
208     }
209     return circuit_id;
210 }
211
212 static void circuit_chain_init(void)
213 {
214     if (circuit_chain_hashtable)
215         g_hash_table_destroy(circuit_chain_hashtable);
216     circuit_chain_hashtable = g_hash_table_new(circuit_chain_hash, circuit_chain_equal);
217     circuit_chain_count = 1;
218 }
219
220
221 /***************************************************************************
222  *
223  * Call information management
224  *
225  */
226
227 /* we keep information on each call in an h223_call_info structure
228  *
229  * We attach the h223_call_info structures to individual calls with
230  * circuit_add_proto_data().
231 */
232
233 typedef struct _h223_mux_element_listitem h223_mux_element_listitem;
234 struct _h223_mux_element_listitem {
235     h223_mux_element          *me;
236     guint32                    first_frame;
237     guint32                    pdu_offset;
238     h223_mux_element_listitem *next;
239 };
240
241 /* we have this information for each stream */
242 typedef struct {
243     h223_mux_element_listitem* mux_table[16];
244 } h223_call_direction_data;
245
246
247 struct _h223_call_info {
248     /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols
249        specified in the annexes
250     */
251     int h223_level;
252
253     /* for H.223 streams over TCP (as opposed to IAX), this
254        stores the source address and port of the first packet spotted,
255        so that we can differentiate directions.
256     */
257     address srcaddress;
258     guint32 srcport;
259
260     h223_call_direction_data direction_data[2];
261 };
262
263 typedef struct _h223_lc_params_listitem h223_lc_params_listitem;
264 struct _h223_lc_params_listitem
265 {
266     h223_lc_params         *lc_params;
267     guint32                 first_frame;
268     guint32                 last_frame;
269     h223_lc_params_listitem *next;
270 };
271
272 typedef struct {
273     h223_lc_params_listitem *lc_params[2];
274     h223_call_info          *call_info;
275 } h223_vc_info;
276
277 static void add_h223_mux_element(h223_call_direction_data *direct, guint8 mc, h223_mux_element *me, guint32 framenum)
278 {
279     h223_mux_element_listitem *li;
280     h223_mux_element_listitem **old_li_ptr;
281     h223_mux_element_listitem *old_li;
282     
283     DISSECTOR_ASSERT(mc < 16);
284     
285     li = se_alloc(sizeof(h223_mux_element_listitem));
286     old_li_ptr = &(direct->mux_table[mc]);
287     old_li = *old_li_ptr;
288     if( !old_li ) {
289         direct->mux_table[mc] = li;
290     } else {
291         while( old_li->next ) {
292             old_li_ptr = &(old_li->next);
293             old_li = *old_li_ptr;
294         }
295         if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset)  )
296             return;
297         else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset )
298             *old_li_ptr = li; /* replace the tail of the list with the new item, since */
299                               /* a single h223 pdu has just set the same MC twice.. */
300         else
301             old_li->next = li;
302     }
303     li->first_frame = framenum;
304     li->pdu_offset = pdu_offset;
305     li->next = 0;
306     li->me = me;
307 }
308
309 static h223_mux_element* find_h223_mux_element(h223_call_direction_data* direct, guint8 mc, guint32 framenum, guint32 pkt_offset)
310 {
311     h223_mux_element_listitem* li;
312     
313     DISSECTOR_ASSERT(mc < 16);
314     
315     li = direct->mux_table[mc];
316     
317     while( li && li->next && li->next->first_frame < framenum )
318         li = li->next;
319     while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset )
320         li = li->next;
321     if( li ) {
322         return li->me;
323     } else {
324         return NULL;
325     }
326 }
327
328 static void add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, guint32 framenum )
329 {
330     h223_lc_params_listitem *li = se_alloc(sizeof(h223_lc_params_listitem));
331     h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction ? 0 : 1]);
332     h223_lc_params_listitem *old_li = *old_li_ptr;
333     if( !old_li ) {
334         vc_info->lc_params[direction ? 0 : 1] = li;
335     } else {
336         while( old_li->next ) {
337             old_li_ptr = &(old_li->next);
338             old_li = *old_li_ptr;
339         }
340         if( framenum < old_li->first_frame )
341             return;
342         else if( framenum == old_li->first_frame )
343             *old_li_ptr = li;
344         else {
345             old_li->next = li;
346             old_li->last_frame = framenum - 1;
347         }
348     }
349     li->first_frame = framenum;
350     li->last_frame = 0;
351     li->next = 0;
352     li->lc_params = lc_params;
353 }
354
355 static h223_lc_params* find_h223_lc_params(h223_vc_info* vc_info, int direction, guint32 framenum)
356 {
357     h223_lc_params_listitem* li = vc_info->lc_params[direction? 0 : 1];
358     while( li && li->next && li->next->first_frame <= framenum )
359         li = li->next;
360     if( li )
361         return li->lc_params;
362     else
363         return NULL;
364 }
365
366 static void init_direction_data(h223_call_direction_data *direct)
367 {
368     int i;
369         h223_mux_element *mc0_element;
370
371     for ( i = 0; i < 16; ++i )
372         direct->mux_table[i] = NULL;
373
374     /* set up MC 0 to contain just VC 0 */
375     mc0_element = se_alloc(sizeof(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;
381 }
382
383 static h223_vc_info* h223_vc_info_new( h223_call_info* call_info )
384 {
385     h223_vc_info *vc_info = se_alloc(sizeof(h223_vc_info));
386     vc_info->lc_params[0] = vc_info->lc_params[1] = NULL;
387     vc_info->call_info = call_info;
388     return vc_info;
389 }
390
391 static void init_logical_channel( guint32 start_frame, h223_call_info* call_info, int vc, int direction, h223_lc_params* params )
392 {
393     guint32 circuit_id = circuit_chain_lookup(call_info, vc);
394     circuit_t *subcircuit;
395     h223_vc_info *vc_info;
396     subcircuit = find_circuit( CT_H223, circuit_id, start_frame );
397
398     if( subcircuit == NULL ) {
399         subcircuit = circuit_new( CT_H223, circuit_id, start_frame );
400 #ifdef DEBUG_H223
401         g_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc);
402 #endif
403         vc_info = h223_vc_info_new( call_info );
404         circuit_add_proto_data( subcircuit, proto_h223, vc_info );
405     } else {
406         vc_info = circuit_get_proto_data( subcircuit, proto_h223 );
407     }
408     add_h223_lc_params( vc_info, direction, params, start_frame );
409 }
410
411 /* create a brand-new h223_call_info structure */
412 static h223_call_info *create_call_info( guint32 start_frame )
413 {
414     h223_call_info *datax;
415     h223_lc_params *vc0_params;
416
417     datax = se_alloc(sizeof(h223_call_info));
418
419     /* initialise the call info */
420     init_direction_data(&datax -> direction_data[0]);
421     init_direction_data(&datax -> direction_data[1]);
422         
423     /* FIXME shouldn't this be figured out dynamically? */
424     datax -> h223_level = 2;
425
426     vc0_params = se_alloc(sizeof(h223_lc_params));
427     vc0_params->al_type = al1Framed;
428     vc0_params->al_params = NULL;
429     vc0_params->segmentable = TRUE;
430     vc0_params->subdissector = srp_handle;
431     init_logical_channel( start_frame, datax, 0, P2P_DIR_SENT, vc0_params );
432     init_logical_channel( start_frame, datax, 0, P2P_DIR_RECV, vc0_params );
433     return datax;
434 }
435
436 /* find or create call_info struct for calls over circuits (eg, IAX) */
437 static h223_call_info *find_or_create_call_info_circ(packet_info * pinfo)
438 {
439     h223_call_info *datax;
440     circuit_t *circ = NULL;
441
442     if(pinfo->ctype != CT_NONE)
443         circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
444     if(circ == NULL)
445         return NULL;
446
447     datax = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
448     
449     if( datax == NULL ) {
450         datax = create_call_info(pinfo->fd->num);
451
452 #ifdef DEBUG_H223
453         g_debug("%u: Created new call %p for circuit %p ctype %d, id %u",
454                 pinfo->fd->num, datax, circ, pinfo->ctype, pinfo->circuit_id);
455 #endif
456         circuit_add_proto_data(circ, proto_h223, datax);
457     }
458     
459     /* work out what direction we're really going in */
460     if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1)
461         pinfo->p2p_dir = P2P_DIR_SENT;
462     
463     return datax;
464 }
465
466 /* find or create call_info struct for calls over conversations (eg, RTP) */
467 static h223_call_info *find_or_create_call_info_conv(packet_info * pinfo)
468 {
469     h223_call_info *datax;
470     conversation_t *conv;
471
472     /* assume we're running atop TCP or RTP; use the conversation support */
473     conv = find_conversation( pinfo->fd->num,
474                               &pinfo->src,&pinfo->dst,
475                               pinfo->ptype,
476                               pinfo->srcport,pinfo->destport, 0 );
477
478     /* both RTP and TCP track their conversations, so just assert here if
479      * we can't find one */
480     DISSECTOR_ASSERT(conv);
481
482     datax = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
483
484     if(datax == NULL && pinfo->ptype == PT_UDP ) {
485         conversation_t *conv2;
486         
487         /* RTP tracks the two sides of the conversation totally separately;
488          * this messes us up totally.
489          *
490          * Look for another converstation, going in the opposite direction.
491          */
492         conv2 = find_conversation( pinfo->fd->num,
493                                   &pinfo->dst,&pinfo->src,
494                                   pinfo->ptype,
495                                   pinfo->destport,pinfo->srcport, 0 );
496         if(conv2 != NULL)
497             datax = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
498
499         if(datax != NULL) {
500 #ifdef DEBUG_H223
501             g_debug("%u: Identified conv %p as reverse of conv %p with call %p and type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
502                     pinfo->fd->num, conv, conv2, datax, pinfo->ptype,
503                     pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
504                     pinfo->destport,
505                     pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
506                     pinfo->srcport);
507 #endif
508             conversation_add_proto_data(conv, proto_h223, datax);
509         }
510     }
511
512     /* we still haven't found any call data - create a new one for this
513      * conversation */
514     if(datax == NULL) {
515         datax = create_call_info(pinfo->fd->num);
516
517 #ifdef DEBUG_H223
518         g_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u",
519                 pinfo->fd->num, datax, conv, pinfo->ptype,
520                 pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3],
521                 pinfo->srcport,
522                 pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3],
523                 pinfo->destport);
524 #endif
525             
526         conversation_add_proto_data(conv, proto_h223, datax);
527         /* add the source details so we can distinguish directions
528          * in future */
529         COPY_ADDRESS(&(datax -> srcaddress), &(pinfo->src));
530         datax -> srcport = pinfo->srcport;
531     }
532
533     /* work out what direction we're really going in */
534     if( ADDRESSES_EQUAL( &(pinfo->src), &(datax->srcaddress))
535         && pinfo->srcport == datax->srcport )
536         pinfo->p2p_dir = P2P_DIR_SENT;
537     else 
538         pinfo->p2p_dir = P2P_DIR_RECV;
539
540     return datax;
541 }
542
543 static h223_call_info *find_or_create_call_info ( packet_info * pinfo )
544 {
545     h223_call_info *datax;
546
547     datax = find_or_create_call_info_circ(pinfo);
548     if(datax == NULL)
549         datax = find_or_create_call_info_conv(pinfo);
550     return datax;
551 }
552
553 /* called from the h245 dissector to handle a MultiplexEntrySend message */
554 static void h223_set_mc( packet_info* pinfo, guint8 mc, h223_mux_element* me )
555 {
556     circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
557     h223_vc_info* vc_info;
558
559     /* if this h245 pdu packet came from an h223 circuit, add the details on
560      * the new mux entry */
561     if(circ) {
562         vc_info = circuit_get_proto_data(circ, proto_h223);
563         add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, me, pinfo->fd->num );
564     }
565 }
566
567 /* called from the h245 dissector to handle an OpenLogicalChannelAck message */
568 static void h223_add_lc( packet_info* pinfo, guint16 lc, h223_lc_params* params )
569 {
570     circuit_t *circ = find_circuit( pinfo->ctype, pinfo->circuit_id, pinfo->fd->num );
571     h223_vc_info* vc_info;
572
573     /* if this h245 pdu packet came from an h223 circuit, add the details on
574      * the new channel */
575     if(circ) {
576         vc_info = circuit_get_proto_data(circ, proto_h223);
577         init_logical_channel( pinfo->fd->num, vc_info->call_info, lc, pinfo->p2p_dir, params );
578     }
579 }
580
581 /************************************************************************************
582  *
583  * AL-PDU dissection
584  */
585
586 const guint8 crctable[256] = {
587         0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
588         0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
589         0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
590         0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
591         0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
592         0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
593         0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
594         0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
595         0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
596         0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
597         0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
598         0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
599         0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
600         0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
601         0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
602         0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf };
603
604 static guint8 h223_al2_crc8bit( tvbuff_t *tvb ) {
605     guint32 len = tvb_reported_length(tvb) - 1;
606     const guint8* datax = tvb_get_ptr( tvb, 0, len );
607     unsigned char crc = 0;
608     guint32 pos = 0;
609     DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1);
610     while ( len-- )
611         crc = crctable[crc^datax[pos++]];
612     return crc;
613 }
614
615 static void dissect_mux_al_pdu( tvbuff_t *tvb,
616                                 packet_info *pinfo,
617                                 proto_tree *vc_tree,
618 /*                                circuit_t* vc_circuit, */
619                                 h223_lc_params* lc_params )
620 {
621     proto_tree *al_tree = NULL;
622     proto_item *al_item, *hidden_item;
623     proto_tree *al_subtree;
624     proto_item *al_subitem = NULL;
625     proto_item *tmp_item;
626     tvbuff_t *next_tvb = NULL;
627     dissector_handle_t subdissector = lc_params->subdissector;
628     guint32 len = tvb_reported_length(tvb);
629
630     guint8 calc_checksum;
631     guint8 real_checksum;
632     gboolean al2_sequenced = FALSE;
633     int data_start;
634
635     switch( lc_params->al_type ) {
636     case al1Framed:
637     case al1NotFramed:
638         al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)",
639                 (lc_params->al_type==al1Framed)?"":"not ");
640         al_tree = proto_item_add_subtree (al_item, ett_h223_al1);
641         if(lc_params->al_type == al1Framed) {
642             hidden_item = proto_tree_add_boolean(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
643             PROTO_ITEM_SET_HIDDEN(hidden_item);
644         }
645         next_tvb = tvb;
646         al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
647         break;
648         
649     case al2WithSequenceNumbers:
650         al2_sequenced = TRUE;
651         /* fall-through */
652     case al2WithoutSequenceNumbers:
653         tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
654
655         al_item = proto_tree_add_item(vc_tree,
656                                       al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
657                                       tvb, 0, -1,FALSE);
658         al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
659
660         PROTO_ITEM_SET_GENERATED(tmp_item);
661
662         /* check minimum payload length */
663         if(len < (al2_sequenced?2U:1U))
664             THROW(BoundsError);
665         
666         data_start = 0;
667         if( al2_sequenced ) {
668             proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
669             data_start++;
670         }
671
672         next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
673         al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
674
675         calc_checksum = h223_al2_crc8bit(tvb);
676         real_checksum = tvb_get_guint8(tvb, len - 1);
677
678         if( calc_checksum == real_checksum ) {
679             proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
680                 "CRC: 0x%02x (correct)", real_checksum );
681         } else {
682             proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
683                 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
684             tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
685             PROTO_ITEM_SET_GENERATED(tmp_item);
686
687             /* don't pass pdus which fail checksums on to the subdissector */
688             subdissector = data_handle;
689         }
690         break;
691     default:
692         call_dissector(data_handle, tvb, pinfo, vc_tree);
693         return;
694     }
695
696     if (!subdissector)
697         subdissector = data_handle;
698
699     al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
700     call_dissector(subdissector, next_tvb, pinfo, al_subtree);
701 }
702
703 /************************************************************************************
704  *
705  * MUX-PDU dissection
706  */
707
708
709 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
710  *
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->fd->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
720  */
721 static void dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb,
722                                     packet_info *pinfo,
723                                     guint32 pkt_offset,
724                                     proto_tree *pdu_tree,
725                                     h223_call_info* call_info,
726                                     guint16 vc, gboolean end_of_mux_sdu)
727 {
728     /* update the circuit details before passing to a subdissector */
729     guint32 orig_circuit = pinfo->circuit_id;
730     guint32 orig_ctype = pinfo->ctype;
731     pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
732     pinfo->ctype=CT_H223;
733
734     TRY {
735         circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
736         proto_tree *vc_tree = NULL;
737         proto_item *vc_item;
738         h223_vc_info *vc_info = NULL;
739         h223_lc_params *lc_params = NULL;
740
741         if(pdu_tree) {
742             vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
743             vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
744         }
745
746         if( subcircuit == NULL ) {
747             g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
748                        pinfo->circuit_id, (void *)call_info, vc );
749         } else {
750             vc_info = circuit_get_proto_data(subcircuit, proto_h223);
751             if( vc_info != NULL ) {
752                 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
753             }
754         }
755
756         
757         if( lc_params != NULL ) {
758                 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
759                     stream_t *substream;
760                     stream_pdu_fragment_t *frag;
761                 
762                     substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
763                     if(substream == NULL )
764                         substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
765                     frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
766
767                     if(frag == NULL ) {
768 #ifdef DEBUG_H223
769                         g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
770                                 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
771 #endif
772                         frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
773                                                next_tvb,pinfo,!end_of_mux_sdu);
774                     } else {
775 #ifdef DEBUG_H223
776                         g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
777                                 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
778 #endif
779                     }
780
781                     next_tvb = stream_process_reassembled(
782                         next_tvb, 0, pinfo, 
783                         "Reassembled H.223 AL-PDU",
784                         frag, &h223_al_frag_items,
785                         NULL, vc_tree);
786                 }
787
788                 if(next_tvb) {
789                     /* fudge to pass pkt_offset down to add_h223_mux_element,
790                      * should it be called */
791                     pdu_offset = pkt_offset;
792                     dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
793                 }
794         } else {
795                 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
796         }
797     }
798
799     /* restore the original circuit details for future PDUs */
800     FINALLY {
801         pinfo->ctype=orig_ctype;
802         pinfo->circuit_id=orig_circuit;
803     }
804     ENDTRY;
805 }
806
807 static guint32 mux_element_sublist_size( h223_mux_element* me )
808 {
809     h223_mux_element *current_me = me;
810     guint32 length = 0;
811     while ( current_me ) {
812         current_me = current_me->next;
813         if ( current_me->sublist )
814             length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
815         else
816             length += current_me->repeat_count;
817     }
818     if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
819         DISSECTOR_ASSERT_NOT_REACHED();
820         length = 1;
821     }
822     return length;
823 }
824
825 /* dissect part of a MUX-PDU payload according to a multiplex list
826  *
827  * tvb          buffer containing entire mux-pdu payload
828  * pinfo        info on the packet containing the last fragment of the MUX-PDU
829  * pkt_offset   offset within the block from the superdissector where the
830  *                MUX-PDU starts (must increase monotonically for constant
831  *                pinfo->fd->num)
832  * pdu_tree     dissection tree for the PDU
833  * call_info    data structure for h223 call
834  * me           top of mux list
835  * offset       offset within tvb to start work
836  * endOfMuxSdu  true if the end-of-sdu flag was set
837  */
838 static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
839                                                proto_tree *pdu_tree,
840                                                h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu )
841 {
842     guint32 len = tvb_reported_length(tvb);
843     guint32 frag_len;
844     guint32 sublist_len;
845     int i;
846     while ( me ) {
847         if ( me->sublist ) {
848             if ( me->repeat_count == 0 ) {
849                 for(sublist_len = mux_element_sublist_size( me->sublist );
850                     offset + sublist_len <= len;
851                     offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
852                                                              call_info, me->sublist, offset, endOfMuxSdu ) );
853             } else {
854                 for(i = 0; i < me->repeat_count; ++i)
855                     offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
856                                                              call_info, me->sublist, offset, endOfMuxSdu );
857             }
858         } else {
859             if ( me->repeat_count == 0 )
860                 frag_len = len - offset;
861             else
862                 frag_len = me->repeat_count;
863             if(frag_len > 0) {
864                 tvbuff_t *next_tvb;
865                 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
866                 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
867                                           call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
868                 offset += frag_len;
869             }
870         }
871         me = me->next;
872     }
873     return offset;
874 }
875
876 /* dissect the payload of a MUX-PDU
877  *
878  * tvb          buffer containing entire mux-pdu payload
879  * pinfo        info on the packet containing the last fragment of the MUX-PDU
880  * pkt_offset   offset within the block from the superdissector where the
881  *                MUX-PDU starts (must increase monotonically for constant
882  *                pinfo->fd->num)
883  * pdu_tree     dissection tree for the PDU
884  * call_info    data structure for h223 call
885  * mc           multiplex code for this PDU
886  * endOfMuxSdu  true if the end-of-sdu flag was set
887  */ 
888 static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
889                                  proto_tree *pdu_tree,
890                                  h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu )
891 {
892     guint32 len = tvb_reported_length(tvb);
893
894     h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
895
896     if( me ) {
897         dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
898     } else {
899         /* no entry found in mux-table. ignore packet and dissect as data */
900         proto_tree *vc_tree = NULL;
901             
902         if(pdu_tree) {
903             proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
904             vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
905         }
906         call_dissector(data_handle,tvb,pinfo,vc_tree);
907     }
908 }
909
910 /* dissect a reassembled mux-pdu
911  *
912  * tvb          buffer containing mux-pdu, including header and closing flag
913  * pinfo        packet info for packet containing the end of the mux-pdu
914  * pkt_offset   offset within the block from the superdissector where the
915  *                MUX-PDU starts (must increase monotonically for constant
916  *                pinfo->fd->num)
917  * h223_tree    dissection tree for h223 protocol; a single item will be added
918  *              (with a sub-tree)
919  * call_info    h223 info structure for this h223 call
920  * pdu_no       index of this pdu within the call
921  */
922 static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo,
923                              guint32 pkt_offset,
924                              proto_tree *h223_tree,
925                              h223_call_info *call_info)
926 {
927     guint32 offset = 0;
928     /* actual (as opposed to reported) payload len */
929     guint32 len;
930     guint32 raw_hdr = 0, correct_hdr = 0;
931     gint32  errors = 0;
932     guint16 closing_flag = 0;
933     guint8 mc = 0;
934     guint8 mpl = 0;
935     gboolean end_of_mux_sdu = FALSE;
936     tvbuff_t *pdu_tvb;
937
938     proto_item *pdu_item = NULL;
939     proto_tree *pdu_tree = NULL;
940
941 #ifdef DEBUG_H223_FRAGMENTATION
942     g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
943             pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
944 #endif
945     
946     switch(call_info->h223_level) {
947         case 0: case 1:
948             raw_hdr = tvb_get_guint8(tvb,0);
949             mc = (guint8)((raw_hdr>>1) & 0xf);
950             end_of_mux_sdu = raw_hdr & 1;
951             offset++;
952             /* closing flag is one byte long for h223 level 0, two for level 1 */
953             len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
954
955             /* XXX should ignore pdus with incorrect HECs */
956             break;
957
958         case 2:
959             raw_hdr = tvb_get_letoh24(tvb,0);
960             errors = golay_errors(raw_hdr);
961             offset += 3;
962             len = tvb_length_remaining(tvb,offset)-2;
963
964             if(errors != -1) {
965                 correct_hdr = raw_hdr ^ (guint32)errors;
966     
967                 mc = (guint8)(correct_hdr & 0xf);
968                 mpl = (guint8)((correct_hdr >> 4) & 0xff);
969
970                 /* we should never have been called if there's not enough data in
971                  * available. */
972                 DISSECTOR_ASSERT(len >= mpl);
973
974                 closing_flag = tvb_get_ntohs(tvb,offset+len);
975                 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
976             } else {
977                 mc = 0;
978                 mpl = len;
979             }
980             break;
981
982         case 3:
983             /* XXX not implemented */
984         default:
985             len=0;
986             DISSECTOR_ASSERT_NOT_REACHED();
987     }
988
989     
990     if( h223_tree ) {
991         if( mpl == 0 ) {
992             pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
993             pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
994         } else {
995             pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
996             pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
997         }
998     }
999
1000     if( pdu_tree ) {
1001         proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
1002         proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1003
1004         switch(call_info->h223_level) {
1005             case 0: case 1:
1006                 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1007                 break;
1008
1009             case 2:
1010                 if( errors == -1 ) {
1011                     proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1012                                                0, 3, raw_hdr,
1013                                                "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1014                 } else {
1015                     if( errors == 0 ) {
1016                         proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1017                                                    0, 3, raw_hdr,
1018                                                    "Raw value: 0x%06x (correct)", raw_hdr );
1019                     } else {
1020                         proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1021                                                    0, 3, raw_hdr,
1022                                                    "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1023                     }
1024                     item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1025                                                correct_hdr);
1026                     PROTO_ITEM_SET_GENERATED(item);
1027                     proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1028                     proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1029                 }
1030                 break;
1031
1032             case 3:
1033                 /* XXX not implemented */
1034             default:
1035                 DISSECTOR_ASSERT_NOT_REACHED();
1036         }
1037     }
1038
1039     if(mpl > 0) {
1040         pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1041         if(errors != -1) {
1042             dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1043         } else {
1044             call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1045         }
1046         offset += mpl;
1047     }
1048
1049     /* any extra data in the PDU, beyond that indictated by the mpl, is
1050        dissected as data. */
1051     len -= mpl;
1052     if( len > 0 ) {
1053         tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1054         proto_tree *vc_tree = NULL;
1055
1056         if( pdu_tree ) {
1057             proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1058             vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1059         }
1060         call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1061
1062         offset += len;
1063     } 
1064
1065     /* add the closing HDLC flag */
1066     if( pdu_tree )
1067         proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1068 }
1069
1070
1071 /************************************************************************************
1072  *
1073  * MUX-PDU delineation and defragmentation
1074  */
1075
1076 /* attempt to parse the header of a mux pdu */
1077 static gboolean attempt_mux_level0_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1078 {
1079     /* level 0 isn't byte-aligned, so is a complete pain to implement */
1080     DISSECTOR_ASSERT_NOT_REACHED();
1081     nbytes = nbytes;
1082     hdr=hdr;
1083     minlen=minlen;
1084     return FALSE;
1085 }
1086
1087 static gboolean attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1088 {
1089     /* this is untested */
1090     DISSECTOR_ASSERT_NOT_REACHED();
1091     
1092     if(nbytes < 2)
1093         return FALSE;
1094
1095     hdr &= 0xffff;
1096     /* don't interpret a repeated hdlc as a header */
1097     if(hdr == 0xE14D)
1098         return FALSE;
1099
1100     /* + 1 byte of header and 2 bytes of closing HDLC */
1101     *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1102     return TRUE;
1103 }
1104
1105 static gboolean attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1106 {
1107     gint32 errors;
1108     
1109     if(nbytes < 3)
1110         return FALSE;
1111
1112     /* + 3 bytes of header and 2 bytes of closing HDLC */
1113     *minlen = 5;
1114
1115     /* bah, we get the header in the wrong order */
1116     hdr =
1117         ((hdr & 0xFF0000) >> 16) |
1118         (hdr & 0x00FF00) |
1119         ((hdr & 0x0000FF) << 16);
1120     
1121     errors = golay_errors(hdr);
1122     if(errors != -1) {
1123         hdr ^= errors;
1124         *minlen += ((hdr >> 4) & 0xff);
1125     }
1126
1127     return TRUE;
1128 }
1129
1130 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1131     attempt_mux_level0_header_parse,
1132     attempt_mux_level1_header_parse,
1133     attempt_mux_level2_3_header_parse,
1134     attempt_mux_level2_3_header_parse
1135 };
1136
1137 static gboolean h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1138 {
1139     guint32 masked;
1140
1141     switch(h223_level) {
1142         case 0:
1143             /* level 0 isn't byte-aligned, so is a complete pain to implement */
1144             DISSECTOR_ASSERT_NOT_REACHED();
1145             return FALSE;
1146
1147         case 1:
1148             masked = tail_buf & 0xffff;
1149             return nbytes >= 2 && masked == 0xE14D;
1150
1151         case 2: case 3:
1152             masked = tail_buf & 0xffff;
1153             return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1154
1155         default:
1156             DISSECTOR_ASSERT_NOT_REACHED();
1157             return FALSE;
1158     }
1159 }
1160
1161 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1162  *
1163  * returns the number of bytes processed, or the negative of the number of
1164  * extra bytes needed, or zero if we don't know yet
1165  */
1166
1167 static gint dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo,
1168                                       proto_tree *h223_tree,
1169                                       h223_call_info *call_info)
1170 {
1171     tvbuff_t *volatile next_tvb;
1172     volatile guint32 offset = start_offset;
1173     gboolean more_frags = TRUE;
1174
1175     gboolean header_parsed = FALSE;
1176     guint32 header_buf = 0, tail_buf = 0;
1177     guint32 pdu_minlen = 0;
1178     
1179
1180 #ifdef DEBUG_H223_FRAGMENTATION
1181     g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1182             pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1183 #endif
1184     
1185     while( more_frags && offset < tvb_reported_length( tvb )) {
1186         guint8 byte = tvb_get_guint8(tvb, offset++);
1187         
1188         /* read a byte into the header buf, if necessary */
1189         if((offset-start_offset) <= 4) {
1190             header_buf <<= 8;
1191             header_buf |= byte;
1192         }
1193
1194         /* read the byte into the tail buf */
1195         tail_buf <<= 8;
1196         tail_buf |= byte;
1197
1198         /* if we haven't parsed the header yet, attempt to do so now */
1199         if(!header_parsed)
1200             /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1201             header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1202                 (offset-start_offset,header_buf,&pdu_minlen);
1203
1204         /* if we have successfully parsed the header, we have sufficient data,
1205          * and we have found the closing hdlc, we are done here */
1206         if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1207             if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1208                 more_frags = FALSE;
1209             }
1210         }
1211     }
1212
1213     if( more_frags ) {
1214         if(pdu_minlen <= (offset-start_offset)) {
1215             /* we haven't found the closing hdlc yet, but we don't know how
1216              * much more we need */
1217 #ifdef DEBUG_H223_FRAGMENTATION
1218             g_debug("\tBailing, requesting more bytes");
1219 #endif
1220             return 0;
1221         } else {
1222             guint32 needed = pdu_minlen-(offset-start_offset);
1223 #ifdef DEBUG_H223_FRAGMENTATION
1224             g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1225 #endif
1226             return - (gint) needed;
1227         }
1228     }
1229
1230     /* create a tvb for the fragment */
1231     next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1232                               offset-start_offset);
1233
1234
1235     /* we catch boundserrors on the pdu so that errors on an
1236      * individual pdu don't screw up the whole of the rest of the
1237      * stream */
1238     TRY {
1239         dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1240     }
1241
1242     CATCH2(BoundsError,ReportedBoundsError) {
1243         if (check_col(pinfo->cinfo, COL_INFO))
1244             col_append_str(pinfo->cinfo, COL_INFO,
1245                            "[Malformed Packet]");
1246         proto_tree_add_protocol_format(h223_tree, proto_malformed,
1247                                        tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1248     }
1249
1250     ENDTRY;
1251
1252     return (offset-start_offset);
1253 }
1254
1255 /************************************************************************************
1256  *
1257  * main dissector entry points
1258  */
1259
1260 /* dissects PDUs from the tvb
1261  *
1262  * Updates desegment_offset and desegment_len if the end of the data didn't
1263  * line up with the end of a pdu.
1264  */
1265 static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1266 {
1267     proto_tree *h223_tree = NULL;
1268     proto_item *h223_item = NULL;
1269     h223_call_info *call_info = NULL;
1270     guint32 offset = 0;
1271
1272     /* set up the protocol and info fields in the summary pane */
1273     if (check_col (pinfo->cinfo, COL_PROTOCOL))
1274         col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
1275
1276     col_clear(pinfo->cinfo, COL_INFO);
1277
1278     /* find or create the call_info for this call */
1279     call_info = find_or_create_call_info(pinfo);
1280
1281     /* add the 'h223' tree to the main tree */
1282     if (tree) {
1283         h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, FALSE);
1284         h223_tree = proto_item_add_subtree (h223_item, ett_h223);
1285     }
1286
1287     while( offset < tvb_reported_length( tvb )) {
1288         int res = dissect_mux_pdu_fragment( tvb, offset, pinfo,
1289                                             h223_tree, call_info);
1290         if(res <= 0) {
1291             /* the end of the tvb held the start of a PDU */
1292             pinfo->desegment_offset = offset;
1293
1294             /* if res != 0, we actually know how much more data we need for a
1295              * PDU.
1296              *
1297              * However, if we return that, it means that we get called twice
1298              * for the next packet; this makes it hard to tell how far throught
1299              * the stream we are and we have to start messing about with
1300              * getting the seqno from the superdissector's private data. So we
1301              * don't do that.
1302              *
1303              * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res);
1304              */
1305             pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1306
1307             if(h223_item) {
1308                 /* shrink the h223 protocol item such that it only includes the
1309                  * bits we dissected */
1310                 proto_item_set_len(h223_item,offset);
1311             }
1312
1313             if(offset == 0) {
1314                 col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1315             }
1316             return;
1317         }
1318         offset += res;
1319     }
1320 }
1321
1322 /* H.223 specifies that the least-significant bit is transmitted first;
1323  * however this is at odds with IAX which transmits bytes with the
1324  * first-received bit as the MSB.
1325  *
1326  * This dissector swaps the ordering of the bits in each byte before using the
1327  * normal entry point.
1328  */
1329 static void dissect_h223_bitswapped (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1330 {
1331     tvbuff_t *reversed_tvb;
1332     guint8 *datax;
1333     guint len;
1334     guint i;
1335
1336     len = tvb_length(tvb);
1337     datax = g_malloc(len);
1338     for( i=0; i<len; i++)
1339         datax[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1340
1341     /*
1342      * Add the reversed tvbuff to the list of tvbuffs to which
1343      * the tvbuff we were handed refers, so it'll get
1344      * cleaned up when that tvbuff is cleaned up.
1345      */
1346     reversed_tvb = tvb_new_child_real_data(tvb, datax,len,tvb_reported_length(tvb));
1347
1348     /* Add a freer */
1349     tvb_set_free_cb(reversed_tvb, g_free);
1350
1351     /* Add the reversed data to the data source list. */
1352     add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1353     
1354     dissect_h223(reversed_tvb,pinfo,tree);
1355 }
1356
1357 /******************************************************************************/
1358
1359 static void h223_init_protocol (void)
1360 {
1361     circuit_chain_init();
1362 }
1363
1364
1365 void proto_register_h223 (void)
1366 {
1367     /* A header field is something you can search/filter on.
1368      * 
1369      * We create a structure to register our fields. It consists of an
1370      * array of hf_register_info structures, each of which are of the format
1371      * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1372      */
1373    
1374     static hf_register_info hf[] = {
1375         { &hf_h223_non_h223_data,
1376           { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1377             "Initial data in stream, not a PDU", HFILL }},
1378
1379         { &hf_h223_mux_stuffing_pdu,
1380           { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1381             "Empty PDU used for stuffing when no data available", HFILL }},
1382
1383         { &hf_h223_mux_pdu,
1384           { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1385             NULL, HFILL }},
1386
1387         { &hf_h223_mux_header,
1388           { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1389             "H.223 MUX header", HFILL }},
1390
1391         { &hf_h223_mux_rawhdr,
1392           { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1393             "Raw header bytes", HFILL }},
1394         
1395         { &hf_h223_mux_correctedhdr,
1396           { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1397             "Corrected header bytes", HFILL }},
1398
1399         { &hf_h223_mux_mc,
1400           { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1401             "H.223 MUX multiplex code", HFILL }},
1402
1403         { &hf_h223_mux_mpl,
1404           { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1405             "H.223 MUX multiplex Payload Length", HFILL }},
1406
1407         { &hf_h223_mux_deact,
1408           { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1409             "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1410
1411         { &hf_h223_mux_vc,
1412           { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1413             "H.223 Virtual Circuit", HFILL }},
1414         
1415         { &hf_h223_mux_extra,
1416           { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_NONE, NULL, 0x0,
1417             "data beyond mpl", HFILL }},
1418         
1419         { &hf_h223_mux_hdlc2,
1420           { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1421             "framing flag", HFILL }},
1422
1423         /* fields for h.223-mux fragments */
1424         { &hf_h223_mux_fragment_overlap,
1425           { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1426             "Fragment overlaps with other fragments", HFILL }},
1427         
1428         { &hf_h223_mux_fragment_overlap_conflict,
1429           { "Conflicting data in fragment overlap",     "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1430             "Overlapping fragments contained conflicting data", HFILL }},
1431         
1432         { &hf_h223_mux_fragment_multiple_tails,
1433           { "Multiple tail fragments found",    "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1434             "Several tails were found when defragmenting the packet", HFILL }},
1435         
1436         { &hf_h223_mux_fragment_too_long_fragment,
1437           { "Fragment too long",        "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1438             "Fragment contained data past end of packet", HFILL }},
1439         
1440         { &hf_h223_mux_fragment_error,
1441           { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1442             "Defragmentation error due to illegal fragments", HFILL }},
1443         
1444         { &hf_h223_mux_fragment,
1445           { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1446             NULL, HFILL }},
1447         
1448         { &hf_h223_mux_fragments,
1449           { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1450             NULL, HFILL }},
1451         
1452         { &hf_h223_mux_reassembled_in,
1453           { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1454             "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1455
1456         /* fields for h.223-al fragments */
1457         { &hf_h223_al_fragment_overlap,
1458           { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1459             "Fragment overlaps with other fragments", HFILL }},
1460         
1461         { &hf_h223_al_fragment_overlap_conflict,
1462           { "Conflicting data in fragment overlap",     "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1463             "Overlapping fragments contained conflicting data", HFILL }},
1464         
1465         { &hf_h223_al_fragment_multiple_tails,
1466           { "Multiple tail fragments found",    "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1467             "Several tails were found when defragmenting the packet", HFILL }},
1468         
1469         { &hf_h223_al_fragment_too_long_fragment,
1470           { "Fragment too long",        "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1471             "Fragment contained data past end of packet", HFILL }},
1472         
1473         { &hf_h223_al_fragment_error,
1474           { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1475             "Defragmentation error due to illegal fragments", HFILL }},
1476         
1477         { &hf_h223_al_fragment,
1478           { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1479             NULL, HFILL }},
1480         
1481         { &hf_h223_al_fragments,
1482           { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1483             NULL, HFILL }},
1484         
1485         { &hf_h223_al_reassembled_in,
1486           { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1487             "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1488
1489         /* h223-als */
1490
1491         { &hf_h223_al1,
1492           { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1493             "H.223 AL-PDU using AL1", HFILL }},
1494
1495         { &hf_h223_al1_framed,
1496           { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1497             NULL, HFILL }},
1498
1499         { &hf_h223_al2,
1500           { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1501             "H.223 AL-PDU using AL2", HFILL }},
1502
1503         { &hf_h223_al2_sequenced,
1504           { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1505             "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1506
1507         { &hf_h223_al2_unsequenced,
1508           { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1509             "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1510
1511         { &hf_h223_al2_seqno,
1512           { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1513             "H.223 AL2 sequence number", HFILL }},
1514
1515         { &hf_h223_al2_crc,
1516           { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1517             NULL, HFILL }},
1518
1519         { &hf_h223_al2_crc_bad,
1520           { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1521             NULL, HFILL }},
1522
1523         { &hf_h223_al_payload,
1524           { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1525             "H.223 AL-PDU Payload", HFILL }},
1526
1527     };
1528
1529     static gint *ett[] = {
1530         &ett_h223,
1531         &ett_h223_non_h223_data,
1532         &ett_h223_mux_stuffing_pdu,
1533         &ett_h223_mux_pdu,
1534         &ett_h223_mux_header,
1535         &ett_h223_mux_deact,
1536         &ett_h223_mux_vc,
1537         &ett_h223_mux_extra,
1538         &ett_h223_mux_fragments,
1539         &ett_h223_mux_fragment,
1540         &ett_h223_al_fragments,
1541         &ett_h223_al_fragment,
1542         &ett_h223_al1,
1543         &ett_h223_al2,
1544         &ett_h223_al_payload
1545     };
1546
1547     proto_h223 =
1548         proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1549     proto_h223_bitswapped =
1550         proto_register_protocol ("Bitswapped ITU-T Recommendation H.223", "H.223 (Bitswapped)", "h223_bitswapped");
1551
1552     proto_register_field_array (proto_h223, hf, array_length (hf));
1553     proto_register_subtree_array (ett, array_length (ett));
1554     register_dissector("h223", dissect_h223, proto_h223);
1555     register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped);
1556         
1557     /* register our init routine to be called at the start of a capture,
1558        to clear out our hash tables etc */
1559     register_init_routine(&h223_init_protocol);
1560
1561     h245_set_h223_set_mc_handle( &h223_set_mc );
1562     h245_set_h223_add_lc_handle( &h223_add_lc );
1563 }
1564
1565 void proto_reg_handoff_h223(void)
1566 {
1567     dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1568     dissector_handle_t h223 = find_dissector("h223");
1569     data_handle = find_dissector("data");
1570     srp_handle = find_dissector("srp");
1571
1572     dissector_add_handle("tcp.port", h223);
1573     dissector_add_handle("tcp.port", h223_bitswapped);
1574     dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1575     dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1576 }
1577 /* vim:set ts=8 et: */