Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-gsm_cbch.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-gsm_cbch.c
2
 * Routines for GSM CBCH dissection - A.K.A. 3GPP 44.012 (GSM 04.12)
3
 *
4
 * Copyright 2011, Mike Morrin <mike.morrin [AT] ipaccess.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "config.h"
14
15
#include <epan/packet.h>
16
#include <epan/reassemble.h>
17
#include <epan/expert.h>
18
19
void proto_register_gsm_cbch(void);
20
void proto_reg_handoff_gsm_cbch(void);
21
22
3
#define CBCH_FRAGMENT_SIZE 22
23
24
static const value_string block_type_lpd_strings[] = {
25
    { 0x00, "NOT Cell Broadcast"},
26
    { 0x01, "Cell Broadcast"},
27
    { 0x02, "NOT Cell Broadcast"},
28
    { 0x03, "NOT Cell Broadcast"},
29
    {    0, NULL}
30
};
31
32
static const value_string block_type_seq_num_values[] = {
33
    { 0x00, "First Block"},
34
    { 0x01, "Second Block"},
35
    { 0x02, "Third Block"},
36
    { 0x03, "Fourth Block"},
37
    { 0x08, "First Schedule Block"},
38
    { 0x0F, "Null message"},
39
    {    0, NULL}
40
};
41
42
static const value_string sched_type_values[] = {
43
    { 0x00, "messages formatted as specified in subclause 3.5 of 3GPP 44.012"},
44
    {    0, NULL}
45
};
46
47
/* Initialize the protocol and registered fields */
48
static int proto_cbch;
49
50
static int hf_gsm_cbch_spare_bit;
51
static int hf_gsm_cbch_lpd;
52
static int hf_gsm_cbch_lb;
53
static int hf_gsm_cbch_seq_num;
54
static int hf_gsm_cbch_sched_type;
55
static int hf_gsm_cbch_sched_begin_slot;
56
static int hf_gsm_cbch_sched_spare;
57
static int hf_gsm_cbch_sched_end_slot;
58
static int hf_gsm_cbch_slot;
59
/* static int hf_gsm_cbch_sched_msg_id; */
60
static int hf_gsm_cbch_padding;
61
static int hf_gsm_cbch_block;
62
63
/* These fields are used when reassembling cbch fragments
64
 */
65
static int hf_cbch_fragments;
66
static int hf_cbch_fragment;
67
static int hf_cbch_fragment_overlap;
68
static int hf_cbch_fragment_overlap_conflict;
69
static int hf_cbch_fragment_multiple_tails;
70
static int hf_cbch_fragment_too_long_fragment;
71
static int hf_cbch_fragment_error;
72
static int hf_cbch_fragment_count;
73
static int hf_cbch_reassembled_in;
74
static int hf_cbch_reassembled_length;
75
76
/* Initialize the subtree pointers */
77
static int ett_cbch_msg;
78
static int ett_schedule_msg;
79
static int ett_schedule_new_msg;
80
static int ett_cbch_fragment;
81
static int ett_cbch_fragments;
82
83
static expert_field ei_gsm_cbch_sched_end_slot;
84
static expert_field ei_gsm_cbch_seq_num_null;
85
static expert_field ei_gsm_cbch_seq_num_reserved;
86
static expert_field ei_gsm_cbch_lpd;
87
88
static dissector_handle_t cbs_handle;
89
90
/* reassembly of CHCH blocks */
91
static reassembly_table cbch_block_reassembly_table;
92
93
/* Structure needed for the fragmentation routines in reassemble.c
94
 */
