Add -Werror when using GCC only to the Makefile.am of the base
[obnox/wireshark/wip.git] / plugins / h223 / 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/iax2_codec_type.h>
42 #include <epan/dissectors/packet-frame.h>
43 #include <epan/dissectors/packet-h245.h>
44
45 #include "packet-h223.h"
46 #include "golay.h"
47
48 #include <string.h>
49
50 /* #define DEBUG_H223 */
51
52 /* debug the mux-pdu defragmentation code. warning: verbose output! */
53 /* #define DEBUG_H223_FRAGMENTATION */
54
55 #define PROTO_TAG_H223  "H223"
56
57 /* Wireshark ID of the H.223 protocol */
58 static int proto_h223 = -1;
59 static int proto_h223_bitswapped = -1;
60
61 /* The following hf_* variables are used to hold the Wireshark IDs of
62  * our header fields; they are filled out when we call
63  * proto_register_field_array() in proto_register_h223()
64  */
65 static int hf_h223_non_h223_data = -1;
66 static int hf_h223_mux_stuffing_pdu = -1;
67 static int hf_h223_mux_pdu = -1;
68 static int hf_h223_mux_header = -1;
69 static int hf_h223_mux_rawhdr = -1;
70 static int hf_h223_mux_correctedhdr = -1;
71 static int hf_h223_mux_mc = -1;
72 static int hf_h223_mux_mpl = -1;
73 static int hf_h223_mux_deact = -1;
74 static int hf_h223_mux_vc = -1;
75 static int hf_h223_mux_extra = -1;
76 static int hf_h223_mux_hdlc2 = -1;
77 static int hf_h223_mux_fragments = -1;
78 static int hf_h223_mux_fragment = -1;
79 static int hf_h223_mux_fragment_overlap = -1;
80 static int hf_h223_mux_fragment_overlap_conflict = -1;
81 static int hf_h223_mux_fragment_multiple_tails = -1;
82 static int hf_h223_mux_fragment_too_long_fragment = -1;
83 static int hf_h223_mux_fragment_error = -1;
84 static int hf_h223_mux_reassembled_in = -1;
85
86 static int hf_h223_al_fragments = -1;
87 static int hf_h223_al_fragment = -1;
88 static int hf_h223_al_fragment_overlap = -1;
89 static int hf_h223_al_fragment_overlap_conflict = -1;
90 static int hf_h223_al_fragment_multiple_tails = -1;
91 static int hf_h223_al_fragment_too_long_fragment = -1;
92 static int hf_h223_al_fragment_error = -1;
93 static int hf_h223_al_reassembled_in = -1;
94
95 static int hf_h223_al1 = -1;
96 static int hf_h223_al1_framed = -1;
97 static int hf_h223_al2 = -1;
98 static int hf_h223_al2_sequenced = -1;
99 static int hf_h223_al2_unsequenced = -1;
100 static int hf_h223_al2_seqno = -1;
101 static int hf_h223_al2_crc = -1;
102 static int hf_h223_al2_crc_bad = -1;
103
104 static int hf_h223_al_payload = -1;
105
106 /* These are the ids of the subtrees that we may be creating */
107 static gint ett_h223 = -1;
108 static gint ett_h223_non_h223_data = -1;
109 static gint ett_h223_mux_stuffing_pdu = -1;
110 static gint ett_h223_mux_pdu = -1;
111 static gint ett_h223_mux_header = -1;
112 static gint ett_h223_mux_deact = -1;
113 static gint ett_h223_mux_vc = -1;
114 static gint ett_h223_mux_extra = -1;
115 static gint ett_h223_mux_fragments = -1;
116 static gint ett_h223_mux_fragment  = -1;
117 static gint ett_h223_al_fragments = -1;
118 static gint ett_h223_al_fragment  = -1;
119 static gint ett_h223_al1 = -1;
120 static gint ett_h223_al2 = -1;
121 static gint ett_h223_al_payload = -1;
122
123 /* These are the handles of our subdissectors */
124 static dissector_handle_t data_handle=NULL;
125 static dissector_handle_t srp_handle=NULL;
126 static dissector_handle_t h245dg_handle=NULL;
127
128 static const fragment_items h223_mux_frag_items = {
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)(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 *data;
415     h223_lc_params *vc0_params;
416
417     data = se_alloc(sizeof(h223_call_info));
418
419     /* initialise the call info */
420     init_direction_data(&data -> direction_data[0]);
421     init_direction_data(&data -> direction_data[1]);
422         
423     /* FIXME shouldn't this be figured out dynamically? */
424     data -> 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, data, 0, P2P_DIR_SENT, vc0_params );
432     init_logical_channel( start_frame, data, 0, P2P_DIR_RECV, vc0_params );
433     return data;
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 *data;
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     data = (h223_call_info *)circuit_get_proto_data(circ, proto_h223);
448     
449     if( data == NULL ) {
450         data = 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, data, circ, pinfo->ctype, pinfo->circuit_id);
455 #endif
456         circuit_add_proto_data(circ, proto_h223, data);
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 data;
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 *data;
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     data = (h223_call_info *)conversation_get_proto_data(conv, proto_h223);
483
484     if(data == 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             data = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223);
498
499         if(data != 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, data, 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, data);
509         }
510     }
511
512     /* we still haven't found any call data - create a new one for this
513      * conversation */
514     if(data == NULL) {
515         data = 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, data, 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, data);
527         /* add the source details so we can distinguish directions
528          * in future */
529         COPY_ADDRESS(&(data -> srcaddress), &(pinfo->src));
530         data -> srcport = pinfo->srcport;
531     }
532
533     /* work out what direction we're really going in */
534     if( ADDRESSES_EQUAL( &(pinfo->src), &(data->srcaddress))
535         && pinfo->srcport == data->srcport )
536         pinfo->p2p_dir = P2P_DIR_SENT;
537     else 
538         pinfo->p2p_dir = P2P_DIR_RECV;
539
540     return data;
541 }
542
543 static h223_call_info *find_or_create_call_info ( packet_info * pinfo )
544 {
545     h223_call_info *data;
546
547     data = find_or_create_call_info_circ(pinfo);
548     if(data == NULL)
549         data = find_or_create_call_info_conv(pinfo);
550     return data;
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* data = 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^data[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;
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             proto_tree_add_boolean_hidden(al_tree, hf_h223_al1_framed, tvb, 0, 1, TRUE );
643         next_tvb = tvb;
644         al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
645         break;
646         
647     case al2WithSequenceNumbers:
648         al2_sequenced = TRUE;
649         /* fall-through */
650     case al2WithoutSequenceNumbers:
651         tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, TRUE );
652
653         al_item = proto_tree_add_item(vc_tree,
654                                       al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced,
655                                       tvb, 0, -1,FALSE);
656         al_tree = proto_item_add_subtree (al_item, ett_h223_al2);
657
658         PROTO_ITEM_SET_GENERATED(tmp_item);
659
660         /* check minimum payload length */
661         if(len < (al2_sequenced?2U:1U))
662             THROW(BoundsError);
663         
664         data_start = 0;
665         if( al2_sequenced ) {
666             proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, TRUE);
667             data_start++;
668         }
669
670         next_tvb = tvb_new_subset( tvb, data_start, len-1-data_start, len-1-data_start );
671         al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, FALSE);
672
673         calc_checksum = h223_al2_crc8bit(tvb);
674         real_checksum = tvb_get_guint8(tvb, len - 1);
675
676         if( calc_checksum == real_checksum ) {
677             proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
678                 "CRC: 0x%02x (correct)", real_checksum );
679         } else {
680             proto_tree_add_uint_format(al_tree, hf_h223_al2_crc, tvb, len - 1, 1, real_checksum,
681                 "CRC: 0x%02x (incorrect, should be 0x%02x)", real_checksum, calc_checksum );
682             tmp_item = proto_tree_add_boolean( al_tree, hf_h223_al2_crc_bad, tvb, len - 1, 1, TRUE );
683             PROTO_ITEM_SET_GENERATED(tmp_item);
684
685             /* don't pass pdus which fail checksums on to the subdissector */
686             subdissector = data_handle;
687         }
688         break;
689     default:
690         call_dissector(data_handle, tvb, pinfo, vc_tree);
691         return;
692     }
693
694     if (!subdissector)
695         subdissector = data_handle;
696
697     al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload);
698     call_dissector(subdissector, next_tvb, pinfo, al_subtree);
699 }
700
701 /************************************************************************************
702  *
703  * MUX-PDU dissection
704  */
705
706
707 /* dissect a fragment of a MUX-PDU which belongs to a particular VC
708  *
709  * tvb          buffer containing the MUX-PDU fragment
710  * pinfo        info on the packet containing the last fragment of the MUX-PDU
711  * pkt_offset   offset within the block from the superdissector where the
712  *                fragment starts (must increase monotonically for constant pinfo->fd->num)
713  * pdu_tree     dissection tree for the PDU; a single item will be added (with
714  *              its own subtree)
715  * vc           VC for this SDU
716  * end_of_mux_sdu true if this is a segmentable VC and this is the last
717  *              fragment in an SDU
718  */
719 static void dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb,
720                                     packet_info *pinfo,
721                                     guint32 pkt_offset,
722                                     proto_tree *pdu_tree,
723                                     h223_call_info* call_info,
724                                     guint16 vc, gboolean end_of_mux_sdu)
725 {
726     /* update the circuit details before passing to a subdissector */
727     guint32 orig_circuit = pinfo->circuit_id;
728     guint32 orig_ctype = pinfo->ctype;
729     pinfo->circuit_id=circuit_chain_lookup(call_info, vc);
730     pinfo->ctype=CT_H223;
731
732     TRY {
733         circuit_t *subcircuit=find_circuit(pinfo->ctype,pinfo->circuit_id,pinfo->fd->num);
734         proto_tree *vc_tree = NULL;
735         proto_item *vc_item;
736         h223_vc_info *vc_info = NULL;
737         h223_lc_params *lc_params = NULL;
738
739         if(pdu_tree) {
740             vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc);
741             vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc);
742         }
743
744         if( subcircuit == NULL ) {
745             g_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->fd->num,
746                        pinfo->circuit_id, call_info, vc );
747         } else {
748             vc_info = circuit_get_proto_data(subcircuit, proto_h223);
749             if( vc_info != NULL ) {
750                 lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->fd->num );
751             }
752         }
753
754         
755         if( lc_params != NULL ) {
756                 if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) {
757                     stream_t *substream;
758                     stream_pdu_fragment_t *frag;
759                 
760                     substream = find_stream_circ(subcircuit,pinfo->p2p_dir);
761                     if(substream == NULL )
762                         substream = stream_new_circ(subcircuit,pinfo->p2p_dir);
763                     frag = stream_find_frag(substream,pinfo->fd->num,pkt_offset);
764
765                     if(frag == NULL ) {
766 #ifdef DEBUG_H223
767                         g_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
768                                 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
769 #endif
770                         frag = stream_add_frag(substream,pinfo->fd->num,pkt_offset,
771                                                next_tvb,pinfo,!end_of_mux_sdu);
772                     } else {
773 #ifdef DEBUG_H223
774                         g_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d",
775                                 pinfo->fd->num, orig_circuit, pinfo->circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu);
776 #endif
777                     }
778
779                     next_tvb = stream_process_reassembled(
780                         next_tvb, 0, pinfo, 
781                         "Reassembled H.223 AL-PDU",
782                         frag, &h223_al_frag_items,
783                         NULL, vc_tree);
784                 }
785
786                 if(next_tvb) {
787                     /* fudge to pass pkt_offset down to add_h223_mux_element,
788                      * should it be called */
789                     pdu_offset = pkt_offset;
790                     dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params );
791                 }
792         } else {
793                 call_dissector(data_handle,next_tvb,pinfo,vc_tree);
794         }
795     }
796
797     /* restore the original circuit details for future PDUs */
798     FINALLY {
799         pinfo->ctype=orig_ctype;
800         pinfo->circuit_id=orig_circuit;
801     }
802     ENDTRY;
803 }
804
805 static guint32 mux_element_sublist_size( h223_mux_element* me )
806 {
807     h223_mux_element *current_me = me;
808     guint32 length = 0;
809     while ( current_me ) {
810         current_me = current_me->next;
811         if ( current_me->sublist )
812             length += current_me->repeat_count * mux_element_sublist_size( current_me->sublist );
813         else
814             length += current_me->repeat_count;
815     }
816     if ( length == 0 ) { /* should never happen, but to avoid infinite loops... */
817         DISSECTOR_ASSERT_NOT_REACHED();
818         length = 1;
819     }
820     return length;
821 }
822
823 /* dissect part of a MUX-PDU payload according to a multiplex list
824  *
825  * tvb          buffer containing entire mux-pdu payload
826  * pinfo        info on the packet containing the last fragment of the MUX-PDU
827  * pkt_offset   offset within the block from the superdissector where the
828  *                MUX-PDU starts (must increase monotonically for constant
829  *                pinfo->fd->num)
830  * pdu_tree     dissection tree for the PDU
831  * call_info    data structure for h223 call
832  * me           top of mux list
833  * offset       offset within tvb to start work
834  * endOfMuxSdu  true if the end-of-sdu flag was set
835  */
836 static guint32 dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
837                                                proto_tree *pdu_tree,
838                                                h223_call_info* call_info, h223_mux_element* me, guint32 offset, gboolean endOfMuxSdu )
839 {
840     guint32 len = tvb_reported_length(tvb);
841     guint32 frag_len;
842     guint32 sublist_len;
843     int i;
844     while ( me ) {
845         if ( me->sublist ) {
846             if ( me->repeat_count == 0 ) {
847                 for(sublist_len = mux_element_sublist_size( me->sublist );
848                     offset + sublist_len <= len;
849                     offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
850                                                              call_info, me->sublist, offset, endOfMuxSdu ) );
851             } else {
852                 for(i = 0; i < me->repeat_count; ++i)
853                     offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree,
854                                                              call_info, me->sublist, offset, endOfMuxSdu );
855             }
856         } else {
857             if ( me->repeat_count == 0 )
858                 frag_len = len - offset;
859             else
860                 frag_len = me->repeat_count;
861             if(frag_len > 0) {
862                 tvbuff_t *next_tvb;
863                 next_tvb = tvb_new_subset(tvb, offset, frag_len, frag_len);
864                 dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree,
865                                           call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu);
866                 offset += frag_len;
867             }
868         }
869         me = me->next;
870     }
871     return offset;
872 }
873
874 /* dissect the payload of a MUX-PDU
875  *
876  * tvb          buffer containing entire mux-pdu payload
877  * pinfo        info on the packet containing the last fragment of the MUX-PDU
878  * pkt_offset   offset within the block from the superdissector where the
879  *                MUX-PDU starts (must increase monotonically for constant
880  *                pinfo->fd->num)
881  * pdu_tree     dissection tree for the PDU
882  * call_info    data structure for h223 call
883  * mc           multiplex code for this PDU
884  * endOfMuxSdu  true if the end-of-sdu flag was set
885  */ 
886 static void dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, guint32 pkt_offset,
887                                  proto_tree *pdu_tree,
888                                  h223_call_info* call_info, guint8 mc, gboolean endOfMuxSdu )
889 {
890     guint32 len = tvb_reported_length(tvb);
891
892     h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->fd->num, pkt_offset );
893
894     if( me ) {
895         dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu );
896     } else {
897         /* no entry found in mux-table. ignore packet and dissect as data */
898         proto_tree *vc_tree = NULL;
899             
900         if(pdu_tree) {
901             proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, FALSE);
902             vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
903         }
904         call_dissector(data_handle,tvb,pinfo,vc_tree);
905     }
906 }
907
908 /* dissect a reassembled mux-pdu
909  *
910  * tvb          buffer containing mux-pdu, including header and closing flag
911  * pinfo        packet info for packet containing the end of the mux-pdu
912  * pkt_offset   offset within the block from the superdissector where the
913  *                MUX-PDU starts (must increase monotonically for constant
914  *                pinfo->fd->num)
915  * h223_tree    dissection tree for h223 protocol; a single item will be added
916  *              (with a sub-tree)
917  * call_info    h223 info structure for this h223 call
918  * pdu_no       index of this pdu within the call
919  */
920 static void dissect_mux_pdu( tvbuff_t *tvb, packet_info * pinfo,
921                              guint32 pkt_offset,
922                              proto_tree *h223_tree,
923                              h223_call_info *call_info)
924 {
925     guint32 offset = 0;
926     /* actual (as opposed to reported) payload len */
927     guint32 len;
928     guint32 raw_hdr = 0, correct_hdr = 0;
929     gint32  errors = 0;
930     guint16 closing_flag = 0;
931     guint8 mc = 0;
932     guint8 mpl = 0;
933     gboolean end_of_mux_sdu = FALSE;
934     tvbuff_t *pdu_tvb;
935
936     proto_item *pdu_item = NULL;
937     proto_tree *pdu_tree = NULL;
938
939 #ifdef DEBUG_H223_FRAGMENTATION
940     g_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u",
941             pinfo->fd->num, pkt_offset, tvb_reported_length(tvb));
942 #endif
943     
944     switch(call_info->h223_level) {
945         case 0: case 1:
946             raw_hdr = tvb_get_guint8(tvb,0);
947             mc = (guint8)((raw_hdr>>1) & 0xf);
948             end_of_mux_sdu = raw_hdr & 1;
949             offset++;
950             /* closing flag is one byte long for h223 level 0, two for level 1 */
951             len = mpl = tvb_length_remaining(tvb, offset)-(call_info->h223_level+1);
952
953             /* XXX should ignore pdus with incorrect HECs */
954             break;
955
956         case 2:
957             raw_hdr = tvb_get_letoh24(tvb,0);
958             errors = golay_errors(raw_hdr);
959             offset += 3;
960             len = tvb_length_remaining(tvb,offset)-2;
961
962             if(errors != -1) {
963                 correct_hdr = raw_hdr ^ (guint32)errors;
964     
965                 mc = (guint8)(correct_hdr & 0xf);
966                 mpl = (guint8)((correct_hdr >> 4) & 0xff);
967
968                 /* we should never have been called if there's not enough data in
969                  * available. */
970                 DISSECTOR_ASSERT(len >= mpl);
971
972                 closing_flag = tvb_get_ntohs(tvb,offset+len);
973                 end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF));
974             } else {
975                 mc = 0;
976                 mpl = len;
977             }
978             break;
979
980         case 3:
981             /* XXX not implemented */
982         default:
983             len=0;
984             DISSECTOR_ASSERT_NOT_REACHED();
985     }
986
987     
988     if( h223_tree ) {
989         if( mpl == 0 ) {
990             pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, FALSE);
991             pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu);
992         } else {
993             pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, FALSE);
994             pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu);
995         }
996     }
997
998     if( pdu_tree ) {
999         proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, FALSE);
1000         proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header);
1001
1002         switch(call_info->h223_level) {
1003             case 0: case 1:
1004                 proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1005                 break;
1006
1007             case 2:
1008                 if( errors == -1 ) {
1009                     proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1010                                                0, 3, raw_hdr,
1011                                                "Raw value: 0x%06x (uncorrectable errors)", raw_hdr );
1012                 } else {
1013                     if( errors == 0 ) {
1014                         proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1015                                                    0, 3, raw_hdr,
1016                                                    "Raw value: 0x%06x (correct)", raw_hdr );
1017                     } else {
1018                         proto_tree_add_uint_format(hdr_tree, hf_h223_mux_rawhdr, tvb,
1019                                                    0, 3, raw_hdr,
1020                                                    "Raw value: 0x%06x (errors are 0x%06x)", raw_hdr, errors );
1021                     }
1022                     item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3,
1023                                                correct_hdr);
1024                     PROTO_ITEM_SET_GENERATED(item);
1025                     proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc);
1026                     proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl);
1027                 }
1028                 break;
1029
1030             case 3:
1031                 /* XXX not implemented */
1032             default:
1033                 DISSECTOR_ASSERT_NOT_REACHED();
1034         }
1035     }
1036
1037     if(mpl > 0) {
1038         pdu_tvb = tvb_new_subset(tvb, offset, len, mpl);
1039         if(errors != -1) {
1040             dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu);
1041         } else {
1042             call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree);
1043         }
1044         offset += mpl;
1045     }
1046
1047     /* any extra data in the PDU, beyond that indictated by the mpl, is
1048        dissected as data. */
1049     len -= mpl;
1050     if( len > 0 ) {
1051         tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, len, len);
1052         proto_tree *vc_tree = NULL;
1053
1054         if( pdu_tree ) {
1055             proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, FALSE);
1056             vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact);
1057         }
1058         call_dissector(data_handle,next_tvb,pinfo,vc_tree);
1059
1060         offset += len;
1061     } 
1062
1063     /* add the closing HDLC flag */
1064     if( pdu_tree )
1065         proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,FALSE);
1066 }
1067
1068
1069 /************************************************************************************
1070  *
1071  * MUX-PDU delineation and defragmentation
1072  */
1073
1074 /* attempt to parse the header of a mux pdu */
1075 static gboolean attempt_mux_level0_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1076 {
1077     /* level 0 isn't byte-aligned, so is a complete pain to implement */
1078     DISSECTOR_ASSERT_NOT_REACHED();
1079     nbytes = nbytes;
1080     hdr=hdr;
1081     minlen=minlen;
1082     return FALSE;
1083 }
1084
1085 static gboolean attempt_mux_level1_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1086 {
1087     /* this is untested */
1088     DISSECTOR_ASSERT_NOT_REACHED();
1089     
1090     if(nbytes < 2)
1091         return FALSE;
1092
1093     hdr &= 0xffff;
1094     /* don't interpret a repeated hdlc as a header */
1095     if(hdr == 0xE14D)
1096         return FALSE;
1097
1098     /* + 1 byte of header and 2 bytes of closing HDLC */
1099     *minlen = (guint8)((hdr >> 12) & 0xff) + 3;
1100     return TRUE;
1101 }
1102
1103 static gboolean attempt_mux_level2_3_header_parse(guint32 nbytes, guint32 hdr, guint32 *minlen)
1104 {
1105     gint32 errors;
1106     
1107     if(nbytes < 3)
1108         return FALSE;
1109
1110     /* + 3 bytes of header and 2 bytes of closing HDLC */
1111     *minlen = 5;
1112
1113     /* bah, we get the header in the wrong order */
1114     hdr =
1115         ((hdr & 0xFF0000) >> 16) |
1116         (hdr & 0x00FF00) |
1117         ((hdr & 0x0000FF) << 16);
1118     
1119     errors = golay_errors(hdr);
1120     if(errors != -1) {
1121         hdr ^= errors;
1122         *minlen += ((hdr >> 4) & 0xff);
1123     }
1124
1125     return TRUE;
1126 }
1127
1128 static gboolean (* const attempt_mux_header_parse[])(guint32 nbytes, guint32 header_buf, guint32 *minlen) = {
1129     attempt_mux_level0_header_parse,
1130     attempt_mux_level1_header_parse,
1131     attempt_mux_level2_3_header_parse,
1132     attempt_mux_level2_3_header_parse
1133 };
1134
1135 static gboolean h223_mux_check_hdlc(int h223_level, guint32 nbytes, guint32 tail_buf)
1136 {
1137     guint32 masked;
1138
1139     switch(h223_level) {
1140         case 0:
1141             /* level 0 isn't byte-aligned, so is a complete pain to implement */
1142             DISSECTOR_ASSERT_NOT_REACHED();
1143             return FALSE;
1144             break;
1145
1146         case 1:
1147             masked = tail_buf & 0xffff;
1148             return nbytes >= 2 && masked == 0xE14D;
1149
1150         case 2: case 3:
1151             masked = tail_buf & 0xffff;
1152             return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF));
1153
1154         default:
1155             DISSECTOR_ASSERT_NOT_REACHED();
1156             return FALSE;
1157     }
1158 }
1159
1160 /* read a pdu (or the start of a pdu) from the tvb, and dissect it
1161  *
1162  * returns the number of bytes processed, or the negative of the number of
1163  * extra bytes needed, or zero if we don't know yet
1164  */
1165
1166 static gint dissect_mux_pdu_fragment( tvbuff_t *tvb, guint32 start_offset, packet_info * pinfo,
1167                                       proto_tree *h223_tree,
1168                                       h223_call_info *call_info)
1169 {
1170     tvbuff_t *volatile next_tvb;
1171     volatile guint32 offset = start_offset;
1172     gboolean more_frags = TRUE;
1173
1174     gboolean header_parsed = FALSE;
1175     guint32 header_buf = 0, tail_buf = 0;
1176     guint32 pdu_minlen = 0;
1177     
1178
1179 #ifdef DEBUG_H223_FRAGMENTATION
1180     g_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left",
1181             pinfo->fd->num,start_offset, tvb_reported_length_remaining( tvb, start_offset ));
1182 #endif
1183     
1184     while( more_frags && offset < tvb_reported_length( tvb )) {
1185         guint8 byte = tvb_get_guint8(tvb, offset++);
1186         
1187         /* read a byte into the header buf, if necessary */
1188         if((offset-start_offset) <= 4) {
1189             header_buf <<= 8;
1190             header_buf |= byte;
1191         }
1192
1193         /* read the byte into the tail buf */
1194         tail_buf <<= 8;
1195         tail_buf |= byte;
1196
1197         /* if we haven't parsed the header yet, attempt to do so now */
1198         if(!header_parsed)
1199             /* this sets current_pdu_header parsed if current_pdu_read == 3 */
1200             header_parsed = (attempt_mux_header_parse[call_info->h223_level])
1201                 (offset-start_offset,header_buf,&pdu_minlen);
1202
1203         /* if we have successfully parsed the header, we have sufficient data,
1204          * and we have found the closing hdlc, we are done here */
1205         if(header_parsed && (offset-start_offset) >= pdu_minlen) {
1206             if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) {
1207                 more_frags = FALSE;
1208             }
1209         }
1210     }
1211
1212     if( more_frags ) {
1213         if(pdu_minlen <= (offset-start_offset)) {
1214             /* we haven't found the closing hdlc yet, but we don't know how
1215              * much more we need */
1216 #ifdef DEBUG_H223_FRAGMENTATION
1217             g_debug("\tBailing, requesting more bytes");
1218 #endif
1219             return 0;
1220         } else {
1221             guint32 needed = pdu_minlen-(offset-start_offset);
1222 #ifdef DEBUG_H223_FRAGMENTATION
1223             g_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed);
1224 #endif
1225             return - (gint) needed;
1226         }
1227     }
1228
1229     /* create a tvb for the fragment */
1230     next_tvb = tvb_new_subset(tvb, start_offset, offset-start_offset,
1231                               offset-start_offset);
1232
1233
1234     /* we catch boundserrors on the pdu so that errors on an
1235      * individual pdu don't screw up the whole of the rest of the
1236      * stream */
1237     TRY {
1238         dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info);
1239     }
1240
1241     CATCH2(BoundsError,ReportedBoundsError) {
1242         if (check_col(pinfo->cinfo, COL_INFO))
1243             col_append_str(pinfo->cinfo, COL_INFO,
1244                            "[Malformed Packet]");
1245         proto_tree_add_protocol_format(h223_tree, proto_malformed,
1246                                        tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1247     }
1248
1249     ENDTRY;
1250
1251     return (offset-start_offset);
1252 }
1253
1254 /************************************************************************************
1255  *
1256  * main dissector entry points
1257  */
1258
1259 /* dissects PDUs from the tvb
1260  *
1261  * Updates desegment_offset and desegment_len if the end of the data didn't
1262  * line up with the end of a pdu.
1263  */
1264 static void dissect_h223 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1265 {
1266     proto_tree *h223_tree = NULL;
1267     proto_item *h223_item = NULL;
1268     h223_call_info *call_info = NULL;
1269     guint32 offset = 0;
1270
1271     /* set up the protocol and info fields in the summary pane */
1272     if (check_col (pinfo->cinfo, COL_PROTOCOL))
1273         col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223);
1274
1275     if (check_col (pinfo->cinfo, COL_INFO))
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                 if(check_col (pinfo->cinfo, COL_INFO))
1315                     col_set_str (pinfo->cinfo, COL_INFO, "(No complete PDUs)");
1316             }
1317             return;
1318         }
1319         offset += res;
1320     }
1321 }
1322
1323 /* H.223 specifies that the least-significant bit is transmitted first;
1324  * however this is at odds with IAX which transmits bytes with the
1325  * first-received bit as the MSB.
1326  *
1327  * This dissector swaps the ordering of the bits in each byte before using the
1328  * normal entry point.
1329  */
1330 static void dissect_h223_bitswapped (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1331 {
1332     tvbuff_t *reversed_tvb;
1333     guint8 *data;
1334     guint len;
1335     guint i;
1336
1337     len = tvb_length(tvb);
1338     data = g_malloc(len);
1339     for( i=0; i<len; i++)
1340         data[i]=BIT_SWAP(tvb_get_guint8(tvb,i));
1341
1342     reversed_tvb = tvb_new_real_data(data,len,tvb_reported_length(tvb));
1343             
1344     /*
1345      * Add the reversed tvbuff to the list of tvbuffs to which
1346      * the tvbuff we were handed refers, so it'll get
1347      * cleaned up when that tvbuff is cleaned up.
1348      */
1349     tvb_set_child_real_data_tvbuff(tvb, reversed_tvb);
1350
1351     /* Add a freer */
1352     tvb_set_free_cb(reversed_tvb, g_free);
1353
1354     /* Add the reversed data to the data source list. */
1355     add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" );
1356     
1357     dissect_h223(reversed_tvb,pinfo,tree);
1358 }
1359
1360 /******************************************************************************/
1361
1362 static void h223_init_protocol (void)
1363 {
1364     circuit_chain_init();
1365 }
1366
1367
1368 void proto_register_h223 (void)
1369 {
1370     /* A header field is something you can search/filter on.
1371      * 
1372      * We create a structure to register our fields. It consists of an
1373      * array of hf_register_info structures, each of which are of the format
1374      * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1375      */
1376    
1377     static hf_register_info hf[] = {
1378         { &hf_h223_non_h223_data,
1379           { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0,
1380             "Initial data in stream, not a PDU", HFILL }},
1381
1382         { &hf_h223_mux_stuffing_pdu,
1383           { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0,
1384             "Empty PDU used for stuffing when no data available", HFILL }},
1385
1386         { &hf_h223_mux_pdu,
1387           { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0,
1388             "H.223 MUX-PDU", HFILL }},
1389
1390         { &hf_h223_mux_header,
1391           { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0,
1392             "H.223 MUX header", HFILL }},
1393
1394         { &hf_h223_mux_rawhdr,
1395           { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1396             "Raw header bytes", HFILL }},
1397         
1398         { &hf_h223_mux_correctedhdr,
1399           { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0,
1400             "Corrected header bytes", HFILL }},
1401
1402         { &hf_h223_mux_mc,
1403           { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0,
1404             "H.223 MUX multiplex code", HFILL }},
1405
1406         { &hf_h223_mux_mpl,
1407           { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT8, BASE_DEC, NULL, 0x0,
1408             "H.223 MUX multiplex Payload Length", HFILL }},
1409
1410         { &hf_h223_mux_deact,
1411           { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0,
1412             "mpl refers to an entry in the multiplex table which is not active", HFILL }},
1413
1414         { &hf_h223_mux_vc,
1415           { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0,
1416             "H.223 Virtual Circuit", HFILL }},
1417         
1418         { &hf_h223_mux_extra,
1419           { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_DEC, NULL, 0x0,
1420             "data beyond mpl", HFILL }},
1421         
1422         { &hf_h223_mux_hdlc2,
1423           { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0,
1424             "framing flag", HFILL }},
1425
1426         /* fields for h.223-mux fragments */
1427         { &hf_h223_mux_fragment_overlap,
1428           { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1429             "Fragment overlaps with other fragments", HFILL }},
1430         
1431         { &hf_h223_mux_fragment_overlap_conflict,
1432           { "Conflicting data in fragment overlap",     "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1433             "Overlapping fragments contained conflicting data", HFILL }},
1434         
1435         { &hf_h223_mux_fragment_multiple_tails,
1436           { "Multiple tail fragments found",    "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1437             "Several tails were found when defragmenting the packet", HFILL }},
1438         
1439         { &hf_h223_mux_fragment_too_long_fragment,
1440           { "Fragment too long",        "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1441             "Fragment contained data past end of packet", HFILL }},
1442         
1443         { &hf_h223_mux_fragment_error,
1444           { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1445             "Defragmentation error due to illegal fragments", HFILL }},
1446         
1447         { &hf_h223_mux_fragment,
1448           { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1449             "H.223 MUX-PDU Fragment", HFILL }},
1450         
1451         { &hf_h223_mux_fragments,
1452           { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1453             "H.223 MUX-PDU Fragments", HFILL }},
1454         
1455         { &hf_h223_mux_reassembled_in,
1456           { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1457             "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }},
1458
1459         /* fields for h.223-al fragments */
1460         { &hf_h223_al_fragment_overlap,
1461           { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1462             "Fragment overlaps with other fragments", HFILL }},
1463         
1464         { &hf_h223_al_fragment_overlap_conflict,
1465           { "Conflicting data in fragment overlap",     "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1466             "Overlapping fragments contained conflicting data", HFILL }},
1467         
1468         { &hf_h223_al_fragment_multiple_tails,
1469           { "Multiple tail fragments found",    "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1470             "Several tails were found when defragmenting the packet", HFILL }},
1471         
1472         { &hf_h223_al_fragment_too_long_fragment,
1473           { "Fragment too long",        "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1474             "Fragment contained data past end of packet", HFILL }},
1475         
1476         { &hf_h223_al_fragment_error,
1477           { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1478             "Defragmentation error due to illegal fragments", HFILL }},
1479         
1480         { &hf_h223_al_fragment,
1481           { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1482             "H.223 AL-PDU Fragment", HFILL }},
1483         
1484         { &hf_h223_al_fragments,
1485           { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1486             "H.223 AL-PDU Fragments", HFILL }},
1487         
1488         { &hf_h223_al_reassembled_in,
1489           { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1490             "This H.223 AL-PDU packet is reassembled in this frame", HFILL }},
1491
1492         /* h223-als */
1493
1494         { &hf_h223_al1,
1495           { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0,
1496             "H.223 AL-PDU using AL1", HFILL }},
1497
1498         { &hf_h223_al1_framed,
1499           { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1500             "", HFILL }},
1501
1502         { &hf_h223_al2,
1503           { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1504             "H.223 AL-PDU using AL2", HFILL }},
1505
1506         { &hf_h223_al2_sequenced,
1507           { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1508             "H.223 AL-PDU using AL2 with sequence numbers", HFILL }},
1509
1510         { &hf_h223_al2_unsequenced,
1511           { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0,
1512             "H.223 AL-PDU using AL2 without sequence numbers", HFILL }},
1513
1514         { &hf_h223_al2_seqno,
1515           { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1516             "H.223 AL2 sequence number", HFILL }},
1517
1518         { &hf_h223_al2_crc,
1519           { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
1520             "CRC", HFILL }},
1521
1522         { &hf_h223_al2_crc_bad,
1523           { "Bad CRC","h223.al2.crc_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1524             "", HFILL }},
1525
1526         { &hf_h223_al_payload,
1527           { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0,
1528             "H.223 AL-PDU Payload", HFILL }},
1529
1530     };
1531
1532     static gint *ett[] = {
1533         &ett_h223,
1534         &ett_h223_non_h223_data,
1535         &ett_h223_mux_stuffing_pdu,
1536         &ett_h223_mux_pdu,
1537         &ett_h223_mux_header,
1538         &ett_h223_mux_deact,
1539         &ett_h223_mux_vc,
1540         &ett_h223_mux_extra,
1541         &ett_h223_mux_fragments,
1542         &ett_h223_mux_fragment,
1543         &ett_h223_al_fragments,
1544         &ett_h223_al_fragment,
1545         &ett_h223_al1,
1546         &ett_h223_al2,
1547         &ett_h223_al_payload
1548     };
1549
1550     if (proto_h223 == -1) { /* execute protocol initialization only once */
1551     proto_h223 =
1552         proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223");
1553     proto_h223_bitswapped =
1554         proto_register_protocol ("Bitswapped ITU-T Recommendation H.223", "H.223 (Bitswapped)", "h223_bitswapped");
1555
1556     proto_register_field_array (proto_h223, hf, array_length (hf));
1557     proto_register_subtree_array (ett, array_length (ett));
1558     register_dissector("h223", dissect_h223, proto_h223);
1559     register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped);
1560         
1561     /* register our init routine to be called at the start of a capture,
1562        to clear out our hash tables etc */
1563     register_init_routine(&h223_init_protocol);
1564     }
1565
1566     h245_set_h223_set_mc_handle( &h223_set_mc );
1567     h245_set_h223_add_lc_handle( &h223_add_lc );
1568 }
1569
1570 void proto_reg_handoff_h223(void)
1571 {
1572     dissector_handle_t h223_bitswapped = find_dissector("h223_bitswapped");
1573     dissector_handle_t h223 = find_dissector("h223");
1574     data_handle = find_dissector("data");
1575     h245dg_handle = find_dissector("h245dg");
1576     srp_handle = find_dissector("srp");
1577
1578     dissector_add_handle("tcp.port", h223);
1579     dissector_add_handle("tcp.port", h223_bitswapped);
1580     dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped);
1581     dissector_add("iax2.dataformat", AST_DATAFORMAT_H223_H245, h223_bitswapped);
1582 }
1583 /* vim:set ts=8 et: */