Coverage Report

Created: 2026-05-14 06:28

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