95
static const fragment_items cbch_frag_items = {
96
    &ett_cbch_fragment,
97
    &ett_cbch_fragments,
98
    &hf_cbch_fragments,
99
    &hf_cbch_fragment,
100
    &hf_cbch_fragment_overlap,
101
    &hf_cbch_fragment_overlap_conflict,
102
    &hf_cbch_fragment_multiple_tails,
103
    &hf_cbch_fragment_too_long_fragment,
104
    &hf_cbch_fragment_error,
105
    &hf_cbch_fragment_count,
106
    &hf_cbch_reassembled_in,
107
    &hf_cbch_reassembled_length,
108
    /* Reassembled data field */
109
    NULL,
110
    "blocks"
111
};
112
113
static const range_string gsm_cbch_sched_begin_slot_rvals[] = {
114
    { 0,     0,     "Out of range (ignoring message)" },
115
    { 1,     1,     "(apparently) Scheduled Scheduling Message" },
116
    { 2,     48,    "(apparently) Unscheduled Scheduling Message" },
117
    { 49,    0xFF,  "Out of range (ignoring message)" },
118
119
    { 0x00, 0x00,  NULL },
120
};
121
122
static void
123
dissect_schedule_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree)
124
0
{
125
0
    unsigned    len, offset  = 0;
126
0
    uint8_t     octet1, i, k = 0;
127
0
    uint8_t     sched_begin, sched_end, new_slots[48];
128
0
    bool        valid_message   = true;
129
0
    uint16_t    other_slots[48];
130
0
    proto_item *item            = NULL, *schedule_item = NULL;
131
0
    proto_tree *sched_tree      = NULL, *sched_subtree = NULL;
132
133
0
    len = tvb_reported_length(tvb);
134
135
0
    col_append_str(pinfo->cinfo, COL_INFO, " CBCH Schedule Message ");
136
137
0
    schedule_item = proto_tree_add_protocol_format(top_tree, proto_cbch, tvb, 0, -1,
138
0
                                                   "GSM CBCH Schedule Message");
139
140
0
    sched_tree = proto_item_add_subtree(schedule_item, ett_schedule_msg);
141
142
0
    proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_type, tvb, offset, 1, ENC_BIG_ENDIAN);
143
0
    octet1 = tvb_get_uint8(tvb, offset);
144
0
    if (0 == (octet1 & 0xC0))
145
0
    {
146
0
        proto_item* slot_item;
147
0
        sched_begin = octet1 & 0x3F;
148
0
        proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_begin_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
149
0
        if ((sched_begin < 1) || (sched_begin > 48))
150
0
        {
151
0
            valid_message = false;
152
0
        }
153
0
        proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_spare, tvb, offset, 1, ENC_BIG_ENDIAN);
154
0
        sched_end = tvb_get_uint8(tvb, offset);
155
0
        slot_item = proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_end_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
156
0
        if (sched_end < sched_begin)
157
0
        {
158
0
            expert_add_info(pinfo, slot_item, &ei_gsm_cbch_sched_end_slot);
159
0
            valid_message = false;
160
0
        }
161
162
0
        if (valid_message)
163
0
        {
164
            /* build an array of new messages */
165
0
            memset(&new_slots,   0xFF, sizeof(new_slots));
166
0
            memset(&other_slots, 0xFF, sizeof(other_slots));
167
168
            /* iterate over the octets */
169
0
            for (i=0; i<6; i++)
170
0
            {
171
0
                uint8_t j;
172
0
                octet1 = tvb_get_uint8(tvb, offset++);
173
174
                /* iterate over the bits */
175
0
                for (j=0; j<8; j++)
176
0
                {
177
0
                    if (octet1 & (0x80>>j))
178
0
                    {
179
0
                        new_slots[k++] = (i<<3) + j + 1;
180
0
                    }
181
0
                }
182
0
            }
183
            /* print the array of new messages */
184
0
            sched_subtree = proto_tree_add_subtree_format(sched_tree, tvb, offset-6, 6, ett_schedule_new_msg, &item,
185
0
                                                            "This schedule contains %d slots with new messages", k);
186
0
            for (i=0; i<k; i++)
187
0
            {
188
0
                DISSECTOR_ASSERT(new_slots[i] <= 48);
189
0
                octet1 = tvb_get_uint8(tvb, offset);
190
0
                if ((octet1 & 0x80) == 0x80)
191
0
                {
192
                    /* MDT 1 */
193
0
                    uint8_t octet2;
194
0
                    uint16_t msg_id;
195
196
0
                    octet2 = tvb_get_uint8(tvb, offset + 1);
197
0
                    msg_id = ((octet1 &0x7F) << 8) + octet2;
198
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset, 2, new_slots[i],
199
0
                                        "%d, Message ID: %d, First transmission of an SMSCB within the Schedule Period",
200
0
                                        new_slots[i], msg_id);
201
0
                    offset +=2;
202
0
                    other_slots[new_slots[i] - 1] = msg_id;
203
0
                }
204
0
                else if ((octet1 & 0xC0) == 0)
205
0
                {
206
                    /* MDT 00 */
207
0
                    if (octet1 == 0)
208
0
                    {
209
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, new_slots[i],
210
0
                                            "%d, Repeat of non-existent slot %d",
211
0
                                            new_slots[i], octet1);
212
0
                    }
213
0
                    else if (octet1 < new_slots[i])
214
0
                    {
215
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, new_slots[i],
216
0
                                            "%d, Message ID: %d, Repeat of Slot %d",
217
0
                                            new_slots[i], other_slots[octet1 - 1], octet1);
218
0
                        other_slots[new_slots[i] - 1] = other_slots[octet1 - 1];
219
0
                    }
