Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-gsm_cbch.c
Line
Count
Source
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
6
#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
12
{
348
12
    fragment_head *frag_data = NULL;
349
12
    uint8_t        octet, lb, lpd, seq_num;
350
12
    uint32_t       offset;
351
12
    proto_item    *cbch_item, *lpd_item, *seq_item;
352
12
    proto_tree    *cbch_tree;
353
12
    tvbuff_t      *reass_tvb = NULL, *msg_tvb = NULL;
354
355
12
    offset = 0;
356
12
    octet  = tvb_get_uint8(tvb, offset);
357
358
    /*
359
     * create the protocol tree
360
     */
361
12
    cbch_item = proto_tree_add_protocol_format(tree, proto_cbch, tvb, 0, -1,
362
12
                                               "GSM CBCH - Block (0x%02x)", octet&3);
363
364
12
    col_append_str(pinfo->cinfo, COL_PROTOCOL, " CBCH");
365
366
12
    cbch_tree = proto_item_add_subtree(cbch_item, ett_cbch_msg);
367
368
12
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_block, tvb, offset, 1, octet);
369
370
12
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_spare_bit, tvb, offset, 1, octet);
371
12
    lpd_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lpd,       tvb, offset, 1, octet);
372
12
    proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lb,        tvb, offset, 1, octet);
373
12
    seq_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_seq_num,   tvb, offset, 1, octet);
374
12
    seq_num =  octet & 0x0F;
375
12
    lpd     = (octet & 0x60) >> 5;
376
12
    lb      = (octet & 0x10) >> 4;
377
378
12
    if (lpd == 1)
379
9
    {
380
9
        switch (seq_num)
381
9
        {
382
3
        case 0x00:
383
3
        case 0x08:
384
3
            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
3
            frag_data = fragment_add_seq_check(&cbch_block_reassembly_table,
395
3
                                               tvb, offset, pinfo, 0, NULL,
396
3
                                               seq_num & 0x03, CBCH_FRAGMENT_SIZE + 1, !lb);
397
3
            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
398
3
                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
399
3
            break;
400
401
1
        case 0x01:
402
2
        case 0x02:
403
3
        case 0x03:
404
3
            pinfo->fragmented = true;
405
3
            offset++; /* step to beginning of payload */
406
3
            frag_data = fragment_add_seq_check(&cbch_block_reassembly_table,
407
3
                                               tvb, offset, pinfo, 0, NULL,
408
3
                                               seq_num, CBCH_FRAGMENT_SIZE, !lb);
409
3
            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
410
3
                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
411
3
            break;
412
413
1
        case 0x0F:
414
1
            expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_null);
415
1
            call_data_dissector(tvb, pinfo, cbch_tree);
416
1
            break;
417
418
2
        default:
419
2
            expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_reserved);
420
2
            call_data_dissector(tvb, pinfo, cbch_tree);
421
2
            break;
422
9
        }
423
9
        if (reass_tvb)