220
0
                    else
221
0
                    {
222
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, new_slots[i],
223
0
                                            "%d, Apparent forward reference to slot %d",
224
0
                                            new_slots[i], octet1);
225
0
                    }
226
0
                }
227
0
                else if (octet1 == 0x40)
228
0
                {
229
                    /* MDT 010000000 */
230
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, new_slots[i],
231
0
                                    "%d Free Message Slot, optional reading", new_slots[i]);
232
0
                    other_slots[new_slots[i] - 1] = 0xFFFE;
233
0
                }
234
0
                else if (octet1 == 0x41)
235
0
                {
236
                    /* MDT 010000001 */
237
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, new_slots[i],
238
0
                                     "%d Free Message Slot, reading advised", new_slots[i]);
239
0
                    other_slots[new_slots[i] - 1] = 0xFFFE;
240
0
                }
241
0
                else
242
0
                {
243
                    /* reserved MDT */
244
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset, 1, new_slots[i],
245
0
                                     "%d reserved MDT: %x", new_slots[i], octet1);
246
0
                    other_slots[new_slots[i] - 1] = 0xFFFE;
247
0
                }
248
0
            }
249
0
            proto_item_set_end(item, tvb, offset);
250
251
            /* print schedule of other messages */
252
0
            sched_subtree = proto_tree_add_subtree(sched_tree, tvb, offset, 0,
253
0
                                ett_schedule_new_msg, &item, "Other message slots in this schedule");
254
0
            for (k=0; offset < len; )
255
0
            {
256
                /* XXX I don't know if a message can validly contain more than
257
                 * 48 slots, but that's the size of the array we create so cap
258
                 * it there to avoid uninitialized memory errors (see bug
259
                 * https://gitlab.com/wireshark/wireshark/-/issues/9270) */
260
0
                if (sched_end > 48)
261
0
                    sched_end = 48;
262
0
                while ((k<sched_end) && (other_slots[k]!=0xFFFF))
263
0
                {
264
0
                    k++;
265
0
                }
266
0
                if (k >= sched_end)
267
0
                    break;
268
269
0
                octet1 = tvb_get_uint8(tvb, offset);
270
0
                if ((octet1 & 0x80) == 0x80)
271
0
                {
272
0
                    if ((offset+1)<len)
273
0
                    {
274
                        /* MDT 1 */
275
0
                        uint8_t octet2;
276
0
                        uint16_t msg_id;
277
278
0
                        octet2 = tvb_get_uint8(tvb, offset + 1);
279
0
                        msg_id = ((octet1 &0x7F) << 8) + octet2;
280
0
                        other_slots[k] = msg_id;
281
0
                        k++;
282
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset, 2, k,
283
0
                                            "%d, Message: %d, First transmission of an SMSCB within the Schedule Period",
284
0
                                            k, msg_id);
285
0
                        offset +=2;
286
0
                    }
287
0
                    else
288
0
                    {
289
                        /* I'm not sure what's supposed to be dissected in this
290
                         * case. Perhaps just an expert info is appropriate?
291
                         * Regardless, we need to increment k to prevent an
292
                         * infinite loop, see
293
                         * https://gitlab.com/wireshark/wireshark/-/issues/8730
294
                         */
295
0
                        ++k;
296
0
                    }
297
0
                }
298
0
                else if (octet1 && ((octet1 & 0xC0) == 0))
299
0
                {
300
                    /* MDT 00 */
301
0
                    if (octet1 < k)
302
0
                    {
303
0
                        other_slots[k] = other_slots[octet1 - 1];
304
0
                        k++;
305
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, k,
306
0
                                            "%d, Message ID: %d, Repeat of Slot %d",
307
0
                                            k, other_slots[octet1 - 1], octet1);
308
0
                    }
309
0
                    else
310
0
                    {
311
0
                        k++;
312
0
                        proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, k,
313
0
                                            "%d, Apparent forward reference to slot %d",
314
0
                                            k, octet1);
315
0
                    }
316
0
                }
317
0
                else if (octet1 == 0x40)
318
0
                {
319
                    /* MDT 010000000 */
320
0
                    k++;
321
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, k,
322
0
                            "%d Free Message Slot, optional reading", k);
323
0
                }
324
0
                else if (octet1 == 0x41)
325
0
                {
326
                    /* MDT 010000001 */
327
0
                    k++;
328
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset++, 1, k,
329
0
                            "%d Free Message Slot, reading advised", k);
330
0
                }
331
0
                else
332
0
                {
333
                    /* reserved MDT */
334
0
                    k++;
335
0
                    proto_tree_add_uint_format_value(sched_subtree, hf_gsm_cbch_slot, tvb, offset, 1, k,
336
0
                            "%d reserved MDT: %x", k, octet1);
337
0
                }
338
0
            }
339
0
            proto_item_set_end(item, tvb, offset);
340
0
            proto_tree_add_item(sched_tree, hf_gsm_cbch_padding, tvb, offset, -1, ENC_NA);
341
0
        }
342
0
    }
343
0
}
344
345
static int
346
dissect_cbch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data  _U_)
347
5
{
348
5
    fragment_head *frag_data = NULL;
349
5
    uint8_t        octet, lb, lpd, seq_num;
350
5
    uint32_t       offset;
351
5
    proto_item    *cbch_item, *lpd_item, *seq_item;
352
5
    proto_tree    *cbch_tree;
353
5
    tvbuff_t      *reass_tvb = NULL, *msg_tvb = NULL;
354
355
5
    offset = 0;
356
5
    octet  = tvb_get_uint8(tvb, offset);
357
358
    /*
359
     * create the protocol tree
360
     */
361
5
    cbch_item = proto_tree_add_protocol_format(tree, proto_cbch, tvb, 0, -1,
362
5
                                               "GSM CBCH - Block (0x%02x)", octet&3);
363
364
5
    col_append_str(pinfo->cinfo, COL_PROTOCOL, " CBCH");
365
366
5
    cbch_tree = proto_item_add_subtree(cbch_item, ett_cbch_msg);
367
368
5
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_block, tvb, offset, 1, octet);
369
370
5
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_spare_bit, tvb, offset, 1, octet);
371
5
    lpd_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lpd,       tvb, offset, 1, octet);
372
5
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lb,        tvb, offset, 1, octet);
373
5
    seq_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_seq_num,   tvb, offset, 1, octet);
374
5
    seq_num =  octet & 0x0F;
375
5
    lpd     = (octet & 0x60) >> 5;
376
5
    lb      = (octet & 0x10) >> 4;
377
378
5
    if (lpd == 1)