424
3
        {
425
            /* Reassembled */
426
427
            /* the tvb contains the reassembled 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
3
            offset = 0;
430
431
3
            octet = tvb_get_uint8(reass_tvb, offset++);
432
3
            msg_tvb = tvb_new_subset_remaining(reass_tvb, offset);
433
434
3
            if (octet & 0x08)
435
0
            {
436
0
                dissect_schedule_message(msg_tvb, pinfo, tree);
437
0
            }
438
3
            else
439
3
            {
440
3
                call_dissector(cbs_handle, msg_tvb, pinfo, tree);
441
3
            }
442
3
        }
443
9
    }
444
3
    else
445
3
    {
446
3
        expert_add_info(pinfo, lpd_item, &ei_gsm_cbch_lpd);
447
3
        call_data_dissector(tvb, pinfo, cbch_tree);
448
3
    }
449
12
    return tvb_captured_length(tvb);
450
12
}
451
452
/* Register the protocol with Wireshark */
453
void
454
proto_register_gsm_cbch(void)
455
16
{
456
    /* Setup list of header fields */
457
16
    static hf_register_info hf_smscb[] =
458
16
        {
459
16
            { &hf_gsm_cbch_spare_bit,
460
16
              { "GSM CBCH spare bit",  "gsm_cbch.block_type.spare",
461
16
                FT_UINT8, BASE_HEX, NULL, 0x80,
462
16
                NULL, HFILL}
463
16
            },
464
16
            { &hf_gsm_cbch_lpd,
465
16
              { "GSM CBCH Link Protocol Discriminator",  "gsm_cbch.block_type.lpd",
466
16
                FT_UINT8, BASE_DEC, VALS(block_type_lpd_strings), 0x60,
467
16
                NULL, HFILL}
468
16
            },
469
16
            { &hf_gsm_cbch_lb,
470
16
              { "GSM CBCH Last Block", "gsm_cbch.block_type.lb",
471
16
                FT_UINT8, BASE_DEC, NULL, 0x10,
472
16
                NULL, HFILL}
473
16
            },
474
16
            { &hf_gsm_cbch_seq_num,
475
16
              { "GSM CBCH Sequence Number",  "gsm_cbch.block_type.seq_num",
476
16
                FT_UINT8, BASE_DEC, VALS(block_type_seq_num_values), 0x0F,
477
16
                NULL, HFILL}
478
16
            },
479
16
            { &hf_gsm_cbch_sched_type,
480
16
              { "GSM CBCH Schedule Type", "gsm_cbch.sched_type",
481
16
                FT_UINT8, BASE_DEC, VALS(sched_type_values), 0xC0,
482
16
                NULL, HFILL}
483
16
            },
484
16
            { &hf_gsm_cbch_sched_begin_slot,
485
16
              { "GSM CBCH Schedule Begin slot", "gsm_cbch.schedule_begin",
486
16
              FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_cbch_sched_begin_slot_rvals), 0x3F,
487
16
                NULL, HFILL}
488
16
            },
489
16
            { &hf_gsm_cbch_sched_spare,
490
16
              { "GSM CBCH Schedule Spare Bits", "gsm_cbch.sched_spare",
491
16
                FT_UINT8, BASE_DEC, NULL, 0xC0,
492
16
                NULL, HFILL}
493
16
            },
494
16
            { &hf_gsm_cbch_sched_end_slot,
495
16
              { "GSM CBCH Schedule End Slot",   "gsm_cbch.sched_end",
496
16
                FT_UINT8, BASE_DEC, NULL, 0x3F,
497
16
                NULL, HFILL}
498
16
            },
499
16
            { &hf_gsm_cbch_slot,
500
16
              { "Slot",   "gsm_cbch.slot",
501
16
                FT_UINT8, BASE_DEC, NULL, 0x0,
502
16
                NULL, HFILL}
503
16
            },
504
16
            { &hf_gsm_cbch_padding,
505
16
              { "Padding",   "gsm_cbch.padding",
506
16
                FT_BYTES, BASE_NONE, NULL, 0x0,
507
16
                NULL, HFILL}
508
16
            },
509
16
            { &hf_gsm_cbch_block,
510
16
              { "CBCH Block",   "gsm_cbch.block",
511
16
                FT_UINT8, BASE_HEX, NULL, 0x0,
512
16
                NULL, HFILL}
513
16
            },
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
16
            { &hf_cbch_fragment_overlap,
525
16
              {   "Fragment overlap",
526
16
                  "gsm_cbch.fragment.overlap",
527
16
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
528
16
                  "Fragment overlaps with other fragments", HFILL
529
16
              }
530
16
            },
531
16
            { &hf_cbch_fragment_overlap_conflict,
532
16
              {   "Conflicting data in fragment overlap",
533
16
                  "gsm_cbch.fragment.overlap.conflict",
534
16
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
535
16
                  "Overlapping fragments contained conflicting data", HFILL
536
16
              }
537
16
            },
538
16
            { &hf_cbch_fragment_multiple_tails,
539
16
              {   "Multiple tail fragments found",
540
16
                  "gsm_cbch.fragment.multipletails",
541
16
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
542
16
                  "Several tails were found when defragmenting the packet", HFILL
543
16
              }
544
16
            },
545
16
            { &hf_cbch_fragment_too_long_fragment,
546
16
              {   "Fragment too long",
547
16
                  "gsm_cbch.fragment.toolongfragment",
548
16
                  FT_BOOLEAN, BASE_NONE, NULL, 0x0,
549
16
                  "Fragment contained data past end of packet", HFILL
550
16
              }
551
16
            },
552
16
            { &hf_cbch_fragment_error,
553
16
              {   "Defragmentation error",
554
16
                  "gsm_cbch.fragment.error",
555
16
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
556
16
                  "Defragmentation error due to illegal fragments", HFILL
557
16
              }
558
16
            },
559
16
            { &hf_cbch_fragment_count,
560
16
              {   "Fragmentation count",
561
16
                  "gsm_cbch.fragment.count",
562
16
                  FT_UINT32, BASE_DEC, NULL, 0x0,
563
16
                  "Count of CBCH Fragments", HFILL
564
16
              }
565
16
            },
566
16
            { &hf_cbch_reassembled_in,
567
16
              {   "Reassembled in",
568
16
                  "gsm_cbch.reassembled.in",
569
16
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
570
16
                  "CBCH fragments are reassembled in the given packet", HFILL
571
16
              }
572
16
            },
573
16
            { &hf_cbch_reassembled_length,
574
16
              {   "Reassembled message length is one less than indicated here",
575
16
                  "gsm_cbch.reassembled.length",
576
16
                  FT_UINT32, BASE_DEC, NULL, 0x0,
577
16
                  "The total length of the reassembled message", HFILL
578
16
              }
579
16
            },
580
16
            { &hf_cbch_fragment,
581
16
              {   "CBCH Fragment",
582
16
                  "gsm_cbch.fragment",
583
16
                  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
584
16
                  NULL, HFILL
585
16
              }
586
16
            },
587
16
            { &hf_cbch_fragments,
588
16
              {   "CBCH Fragments",
589
16
                  "gsm_cbch.fragments",
590
16
                  FT_NONE, BASE_NONE, NULL, 0x0,
591
16
                  NULL, HFILL
592
16
              }
593
16
            }
594
16
        };
595
596
/* Setup protocol subtree array */
597
16
    static int *ett[] = {
598
16
        &ett_cbch_msg,
599
16
        &ett_schedule_msg,
600
16
        &ett_schedule_new_msg,
601
16
        &ett_cbch_fragment,
602
16
        &ett_cbch_fragments,
603
16
    };
604
605
16
    expert_module_t* expert_cbch;
606
607
16
    static ei_register_info ei[] = {
608
16
        { &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
16
        { &ei_gsm_cbch_seq_num_null, { "gsm_cbch.block_type.seq_num.null", PI_PROTOCOL, PI_NOTE, "NULL message", EXPFILL }},
610
16
        { &ei_gsm_cbch_seq_num_reserved, { "gsm_cbch.block_type.seq_num.reserved", PI_PROTOCOL, PI_NOTE, "Reserved Sequence Number", EXPFILL }},
611
16
        { &ei_gsm_cbch_lpd, { "gsm_cbch.block_type.lpd.invalid", PI_PROTOCOL, PI_WARN, "Invalid Link Protocol Discriminator", EXPFILL }},
612
16
    };
613
614
    /* Register the protocol name and description */
615
16
    proto_cbch = proto_register_protocol("GSM Cell Broadcast Channel", "GSM CBCH", "gsm_cbch");
616
16
    proto_register_field_array(proto_cbch, hf_smscb, array_length(hf_smscb));
617
16
    expert_cbch = expert_register_protocol(proto_cbch);
618
16
    expert_register_field_array(expert_cbch, ei, array_length(ei));
619
620
    /* subdissector code */
621
16
    register_dissector("gsm_cbch", dissect_cbch, proto_cbch);
622
623
16
    reassembly_table_register(&cbch_block_reassembly_table,
624
16
                          &addresses_reassembly_table_functions);
625
626
    /* subtree array */
627
16
    proto_register_subtree_array(ett, array_length(ett));
628
16
}
629
630
void
631
proto_reg_handoff_gsm_cbch(void)
632
16
{
633
16
    cbs_handle  = find_dissector_add_dependency("gsm_cbs", proto_cbch);
634
16
}
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
 */