379
4
    {
380
4
        switch (seq_num)
381
4
        {
382
1
        case 0x00:
383
1
        case 0x08:
384
1
            pinfo->fragmented = true;
385
            /* we should have a unique ID for the reassembled page, but we don't really have anything from the protocol...
386
               The GSM frame number div 4 might be used for this, but it has not been passed to this layer and does not
387
               exist at all if the message is being passed over the RSL interface.
388
               So we just use 0... */
389
390
            /* after reassembly we will need to know if this is a scheduling message,
391
               this information is carried in the initial sequence number, not the payload,
392
               so we prepend the reassembly with the octet containing the initial sequence number
393
               to allow later dissection of the payload */
394
1
            frag_data = fragment_add_seq_check(&cbch_block_reassembly_table,
395
1
                                               tvb, offset, pinfo, 0, NULL,
396
1
                                               seq_num & 0x03, CBCH_FRAGMENT_SIZE + 1, !lb);
397
1
            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
398
1
                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
399
1
            break;
400
401
0
        case 0x01:
402
1
        case 0x02:
403
2
        case 0x03:
404
2
            pinfo->fragmented = true;
405
2
            offset++; /* step to beginning of payload */
406
2
            frag_data = fragment_add_seq_check(&cbch_block_reassembly_table,
407
2
                                               tvb, offset, pinfo, 0, NULL,
408
2
                                               seq_num, CBCH_FRAGMENT_SIZE, !lb);
409
2
            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
410
2
                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
411
2
            break;
412
413
0
        case 0x0F:
414
0
            expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_null);
415
0
            call_data_dissector(tvb, pinfo, cbch_tree);
416
0
            break;
417
418
1
        default:
419
1
            expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_reserved);
420
1
            call_data_dissector(tvb, pinfo, cbch_tree);
421
1
            break;
422
4
        }
423
4
        if (reass_tvb)
424
1
        {
425
            /* Reassembled */
426
427
            /* the tvb contains the reassmbled message prepended with the sequence number octet from the first block
428
               We use this to determine whether this is a normal message or a scheduling message */
429
1
            offset = 0;
430
431
1
            octet = tvb_get_uint8(reass_tvb, offset++);
432
1
            msg_tvb = tvb_new_subset_remaining(reass_tvb, offset);
433
434
1
            if (octet & 0x08)
435
0
            {
436
0
                dissect_schedule_message(msg_tvb, pinfo, tree);
437
0
            }
438
1
            else
439
1
            {
440
1
                call_dissector(cbs_handle, msg_tvb, pinfo, tree);
441
1
            }
442
1
        }
443
4
    }
444
1
    else
445
1
    {
446
1
        expert_add_info(pinfo, lpd_item, &ei_gsm_cbch_lpd);
447
1
        call_data_dissector(tvb, pinfo, cbch_tree);
448
1
    }
449
5
    return tvb_captured_length(tvb);
450
5
}
451
452
/* Register the protocol with Wireshark */
453
void
454
proto_register_gsm_cbch(void)
455
14
{
456
    /* Setup list of header fields */
457
14
    static hf_register_info hf_smscb[] =
458
14
        {
459
14
            { &hf_gsm_cbch_spare_bit,
460
14
              { "GSM CBCH spare bit",  "gsm_cbch.block_type.spare",
461
14
                FT_UINT8, BASE_HEX, NULL, 0x80,
462
14
                NULL, HFILL}
463
14
            },
464
14
            { &hf_gsm_cbch_lpd,
465
14
              { "GSM CBCH Link Protocol Discriminator",  "gsm_cbch.block_type.lpd",
466
14
                FT_UINT8, BASE_DEC, VALS(block_type_lpd_strings), 0x60,
467
14
                NULL, HFILL}
468
14
            },
469
14
            { &hf_gsm_cbch_lb,
470
14
              { "GSM CBCH Last Block", "gsm_cbch.block_type.lb",
471
14
                FT_UINT8, BASE_DEC, NULL, 0x10,
472
14
                NULL, HFILL}
473
14
            },
474
14
            { &hf_gsm_cbch_seq_num,
475
14
              { "GSM CBCH Sequence Number",  "gsm_cbch.block_type.seq_num",
476
14
                FT_UINT8, BASE_DEC, VALS(block_type_seq_num_values), 0x0F,
477
14
                NULL, HFILL}
478
14
            },
479
14
            { &hf_gsm_cbch_sched_type,
480
14
              { "GSM CBCH Schedule Type", "gsm_cbch.sched_type",
481
14
                FT_UINT8, BASE_DEC, VALS(sched_type_values), 0xC0,
482
14
                NULL, HFILL}
483
14
            },
484
14
            { &hf_gsm_cbch_sched_begin_slot,
485
14
              { "GSM CBCH Schedule Begin slot", "gsm_cbch.schedule_begin",
486
14
              FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_cbch_sched_begin_slot_rvals), 0x3F,
487
14
                NULL, HFILL}
488
14
            },
489
14
            { &hf_gsm_cbch_sched_spare,
490
14
              { "GSM CBCH Schedule Spare Bits", "gsm_cbch.sched_spare",
491
14
                FT_UINT8, BASE_DEC, NULL, 0xC0,
492
14
                NULL, HFILL}
493
14
            },
494
14
            { &hf_gsm_cbch_sched_end_slot,
495
14
              { "GSM CBCH Schedule End Slot",   "gsm_cbch.sched_end",
496
14
                FT_UINT8, BASE_DEC, NULL, 0x3F,
497
14
                NULL, HFILL}
498
14
            },
499
14
            { &hf_gsm_cbch_slot,
500
14
              { "Slot",   "gsm_cbch.slot",
501
14
                FT_UINT8, BASE_DEC, NULL, 0x0,
502
14
                NULL, HFILL}
503
14
            },
504
14
            { &hf_gsm_cbch_padding,
505
14
              { "Padding",   "gsm_cbch.padding",
506
14
                FT_BYTES, BASE_NONE, NULL, 0x0,
507
14
                NULL, HFILL}
508
14
            },
509
14
            { &hf_gsm_cbch_block,
510
14
              { "CBCH Block",   "gsm_cbch.block",
511
14
                FT_UINT8, BASE_HEX, NULL, 0x0,
512
14
                NULL, HFILL}
513
14
            },
514
515
#if 0
516
            { &hf_gsm_cbch_sched_msg_id,
517
              { "GSM CBCH Schedule Message ID", "gsm_cbch.sched_msg_id",
518
                FT_UINT16, BASE_DEC, NULL, 0x0,
519
                NULL, HFILL}
520
            },
521
#endif
522
            /* Fragment fields
523
             */
524
14
            { &hf_cbch_fragment_overlap,
525
14
              {   "Fragment overlap",
526
14
                  "gsm_cbch.fragment.overlap",
527
14
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
528
14
                  "Fragment overlaps with other fragments", HFILL
529
14
              }
530
14
            },
531
14
            { &hf_cbch_fragment_overlap_conflict,
532
14
              {   "Conflicting data in fragment overlap",
533
14
                  "gsm_cbch.fragment.overlap.conflict",
534
14
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
535
14
                  "Overlapping fragments contained conflicting data", HFILL
536
14
              }
537
14
            },
538
14
            { &hf_cbch_fragment_multiple_tails,
539
14
              {   "Multiple tail fragments found",
540
14
                  "gsm_cbch.fragment.multipletails",
541
14
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
542
14
                  "Several tails were found when defragmenting the packet", HFILL
543
14
              }
544
14
            },
545
14
            { &hf_cbch_fragment_too_long_fragment,
546
14
              {   "Fragment too long",
547
14
                  "gsm_cbch.fragment.toolongfragment",
548
14
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
549
14
                  "Fragment contained data past end of packet", HFILL
550
14
              }
551
14
            },
552
14
            { &hf_cbch_fragment_error,
553
14
              {   "Defragmentation error",
554
14
                  "gsm_cbch.fragment.error",
555
14
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
556
14
                  "Defragmentation error due to illegal fragments", HFILL
557
14
              }
558
14
            },
559
14
            { &hf_cbch_fragment_count,
560
14
              {   "Fragmentation count",
561
14
                  "gsm_cbch.fragment.count",
562
14
                  FT_UINT32, BASE_DEC, NULL, 0x0,
563
14
                  "Count of CBCH Fragments", HFILL
564
14
              }
565
14
            },
566
14
            { &hf_cbch_reassembled_in,
567
14
              {   "Reassembled in",
568
14
                  "gsm_cbch.reassembled.in",
569
14
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
570
14
                  "CBCH fragments are reassembled in the given packet", HFILL
571
14
              }
572
14
            },
573
14
            { &hf_cbch_reassembled_length,
574
14
              {   "Reassembled message length is one less than indicated here",
575
14
                  "gsm_cbch.reassembled.length",
576
14
                  FT_UINT32, BASE_DEC, NULL, 0x0,
577
14
                  "The total length of the reassembled message", HFILL
578
14
              }
579
14
            },
580
14
            { &hf_cbch_fragment,
581
14
              {   "CBCH Fragment",
582
14
                  "gsm_cbch.fragment",
583
14
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
584
14
                  NULL, HFILL
585
14
              }
586
14
            },
587
14
            { &hf_cbch_fragments,
588
14
              {   "CBCH Fragments",
589
14
                  "gsm_cbch.fragments",
590
14
                  FT_NONE, BASE_NONE, NULL, 0x0,
591
14
                  NULL, HFILL
592
14
              }
593
14
            }
594
14
        };
595
596
/* Setup protocol subtree array */
597
14
    static int *ett[] = {
598
14
        &ett_cbch_msg,
599
14
        &ett_schedule_msg,
600
14
        &ett_schedule_new_msg,
601
14
        &ett_cbch_fragment,
602
14
        &ett_cbch_fragments,
603
14
    };
604
605
14
    expert_module_t* expert_cbch;
606
607
14
    static ei_register_info ei[] = {
608
14
        { &ei_gsm_cbch_sched_end_slot, { "gsm_cbch.sched_end.bad_range", PI_PROTOCOL, PI_WARN, "End Slot Number less than Begin Slot Number: ignoring message", EXPFILL }},
609
14
        { &ei_gsm_cbch_seq_num_null, { "gsm_cbch.block_type.seq_num.null", PI_PROTOCOL, PI_NOTE, "NULL message", EXPFILL }},
610
14
        { &ei_gsm_cbch_seq_num_reserved, { "gsm_cbch.block_type.seq_num.reserved", PI_PROTOCOL, PI_NOTE, "Reserved Sequence Number", EXPFILL }},
611
14
        { &ei_gsm_cbch_lpd, { "gsm_cbch.block_type.lpd.invalid", PI_PROTOCOL, PI_WARN, "Invalid Link Protocol Discriminator", EXPFILL }},
612
14
    };
613
614
    /* Register the protocol name and description */
615
14
    proto_cbch = proto_register_protocol("GSM Cell Broadcast Channel", "GSM CBCH", "gsm_cbch");
616
14
    proto_register_field_array(proto_cbch, hf_smscb, array_length(hf_smscb));
617
14
    expert_cbch = expert_register_protocol(proto_cbch);
618
14
    expert_register_field_array(expert_cbch, ei, array_length(ei));
619
620
    /* subdissector code */
621
14
    register_dissector("gsm_cbch", dissect_cbch, proto_cbch);
622
623
14
    reassembly_table_register(&cbch_block_reassembly_table,
624
14
                          &addresses_reassembly_table_functions);
625
626
    /* subtree array */
627
14
    proto_register_subtree_array(ett, array_length(ett));
628
14
}
629
630
void
631
proto_reg_handoff_gsm_cbch(void)
632
14
{
633
14
    cbs_handle  = find_dissector_add_dependency("gsm_cbs", proto_cbch);
634
14
}
635
636
/*
637
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
638
 *
639
 * Local variables:
640
 * c-basic-offset: 4
641
 * tab-width: 8
642
 * indent-tabs-mode: nil
643
 * End:
644
 *
645
 * vi: set shiftwidth=4 tabstop=8 expandtab:
646
 * :indentSize=4:tabSize=8:noTabs=true:
647
 */