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-catapult-dct2000.c
Line
Count
Source
1
/* packet-catapult-dct2000.c
2
 * Routines for Catapult DCT2000 packet stub header disassembly
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
13
#include <stdio.h>      /* for sscanf() */
14
15
#include <epan/packet.h>
16
#include <epan/expert.h>
17
#include <epan/prefs.h>
18
#include <epan/addr_resolv.h>
19
#include <epan/proto_data.h>
20
#include <epan/tfs.h>
21
22
#include <wsutil/strtoi.h>
23
24
#include <wiretap/catapult_dct2000.h>
25
#include "packet-umts_fp.h"
26
#include "packet-umts_rlc.h"
27
28
#include "packet-mac-lte.h"
29
#include "packet-rlc-lte.h"
30
#include "packet-pdcp-lte.h"
31
32
#include "packet-mac-nr.h"
33
#include "packet-pdcp-nr.h"
34
35
void proto_reg_handoff_catapult_dct2000(void);
36
void proto_register_catapult_dct2000(void);
37
38
/* Protocol and registered fields. */
39
static int proto_catapult_dct2000;
40
41
static int hf_catapult_dct2000_context;
42
static int hf_catapult_dct2000_port_number;
43
static int hf_catapult_dct2000_timestamp;
44
static int hf_catapult_dct2000_protocol;
45
static int hf_catapult_dct2000_variant;
46
static int hf_catapult_dct2000_outhdr;
47
static int hf_catapult_dct2000_direction;
48
static int hf_catapult_dct2000_encap;
49
static int hf_catapult_dct2000_unparsed_data;
50
static int hf_catapult_dct2000_comment;
51
static int hf_catapult_dct2000_sprint;
52
static int hf_catapult_dct2000_error_comment;
53
static int hf_catapult_dct2000_tty;
54
static int hf_catapult_dct2000_tty_line;
55
static int hf_catapult_dct2000_dissected_length;
56
57
static int hf_catapult_dct2000_ipprim_addresses;
58
static int hf_catapult_dct2000_ipprim_src_addr_v4;
59
static int hf_catapult_dct2000_ipprim_src_addr_v6;
60
static int hf_catapult_dct2000_ipprim_dst_addr_v4;
61
static int hf_catapult_dct2000_ipprim_dst_addr_v6;
62
static int hf_catapult_dct2000_ipprim_addr_v4;
63
static int hf_catapult_dct2000_ipprim_addr_v6;
64
static int hf_catapult_dct2000_ipprim_udp_src_port;
65
static int hf_catapult_dct2000_ipprim_udp_dst_port;
66
static int hf_catapult_dct2000_ipprim_udp_port;
67
static int hf_catapult_dct2000_ipprim_tcp_src_port;
68
static int hf_catapult_dct2000_ipprim_tcp_dst_port;
69
static int hf_catapult_dct2000_ipprim_tcp_port;
70
static int hf_catapult_dct2000_ipprim_conn_id;
71
72
static int hf_catapult_dct2000_sctpprim_addresses;
73
static int hf_catapult_dct2000_sctpprim_dst_addr_v4;
74
static int hf_catapult_dct2000_sctpprim_dst_addr_v6;
75
static int hf_catapult_dct2000_sctpprim_addr_v4;
76
static int hf_catapult_dct2000_sctpprim_addr_v6;
77
static int hf_catapult_dct2000_sctpprim_dst_port;
78
79
static int hf_catapult_dct2000_ueid;
80
static int hf_catapult_dct2000_srbid;
81
static int hf_catapult_dct2000_drbid;
82
static int hf_catapult_dct2000_cellid;
83
static int hf_catapult_dct2000_bcch_transport;
84
static int hf_catapult_dct2000_rlc_op;
85
static int hf_catapult_dct2000_rlc_channel_type;
86
static int hf_catapult_dct2000_rlc_mui;
87
static int hf_catapult_dct2000_rlc_cnf;
88
static int hf_catapult_dct2000_rlc_discard_req;
89
static int hf_catapult_dct2000_carrier_type;
90
static int hf_catapult_dct2000_cell_group;
91
static int hf_catapult_dct2000_carrier_id;
92
93
static int hf_catapult_dct2000_security_mode_params;
94
static int hf_catapult_dct2000_uplink_sec_mode;
95
static int hf_catapult_dct2000_downlink_sec_mode;
96
static int hf_catapult_dct2000_ciphering_algorithm;
97
static int hf_catapult_dct2000_ciphering_key;
98
static int hf_catapult_dct2000_integrity_algorithm;
99
static int hf_catapult_dct2000_integrity_key;
100
101
static int hf_catapult_dct2000_lte_ccpri_opcode;
102
static int hf_catapult_dct2000_lte_ccpri_status;
103
static int hf_catapult_dct2000_lte_ccpri_channel;
104
105
static int hf_catapult_dct2000_lte_nas_rrc_opcode;
106
static int hf_catapult_dct2000_lte_nas_rrc_establish_cause;
107
static int hf_catapult_dct2000_lte_nas_rrc_priority;
108
static int hf_catapult_dct2000_lte_nas_rrc_release_cause;
109
110
static int hf_catapult_dct2000_nr_nas_s1ap_opcode;
111
112
/* UMTS RLC fields */
113
static int hf_catapult_dct2000_rbid;
114
static int hf_catapult_dct2000_ccch_id;
115
static int hf_catapult_dct2000_no_crc_error;
116
static int hf_catapult_dct2000_crc_error;
117
static int hf_catapult_dct2000_clear_tx_buffer;
118
static int hf_catapult_dct2000_buffer_occupancy;
119
static int hf_catapult_dct2000_pdu_size;
120
static int hf_catapult_dct2000_ueid_type;
121
static int hf_catapult_dct2000_tx_priority;
122
static int hf_catapult_dct2000_last_in_seg_set;
123
static int hf_catapult_dct2000_rx_timing_deviation;
124
static int hf_catapult_dct2000_transport_channel_type;
125
static int hf_catapult_dct2000_no_padding_bits;
126
127
static int hf_catapult_dct2000_rawtraffic_interface;
128
static int hf_catapult_dct2000_rawtraffic_direction;
129
static int hf_catapult_dct2000_rawtraffic_pdu;
130
131
132
/* Variables used for preferences */
133
static bool catapult_dct2000_try_ipprim_heuristic = true;
134
static bool catapult_dct2000_try_sctpprim_heuristic = true;
135
static bool catapult_dct2000_dissect_lte_rrc = true;
136
static bool catapult_dct2000_dissect_mac_lte_oob_messages = true;
137
static bool catapult_dct2000_dissect_old_protocol_names;
138
static bool catapult_dct2000_use_protocol_name_as_dissector_name;
139
140
/* Protocol subtree. */
141
static int ett_catapult_dct2000;
142
static int ett_catapult_dct2000_ipprim;
143
static int ett_catapult_dct2000_sctpprim;
144
static int ett_catapult_dct2000_tty;
145
static int ett_catapult_dct2000_security_mode_params;
146
147
static expert_field ei_catapult_dct2000_lte_ccpri_status_error;
148
static expert_field ei_catapult_dct2000_error_comment_expert;
149
static expert_field ei_catapult_dct2000_string_invalid;
150
151
static const value_string direction_vals[] = {
152
    { 0,   "Sent" },
153
    { 1,   "Received" },
154
    { 0,   NULL },
155
};
156
157
static const value_string encap_vals[] = {
158
    { WTAP_ENCAP_RAW_IP,                 "Raw IP" },
159
    { WTAP_ENCAP_ETHERNET,               "Ethernet" },
160
    { WTAP_ENCAP_ISDN,                   "LAPD" },
161
    { WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,   "ATM (PDUs untruncated)" },
162
    { WTAP_ENCAP_PPP,                    "PPP" },
163
    { DCT2000_ENCAP_SSCOP,               "SSCOP" },
164
    { WTAP_ENCAP_FRELAY,                 "Frame Relay" },
165
    { WTAP_ENCAP_MTP2,                   "MTP2" },
166
    { DCT2000_ENCAP_NBAP,                "NBAP" },
167
    { DCT2000_ENCAP_UNHANDLED,           "No Direct Encapsulation" },
168
    { 0,                                 NULL },
169
};
170
171
static const value_string bcch_transport_vals[] = {
172
    { BCH_TRANSPORT,    "BCH" },
173
    { DLSCH_TRANSPORT,  "DLSCH" },
174
    { 0,   NULL },
175
};
176
177
178
#define RLC_MGMT_ASSIGN                 0x41
179
0
#define RLC_AM_DATA_REQ                 0x60
180
0
#define RLC_AM_DATA_IND                 0x61
181
#define RLC_AM_DATA_CONF                0x62
182
0
#define RLC_UM_DATA_REQ                 0x70
183
0
#define RLC_UM_DATA_IND                 0x71
184
#define RLC_UM_DATA_CONF                0x74
185
0
#define RLC_TR_DATA_REQ                 0x80
186
0
#define RLC_TR_DATA_IND                 0x81
187
#define RLC_TR_DATA_CONF                0x83
188
189
static const value_string rlc_op_vals[] = {
190
    { RLC_AM_DATA_REQ,   "[UL] [AM]" },
191
    { RLC_AM_DATA_IND,   "[DL] [AM]" },
192
    { RLC_UM_DATA_REQ,   "[UL] [UM]"},
193
    { RLC_UM_DATA_IND,   "[DL] [UM]"},
194
    { RLC_TR_DATA_REQ,   "[UL] [TM]"},
195
    { RLC_TR_DATA_IND,   "[DL] [TM]"},
196
    { 0,   NULL }
197
};
198
199
200
static const value_string rlc_logical_channel_vals[] = {
201
    { Channel_DCCH,  "DCCH"},
202
    { Channel_BCCH,  "BCCH"},
203
    { Channel_CCCH,  "CCCH"},
204
    { Channel_PCCH,  "PCCH"},
205
    { 0,             NULL}
206
};
207
208
209
#define CCPRI_REQ 1
210
#define CCPRI_IND 2
211
212
static const value_string ccpri_opcode_vals[] = {
213
    { CCPRI_REQ,     "REQUEST"},
214
    { CCPRI_IND,     "INDICATION"},
215
    { 0,             NULL}
216
};
217
218
static const value_string rlc_rbid_vals[] = {
219
    { 1,     "DCH1"},
220
    { 2,     "DCH2"},
221
    { 3,     "DCH3"},
222
    { 4,     "DCH4"},
223
    { 5,     "DCH5"},
224
    { 6,     "DCH6"},
225
    { 7,     "DCH7"},
226
    { 8,     "DCH8"},
227
    { 9,     "DCH9"},
228
    { 10,    "DCH10"},
229
    { 11,    "DCH11"},
230
    { 12,    "DCH12"},
231
    { 13,    "DCH13"},
232
    { 14,    "DCH14"},
233
    { 15,    "DCH15"},
234
    { 17,    "BCCH"},
235
    { 18,    "CCCH"},
236
    { 19,    "PCCH"},
237
    { 20,    "SHCCH"},
238
    { 21,    "CTCH"},
239
    { 23,    "MCCH"},
240
    { 24,    "MSCH"},
241
    { 25,    "MTCH"},
242
    { 0,     NULL}
243
};
244
static value_string_ext rlc_rbid_vals_ext = VALUE_STRING_EXT_INIT(rlc_rbid_vals);
245
246
static const value_string ueid_type_vals[] = {
247
    { 0,     "URNTI"},
248
    { 1,     "CRNTI"},
249
    { 0,     NULL}
250
};
251
252
static const value_string transport_channel_type_vals[] = {
253
    { 1,     "RACH"},
254
    { 2,     "FACH"},
255
    { 3,     "BCH"},
256
    { 4,     "PCH"},
257
    { 6,     "USCH"},
258
    { 7,     "DSCH"},
259
    { 8,     "DCH"},
260
    { 9,     "HSDSCH"},
261
    { 10,    "EDCH"},
262
    { 0,     NULL}
263
};
264
265
0
#define LTE_NAS_RRC_DATA_IND       0x02
266
0
#define LTE_NAS_RRC_DATA_REQ       0x03
267
0
#define LTE_NAS_RRC_ESTABLISH_REQ  0x06
268
0
#define LTE_NAS_RRC_RELEASE_IND    0x08
269
270
static const value_string lte_nas_rrc_opcode_vals[] = {
271
    { LTE_NAS_RRC_DATA_IND,        "Data-Ind"},
272
    { LTE_NAS_RRC_DATA_REQ,        "Data-Req"},
273
    { LTE_NAS_RRC_ESTABLISH_REQ,   "Establish-Req"},
274
    { LTE_NAS_RRC_RELEASE_IND,     "Release-Ind"},
275
    { 0,     NULL}
276
};
277
278
279
#define NAS_S1AP_DATA_REQ       0x00
280
0
#define NAS_S1AP_DATA_IND       0x01
281
282
static const value_string nas_s1ap_opcode_vals[] = {
283
    { NAS_S1AP_DATA_REQ,        "Data-Req"},
284
    { NAS_S1AP_DATA_IND,        "Data-Ind"},
285
    { 0,     NULL}
286
};
287
288
289
/* Distinguish between similar 4G or 5G protocols */
290
enum LTE_or_NR {
291
    LTE,
292
    NR
293
};
294
295
static const value_string carrier_type_vals[] = {
296
    { 0,        "LTE"},
297
    { 1,        "CatM"},
298
    { 2,        "NBIoT"},
299
    { 3,        "NR"},
300
    { 0,     NULL}
301
};
302
303
304
static const value_string security_mode_vals[] = {
305
    { 0,        "None"},
306
    { 1,        "Integrity only"},
307
    { 2,        "Ciphering and Integrity"},
308
    { 0,     NULL}
309
};
310
311
static const value_string ciphering_algorithm_vals[] = {
312
    { 0,        "EEA0"},
313
    { 1,        "EEA1"},
314
    { 2,        "EEA2"},
315
    { 3,        "EEA3"},
316
    { 0,     NULL}
317
};
318
319
static const value_string integrity_algorithm_vals[] = {
320
    { 0,        "EIA0"},
321
    { 1,        "EIA1"},
322
    { 2,        "EIA2"},
323
    { 3,        "EIA3"},
324
    { 0,     NULL}
325
};
326
327
328
0
#define MAX_OUTHDR_VALUES 32
329
330
static int proto_fp;
331
static int proto_umts_rlc;
332
333
static int proto_rlc_lte;
334
static int proto_pdcp_lte;
335
336
337
static dissector_handle_t mac_lte_handle;
338
static dissector_handle_t rlc_lte_handle;
339
static dissector_handle_t pdcp_lte_handle;
340
static dissector_handle_t catapult_dct2000_handle;
341
static dissector_handle_t nrup_handle;
342
343
static dissector_handle_t mac_nr_handle;
344
345
static dissector_handle_t eth_handle;
346
347
static dissector_handle_t look_for_dissector(const char *protocol_name);
348
static unsigned parse_outhdr_string(const char *outhdr_string, int outhdr_length, unsigned *outhdr_values);
349
350
static void attach_fp_info(packet_info *pinfo, bool received,
351
                           const char *protocol_name, int variant,
352
                           unsigned *outhdr_values, unsigned outhdr_values_found);
353
static void attach_rlc_info(packet_info *pinfo, uint32_t urnti, uint8_t rbid,
354
                            bool is_sent, unsigned *outhdr_values,
355
                            unsigned outhdr_values_found);
356
357
static void attach_mac_lte_info(packet_info *pinfo, unsigned *outhdr_values,
358
                                unsigned outhdr_values_found);
359
static void attach_rlc_lte_info(packet_info *pinfo, unsigned *outhdr_values,
360
                                unsigned outhdr_values_found);
361
static void attach_pdcp_lte_info(packet_info *pinfo, unsigned *outhdr_values,
362
                                 unsigned outhdr_values_found);
363
364
365
/* Return the number of bytes used to encode the length field
366
   (we're not interested in the length value itself) */
367
static int skipASNLength(uint8_t value)
368
0
{
369
0
    if ((value & 0x80) == 0)
370
0
    {
371
0
        return 1;
372
0
    }
373
0
    else
374
0
    {
375
0
        return ((value & 0x03) == 1) ? 2 : 3;
376
0
    }
377
0
}
378
379
380
/* Look for the protocol data within an ipprim packet.
381
   Only set *data_offset if data field found. */
382
static bool find_ipprim_data_offset(tvbuff_t *tvb, int *data_offset, uint8_t direction,
383
                                        uint32_t *source_addr_offset, uint8_t *source_addr_length,
384
                                        uint32_t *dest_addr_offset,   uint8_t *dest_addr_length,
385
                                        uint32_t *source_port_offset, uint32_t *dest_port_offset,
386
                                        port_type *type_of_port,
387
                                        uint16_t *conn_id_offset)
388
0
{
389
0
    uint8_t length;
390
0
    int    offset = *data_offset;
391
392
    /* Get the ipprim command code. */
393
0
    uint8_t tag = tvb_get_uint8(tvb, offset++);
394
395
    /* Only accept UDP or TCP data request or indication */
396
0
    switch (tag) {
397
0
        case 0x23:  /* UDP data request */
398
0
        case 0x24:  /* UDP data indication */
399
0
            *type_of_port = PT_UDP;
400
0
            break;
401
0
        case 0x45:  /* TCP data request */
402
0
        case 0x46:  /* TCP data indication */
403
0
            *type_of_port = PT_TCP;
404
0
            break;
405
0
        default:
406
0
            return false;
407
0
    }
408
409
    /* Skip any other TLC fields before reach payload */
410
0
    while (tvb_reported_length_remaining(tvb, offset) > 2) {
411
        /* Look at next tag */
412
0
        tag = tvb_get_uint8(tvb, offset++);
413
414
        /* Is this the data payload we're expecting? */
415
0
        if (((tag == 0x34) && (*type_of_port == PT_UDP)) ||
416
0
            ((tag == 0x48) && (*type_of_port == PT_TCP))) {
417
418
0
            *data_offset = offset;
419
0
            return true;
420
0
        }
421
0
        else {
422
            /* Read length in next byte */
423
0
            length = tvb_get_uint8(tvb, offset++);
424
425
0
            if (tag == 0x31 && length >=4) {
426
                /* Remote IP address */
427
0
                if (direction == 0) {
428
                    /* Sent *to* remote, so dest */
429
0
                    *dest_addr_offset = offset;
430
0
                    *dest_addr_length = (length/4) * 4;
431
0
                }
432
0
                else {
433
0
                    *source_addr_offset = offset;
434
0
                    *source_addr_length = (length/4) * 4;
435
0
                }
436
437
                /* Remote port follows (if present) */
438
0
                if ((length % 4) == 2) {
439
0
                    if (direction == 0) {
440
0
                        *dest_port_offset = offset + *dest_addr_length;
441
0
                    }
442
0
                    else {
443
0
                        *source_port_offset = offset + *source_addr_length;
444
0
                    }
445
0
                }
446
0
            }
447
0
            else
448
0
            if (tag == 0x32) {
449
0
                if (length == 4 || length == 16) {
450
                    /* Local IP address */
451
0
                    if (direction == 0) {
452
                        /* Sent *from* local, so source */
453
0
                        *source_addr_offset = offset;
454
0
                        *source_addr_length = length;
455
0
                    }
456
0
                    else {
457
0
                        *dest_addr_offset = offset;
458
0
                        *dest_addr_length = length;
459
0
                    }
460
0
                }
461
0
            }
462
0
            else
463
0
            if (tag == 0x33 && length == 2) {
464
                /* Get local port */
465
0
                if (direction == 0) {
466
                    /* Sent from local, so source */
467
0
                    *source_port_offset = offset;
468
0
                }
469
0
                else {
470
0
                    *dest_port_offset = offset;
471
0
                }
472
0
            }
473
0
            else
474
0
            if (tag == 0x36 && length == 2) {
475
                /* Get conn_id */
476
0
                *conn_id_offset = offset;
477
0
            }
478
479
            /* Skip the length of the indicated value */
480
0
            offset += length;
481
0
        }
482
0
    }
483
484
    /* No data found... */
485
0
    return false;
486
0
}
487
488
489
490
/* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
491
   Only set *data_offset if data field found. */
492
static bool find_sctpprim_variant1_data_offset(tvbuff_t *tvb, int *data_offset,
493
                                                   uint32_t *dest_addr_offset,
494
                                                   uint16_t *dest_addr_length,
495
                                                   uint32_t *dest_port_offset)
496
0
{
497
0
    int offset = *data_offset;
498
499
    /* Get the sctpprim command code. */
500
0
    uint8_t first_tag = tvb_get_uint8(tvb, offset++);
501
0
    uint8_t tag;
502
0
    uint8_t first_length_byte;
503
504
    /* Only accept interested in data requests or indications */
505
0
    switch (first_tag) {
506
0
        case 0x04:  /* data request */
507
0
        case 0x62:  /* data indication */
508
0
            break;
509
0
        default:
510
0
            return false;
511
0
    }
512
513
0
    first_length_byte = tvb_get_uint8(tvb, offset);
514
0
    offset += skipASNLength(first_length_byte);
515
516
    /* Skip any other fields before reach payload */
517
0
    while (tvb_reported_length_remaining(tvb, offset) > 2) {
518
        /* Look at next tag */
519
0
        tag = tvb_get_uint8(tvb, offset++);
520
521
        /* Is this the data payload we're expecting? */
522
0
        if (tag == 0x19) {
523
0
            *data_offset = offset;
524
0
            return true;
525
0
        }
526
0
        else {
527
            /* Skip length field */
528
0
            offset++;
529
0
            switch (tag) {
530
0
                case 0x0a: /* destPort */
531
0
                    *dest_port_offset = offset;
532
0
                    offset += 2;
533
0
                    break;
534
535
0
                case 0x01: /* sctpInstanceNum */
536
0
                case 0x1e: /* strseqnum */
537
0
                case 0x0d: /* streamnum */
538
0
                    offset += 2;
539
0
                    continue;
540
541
0
                case 0x09: /* ipv4Address */
542
0
                    *dest_addr_offset = offset;
543
0
                    *dest_addr_length = 4;
544
0
                    offset += 4;
545
0
                    break;
546
547
0
                case 0x1d:
548
0
                case 0x0c: /* payloadType */
549
0
                    offset += 4;
550
0
                    continue;
551
552
0
                default:
553
                    /* Fail if not a known header field */
554
0
                    return false;
555
0
            }
556
0
        }
557
0
    }
558
559
    /* No data found... */
560
0
    return false;
561
0
}
562
563
/* Look for the protocol data within an sctpprim (variant 3) packet.
564
   Return value indicates whether this header found.
565
   Only set *data_offset if data field found. */
566
static bool find_sctpprim_variant3_data_offset(tvbuff_t *tvb, int *data_offset,
567
                                                   uint32_t *dest_addr_offset,
568
                                                   uint16_t *dest_addr_length,
569
                                                   uint32_t *dest_port_offset)
570
0
{
571
0
    uint16_t tag    = 0;
572
0
    uint16_t length = 0;
573
0
    int     offset = *data_offset;
574
575
    /* Get the sctpprim (2 byte) command code. */
576
0
    uint16_t top_tag = tvb_get_ntohs(tvb, offset);
577
0
    offset += 2;
578
579
    /* Only interested in data requests or indications */
580
0
    if ((top_tag != 0x0400) &&  /* SendDataReq */
581
0
       (top_tag != 0x6200)) {  /* DataInd */
582
0
        return false;
583
0
    }
584
585
    /* Overall length field is next 2 bytes */
586
0
    offset += 2;
587
588
    /* Rx/Tx ops have different formats */
589
590
    /*****************/
591
    /* DataInd        */
592
0
    if (top_tag == 0x6200) {
593
        /* Next 2 bytes are associate ID */
594
0
        offset += 2;
595
596
        /* Next 2 bytes are destination port */
597
0
        *dest_port_offset = offset;
598
0
        offset += 2;
599
600
        /* Destination address should follow - check tag */
601
0
        tag = tvb_get_ntohs(tvb, offset);
602
0
        if (tag != 0x0900) {
603
0
            return false;
604
0
        }
605
0
        else {
606
            /* Skip tag */
607
0
            offset += 2;
608
609
            /* Length field */
610
0
            length = tvb_get_ntohs(tvb, offset) / 2;
611
0
            if ((length != 4) && (length != 16))
612
0
            {
613
0
                return false;
614
0
            }
615
0
            offset += 2;
616
617
            /* Address data is here */
618
0
            *dest_addr_offset = offset;
619
0
            *dest_addr_length = length;
620
621
0
            offset += length;
622
0
        }
623
624
        /* Not interested in remaining (fixed) fields */
625
0
        if (tvb_reported_length_remaining(tvb, offset) > (4 + 2 + 2 + 4)) {
626
0
            offset += (4 + 2 + 2 + 4);
627
0
        }
628
0
        else {
629
0
            return false;
630
0
        }
631
632
        /* Data should now be here */
633
0
        tag = tvb_get_ntohs(tvb, offset);
634
0
        offset += 2;
635
0
        if (tag == 0x1900) {
636
            /* 2-byte length field */
637
0
            offset += 2;
638
639
            /* Data is here!!! */
640
0
            *data_offset = offset;
641
0
            return true;
642
0
        }
643
0
        else {
644
0
            return false;
645
0
        }
646
0
    }
647
648
    /***********************************/
649
    /* SendDataReq (top_tag == 0x0400) */
650
0
    else {
651
        /* AssociateId should follow - check tag */
652
0
        tag = tvb_get_ntohs(tvb, offset);
653
0
        if (tag != 0x2400) {
654
0
            return false;
655
0
        }
656
0
        else {
657
            /* Skip tag */
658
0
            offset += 2;
659
660
            /* Skip 2-byte value */
661
0
            offset += 2;
662
0
        }
663
664
        /* Get tag */
665
0
        tag = tvb_get_ntohs(tvb, offset);
666
0
        offset += 2;
667
668
        /* Some optional params */
669
0
        while ((tag != 0x0c00) && (tvb_reported_length_remaining(tvb, offset) > 4)) {
670
0
            switch (tag) {
671
0
                case 0x0900:   /* Dest address */
672
                    /* Length field */
673
0
                    length = tvb_get_ntohs(tvb, offset) / 2;
674
0
                    if ((length != 4) && (length != 16)) {
675
0
                        return false;
676
0
                    }
677
0
                    offset += 2;
678
679
                    /* Address data is here */
680
0
                    *dest_addr_offset = offset;
681
0
                    *dest_addr_length = length;
682
683
0
                    offset += length;
684
0
                    break;
685
686
0
                case 0x0a00:   /* Dest port number */
687
0
                    *dest_port_offset = offset;
688
0
                    offset += 2;
689
0
                    break;
690
691
0
                case 0x0d00:   /* StreamNum */
692
0
                    offset += 2;
693
0
                    break;
694
695
696
0
                default:
697
0
                    return false;
698
0
            }
699
700
            /* Get the next tag */
701
0
            tag = tvb_get_ntohs(tvb, offset);
702
0
            offset += 2;
703
0
        }
704
705
706
        /* Mandatory payload type */
707
0
        if (tag != 0x0c00) {
708
0
            return false;
709
0
        }
710
0
        length = tvb_get_ntohs(tvb, offset) / 2;
711
0
        offset += 2;
712
0
        offset += length;
713
714
715
        /* Optional options */
716
0
        tag = tvb_get_ntohs(tvb, offset);
717
0
        offset += 2;
718
0
        if (tag == 0x0b00) {
719
0
            length = tvb_get_ntohs(tvb, offset) / 2;
720
0
            offset += 2;
721
722
0
            offset += length;
723
724
            /* Get next tag */
725
0
            tag = tvb_get_ntohs(tvb, offset);
726
0
            offset += 2;
727
0
        }
728
729
730
        /* Data should now be here!! */
731
0
        if (tag == 0x1900) {
732
            /* 2-byte length field */
733
0
            offset += 2;
734
735
            /* Data is here!!! */
736
0
            *data_offset = offset;
737
0
            return true;
738
0
        }
739
0
        else {
740
0
            return false;
741
0
        }
742
0
    }
743
0
}
744
745
746
/* Dissect a UMTS RLC frame by:
747
   - parsing the primitive header
748
   - passing those values + outheader to dissector
749
   - calling the UMTS RLC dissector */
750
static void dissect_rlc_umts(tvbuff_t *tvb, int offset,
751
                             packet_info *pinfo, proto_tree *tree,
752
                             bool is_sent, unsigned *outhdr_values,
753
                             unsigned outhdr_values_found)
754
0
{
755
0
    uint8_t             tag;
756
0
    bool                ueid_set        = false, rbid_set=false;
757
0
    uint32_t            ueid            = 0;
758
0
    uint8_t             rbid            = 0;
759
0
    uint8_t             length;
760
0
    tvbuff_t           *rlc_tvb;
761
0
    dissector_handle_t  rlc_umts_handle = 0;
762
763
    /* Top-level opcode */
764
0
    tag = tvb_get_uint8(tvb, offset++);
765
0
    switch (tag) {
766
0
        case 0xc0:    /* mac data request */
767
0
        case 0xc1:    /* mac data indication */
768
0
            break;
769
770
0
        default:
771
            /* No data to dissect */
772
0
            return;
773
0
    }
774
775
    /* Keep going until reach data tag or end of frame */
776
0
    while ((tag != 0x41) && tvb_reported_length_remaining(tvb, offset)) { /* i.e. Data */
777
0
        tag = tvb_get_uint8(tvb, offset++);
778
0
        switch (tag) {
779
0
            case 0x72:  /* UE Id */
780
0
                ueid = tvb_get_ntohl(tvb, offset);
781
0
                offset += 2;
782
0
                proto_tree_add_item(tree, hf_catapult_dct2000_ueid, tvb, offset, 2, ENC_BIG_ENDIAN);
783
0
                offset += 2;
784
0
                ueid_set = true;
785
0
                break;
786
0
            case 0xa2:  /* RBID */
787
0
                offset++;  /* skip length */
788
0
                proto_tree_add_item_ret_uint8(tree, hf_catapult_dct2000_rbid, tvb, offset, 1, ENC_BIG_ENDIAN, &rbid);
789
0
                offset++;
790
0
                rbid_set = true;
791
0
                break;
792
0
            case 0x22:  /* CCCH-id setting rbid to CCCH! */
793
0
                offset++;  /* skip length */
794
0
                proto_tree_add_item(tree, hf_catapult_dct2000_ccch_id, tvb, offset, 1, ENC_BIG_ENDIAN);
795
0
                offset++;
796
0
                rbid = 18;
797
0
                break;
798
0
            case 0xc4:  /* No CRC error */
799
0
                proto_tree_add_item(tree, hf_catapult_dct2000_no_crc_error, tvb, offset-1, 1, ENC_NA);
800
0
                break;
801
0
            case 0xc5:  /* CRC error */
802
0
                proto_tree_add_item(tree, hf_catapult_dct2000_crc_error, tvb, offset-1, 1, ENC_NA);
803
0
                break;
804
0
            case 0xf7:  /* Clear Tx Buffer */
805
0
                proto_tree_add_item(tree, hf_catapult_dct2000_clear_tx_buffer, tvb, offset-1, 1, ENC_NA);
806
0
                break;
807
808
0
            case 0x41:  /* Data !!! */
809
0
                offset += skipASNLength(tvb_get_uint8(tvb, offset));
810
0
                break;
811
812
0
            default:
813
                /* For other fields, just skip length and following data */
814
0
                length = tvb_get_uint8(tvb, offset++);
815
0
                switch (tag) {
816
0
                    case 0x42:   /* Buffer Occupancy */
817
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_buffer_occupancy, tvb, offset, length, ENC_BIG_ENDIAN);
818
0
                        break;
819
0
                    case 0x49:   /* PDU Size */
820
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_pdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
821
0
                        break;
822
0
                    case 0x47:   /* UEId type */
823
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_ueid_type, tvb, offset, 1, ENC_BIG_ENDIAN);
824
0
                        break;
825
0
                    case 0x4e:   /* Tx Priority */
826
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_tx_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
827
0
                        break;
828
0
                    case 0x4c:   /* Last in seg set */
829
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_last_in_seg_set, tvb, offset, 1, ENC_BIG_ENDIAN);
830
0
                        break;
831
0
                    case 0x43:   /* Rx timing deviation */
832
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_rx_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN);
833
0
                        break;
834
0
                    case 0x46:   /* Transport channel type */
835
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_transport_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
836
0
                        break;
837
0
                    case 0xc2:   /* Number of padding bits */
838
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_no_padding_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
839
0
                        break;
840
841
0
                    default:
842
0
                        break;
843
844
845
0
                }
846
0
                offset += length;
847
0
        }
848
0
    }
849
850
    /* Have we got enough info to call dissector */
851
0
    if ((tag == 0x41) && ueid_set && rbid_set) {
852
0
        attach_rlc_info(pinfo, ueid, rbid, is_sent, outhdr_values,
853
0
                        outhdr_values_found);
854
855
        /* Set appropriate RLC dissector handle */
856
0
        switch (rbid) {
857
0
            case 1:  case 2:  case 3:  case 4:  case 5:
858
0
            case 6:  case 7:  case 8:  case 9:  case 10:
859
0
            case 11: case 12: case 13: case 14: case 15:
860
                /* DCH channels. */
861
                /*   TODO: can't really tell if these are control or transport...
862
                     maybe control with preferences (UAT?) between "rlc.ps_dtch" and "rlc.dcch" ? */
863
0
                rlc_umts_handle = find_dissector("rlc.dch_unknown");
864
0
                break;
865
0
            case 18:
866
0
                rlc_umts_handle = find_dissector("rlc.ccch");
867
0
                break;
868
0
            case 21:
869
0
                rlc_umts_handle = find_dissector("rlc.ctch");
870
0
                break;
871
872
0
            default:
873
                /* Give up here */
874
0
                return;
875
0
        }
876
877
        /* Call UMTS RLC dissector */
878
0
        if (rlc_umts_handle != 0) {
879
0
            rlc_tvb = tvb_new_subset_remaining(tvb, offset);
880
0
            call_dissector_only(rlc_umts_handle, rlc_tvb, pinfo, tree, NULL);
881
0
        }
882
0
    }
883
0
}
884
885
static char* get_key(wmem_allocator_t *allocator, tvbuff_t*tvb, int offset)
886
0
{
887
0
    return tvb_bytes_to_str(allocator, tvb, offset, 16);
888
0
}
889
890
891
/* Dissect an RRC LTE or NR frame by first parsing the header entries then passing
892
   the data to the RRC dissector, according to direction and channel type. */
893
static void dissect_rrc_lte_nr(tvbuff_t *tvb, int offset,
894
                               packet_info *pinfo, proto_tree *tree,
895
                               enum LTE_or_NR lte_or_nr)
896
0
{
897
0
    uint8_t             opcode, tag;
898
0
    dissector_handle_t  protocol_handle = 0;
899
0
    bool                isUplink        = false;
900
0
    LogicalChannelType  logicalChannelType;
901
0
    uint16_t            cell_id;
902
0
    uint8_t             bcch_transport  = 0;
903
0
    uint32_t            ueid = 0;
904
0
    tvbuff_t           *rrc_tvb;
905
906
    /* Top-level opcode */
907
0
    opcode = tvb_get_uint8(tvb, offset++);
908
0
    switch (opcode) {
909
0
        case 0x00:    /* Data_Req_UE */
910
0
        case 0x05:    /* Data_Req_UE_SM */
911
0
        case 0x04:    /* Data_Ind_eNodeB */
912
0
            isUplink = true;
913
0
            break;
914
915
0
        case 0x02:    /* Data_Req_eNodeB */
916
0
        case 0x03:    /* Data_Ind_UE */
917
0
        case 0x07:    /* Data_Ind_UE_SM */
918
0
            isUplink = false;
919
0
            break;
920
921
0
        default:
922
            /* Unexpected opcode tag! */
923
0
            return;
924
0
    }
925
926
    /* Skip length */
927
0
    offset += skipASNLength(tvb_get_uint8(tvb, offset));
928
929
    /* Get next tag */
930
0
    tag = tvb_get_uint8(tvb, offset++);
931
0
    switch (tag) {
932
0
        case 0x12:    /* UE_Id_LCId */
933
0
        {
934
            /* Dedicated channel info */
935
936
            /* Skip length */
937
0
            offset++;
938
939
0
            logicalChannelType = Channel_DCCH;
940
941
            /* UEId */
942
0
            proto_tree_add_item_ret_uint(tree, hf_catapult_dct2000_ueid, tvb, offset, 2, ENC_BIG_ENDIAN, &ueid);
943
0
            offset += 2;
944
945
            /* Get tag of channel type */
946
0
            tag = tvb_get_uint8(tvb, offset++);
947
948
0
            switch (tag) {
949
0
                case 0:
950
0
                    offset++;
951
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
952
0
                                    tvb_get_uint8(tvb, offset));
953
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_srbid,
954
0
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
955
0
                    offset++;
956
0
                    break;
957
0
                case 1:
958
0
                    offset++;
959
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
960
0
                                    tvb_get_uint8(tvb, offset));
961
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_drbid,
962
0
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
963
0
                    offset++;
964
0
                    break;
965
966
0
                default:
967
                    /* Unexpected channel type */
968
0
                    return;
969
0
            }
970
971
0
            break;
972
0
        }
973
974
0
        case 0x1a:     /* Cell_LCId */
975
976
            /* Common channel info */
977
978
            /* Skip length */
979
0
            offset++;
980
981
            /* Cell-id */
982
0
            proto_tree_add_item(tree, hf_catapult_dct2000_cellid,
983
0
                                tvb, offset, 2, ENC_BIG_ENDIAN);
984
0
            cell_id = tvb_get_ntohs(tvb, offset);
985
0
            offset += 2;
986
987
            /* Logical channel type */
988
0
            proto_tree_add_item(tree, hf_catapult_dct2000_rlc_channel_type,
989
0
                                tvb, offset, 1, ENC_BIG_ENDIAN);
990
0
            logicalChannelType = (LogicalChannelType)tvb_get_uint8(tvb, offset);
991
0
            offset++;
992
993
            /* Won't be seen if RRC decoder is called... */
994
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " cell-id=%u %s",
995
0
                            cell_id,
996
0
                            val_to_str_const(logicalChannelType, rlc_logical_channel_vals,
997
0
                                             "UNKNOWN-CHANNEL"));
998
999
1000
0
            switch (logicalChannelType) {
1001
0
                case Channel_BCCH:
1002
                    /* Skip length */
1003
0
                    offset++;
1004
1005
                    /* Transport channel type */
1006
0
                    bcch_transport = tvb_get_uint8(tvb, offset);
1007
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_bcch_transport,
1008
0
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
1009
0
                    offset++;
1010
0
                    break;
1011
1012
0
                case Channel_CCCH:
1013
                    /* Skip length */
1014
0
                    offset++;
1015
1016
                    /* UEId */
1017
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_ueid,
1018
0
                                        tvb, offset, 2, ENC_BIG_ENDIAN);
1019
0
                    offset += 2;
1020
0
                    break;
1021
1022
0
                default:
1023
0
                    break;
1024
0
            }
1025
0
            break;
1026
1027
0
        default:
1028
            /* Unexpected tag */
1029
0
            return;
1030
0
    }
1031
1032
    /* Optional Carrier Id */
1033
0
    if (tvb_get_uint8(tvb, offset)==0x1e) {
1034
0
        offset += 2;  /* tag + len of 1 */
1035
0
        proto_tree_add_item(tree, hf_catapult_dct2000_carrier_id,
1036
0
                            tvb, offset, 1, ENC_BIG_ENDIAN);
1037
0
        offset++;
1038
0
    }
1039
1040
    /* Optional Carrier Type */
1041
0
    if (tvb_get_uint8(tvb, offset)==0x20) {
1042
0
        offset += 2;
1043
0
        proto_tree_add_item(tree, hf_catapult_dct2000_carrier_type,
1044
0
                            tvb, offset, 1, ENC_BIG_ENDIAN);
1045
0
        offset++;
1046
0
    }
1047
1048
    /* Optional Cell Group */
1049
0
    if (tvb_get_uint8(tvb, offset)==0x22) {
1050
0
        offset += 2;
1051
0
        proto_tree_add_item(tree, hf_catapult_dct2000_cell_group,
1052
0
                            tvb, offset, 1, ENC_BIG_ENDIAN);
1053
0
        offset++;
1054
0
    }
1055
1056
0
    if (opcode == 0x07) {
1057
        /* Data_Ind_UE_SM - 1 byte MAC */
1058
0
        offset++;
1059
0
    }
1060
0
    else if (opcode == 0x05) {
1061
        /* Data_Req_UE_SM - SecurityMode Params */
1062
        /* N.B. DRB keys do not get configured here.. */
1063
0
        offset++;  /* tag */
1064
0
        uint8_t len = tvb_get_uint8(tvb, offset++); /* length */
1065
1066
        /* Uplink Sec Mode */
1067
0
        proto_item *sc_ti;
1068
0
        proto_tree *sc_tree;
1069
0
        sc_ti = proto_tree_add_item(tree, hf_catapult_dct2000_security_mode_params, tvb, offset, len, ENC_NA);
1070
0
        sc_tree = proto_item_add_subtree(sc_ti, ett_catapult_dct2000_security_mode_params);
1071
1072
0
        uint32_t uplink_sec_mode;
1073
0
        proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_uplink_sec_mode,
1074
0
                                     tvb, offset++, 1, ENC_BIG_ENDIAN, &uplink_sec_mode);
1075
1076
        /* Downlink Sec Mode */
1077
0
        uint32_t downlink_sec_mode;
1078
0
        proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_downlink_sec_mode,
1079
0
                                     tvb, offset++, 1, ENC_BIG_ENDIAN, &downlink_sec_mode);
1080
1081
0
        if (len > 2) {
1082
0
            offset++;  /* tag Should be 0x21 */
1083
0
            offset++; /* len */
1084
1085
0
            tag = tvb_get_uint8(tvb, offset++);
1086
0
            if (tag == 0x25) {
1087
                /* Cell Group Id */
1088
0
                offset++;
1089
0
                proto_tree_add_item(sc_tree, hf_catapult_dct2000_cell_group,
1090
0
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
1091
0
            }
1092
1093
            /* Optional cryptParams */
1094
0
            if (tag == 0x2) {
1095
0
                uint32_t cipher_algorithm;
1096
1097
0
                len = tvb_get_uint8(tvb, offset++);
1098
1099
                /* Cipher algorithm (required) */
1100
0
                offset += 2; /* Skip tag and length */
1101
0
                proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_ciphering_algorithm,
1102
0
                                             tvb, offset++, 1, ENC_BIG_ENDIAN, &cipher_algorithm);
1103
1104
                /* Ciphering key (optional) */
1105
0
                if (len > 3) {
1106
                    /* Skip tag and length */
1107
0
                    offset += 2;
1108
0
                    proto_tree_add_item(sc_tree, hf_catapult_dct2000_ciphering_key,
1109
0
                                        tvb, offset, 16, ENC_NA);
1110
0
                    char *key = get_key(pinfo->pool, tvb, offset);
1111
1112
0
                    if (!PINFO_FD_VISITED(pinfo)) {
1113
0
                        if (lte_or_nr == NR) {
1114
0
                            set_pdcp_nr_rrc_ciphering_key(ueid, key, pinfo->num);
1115
0
                        }
1116
0
                        else {
1117
0
                            set_pdcp_lte_rrc_ciphering_key(ueid, key, pinfo->num);
1118
0
                        }
1119
0
                    }
1120
0
                    offset += 16;
1121
0
                }
1122
0
            }
1123
0
            else {
1124
0
                offset--;
1125
0
            }
1126
1127
            /* Now should be Auth params (required) */
1128
0
            uint32_t integrity_algorithm;
1129
            /* Skip tag */
1130
0
            offset++;
1131
1132
0
            len = tvb_get_uint8(tvb, offset++);
1133
1134
            /* Integrity algorithm (required) */
1135
0
            offset += 2; /* Skip tag and length */
1136
0
            proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_integrity_algorithm,
1137
0
                                         tvb, offset++, 1, ENC_BIG_ENDIAN, &integrity_algorithm);
1138
1139
            /* Integrity key (optional */
1140
0
            if (len > 3) {
1141
                /* Skip tag and length */
1142
0
                offset += 2;
1143
0
                proto_tree_add_item(sc_tree, hf_catapult_dct2000_integrity_key,
1144
0
                                    tvb, offset, 16, ENC_NA);
1145
0
                char *key = get_key(pinfo->pool, tvb, offset);
1146
1147
0
                if (!PINFO_FD_VISITED(pinfo)) {
1148
0
                    if (lte_or_nr == NR) {
1149
0
                        set_pdcp_nr_rrc_integrity_key(ueid, key, pinfo->num);
1150
0
                    }
1151
0
                    else {
1152
0
                        set_pdcp_lte_rrc_integrity_key(ueid, key, pinfo->num);
1153
0
                    }
1154
0
                }
1155
0
                offset += 16;
1156
0
            }
1157
0
        }
1158
0
    }
1159
1160
    /* Optional data tag may follow */
1161
0
    if (!tvb_reported_length_remaining(tvb, offset)) {
1162
0
        return;
1163
0
    }
1164
0
    tag = tvb_get_uint8(tvb, offset++);
1165
0
    if (tag != 0xaa) {
1166
0
        return;
1167
0
    }
1168
1169
    /* Skip length */
1170
0
    offset += skipASNLength(tvb_get_uint8(tvb, offset));
1171
1172
    /* Look up dissector handle corresponding to direction and channel type */
1173
0
    if (isUplink) {
1174
1175
        /* Uplink channel types */
1176
0
        switch (logicalChannelType) {
1177
0
            case Channel_DCCH:
1178
0
                if (lte_or_nr == LTE) {
1179
0
                    protocol_handle = find_dissector("lte_rrc.ul_dcch");
1180
0
                }
1181
0
                else {
1182
0
                    protocol_handle = find_dissector("nr-rrc.ul.dcch");
1183
0
                }
1184
0
                break;
1185
0
            case Channel_CCCH:
1186
0
                if (lte_or_nr == LTE) {
1187
0
                    protocol_handle = find_dissector("lte_rrc.ul_ccch");
1188
0
                }
1189
0
                else {
1190
0
                    if (tvb_captured_length_remaining(tvb, offset) == 6) {
1191
0
                        protocol_handle = find_dissector("nr-rrc.ul.ccch");
1192
0
                    }
1193
0
                    else {
1194
                        /* Should be 8 bytes.. */
1195
0
                        protocol_handle = find_dissector("nr-rrc.ul.ccch1");
1196
0
                    }
1197
0
                }
1198
0
                break;
1199
1200
0
            default:
1201
                /* Unknown Uplink channel type */
1202
0
                break;
1203
0
        }
1204
0
    } else {
1205
1206
        /* Downlink channel types */
1207
0
        switch (logicalChannelType) {
1208
0
            case Channel_DCCH:
1209
0
                if (lte_or_nr == LTE) {
1210
0
                    protocol_handle = find_dissector("lte_rrc.dl_dcch");
1211
0
                }
1212
0
                else {
1213
0
                    protocol_handle = find_dissector("nr-rrc.dl.dcch");
1214
0
                }
1215
0
                break;
1216
0
            case Channel_CCCH:
1217
0
                if (lte_or_nr == LTE) {
1218
0
                    protocol_handle = find_dissector("lte_rrc.dl_ccch");
1219
0
                }
1220
0
                else {
1221
0
                    protocol_handle = find_dissector("nr-rrc.dl.ccch");
1222
0
                }
1223
0
                break;
1224
0
            case Channel_PCCH:
1225
0
                if (lte_or_nr == LTE) {
1226
0
                    protocol_handle = find_dissector("lte_rrc.pcch");
1227
0
                }
1228
0
                else {
1229
0
                    protocol_handle = find_dissector("nr-rrc.pcch");
1230
0
                }
1231
0
                break;
1232
0
            case Channel_BCCH:
1233
0
                if (bcch_transport == 1) {
1234
0
                    if (lte_or_nr == LTE) {
1235
0
                        protocol_handle = find_dissector("lte_rrc.bcch_bch");
1236
0
                    }
1237
0
                    else {
1238
0
                        protocol_handle = find_dissector("nr-rrc.bcch.bch");
1239
0
                    }
1240
0
                }
1241
0
                else {
1242
0
                    if (lte_or_nr == LTE) {
1243
0
                        protocol_handle = find_dissector("lte_rrc.bcch_dl_sch");
1244
0
                    }
1245
0
                    else {
1246
0
                        protocol_handle = find_dissector("nr-rrc.bcch.dl.sch");
1247
0
                    }
1248
0
                }
1249
0
                break;
1250
1251
0
            default:
1252
                /* Unknown Downlink channel type */
1253
0
                break;
1254
0
        }
1255
0
    }
1256
1257
    /* Send to RRC dissector, if got here, have sub-dissector and some data left */
1258
0
    if ((protocol_handle != NULL) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
1259
1260
        /* Set MAC-NR info for this PDU.  Needed so that UEId can be found for this frame,
1261
         * as used by MAC/RLC/PDCP configuration from RRC dissector */
1262
0
        if (ueid) {
1263
0
            struct mac_nr_info *p_mac_nr_info;
1264
0
            p_mac_nr_info = wmem_new0(wmem_file_scope(), struct mac_nr_info);
1265
0
            p_mac_nr_info->ueid = ueid;
1266
0
            p_mac_nr_info->direction = (isUplink) ? DIRECTION_UPLINK : DIRECTION_DOWNLINK;
1267
            /* Store info in packet */
1268
0
            set_mac_nr_proto_data(pinfo, p_mac_nr_info);
1269
0
        }
1270
1271
0
        rrc_tvb = tvb_new_subset_remaining(tvb, offset);
1272
0
        call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
1273
0
    }
1274
0
}
1275
1276
1277
/* Dissect an CCPRI LTE frame by first parsing the header entries then passing
1278
   the data to the CPRI C&M dissector
1279
1280
   XXX - is this the Common Public Radio Interface?  If so, what's the extra
1281
   "C" in "CCPRI"?  And why is the LAPB dissector involved here?  The CPRI
1282
   spec just speaks of HDLC; LAPB is certainly a HDLC-based protocol, but
1283
   that doesn't mean every HDLC-based protocol is LAPB. */
1284
static void dissect_ccpri_lte(tvbuff_t *tvb, int offset,
1285
                              packet_info *pinfo, proto_tree *tree)
1286
0
{
1287
0
    uint8_t             opcode;
1288
0
    uint8_t             tag;
1289
0
    tvbuff_t           *ccpri_tvb;
1290
0
    dissector_handle_t  protocol_handle = 0;
1291
0
    uint16_t            length;
1292
1293
    /* Top-level opcode */
1294
0
    proto_tree_add_item_ret_uint8(tree, hf_catapult_dct2000_lte_ccpri_opcode, tvb, offset, 1, ENC_BIG_ENDIAN, &opcode);
1295
0
    offset++;
1296
1297
    /* Skip 2-byte length field */
1298
0
    offset += 2;
1299
1300
    /* Cell-id */
1301
0
    proto_tree_add_item(tree, hf_catapult_dct2000_cellid,
1302
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
1303
0
    offset += 2;
1304
1305
    /* Status (ind only) */
1306
0
    if (opcode == 2) {
1307
0
        proto_item *ti;
1308
0
        uint8_t status = tvb_get_uint8(tvb, offset);
1309
0
        ti = proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_status,
1310
0
                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1311
0
        offset++;
1312
1313
0
        if (status != 0) {
1314
0
            expert_add_info(pinfo, ti, &ei_catapult_dct2000_lte_ccpri_status_error);
1315
1316
0
        }
1317
0
    }
1318
1319
    /* Channel ID */
1320
0
    proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_channel,
1321
0
                        tvb, offset, 1, ENC_BIG_ENDIAN);
1322
0
    offset++;
1323
1324
    /* Data tag must follow */
1325
0
    tag = tvb_get_uint8(tvb, offset++);
1326
0
    if (tag != 2) {
1327
0
        return;
1328
0
    }
1329
1330
    /* Skip length */
1331
0
    length = tvb_get_ntohs(tvb, offset);
1332
0
    offset += 2;
1333
1334
    /* Send remainder to lapb dissector; I assume "CPRI" is the Common
1335
       Public Radio Interface, in which case the "lapb" dissector is
1336
       being used to dissect the HDLC used by CPRI, and in which case
1337
       we should really have a CPRI dissector that dissects its HDLC
1338
       and then hands off to a CPRI C&M dissector. */
1339
0
    protocol_handle = find_dissector("lapb");
1340
0
    if ((protocol_handle != NULL) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
1341
0
        ccpri_tvb = tvb_new_subset_length(tvb, offset, length);
1342
0
        call_dissector_only(protocol_handle, ccpri_tvb, pinfo, tree, NULL);
1343
0
    }
1344
0
}
1345
1346
1347
1348
1349
/* Dissect a PDCP LTE frame by first parsing the RLCPrim header then passing
1350
   the data to the PDCP LTE dissector */
1351
static void dissect_pdcp_lte(tvbuff_t *tvb, int offset,
1352
                             packet_info *pinfo, proto_tree *tree)
1353
0
{
1354
0
    uint8_t               opcode;
1355
0
    uint8_t               tag;
1356
0
    struct pdcp_lte_info *p_pdcp_lte_info;
1357
0
    tvbuff_t             *pdcp_lte_tvb;
1358
0
    uint16_t              ueid;
1359
0
    uint8_t               channelId;
1360
1361
    /* Look this up so can update channel info */
1362
0
    p_pdcp_lte_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1363
0
    if (p_pdcp_lte_info == NULL) {
1364
        /* This really should be set...can't dissect anything without it */
1365
0
        return;
1366
0
    }
1367
1368
    /* Top-level opcode */
1369
0
    opcode = tvb_get_uint8(tvb, offset);
1370
0
    if (tree) {
1371
0
        proto_tree_add_item(tree, hf_catapult_dct2000_rlc_op, tvb, offset, 1, ENC_BIG_ENDIAN);
1372
0
    }
1373
0
    offset++;
1374
1375
0
    col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, rlc_op_vals, "Unknown"));
1376
1377
    /* Assume UE side, so REQ is UL, IND is DL */
1378
0
    switch (opcode) {
1379
0
       case RLC_AM_DATA_REQ:
1380
0
       case RLC_UM_DATA_REQ:
1381
0
       case RLC_TR_DATA_REQ:
1382
0
           p_pdcp_lte_info->direction = DIRECTION_UPLINK;
1383
0
           break;
1384
1385
0
       default:
1386
0
           p_pdcp_lte_info->direction = DIRECTION_DOWNLINK;
1387
0
    }
1388
1389
    /* Parse header */
1390
0
    switch (opcode) {
1391
0
        case RLC_AM_DATA_REQ:
1392
0
        case RLC_AM_DATA_IND:
1393
0
        case RLC_UM_DATA_REQ:
1394
0
        case RLC_UM_DATA_IND:
1395
0
        case RLC_TR_DATA_REQ:
1396
0
        case RLC_TR_DATA_IND:
1397
1398
            /* Get next tag */
1399
0
            tag = tvb_get_uint8(tvb, offset++);
1400
0
            switch (tag) {
1401
0
                case 0x10:    /* UE_Id_LCId */
1402
1403
                    /* Dedicated channel info */
1404
1405
                    /* Length will fit in one byte here */
1406
0
                    offset++;
1407
1408
0
                    p_pdcp_lte_info->channelType = Channel_DCCH;
1409
1410
                    /* UEId */
1411
0
                    proto_tree_add_item_ret_uint16(tree, hf_catapult_dct2000_ueid, tvb, offset, 2, ENC_BIG_ENDIAN, &ueid);
1412
0
                    col_append_fstr(pinfo->cinfo, COL_INFO,
1413
0
                                    " UEId=%u", ueid);
1414
0
                    p_pdcp_lte_info->ueid = ueid;
1415
0
                    offset += 2;
1416
1417
                    /* Get tag of channel type */
1418
0
                    tag = tvb_get_uint8(tvb, offset++);
1419
1420
0
                    switch (tag) {
1421
0
                        case 0:
1422
0
                            offset++;
1423
0
                            channelId = tvb_get_uint8(tvb, offset);
1424
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
1425
0
                                            channelId);
1426
0
                            proto_tree_add_item(tree, hf_catapult_dct2000_srbid,
1427
0
                                                tvb, offset++, 1, ENC_BIG_ENDIAN);
1428
0
                            p_pdcp_lte_info->channelId = channelId;
1429
0
                            break;
1430
0
                        case 1:
1431
0
                            offset++;
1432
0
                            channelId = tvb_get_uint8(tvb, offset);
1433
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
1434
0
                                            channelId);
1435
0
                            proto_tree_add_item(tree, hf_catapult_dct2000_drbid,
1436
0
                                                tvb, offset++, 1, ENC_BIG_ENDIAN);
1437
0
                            p_pdcp_lte_info->channelId = channelId;
1438
0
                            break;
1439
1440
0
                        default:
1441
                            /* Unexpected channel type */
1442
0
                            return;
1443
0
                    }
1444
0
                    break;
1445
1446
0
                case 0x1a:     /* Cell_LCId */
1447
1448
                    /* Common channel info */
1449
1450
                    /* Skip length */
1451
0
                    offset++;
1452
1453
                    /* Cell-id */
1454
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_cellid,
1455
0
                                        tvb, offset, 2, ENC_BIG_ENDIAN);
1456
0
                    offset += 2;
1457
1458
                    /* Logical channel type */
1459
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_rlc_channel_type,
1460
0
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
1461
0
                    p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_uint8(tvb, offset++);
1462
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1463
0
                                    val_to_str_const(p_pdcp_lte_info->channelType, rlc_logical_channel_vals,
1464
0
                                                     "UNKNOWN-CHANNEL"));
1465
1466
0
                    switch (p_pdcp_lte_info->channelType) {
1467
0
                        case Channel_BCCH:
1468
                            /* Skip length */
1469
0
                            offset++;
1470
1471
                            /* Transport channel type */
1472
0
                            p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_uint8(tvb, offset);
1473
0
                            proto_tree_add_item(tree, hf_catapult_dct2000_bcch_transport,
1474
0
                                                tvb, offset, 1, ENC_BIG_ENDIAN);
1475
0
                            offset++;
1476
0
                            break;
1477
1478
0
                        case Channel_CCCH:
1479
                            /* Skip length */
1480
0
                            offset++;
1481
1482
                            /* UEId */
1483
0
                            proto_tree_add_item_ret_uint16(tree, hf_catapult_dct2000_ueid,
1484
0
                                                           tvb, offset, 2, ENC_BIG_ENDIAN, &ueid);
1485
0
                            offset += 2;
1486
1487
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " UEId=%u", ueid);
1488
0
                            break;
1489
1490
0
                        default:
1491
0
                            break;
1492
0
                    }
1493
0
                    break;
1494
1495
0
                default:
1496
                    /* Unexpected tag */
1497
0
                    return;
1498
0
            }
1499
1500
            /* Other optional fields may follow */
1501
0
            tag = tvb_get_uint8(tvb, offset++);
1502
0
            while ((tag != 0x41) && (tvb_reported_length_remaining(tvb, offset) > 2)) {
1503
1504
0
                if (tag == 0x35) {
1505
                    /* This is MUI */
1506
0
                    offset++;
1507
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_rlc_mui,
1508
0
                                        tvb, offset, 2, ENC_BIG_ENDIAN);
1509
0
                    offset += 2;
1510
1511
                    /* CNF follows MUI in AM */
1512
0
                    if ((opcode == RLC_AM_DATA_REQ) || (opcode == RLC_AM_DATA_IND)) {
1513
0
                        proto_tree_add_item(tree, hf_catapult_dct2000_rlc_cnf,
1514
0
                                               tvb, offset, 1, ENC_NA);
1515
0
                        offset++;
1516
0
                    }
1517
0
                }
1518
0
                else if (tag == 0x45) {
1519
                    /* Discard Req */
1520
0
                    offset++;
1521
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_rlc_discard_req,
1522
0
                                           tvb, offset, 1, ENC_NA);
1523
0
                    offset++;
1524
0
                }
1525
1526
0
                tag = tvb_get_uint8(tvb, offset++);
1527
0
            }
1528
1529
1530
            /********************************/
1531
            /* Should be at data tag now    */
1532
1533
            /* Call PDCP LTE dissector */
1534
0
            pdcp_lte_tvb = tvb_new_subset_remaining(tvb, offset);
1535
0
            call_dissector_only(pdcp_lte_handle, pdcp_lte_tvb, pinfo, tree, NULL);
1536
1537
0
            break;
1538
1539
0
        default:
1540
0
            return;
1541
0
    }
1542
0
}
1543
1544
1545
1546
1547
1548
/* Look up dissector by protocol name.  Fix up known name mis-matches.
1549
   This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */
1550
static dissector_handle_t look_for_dissector(const char *protocol_name)
1551
0
{
1552
0
    if (strncmp(protocol_name, "diameter", strlen("diameter")) == 0) {
1553
0
        return find_dissector("diameter");
1554
0
    }
1555
0
    else
1556
0
    if (strncmp(protocol_name, "gtpv2_r", 7) == 0) {
1557
0
        return find_dissector("gtpv2");
1558
0
    }
1559
0
    else
1560
0
    if (strncmp(protocol_name, "s1ap", 4) == 0) {
1561
0
        return find_dissector("s1ap");
1562
0
    }
1563
0
    else
1564
0
    if (strncmp(protocol_name, "x2ap_r", 6) == 0) {
1565
0
        return find_dissector("x2ap");
1566
0
    }
1567
0
    else
1568
0
    if (strncmp(protocol_name, "xnap_r1", 7) == 0) {
1569
0
        return find_dissector("xnap");
1570
0
    }
1571
0
    else
1572
0
    if (strncmp(protocol_name, "ngap_r1", 7) == 0) {
1573
0
        return find_dissector("ngap");
1574
0
    }
1575
1576
    /* Only check really old names to convert if preference is checked */
1577
0
    else if (catapult_dct2000_dissect_old_protocol_names) {
1578
        /* Use known aliases and protocol name prefixes */
1579
0
        if (strcmp(protocol_name, "tbcp") == 0) {
1580
0
            return find_dissector("rtcp");
1581
0
        }
1582
0
        else
1583
0
        if ((strcmp(protocol_name, "xcap_caps") == 0) ||
1584
0
            (strcmp(protocol_name, "soap") == 0) ||
1585
0
            (strcmp(protocol_name, "mm1") == 0) ||
1586
0
            (strcmp(protocol_name, "mm3") == 0) ||
1587
0
            (strcmp(protocol_name, "mm7") == 0)) {
1588
1589
0
             return find_dissector("http");
1590
0
        }
1591
0
        else
1592
0
        if ((strncmp(protocol_name, "fp_r", 4) == 0) ||
1593
0
            (strcmp(protocol_name, "fpiur_r5") == 0)) {
1594
1595
0
            return find_dissector("fp");
1596
0
        }
1597
0
        else
1598
0
        if (strncmp(protocol_name, "iuup_rtp_r", strlen("iuup_rtp_r")) == 0) {
1599
0
            return find_dissector("rtp");
1600
0
        }
1601
0
        else
1602
0
        if (strcmp(protocol_name, "sipt") == 0) {
1603
0
            return find_dissector("sip");
1604
0
        }
1605
0
        else
1606
0
        if (strncmp(protocol_name, "nbap_sctp", strlen("nbap_sctp")) == 0) {
1607
0
            return find_dissector("nbap");
1608
0
        }
1609
0
        else
1610
0
        if (strcmp(protocol_name, "dhcpv4") == 0) {
1611
0
            return find_dissector("dhcp");
1612
0
        }
1613
0
        else
1614
0
        if (strcmp(protocol_name, "wimax") == 0) {
1615
0
            return find_dissector("wimaxasncp");
1616
0
        }
1617
0
        else
1618
0
        if (strncmp(protocol_name, "sabp", strlen("sabp")) == 0) {
1619
0
            return find_dissector("sabp");
1620
0
        }
1621
0
        else
1622
0
        if (strcmp(protocol_name, "wtp") == 0) {
1623
0
            return find_dissector("wtp-udp");
1624
0
        }
1625
0
        else
1626
0
        if (strncmp(protocol_name, "gtp", strlen("gtp")) == 0) {
1627
0
            return find_dissector("gtp");
1628
0
        }
1629
0
    }
1630
1631
    /* Try for an exact match */
1632
0
    return find_dissector(protocol_name);
1633
0
}
1634
1635
1636
/* Populate outhdr_values array with numbers found in outhdr_string */
1637
static unsigned parse_outhdr_string(const char *outhdr_string, int outhdr_string_len, unsigned *outhdr_values)
1638
0
{
1639
0
    int   n                 = 0;
1640
0
    int   outhdr_values_found;
1641
1642
    /* Populate values array */
1643
0
    for (outhdr_values_found=0; outhdr_values_found < MAX_OUTHDR_VALUES; ) {
1644
1645
0
        unsigned  digit_array[MAX_OUTHDR_VALUES];
1646
0
        unsigned  number_digits = 0;
1647
1648
0
        unsigned   number = 0;
1649
0
        unsigned   multiplier = 1;
1650
0
        unsigned   d;
1651
1652
        /* Find digits */
1653
0
        for ( ; (n < outhdr_string_len) && (number_digits < MAX_OUTHDR_VALUES); n++) {
1654
0
            if (!g_ascii_isdigit(outhdr_string[n])) {
1655
0
                break;
1656
0
            }
1657
0
            else {
1658
0
                digit_array[number_digits++] = outhdr_string[n] - '0';
1659
0
            }
1660
0
        }
1661
1662
0
        if (number_digits == 0) {
1663
            /* No more numbers left */
1664
0
            break;
1665
0
        }
1666
1667
        /* Convert digits into value (much faster than format_text() + atoi()) */
1668
0
        for (d=number_digits; d > 0; d--) {
1669
0
            number += ((digit_array[d-1]) * multiplier);
1670
0
            multiplier *= 10;
1671
0
        }
1672
0
        outhdr_values[outhdr_values_found++] = number;
1673
1674
        /* Skip comma */
1675
0
        n++;
1676
0
    }
1677
0
    return outhdr_values_found;
1678
0
}
1679
1680
1681
1682
/* Fill in an FP packet info struct and attach it to the packet for the FP
1683
   dissector to use */
1684
static void attach_fp_info(packet_info *pinfo, bool received,
1685
                           const char *protocol_name, int variant,
1686
                           unsigned *outhdr_values, unsigned outhdr_values_found)
1687
0
{
1688
0
    unsigned i = 0;
1689
0
    int   chan;
1690
0
    unsigned tf_start, num_chans_start;
1691
0
    int   node_type;
1692
0
    int   calculated_variant;
1693
1694
    /* Only need to set info once per session. */
1695
0
    struct fp_info *p_fp_info = (struct fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1696
0
    if (p_fp_info != NULL) {
1697
0
        return;
1698
0
    }
1699
1700
    /* Allocate struct */
1701
0
    p_fp_info = wmem_new0(wmem_file_scope(), struct fp_info);
1702
1703
    /* Check that the number of outhdr values looks sensible */
1704
0
    if (((strcmp(protocol_name, "fpiur_r5") == 0) && (outhdr_values_found != 2)) ||
1705
0
        (outhdr_values_found < 5)) {
1706
1707
0
        return;
1708
0
    }
1709
1710
    /* 3gpp release (99, 4, 5, 6, 7) */
1711
0
    if (strcmp(protocol_name, "fp") == 0) {
1712
0
        p_fp_info->release = 99;
1713
0
    }
1714
0
    else if (strcmp(protocol_name, "fp_r4") == 0) {
1715
0
        p_fp_info->release = 4;
1716
0
    }
1717
0
    else if (strcmp(protocol_name, "fp_r5") == 0) {
1718
0
        p_fp_info->release = 5;
1719
0
    }
1720
0
    else if (strcmp(protocol_name, "fp_r6") == 0) {
1721
0
        p_fp_info->release = 6;
1722
0
    }
1723
0
    else if (strcmp(protocol_name, "fp_r7") == 0) {
1724
0
        p_fp_info->release = 7;
1725
0
    }
1726
0
    else if (strcmp(protocol_name, "fp_r8") == 0) {
1727
0
        p_fp_info->release = 8;
1728
0
    }
1729
0
    else if (strcmp(protocol_name, "fpiur_r5") == 0) {
1730
0
        p_fp_info->release = 5;
1731
0
    }
1732
0
    else {
1733
        /* Really shouldn't get here */
1734
0
        DISSECTOR_ASSERT_NOT_REACHED();
1735
0
        return;
1736
0
    }
1737
1738
    /* Release date is derived from variant number */
1739
    /* Only R6 sub-versions currently influence format within a release */
1740
0
    switch (p_fp_info->release) {
1741
0
        case 6:
1742
0
            if (variant < 256) {
1743
0
                calculated_variant = variant;
1744
0
            }
1745
0
            else {
1746
0
                calculated_variant = variant / 256;
1747
0
            }
1748
1749
0
            switch (calculated_variant) {
1750
0
                case 1:
1751
0
                    p_fp_info->release_year = 2005;
1752
0
                    p_fp_info->release_month = 6;
1753
0
                    break;
1754
0
                case 2:
1755
0
                    p_fp_info->release_year = 2005;
1756
0
                    p_fp_info->release_month = 9;
1757
0
                    break;
1758
0
                case 3:
1759
0
                default:
1760
0
                    p_fp_info->release_year = 2006;
1761
0
                    p_fp_info->release_month = 3;
1762
0
                    break;
1763
0
            }
1764
0
            break;
1765
0
        case 7:
1766
0
            p_fp_info->release_year = 2008;
1767
0
            p_fp_info->release_month = 3;
1768
0
            break;
1769
1770
0
        case 8:
1771
0
            p_fp_info->release_year = 2010;
1772
0
            p_fp_info->release_month = 6;
1773
0
            break;
1774
1775
1776
0
        default:
1777
0
            p_fp_info->release_year = 0;
1778
0
            p_fp_info->release_month = 0;
1779
0
    }
1780
1781
1782
    /* Channel type */
1783
0
    p_fp_info->channel = outhdr_values[i++];
1784
    /* Sad hack until this value is filled in properly */
1785
0
    if (p_fp_info->channel == 0) {
1786
0
        p_fp_info->channel = CHANNEL_DCH;
1787
0
    }
1788
1789
    /* Derive direction from node type/side */
1790
0
    node_type = outhdr_values[i++];
1791
0
    p_fp_info->is_uplink = (( received  && (node_type == 2)) ||
1792
0
                            (!received  && (node_type == 1)));
1793
1794
    /* Division type introduced for R7 */
1795
0
    if ((p_fp_info->release == 7) ||
1796
0
        (p_fp_info->release == 8)) {
1797
0
        p_fp_info->division = (enum division_type)outhdr_values[i++];
1798
0
    }
1799
1800
    /* HS-DSCH config */
1801
0
    if (p_fp_info->channel == CHANNEL_HSDSCH) {
1802
0
        if ((p_fp_info->release == 7) ||
1803
0
            (p_fp_info->release == 8)) {
1804
            /* Entity (MAC-hs or MAC-ehs) used */
1805
0
            if (outhdr_values[i++]) {
1806
0
                p_fp_info->hsdsch_entity = ehs;
1807
0
            }
1808
0
        }
1809
0
        else {
1810
            /* This is the pre-R7 default */
1811
0
            p_fp_info->hsdsch_entity = hs;
1812
0
        }
1813
0
    }
1814
1815
1816
    /* IUR only uses the above... */
1817
0
    if (strcmp(protocol_name, "fpiur_r5") == 0) {
1818
        /* Store info in packet */
1819
0
        p_fp_info->iface_type = IuR_Interface;
1820
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1821
0
        return;
1822
0
    }
1823
1824
    /* DCH CRC present... */
1825
0
    p_fp_info->dch_crc_present = outhdr_values[i++];
1826
1827
    /* ... but don't trust for edch */
1828
0
    if (p_fp_info->channel == CHANNEL_EDCH) {
1829
0
        p_fp_info->dch_crc_present = 2; /* unknown */
1830
0
    }
1831
1832
    /* How many paging indications (if PCH data) */
1833
0
    p_fp_info->paging_indications = outhdr_values[i++];
1834
1835
    /* Number of channels (for coordinated channels) */
1836
0
    p_fp_info->num_chans = outhdr_values[i++];
1837
0
    if (p_fp_info->num_chans > MAX_FP_CHANS) {
1838
0
        p_fp_info->num_chans = MAX_FP_CHANS;
1839
0
    }
1840
1841
    /* EDCH-Common is always T2 */
1842
0
    if (p_fp_info->channel == CHANNEL_EDCH_COMMON) {
1843
0
        p_fp_info->edch_type = 1;
1844
0
    }
1845
1846
0
    if (p_fp_info->channel != CHANNEL_EDCH) {
1847
        /* TF size for each channel */
1848
0
        tf_start = i;
1849
0
        for (chan=0; chan < p_fp_info->num_chans; chan++) {
1850
0
            if (outhdr_values_found > tf_start+chan) {
1851
0
                p_fp_info->chan_tf_size[chan] = outhdr_values[tf_start+chan];
1852
0
            } else {
1853
0
                p_fp_info->chan_tf_size[chan] = 0;
1854
0
            }
1855
0
        }
1856
1857
        /* Number of TBs for each channel */
1858
0
        num_chans_start = tf_start + p_fp_info->num_chans;
1859
0
        for (chan=0; chan < p_fp_info->num_chans; chan++) {
1860
0
            if (outhdr_values_found > num_chans_start+chan) {
1861
0
                p_fp_info->chan_num_tbs[chan] = outhdr_values[num_chans_start+chan];
1862
0
            } else {
1863
0
                p_fp_info->chan_num_tbs[chan] = 0;
1864
0
            }
1865
0
        }
1866
0
    }
1867
    /* EDCH info */
1868
0
    else {
1869
0
        int n;
1870
1871
0
        p_fp_info->no_ddi_entries = outhdr_values[i++];
1872
0
        if (p_fp_info->no_ddi_entries > MAX_EDCH_DDIS) {
1873
0
            p_fp_info->no_ddi_entries = MAX_EDCH_DDIS;
1874
0
        }
1875
1876
        /* DDI values */
1877
0
        for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1878
0
            if (outhdr_values_found > i) {
1879
0
                p_fp_info->edch_ddi[n] = outhdr_values[i++];
1880
0
            } else {
1881
0
                p_fp_info->edch_ddi[n] = 0;
1882
0
            }
1883
0
        }
1884
1885
        /* Corresponding MAC-d sizes */
1886
0
        for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1887
0
            if (outhdr_values_found > i) {
1888
0
                p_fp_info->edch_macd_pdu_size[n] = outhdr_values[i++];
1889
0
            } else {
1890
0
                p_fp_info->edch_macd_pdu_size[n] = 0;
1891
0
            }
1892
0
        }
1893
1894
0
        if (strcmp(protocol_name, "fp_r8") == 0) {
1895
0
            if (outhdr_values_found > i) {
1896
0
                p_fp_info->edch_type = outhdr_values[i];
1897
0
            } else {
1898
0
                p_fp_info->edch_type = 0;
1899
0
            }
1900
0
        }
1901
0
        else {
1902
0
            p_fp_info->edch_type = 0;
1903
0
        }
1904
0
    }
1905
1906
    /* Interface must be IuB */
1907
0
    p_fp_info->iface_type = IuB_Interface;
1908
1909
    /* Store info in packet */
1910
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1911
0
}
1912
1913
1914
/* Fill in an RLC packet info struct and attach it to the packet for the RLC
1915
   dissector to use */
1916
static void attach_rlc_info(packet_info *pinfo, uint32_t urnti, uint8_t rbid,
1917
                            bool is_sent, unsigned *outhdr_values,
1918
                            unsigned outhdr_values_found)
1919
0
{
1920
    /* Only need to set info once per session. */
1921
0
    struct fp_info  *p_fp_info;
1922
0
    struct rlc_info *p_rlc_info = (struct rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1923
1924
0
    if (p_rlc_info != NULL) {
1925
0
        return;
1926
0
    }
1927
1928
    /* Check that the number of outhdr values looks correct */
1929
0
    if (outhdr_values_found != 2) {
1930
0
        return;
1931
0
    }
1932
1933
    /* Allocate structs */
1934
0
    p_rlc_info = wmem_new(wmem_file_scope(), struct rlc_info);
1935
0
    p_fp_info = wmem_new0(wmem_file_scope(), struct fp_info);
1936
1937
    /* Fill in struct fields for first (only) PDU in this frame */
1938
1939
    /* Urnti.  Just use UEId */
1940
0
    p_rlc_info->ueid[0] = urnti;
1941
1942
    /* ciphered (off by default) */
1943
0
    p_rlc_info->ciphered[0] = false;
1944
1945
    /* deciphered (off by default) */
1946
0
    p_rlc_info->deciphered[0] = false;
1947
1948
    /* Mode. */
1949
0
    switch (outhdr_values[1]) {
1950
0
        case 1:
1951
0
            p_rlc_info->mode[0] = RLC_TM;
1952
0
            break;
1953
0
        case 2:
1954
0
            p_rlc_info->mode[0] = RLC_UM;
1955
0
            break;
1956
0
        case 3:
1957
0
            p_rlc_info->mode[0] = RLC_AM;
1958
0
            break;
1959
0
        case 4:
1960
0
            p_rlc_info->mode[0] = RLC_UM;
1961
0
            p_rlc_info->ciphered[0] = true;
1962
0
            break;
1963
0
        case 5:
1964
0
            p_rlc_info->mode[0] = RLC_AM;
1965
0
            p_rlc_info->ciphered[0] = true;
1966
0
            break;
1967
0
        default:
1968
0
            return;
1969
0
    }
1970
1971
    /* rbid. TODO: does this need conversion? */
1972
0
    p_rlc_info->rbid[0] = rbid;
1973
1974
    /* li_size */
1975
0
    p_rlc_info->li_size[0] = (enum rlc_li_size)outhdr_values[0];
1976
1977
    /* Store info in packet */
1978
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, p_rlc_info);
1979
1980
    /* Also store minimal FP info consulted by RLC dissector
1981
       TODO: Don't really know direction, but use S/R flag to make
1982
       logs in same context consistent. Will be correct for NodeB logs,
1983
       but RLC dissector seems to not use anyway... */
1984
0
    p_fp_info->is_uplink = is_sent;
1985
0
    p_fp_info->cur_tb = 0; /* Always the first/only one */
1986
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1987
0
}
1988
1989
1990
/* Fill in a MAC LTE packet info struct and attach it to the packet for that
1991
   dissector to use */
1992
static void attach_mac_lte_info(packet_info *pinfo, unsigned *outhdr_values, unsigned outhdr_values_found)
1993
0
{
1994
0
    struct mac_lte_info *p_mac_lte_info;
1995
0
    unsigned int         i = 0;
1996
1997
    /* Only need to set info once per session. */
1998
0
    p_mac_lte_info = get_mac_lte_proto_data(pinfo);
1999
0
    if (p_mac_lte_info != NULL) {
2000
0
        return;
2001
0
    }
2002
2003
    /* Allocate & zero struct */
2004
0
    p_mac_lte_info = wmem_new0(wmem_file_scope(), struct mac_lte_info);
2005
2006
    /* Populate the struct from outhdr values */
2007
0
    p_mac_lte_info->crcStatusValid = false;  /* not set yet */
2008
2009
0
    p_mac_lte_info->radioType = outhdr_values[i++] + 1;        // 1
2010
0
    p_mac_lte_info->rntiType = outhdr_values[i++];             // 2
2011
0
    p_mac_lte_info->direction = outhdr_values[i++];            // 3
2012
    /* Set these extra PHY present flags to false by default */
2013
0
    if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2014
0
        p_mac_lte_info->detailed_phy_info.ul_info.present = false;
2015
0
    }
2016
0
    else {
2017
0
        p_mac_lte_info->detailed_phy_info.dl_info.present = false;
2018
0
    }
2019
2020
0
    p_mac_lte_info->sfnSfInfoPresent = true;
2021
0
    p_mac_lte_info->subframeNumber = outhdr_values[i++];       // 4
2022
0
    p_mac_lte_info->isPredefinedData = outhdr_values[i++];     // 5
2023
0
    p_mac_lte_info->rnti = outhdr_values[i++];                 // 6
2024
0
    p_mac_lte_info->ueid = outhdr_values[i++];                 // 7
2025
0
    p_mac_lte_info->length = outhdr_values[i++];               // 8
2026
0
    if (outhdr_values_found > 8) {
2027
0
        p_mac_lte_info->reTxCount = outhdr_values[i++];        // 9
2028
0
    }
2029
    /* TODO: delete if won't see this special case anymore? */
2030
0
    if (outhdr_values_found == 10) {
2031
        /* CRC only valid for Downlink */
2032
0
        if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
2033
0
            p_mac_lte_info->crcStatusValid = true;
2034
0
            p_mac_lte_info->crcStatus = (mac_lte_crc_status)outhdr_values[i++]; // 10
2035
0
        }
2036
0
        else {
2037
0
            i++;     // 10 (ignoring for UL)
2038
0
        }
2039
0
    }
2040
2041
0
    p_mac_lte_info->dl_retx = dl_retx_unknown;
2042
2043
0
    if (outhdr_values_found > 10) {
2044
        /* Extra PHY parameters */
2045
0
        if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
2046
0
            p_mac_lte_info->detailed_phy_info.dl_info.present = outhdr_values[i++];         // 10
2047
0
            p_mac_lte_info->detailed_phy_info.dl_info.dci_format = outhdr_values[i++];      // 11
2048
0
            p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type = outhdr_values[i++]; // 12
2049
0
            p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level = outhdr_values[i++];  // 13
2050
0
            p_mac_lte_info->detailed_phy_info.dl_info.mcs_index = outhdr_values[i++];          // 14
2051
0
            p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index = outhdr_values[i++]; // 15
2052
0
            p_mac_lte_info->dl_retx = (outhdr_values[i++]) ? dl_retx_yes : dl_retx_no;  // 16
2053
2054
0
            p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length = outhdr_values[i++]; // 17
2055
0
            p_mac_lte_info->crcStatusValid = true;                                                // 18
2056
0
            p_mac_lte_info->crcStatus = (mac_lte_crc_status)outhdr_values[i++];
2057
0
            if (outhdr_values_found > 18) {
2058
0
                p_mac_lte_info->detailed_phy_info.dl_info.harq_id = outhdr_values[i++];    // 19
2059
0
                p_mac_lte_info->detailed_phy_info.dl_info.ndi = outhdr_values[i++];        // 20
2060
0
            }
2061
0
            if (outhdr_values_found > 20) {
2062
0
                p_mac_lte_info->detailed_phy_info.dl_info.transport_block = outhdr_values[i++];  // 21
2063
0
            }
2064
0
        }
2065
0
        else {
2066
            /* Uplink */
2067
0
            p_mac_lte_info->detailed_phy_info.ul_info.present = outhdr_values[i++];          // 10
2068
0
            p_mac_lte_info->detailed_phy_info.ul_info.modulation_type = outhdr_values[i++];  // 11
2069
0
            p_mac_lte_info->detailed_phy_info.ul_info.tbs_index = outhdr_values[i++];        // 12
2070
0
            p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length = outhdr_values[i++]; // 13
2071
0
            p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start = outhdr_values[i++];  // 14
2072
            /* Skip retx flag */
2073
0
            i++;                                                                                  // 15
2074
2075
            /* TODO: delete if won't see this special case anymore? */
2076
0
            if (outhdr_values_found == 16) {
2077
0
                p_mac_lte_info->subframeNumberOfGrantPresent = true;
2078
0
                p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];   // 16
2079
0
            }
2080
0
            if (outhdr_values_found > 16) {
2081
0
                p_mac_lte_info->detailed_phy_info.ul_info.harq_id = outhdr_values[i++]; // 16
2082
0
                p_mac_lte_info->detailed_phy_info.ul_info.ndi = outhdr_values[i++];     // 17
2083
2084
0
                p_mac_lte_info->subframeNumberOfGrantPresent = true;
2085
0
                p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];             // 18
2086
0
            }
2087
0
        }
2088
0
    }
2089
2090
    /* System frame number */
2091
0
    if (i < outhdr_values_found) {
2092
0
        p_mac_lte_info->sysframeNumber = outhdr_values[i++];
2093
0
    }
2094
2095
0
    if ((p_mac_lte_info->direction == DIRECTION_UPLINK) &&
2096
0
        (i < outhdr_values_found)) {
2097
2098
0
        p_mac_lte_info->isPHICHNACK = outhdr_values[i++];
2099
0
    }
2100
2101
0
    if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2102
        /* R10 parameter not set yet */
2103
0
        p_mac_lte_info->isExtendedBSRSizes = false;
2104
0
    }
2105
2106
0
    if (i < outhdr_values_found) {
2107
        /* Carrier ID */
2108
0
        p_mac_lte_info->carrierId = (mac_lte_carrier_id)outhdr_values[i++];
2109
0
    }
2110
2111
    /* Remaining fields not (yet?) supported in
2112
       the mac-lte dissector. */
2113
0
    if (i++ < outhdr_values_found) {
2114
        /* Serving cell index */
2115
0
    }
2116
0
    if (i < outhdr_values_found) {
2117
        /* UE Type */
2118
0
    }
2119
2120
    /* Store info in packet */
2121
0
    set_mac_lte_proto_data(pinfo, p_mac_lte_info);
2122
0
}
2123
2124
2125
/* Fill in a RLC LTE packet info struct and attach it to the packet for that
2126
   dissector to use */
2127
static void attach_rlc_lte_info(packet_info *pinfo, unsigned *outhdr_values,
2128
                                unsigned outhdr_values_found _U_)
2129
0
{
2130
0
    struct rlc_lte_info *p_rlc_lte_info;
2131
0
    unsigned int         i = 0;
2132
2133
    /* Only need to set info once per session. */
2134
0
    p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2135
0
    if (p_rlc_lte_info != NULL) {
2136
0
        return;
2137
0
    }
2138
2139
    /* Allocate & zero struct */
2140
0
    p_rlc_lte_info = wmem_new0(wmem_file_scope(), rlc_lte_info);
2141
2142
0
    p_rlc_lte_info->rlcMode = outhdr_values[i++];
2143
0
    p_rlc_lte_info->direction = outhdr_values[i++];
2144
0
    p_rlc_lte_info->priority = outhdr_values[i++];
2145
0
    p_rlc_lte_info->sequenceNumberLength = outhdr_values[i++];
2146
0
    p_rlc_lte_info->channelId = outhdr_values[i++];
2147
0
    p_rlc_lte_info->channelType = outhdr_values[i++];
2148
0
    p_rlc_lte_info->ueid = outhdr_values[i++];
2149
0
    p_rlc_lte_info->pduLength = outhdr_values[i];
2150
2151
    /* Store info in packet */
2152
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
2153
0
}
2154
2155
/* Fill in a PDCP LTE packet info struct and attach it to the packet for the PDCP LTE
2156
   dissector to use */
2157
static void attach_pdcp_lte_info(packet_info *pinfo, unsigned *outhdr_values,
2158
                                 unsigned outhdr_values_found _U_)
2159
0
{
2160
0
    struct pdcp_lte_info *p_pdcp_lte_info;
2161
0
    unsigned int          i = 0;
2162
2163
    /* Only need to set info once per session. */
2164
0
    p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
2165
0
    if (p_pdcp_lte_info != NULL) {
2166
0
        return;
2167
0
    }
2168
2169
    /* Allocate & zero struct */
2170
0
    p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
2171
2172
0
    p_pdcp_lte_info->no_header_pdu = outhdr_values[i++];
2173
0
    p_pdcp_lte_info->plane = (enum pdcp_plane)outhdr_values[i++];
2174
0
    if (p_pdcp_lte_info->plane != USER_PLANE) {
2175
0
        p_pdcp_lte_info->plane = SIGNALING_PLANE;
2176
0
    }
2177
0
    p_pdcp_lte_info->seqnum_length = outhdr_values[i++];
2178
2179
0
    p_pdcp_lte_info->rohc.rohc_compression = outhdr_values[i++];
2180
0
    p_pdcp_lte_info->rohc.rohc_ip_version = outhdr_values[i++];
2181
0
    p_pdcp_lte_info->rohc.cid_inclusion_info = outhdr_values[i++];
2182
0
    p_pdcp_lte_info->rohc.large_cid_present = outhdr_values[i++];
2183
0
    p_pdcp_lte_info->rohc.mode = (enum rohc_mode)outhdr_values[i++];
2184
0
    p_pdcp_lte_info->rohc.rnd = outhdr_values[i++];
2185
0
    p_pdcp_lte_info->rohc.udp_checksum_present = outhdr_values[i++];
2186
0
    p_pdcp_lte_info->rohc.profile = outhdr_values[i];
2187
2188
    /* Remaining 2 (fixed) fields are ah_length and gre_checksum */
2189
2190
    /* Store info in packet */
2191
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
2192
0
}
2193
2194
2195
/* Attempt to show tty (raw character messages) as text lines. */
2196
static void dissect_tty_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
2197
0
{
2198
0
    unsigned    linelen, next_offset;
2199
0
    proto_tree *tty_tree;
2200
0
    proto_item *ti;
2201
0
    int         lines = 0;
2202
2203
    /* Create tty tree. */
2204
0
    ti = proto_tree_add_item(tree, hf_catapult_dct2000_tty, tvb, offset, -1, ENC_NA);
2205
0
    tty_tree = proto_item_add_subtree(ti, ett_catapult_dct2000_tty);
2206
2207
    /* Show the tty lines one at a time. */
2208
0
    while (tvb_offset_exists(tvb, offset)) {
2209
        /* Find the end of the line. */
2210
0
        tvb_find_line_end_unquoted_remaining(tvb, offset, &linelen, &next_offset);
2211
2212
        /* Extract & add the string. */
2213
0
        char *string = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, linelen, ENC_ASCII);
2214
0
        if (g_ascii_isprint(string[0])) {
2215
            /* If the first byte of the string is printable ASCII treat as string... */
2216
0
            proto_tree_add_string_format(tty_tree, hf_catapult_dct2000_tty_line,
2217
0
                                         tvb, offset,
2218
0
                                         linelen, string,
2219
0
                                         "%s", string);
2220
0
        }
2221
0
        else {
2222
            /* Otherwise show as $hex */
2223
0
            int tty_string_length = tvb_reported_length_remaining(tvb, offset);
2224
2225
0
            wmem_strbuf_t *hex_buf = wmem_strbuf_new(pinfo->pool, "$");
2226
0
            wmem_strbuf_append(hex_buf, tvb_bytes_to_str(pinfo->pool, tvb, offset, tty_string_length));
2227
2228
0
            string = wmem_strbuf_finalize(hex_buf);
2229
0
        }
2230
0
        lines++;
2231
2232
        /* Show first line in info column */
2233
0
        if (lines == 1) {
2234
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "tty (%s", string);
2235
0
            proto_item_append_text(ti, " (%s)", string);
2236
0
        }
2237
2238
        /* Move onto next line. */
2239
0
        offset = next_offset;
2240
0
    }
2241
2242
    /* Close off summary of tty message in info column */
2243
0
    if (lines != 0) {
2244
0
        col_append_str(pinfo->cinfo, COL_INFO, (lines > 1) ? "...)" : ")");
2245
0
    }
2246
0
}
2247
2248
2249
/* Scan the log comment looking for notable out-of-band MAC events that should
2250
   be sent to the MAC dissector */
2251
static void check_for_oob_mac_lte_events(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
2252
                                         const char *string)
2253
0
{
2254
0
    unsigned             number_of_ues;
2255
0
    unsigned             ueids[MAX_SRs];
2256
0
    unsigned             rntis[MAX_SRs];
2257
0
    unsigned             rapid;
2258
0
    unsigned             rach_attempt_number;
2259
0
    unsigned             temp;
2260
0
    mac_lte_oob_event    oob_event;
2261
0
    struct mac_lte_info *p_mac_lte_info;
2262
2263
    /* Current strings of interest begin with ">> ", so if don't see, avoid sscanf() calls. */
2264
0
    if (strncmp(string, ">> ", 3) != 0) {
2265
0
        return;
2266
0
    }
2267
2268
    /*********************************************/
2269
    /* Look for strings matching formats         */
2270
2271
    /* RACH Preamble request */
2272
0
    if (sscanf(string, ">> RACH Preamble Request [CarrierId=%u] [LTE UE = %u] [RAPID = %u] [Attempt = %u",
2273
0
               &temp, &ueids[0], &rapid, &rach_attempt_number) == 4) {
2274
0
        oob_event = ltemac_send_preamble;
2275
0
    }
2276
2277
    /* Scheduling Requests */
2278
0
    else if (sscanf(string, ">> Schedule Requests (%u)  [CarrierId=%u][UE=%u][RNTI=%u]",
2279
0
                    &number_of_ues, &temp, &ueids[0], &rntis[0]) == 4) {
2280
0
        const char *current_position;
2281
2282
        /* Newer, multi-UE format */
2283
0
        oob_event = ltemac_send_sr;
2284
2285
        /* Parse other ueid/rnti pairs */
2286
0
        number_of_ues = MIN(number_of_ues, MAX_SRs);
2287
0
        if (number_of_ues > 1) {
2288
0
            current_position = string;
2289
2290
0
            for (unsigned n=1; n < number_of_ues; n++) {
2291
2292
                /* Find the start of the next entry */
2293
0
                current_position = strstr(current_position, "] ");
2294
0
                if (current_position != NULL) {
2295
0
                    current_position += 2;
2296
0
                }
2297
0
                else {
2298
                    /* This is an error - shouldn't happen */
2299
0
                    return;
2300
0
                }
2301
2302
                /* Read this entry */
2303
0
                if (sscanf(current_position, "[UE=%u][RNTI=%u]", &ueids[n], &rntis[n]) != 2) {
2304
                    /* Assuming that if we can't read this one there is no point trying others */
2305
0
                    number_of_ues = n;
2306
0
                    break;
2307
0
                }
2308
0
            }
2309
0
        }
2310
0
    }
2311
2312
    /* SR failures */
2313
0
    else if (sscanf(string, ">> INFO (inst %u) MAC:    [UE = %u]    SR failed (CRNTI=%u)",
2314
0
                    &temp, &ueids[0], &rntis[0]) == 3) {
2315
0
        oob_event = ltemac_sr_failure;
2316
0
    }
2317
2318
    /* No events found */
2319
0
    else return;
2320
2321
2322
    /********************************************/
2323
    /* We have an event. Allocate & zero struct */
2324
0
    p_mac_lte_info = wmem_new0(wmem_file_scope(), mac_lte_info);
2325
2326
    /* This indicates to MAC dissector that it has an oob event */
2327
0
    p_mac_lte_info->length = 0;
2328
2329
0
    switch (oob_event) {
2330
0
        case ltemac_send_preamble:
2331
0
            p_mac_lte_info->ueid = ueids[0];
2332
0
            p_mac_lte_info->rapid = rapid;
2333
0
            p_mac_lte_info->rach_attempt_number = rach_attempt_number;
2334
0
            p_mac_lte_info->direction = DIRECTION_UPLINK;
2335
0
           break;
2336
0
        case ltemac_send_sr:
2337
0
            for (unsigned n=0; n < number_of_ues; n++) {
2338
0
                p_mac_lte_info->oob_ueid[n] = ueids[n];
2339
0
                p_mac_lte_info->oob_rnti[n] = rntis[n];
2340
0
            }
2341
0
            p_mac_lte_info->number_of_srs = number_of_ues;
2342
0
            p_mac_lte_info->direction = DIRECTION_UPLINK;
2343
0
            break;
2344
0
        case ltemac_sr_failure:
2345
0
            p_mac_lte_info->rnti = rntis[0];
2346
0
            p_mac_lte_info->ueid = ueids[0];
2347
0
            p_mac_lte_info->direction = DIRECTION_DOWNLINK;
2348
0
            break;
2349
0
    }
2350
2351
0
    p_mac_lte_info->radioType = FDD_RADIO; /* TODO: will be the same as rest of log... */
2352
0
    p_mac_lte_info->sfnSfInfoPresent = false;  /* We don't have this */
2353
0
    p_mac_lte_info->oob_event = oob_event;
2354
2355
    /* Store info in packet */
2356
0
    set_mac_lte_proto_data(pinfo, p_mac_lte_info);
2357
2358
    /* Call MAC dissector */
2359
0
    call_dissector_only(mac_lte_handle, tvb, pinfo, tree, NULL);
2360
0
}
2361
2362
static uint8_t
2363
hex_from_char(char c)
2364
0
{
2365
0
    if ((c >= '0') && (c <= '9')) {
2366
0
        return c - '0';
2367
0
    }
2368
2369
0
    if ((c >= 'a') && (c <= 'f')) {
2370
0
        return 0x0a + (c - 'a');
2371
0
    }
2372
2373
    /* Not a valid hex string character */
2374
0
    return 0xff;
2375
0
}
2376
2377
2378
/*****************************************/
2379
/* Main dissection function.             */
2380
/*****************************************/
2381
static int
2382
dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2383
0
{
2384
0
    proto_tree         *dct2000_tree = NULL;
2385
0
    proto_item         *ti           = NULL;
2386
0
    int                 offset       = 0;
2387
0
    unsigned            context_length;
2388
0
    const char         *context_name;
2389
0
    uint8_t             port_number;
2390
0
    unsigned            protocol_length;
2391
0
    unsigned            timestamp_length;
2392
0
    const char         *timestamp_string;
2393
0
    unsigned            variant_length;
2394
0
    const char         *variant_string;
2395
0
    uint32_t            variant;
2396
0
    unsigned            outhdr_length;
2397
0
    const char         *outhdr_string;
2398
0
    uint8_t             direction;
2399
0
    tvbuff_t           *next_tvb;
2400
0
    int                 encap;
2401
0
    dissector_handle_t  protocol_handle = 0;
2402
0
    dissector_handle_t  heur_protocol_handle = 0;
2403
0
    void               *protocol_data = 0;
2404
0
    int                 sub_dissector_result = 0;
2405
0
    const char         *protocol_name;
2406
0
    bool                is_comment, is_sprint = false;
2407
0
    unsigned            outhdr_values[MAX_OUTHDR_VALUES];
2408
0
    unsigned            outhdr_values_found;
2409
2410
    /* Set Protocol */
2411
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCT2000");
2412
2413
    /* Clear Info */
2414
0
    col_clear(pinfo->cinfo, COL_INFO);
2415
2416
    /* Create root (protocol) tree. */
2417
0
    if (tree) {
2418
0
        ti = proto_tree_add_item(tree, proto_catapult_dct2000, tvb, offset, -1, ENC_NA);
2419
0
        dct2000_tree = proto_item_add_subtree(ti, ett_catapult_dct2000);
2420
0
    }
2421
2422
    /*********************************************************************/
2423
    /* Note that these are the fields of the stub header as written out  */
2424
    /* by the wiretap module                                             */
2425
2426
    /* Context Name */
2427
0
    context_name = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &context_length, ENC_ASCII);
2428
0
    if (dct2000_tree) {
2429
0
        proto_tree_add_string(dct2000_tree, hf_catapult_dct2000_context, tvb,
2430
0
                            offset, context_length, context_name);
2431
0
    }
2432
0
    offset += context_length;
2433
2434
    /* Context port number */
2435
0
    port_number = tvb_get_uint8(tvb, offset);
2436
0
    if (dct2000_tree) {
2437
0
        proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_port_number, tvb,
2438
0
                            offset, 1, ENC_BIG_ENDIAN);
2439
0
    }
2440
0
    offset++;
2441
2442
    /* Timestamp in file */
2443
0
    timestamp_string = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &timestamp_length, ENC_ASCII);
2444
0
    if (dct2000_tree) {
2445
        /* g_ascii_strtod(timestamp_string, NULL)) is much simpler, but *very* slow..
2446
           There will be seconds, a dot, and 4 decimal places.
2447
           N.B. timestamp_length also includes following NULL character */
2448
0
        if (timestamp_length < 7) {
2449
            /* Can't properly parse, but leave showing how far we got */
2450
0
            return offset;
2451
0
        }
2452
2453
        /* Seconds. */
2454
0
        int seconds = 0;
2455
0
        int multiplier = 1;
2456
0
        for (int d=timestamp_length-7; d >= 0; d--) {
2457
0
            seconds += ((timestamp_string[d]-'0') * multiplier);
2458
0
            multiplier *= 10;
2459
0
        }
2460
2461
        /* Subseconds (4 digits). N.B. trailing zeros are written out by wiretap module. */
2462
0
        int subseconds = 0;
2463
0
        subseconds += (timestamp_string[timestamp_length-2]-'0');
2464
0
        subseconds += (timestamp_string[timestamp_length-3]-'0')*10;
2465
0
        subseconds += (timestamp_string[timestamp_length-4]-'0')*100;
2466
0
        subseconds += (timestamp_string[timestamp_length-5]-'0')*1000;
2467
2468
0
        proto_tree_add_double(dct2000_tree, hf_catapult_dct2000_timestamp, tvb,
2469
0
                              offset, timestamp_length,
2470
0
                              seconds+(subseconds/10000.0));
2471
0
    }
2472
0
    offset += timestamp_length;
2473
2474
2475
    /* DCT2000 protocol name */
2476
0
    protocol_name = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &protocol_length, ENC_ASCII);
2477
0
    if (dct2000_tree) {
2478
0
        proto_tree_add_string(dct2000_tree, hf_catapult_dct2000_protocol, tvb,
2479
0
                            offset, protocol_length, protocol_name);
2480
0
    }
2481
0
    is_comment = (strcmp(protocol_name, "comment") == 0);
2482
0
    if (!is_comment) {
2483
0
        is_sprint = (strcmp(protocol_name, "sprint") == 0);
2484
0
    }
2485
0
    offset += protocol_length;
2486
2487
2488
    /* Protocol Variant */
2489
0
    variant_string = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &variant_length, ENC_ASCII);
2490
0
    if (!is_comment && !is_sprint) {
2491
0
        proto_tree_add_string(dct2000_tree, hf_catapult_dct2000_variant, tvb,
2492
0
                            offset, variant_length, variant_string);
2493
0
    }
2494
0
    offset += variant_length;
2495
2496
    /* Outhdr (shown as string) */
2497
0
    outhdr_string = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &outhdr_length, ENC_ASCII);
2498
0
    if (!is_comment && !is_sprint && (outhdr_length > 1)) {
2499
0
        proto_tree_add_string(dct2000_tree, hf_catapult_dct2000_outhdr, tvb,
2500
0
                            offset, outhdr_length, outhdr_string);
2501
0
    }
2502
0
    offset += outhdr_length;
2503
2504
2505
    /* Direction */
2506
0
    direction = tvb_get_uint8(tvb, offset);
2507
0
    if (dct2000_tree) {
2508
0
        proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
2509
0
                            offset, 1, ENC_BIG_ENDIAN);
2510
0
    }
2511
0
    offset++;
2512
2513
    /* Read frame encapsulation set by wiretap */
2514
0
    if (!is_comment && !is_sprint) {
2515
0
        proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_encap, tvb, offset, 1, ENC_BIG_ENDIAN);
2516
0
    }
2517
0
    encap = tvb_get_uint8(tvb, offset);
2518
0
    offset++;
2519
2520
    /* Add useful details to protocol tree label */
2521
0
    proto_item_append_text(ti, "   context=%s.%u   t=%s   %c   prot=%s (v=%s)",
2522
0
                           context_name,
2523
0
                           port_number,
2524
0
                           timestamp_string,
2525
0
                           (direction == 0) ? 'S' : 'R',
2526
0
                           protocol_name,
2527
0
                           variant_string);
2528
2529
2530
0
    memset(outhdr_values, 0, sizeof outhdr_values);
2531
0
    outhdr_values_found = 0;
2532
2533
    /* FP protocols need info from outhdr attached */
2534
0
    if ((strcmp(protocol_name, "fp") == 0) ||
2535
0
        (strncmp(protocol_name, "fp_r", 4) == 0) ||
2536
0
        (strcmp(protocol_name, "fpiur_r5") == 0)) {
2537
2538
0
        outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2539
0
                                                  outhdr_values);
2540
0
        if (ws_strtou32(variant_string, NULL, &variant))
2541
0
            attach_fp_info(pinfo, direction, protocol_name, variant,
2542
0
                           outhdr_values, outhdr_values_found);
2543
0
        else
2544
0
            expert_add_info(pinfo, ti, &ei_catapult_dct2000_string_invalid);
2545
0
    }
2546
2547
    /* RLC protocols need info from outhdr attached */
2548
0
    else if ((strcmp(protocol_name, "rlc") == 0) ||
2549
0
             (strcmp(protocol_name, "rlc_r4") == 0) ||
2550
0
             (strcmp(protocol_name, "rlc_r5") == 0) ||
2551
0
             (strcmp(protocol_name, "rlc_r6") == 0) ||
2552
0
             (strcmp(protocol_name, "rlc_r7") == 0) ||
2553
0
             (strcmp(protocol_name, "rlc_r8") == 0) ||
2554
0
             (strcmp(protocol_name, "rlc_r9") == 0)) {
2555
2556
0
        outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2557
0
                                                  outhdr_values);
2558
        /* Can't attach info yet.  Need combination of outheader values
2559
           and fields parsed from primitive header... */
2560
0
    }
2561
2562
    /* LTE MAC needs info attached */
2563
0
    else if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2564
0
             (strcmp(protocol_name, "mac_r9_lte") == 0) ||
2565
0
             (strcmp(protocol_name, "mac_r10_lte") == 0)) {
2566
0
        outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2567
0
                                                  outhdr_values);
2568
0
        attach_mac_lte_info(pinfo, outhdr_values, outhdr_values_found);
2569
0
    }
2570
2571
    /* LTE RLC needs info attached */
2572
0
    else if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2573
0
             (strcmp(protocol_name, "rlc_r9_lte") == 0) ||
2574
0
             (strcmp(protocol_name, "rlc_r10_lte") == 0)) {
2575
0
        outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2576
0
                                                  outhdr_values);
2577
0
        attach_rlc_lte_info(pinfo, outhdr_values, outhdr_values_found);
2578
0
    }
2579
2580
    /* LTE PDCP needs info attached */
2581
0
    else if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2582
0
             (strcmp(protocol_name, "pdcp_r9_lte") == 0) ||
2583
0
             (strcmp(protocol_name, "pdcp_r10_lte") == 0)) {
2584
0
        outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2585
0
                                                  outhdr_values);
2586
0
        attach_pdcp_lte_info(pinfo, outhdr_values, outhdr_values_found);
2587
0
    }
2588
2589
0
    else if ((strcmp(protocol_name, "nas_rrc_r8_lte") == 0) ||
2590
0
             (strcmp(protocol_name, "nas_rrc_r9_lte") == 0) ||
2591
0
             (strcmp(protocol_name, "nas_rrc_r10_lte") == 0) ||
2592
0
             (strcmp(protocol_name, "nas_rrc_r13_lte") == 0) ||
2593
0
             (strcmp(protocol_name, "nas_rrc_r15_5gnr") == 0)) {
2594
0
        bool nas_body_found = true;
2595
0
        uint8_t opcode = tvb_get_uint8(tvb, offset);
2596
0
        proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_opcode,
2597
0
                            tvb, offset++, 1, ENC_BIG_ENDIAN);
2598
2599
0
        offset++;   /* Skip overall length */
2600
2601
0
        switch (opcode) {
2602
0
            case LTE_NAS_RRC_DATA_IND:
2603
0
            case LTE_NAS_RRC_DATA_REQ:
2604
                /* UEId */
2605
0
                offset++; /* tag */
2606
0
                offset += 2; /* 2 wasted bytes of UEId*/
2607
0
                proto_tree_add_item(tree, hf_catapult_dct2000_ueid,
2608
0
                                    tvb, offset, 2, ENC_BIG_ENDIAN);
2609
0
                offset += 2;
2610
0
                break;
2611
0
            case LTE_NAS_RRC_ESTABLISH_REQ:
2612
                /* UEId */
2613
0
                offset++; /* tag */
2614
0
                offset += 2; /* 2 wasted bytes of UEId*/
2615
0
                proto_tree_add_item(tree, hf_catapult_dct2000_ueid,
2616
0
                                    tvb, offset, 2, ENC_BIG_ENDIAN);
2617
0
                offset += 2;
2618
2619
                /* Establish cause. TODO: value_string */
2620
0
                offset += 2;  /* tag + length */
2621
0
                proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_establish_cause,
2622
0
                                    tvb, offset++, 1, ENC_BIG_ENDIAN);
2623
2624
                /* Priority.  TODO: Vals are low | high */
2625
0
                offset += 2;  /* tag + length */
2626
0
                proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_priority,
2627
0
                                    tvb, offset++, 1, ENC_BIG_ENDIAN);
2628
0
                break;
2629
0
            case LTE_NAS_RRC_RELEASE_IND:
2630
                /* UEId */
2631
0
                offset++; /* tag */
2632
0
                offset += 2; /* 2 wasted bytes of UEId*/
2633
0
                proto_tree_add_item(tree, hf_catapult_dct2000_ueid,
2634
0
                                    tvb, offset, 2, ENC_BIG_ENDIAN);
2635
0
                offset += 2;
2636
2637
                /* Release cause.  TODO: value_string */
2638
0
                offset += 2;  /* tag + length */
2639
0
                proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_release_cause,
2640
0
                                    tvb, offset++, 1, ENC_BIG_ENDIAN);
2641
0
                break;
2642
2643
0
            default:
2644
0
                nas_body_found = false;
2645
0
                break;
2646
0
        }
2647
2648
        /* Look up dissector if it looks right */
2649
0
        if (nas_body_found) {
2650
0
            offset += 2;  /* L3 tag + len */
2651
0
            if (strcmp(protocol_name, "nas_rrc_r15_5gnr") == 0) {
2652
0
                protocol_handle = find_dissector("nas-5gs");
2653
0
            }
2654
0
            else {
2655
0
                protocol_handle = find_dissector("nas-eps");
2656
0
            }
2657
0
        }
2658
0
    }
2659
2660
    /* NR NAS for S1AP */
2661
0
    else if (strcmp(protocol_name, "nas_s1ap_r15_5gnr") == 0) {
2662
0
        uint8_t opcode = tvb_get_uint8(tvb, offset);
2663
0
        if (opcode <= NAS_S1AP_DATA_IND) {
2664
            /* Opcode tag (only interested in ones that carry NAS PDU) */
2665
0
            proto_tree_add_item(tree, hf_catapult_dct2000_nr_nas_s1ap_opcode,
2666
0
                                tvb, offset++, 1, ENC_BIG_ENDIAN);
2667
2668
            /* Skip overall length */
2669
0
            offset += skipASNLength(tvb_get_uint8(tvb, offset));
2670
2671
            /* UE Id. Skip tag and fixed length */
2672
0
            offset += 2;
2673
            /* Ignore first 2 bytes of UEId */
2674
0
            offset += 2;
2675
0
            proto_tree_add_item(tree, hf_catapult_dct2000_ueid,
2676
0
                                tvb, offset, 2, ENC_BIG_ENDIAN);
2677
0
            offset += 2;
2678
2679
            /* NAS PDU tag is 2 bytes */
2680
0
            uint16_t data_tag = tvb_get_ntohs(tvb, offset);
2681
0
            if (data_tag == 0x0021) {
2682
0
                offset += 2;
2683
                /* Also skip length */
2684
0
                offset += 2;
2685
0
                protocol_handle = find_dissector("nas-5gs");
2686
2687
                /* N.B. Ignoring some optional fields after the NAS PDU */
2688
0
            }
2689
0
        }
2690
0
    }
2691
2692
2693
    /* Note that the first item of pinfo->pseudo_header->dct2000 will contain
2694
       the pseudo-header needed (in some cases) by the Wireshark dissector that
2695
       this packet data will be handed off to. */
2696
2697
2698
    /***********************************************************************/
2699
    /* Now hand off to the dissector of intended packet encapsulation type */
2700
2701
    /* Get protocol handle, and set p2p_dir where necessary.
2702
       (packet-frame.c won't copy it from pseudo-header because it doesn't
2703
        know about Catapult DCT2000 encap type...)
2704
    */
2705
0
    switch (encap) {
2706
0
        case WTAP_ENCAP_RAW_IP:
2707
0
            protocol_handle = find_dissector("ip");
2708
#if 0
2709
            /* TODO: this doesn't work yet.
2710
               pseudo_header isn't copied from wtap to pinfo... */
2711
            if ((pinfo->pseudo_header != NULL) &&
2712
                (pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid != 0)) {
2713
2714
                proto_item *ti;
2715
2716
                /* Add PDCP thread info as generated fields */
2717
                ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_ueid, tvb, 0, 0,
2718
                                         pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid);
2719
                proto_item_set_generated(ti);
2720
                ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_drbid, tvb, 0, 0,
2721
                                         pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.drbid);
2722
                proto_item_set_generated(ti);
2723
            }
2724
#endif
2725
0
            break;
2726
0
        case WTAP_ENCAP_ETHERNET:
2727
0
            protocol_handle = find_dissector("eth_withoutfcs");
2728
0
            break;
2729
0
        case WTAP_ENCAP_ISDN:
2730
            /*
2731
             * XXX - if the file can handle B-channel traffic as well
2732
             * as D-channel traffic, have the libwiretap code fill
2733
             * in the channel, and call the ISDN dissector rather
2734
             * than the LAPD-with-pseudoheader dissector.
2735
             */
2736
0
            protocol_handle = find_dissector("lapd-phdr");
2737
0
            protocol_data = &pinfo->pseudo_header->dct2000.inner_pseudo_header.isdn;
2738
0
            break;
2739
0
        case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
2740
0
            protocol_handle = find_dissector("atm_untruncated");
2741
0
            protocol_data = &pinfo->pseudo_header->dct2000.inner_pseudo_header.atm;
2742
0
            break;
2743
0
        case WTAP_ENCAP_PPP:
2744
0
            protocol_handle = find_dissector("ppp_hdlc");
2745
0
            pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent;
2746
0
            break;
2747
0
        case DCT2000_ENCAP_SSCOP:
2748
0
            protocol_handle = find_dissector("sscop");
2749
0
            break;
2750
0
        case WTAP_ENCAP_FRELAY:
2751
0
            protocol_handle = find_dissector("fr");
2752
0
            break;
2753
0
        case DCT2000_ENCAP_MTP2:
2754
0
            protocol_handle = find_dissector("mtp2");
2755
0
            break;
2756
0
        case DCT2000_ENCAP_NBAP:
2757
0
            protocol_handle = find_dissector("nbap");
2758
0
            break;
2759
2760
0
        case DCT2000_ENCAP_UNHANDLED:
2761
            /**********************************************************/
2762
            /* The wiretap module wasn't able to set an encapsulation */
2763
            /* type, but it may still be possible to dissect the data */
2764
            /* if we know about the protocol or if we can recognise   */
2765
            /* and parse or skip a primitive header                   */
2766
            /**********************************************************/
2767
2768
            /* Show context.port in src or dest column as appropriate */
2769
0
            if (direction == 0) {
2770
0
                col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
2771
0
                             "%s.%u",
2772
0
                             context_name,
2773
0
                             port_number);
2774
0
            }
2775
0
            else
2776
0
            if (direction == 1) {
2777
0
                col_add_fstr(pinfo->cinfo, COL_DEF_DST,
2778
0
                             "%s.%u",
2779
0
                             context_name,
2780
0
                             port_number);
2781
0
            }
2782
2783
2784
            /**************************************************************************/
2785
            /* These protocols have no encapsulation type, just look them up directly */
2786
2787
0
            if ((strcmp(protocol_name, "rlc") == 0) ||
2788
0
                (strcmp(protocol_name, "rlc_r4") == 0) ||
2789
0
                (strcmp(protocol_name, "rlc_r5") == 0) ||
2790
0
                (strcmp(protocol_name, "rlc_r6") == 0) ||
2791
0
                (strcmp(protocol_name, "rlc_r7") == 0) ||
2792
0
                (strcmp(protocol_name, "rlc_r8") == 0) ||
2793
0
                (strcmp(protocol_name, "rlc_r9") == 0)) {
2794
2795
0
                dissect_rlc_umts(tvb, offset, pinfo, tree, direction,
2796
0
                                 outhdr_values, outhdr_values_found);
2797
0
                return tvb_captured_length(tvb);
2798
0
            }
2799
2800
0
            else
2801
0
            if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2802
0
                (strcmp(protocol_name, "mac_r9_lte") == 0) ||
2803
0
                (strcmp(protocol_name, "mac_r10_lte") == 0)) {
2804
0
                protocol_handle = mac_lte_handle;
2805
0
            }
2806
2807
0
            else
2808
0
            if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2809
0
                (strcmp(protocol_name, "rlc_r9_lte") == 0) ||
2810
0
                (strcmp(protocol_name, "rlc_r10_lte") == 0)) {
2811
0
                protocol_handle = rlc_lte_handle;
2812
0
            }
2813
2814
0
            else
2815
0
            if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2816
0
                (strcmp(protocol_name, "pdcp_r9_lte") == 0) ||
2817
0
                (strcmp(protocol_name, "pdcp_r10_lte") == 0)) {
2818
                /* Dissect proprietary header, then pass remainder to PDCP */
2819
0
                dissect_pdcp_lte(tvb, offset, pinfo, tree);
2820
0
                return tvb_captured_length(tvb);
2821
0
            }
2822
2823
2824
            /* Work with generic XML protocol. */
2825
0
            else
2826
0
            if (strcmp(protocol_name, "xml") == 0) {
2827
0
                protocol_handle = find_dissector("xml");
2828
0
            }
2829
2830
2831
            /* Attempt to show tty messages as raw text */
2832
0
            else
2833
0
            if (strcmp(protocol_name, "tty") == 0) {
2834
0
                dissect_tty_lines(tvb, pinfo, dct2000_tree, offset);
2835
0
                return tvb_captured_length(tvb);
2836
0
            }
2837
2838
0
            else
2839
0
            if (strcmp(protocol_name, "sipprim") == 0) {
2840
0
                protocol_handle = find_dissector("sipprim");
2841
0
            }
2842
2843
0
            else
2844
0
            if (strcmp(protocol_name, "comment") == 0) {
2845
                /* Extract & add the string. */
2846
0
                proto_item *string_ti;
2847
0
                const char *string;
2848
2849
                /* Show comment string */
2850
0
                string_ti = proto_tree_add_item_ret_string(dct2000_tree, hf_catapult_dct2000_comment, tvb,
2851
0
                                                offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)&string);
2852
0
                col_append_str(pinfo->cinfo, COL_INFO, string);
2853
2854
0
                if (catapult_dct2000_dissect_mac_lte_oob_messages) {
2855
                    /* Look into string for out-of-band MAC events, such as SRReq, SRInd */
2856
0
                    check_for_oob_mac_lte_events(pinfo, tvb, tree, string);
2857
0
                }
2858
2859
                /* Look for and flag generic error messages */
2860
0
                if (strncmp(string, ">> ERR", 6) == 0) {
2861
0
                    proto_item *error_ti = proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_error_comment, tvb,
2862
0
                                                               offset, -1, ENC_NA);
2863
0
                    proto_item_set_generated(error_ti);
2864
0
                    expert_add_info_format(pinfo, string_ti, &ei_catapult_dct2000_error_comment_expert,
2865
0
                                          "%s", string);
2866
0
                }
2867
2868
2869
                /* Look for logged MAC-NR PDU */
2870
                /* Example contents would be:
2871
                    $Debug  - NRMAC PDU: direction=0 rntiType=3 rnti=8495 ueid=1 SN=0 SFN=0 length=22 $40111212121212121212121212121212121212121212
2872
                */
2873
0
                int dir, rntiType, rnti, ueid, sn, sfn, length;
2874
2875
0
                if ((sscanf(string, "L1_App: NRMAC PDU: direction=%d rntiType=%d rnti=%d ueid=%d SN=%d  SFN=%d length=%d $",
2876
0
                            &dir, &rntiType, &rnti, &ueid, &sn, &sfn, &length) == 7) ||
2877
0
                    (sscanf(string, "NRMAC PDU: direction=%d rntiType=%d rnti=%d ueid=%d SN=%d  SFN=%d length=%d $",
2878
0
                            &dir, &rntiType, &rnti, &ueid, &sn, &sfn, &length) == 7))
2879
0
                {
2880
0
                    struct mac_nr_info *p_mac_nr_info;
2881
2882
                    /* Only need to set info once per session? */
2883
                    /* p_mac_nr_info = get_mac_nr_proto_data(pinfo); */
2884
2885
                    /* Allocate & zero struct */
2886
0
                    p_mac_nr_info = wmem_new0(wmem_file_scope(), struct mac_nr_info);
2887
2888
                    /* Populate the struct from outhdr values */
2889
0
                    p_mac_nr_info->radioType = FDD_RADIO;
2890
2891
                    /* Map internal RNTI type -> Wireshark #defines from packet-mac-nr.h */
2892
0
                    switch (rntiType) {
2893
0
                        case 2:
2894
0
                            p_mac_nr_info->rntiType = P_RNTI;
2895
0
                            break;
2896
0
                        case 3:
2897
0
                            p_mac_nr_info->rntiType = RA_RNTI;
2898
0
                            break;
2899
0
                        case 4:
2900
0
                            p_mac_nr_info->rntiType = C_RNTI; /* temp C-RNTI */
2901
0
                            break;
2902
0
                        case 5:
2903
0
                            p_mac_nr_info->rntiType = C_RNTI;
2904
0
                            break;
2905
0
                        case 6:
2906
0
                            p_mac_nr_info->rntiType = MSGB_RNTI;
2907
0
                            break;
2908
0
                        default:
2909
0
                            p_mac_nr_info->rntiType = NO_RNTI;
2910
0
                            break;
2911
0
                    }
2912
2913
0
                    p_mac_nr_info->direction = dir;
2914
0
                    p_mac_nr_info->rnti = rnti;
2915
                    // 0xFFFF trumps logged rntiType...
2916
0
                    if (rnti == 65535) {
2917
0
                        p_mac_nr_info->rntiType = SI_RNTI;
2918
0
                    }
2919
0
                    p_mac_nr_info->ueid = ueid;
2920
2921
0
                    p_mac_nr_info->phr_type2_othercell = false;
2922
2923
0
                    p_mac_nr_info->length = length;
2924
2925
                    /* Always present. TODO: miss out if both zero? */
2926
0
                    p_mac_nr_info->sfnSlotInfoPresent = true;
2927
0
                    p_mac_nr_info->sysframeNumber = sfn;
2928
0
                    p_mac_nr_info->slotNumber = sn;  /* only right if mu==0, but don't know SCS */
2929
2930
                    /* Store info in packet */
2931
0
                    set_mac_nr_proto_data(pinfo, p_mac_nr_info);
2932
2933
                    /* Payload is from $ to end of string */
2934
0
                    int data_offset = 0;
2935
0
                    for (unsigned int n=0; n < strlen(string); n++) {
2936
0
                        if (string[n] == '$') {
2937
0
                            data_offset = n;
2938
0
                            break;
2939
0
                        }
2940
0
                    }
2941
2942
                    /* Convert data to hex. */
2943
0
                    char *mac_data = (char *)wmem_alloc(pinfo->pool, 2 + (strlen(string)-data_offset)/2);
2944
0
                    int idx, m;
2945
0
                    for (idx=0, m=data_offset+1; string[m] != '\0'; m+=2, idx++) {
2946
0
                        mac_data[idx] = (hex_from_char(string[m]) << 4) + hex_from_char(string[m+1]);
2947
0
                    }
2948
2949
                    /* Create tvb */
2950
0
                    tvbuff_t *mac_nr_tvb = tvb_new_child_real_data(tvb, (const uint8_t*)mac_data, idx, idx);
2951
0
                    add_new_data_source(pinfo, mac_nr_tvb, "MAC-NR Payload");
2952
                    /* Call the dissector! */
2953
0
                    call_dissector_only(mac_nr_handle, mac_nr_tvb, pinfo, tree, NULL);
2954
0
                }
2955
2956
                /* Look for logged NRUP PDU */
2957
0
                const char *nrup_pattern = "NRUP PDU: ";
2958
0
                char *start = strstr(string, nrup_pattern);
2959
0
                if (start) {
2960
0
                    int off = 0;
2961
2962
0
                    while (start[off] && start[off] != '$') {
2963
0
                        off++;
2964
0
                    }
2965
2966
0
                    const char *payload = &start[off+1];
2967
2968
                    /* Pad out to nearest 4 bytes if necessary. */
2969
                    /* Convert data to hex. */
2970
0
                    #define MAX_NRUP_DATA_LENGTH 200
2971
0
                    static uint8_t nrup_data[MAX_NRUP_DATA_LENGTH];
2972
0
                    int idx, m;
2973
2974
                    /* The rest (or all) is data! */
2975
0
                    for (m=0, idx=0; payload[m] != '\0' && idx < MAX_NRUP_DATA_LENGTH-4; m+=2, idx++) {
2976
0
                        nrup_data[idx] = (hex_from_char(payload[m]) << 4) + hex_from_char(payload[m+1]);
2977
0
                    }
2978
0
                    length = idx;
2979
                    /* Pad out to nearest 4 bytes if necessary. */
2980
0
                    if (length % 4 != 0) {
2981
0
                        for (int p=length % 4; p < 4; p++) {
2982
0
                            nrup_data[length++] = '\0';
2983
0
                        }
2984
0
                    }
2985
2986
                    /* Create separate NRUP tvb */
2987
                    /* XXX - Should the reported length be based upon
2988
                     * strlen(payload) / 2 as we might have truncated? */
2989
0
                    tvbuff_t *nrup_tvb = tvb_new_child_real_data(tvb, nrup_data, length, length);
2990
0
                    add_new_data_source(pinfo, nrup_tvb, "NRUP Payload");
2991
2992
                    /* Call the dissector! */
2993
0
                    call_dissector_only(nrup_handle, nrup_tvb, pinfo, tree, NULL);
2994
0
                }
2995
2996
                /* Read key info from formatted lines */
2997
                /* e.g. NRPDCP: RRCPRIM:ueId=   1;setThreadAuthKey: RRC id=1 alg 2 key: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 */
2998
0
                if (strstr(string, "setThreadAuthKey:")) {
2999
0
                    unsigned ue_id, id, alg;
3000
0
                    if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId=   %u;setThreadAuthKey: RRC id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
3001
0
                        char *key = g_strdup(strstr(string, "key: ")+5);
3002
0
                        set_pdcp_nr_rrc_integrity_key(ue_id, key, pinfo->num);
3003
0
                        g_free(key);
3004
0
                    }
3005
0
                    else if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId=   %u;setThreadAuthKey: UP id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
3006
0
                        char *key = g_strdup(strstr(string, "key: ")+5);
3007
0
                        set_pdcp_nr_up_integrity_key(ue_id, key, pinfo->num);
3008
0
                        g_free(key);
3009
0
                    }
3010
0
                }
3011
0
                else if (strstr(string, "setThreadCryptKey:")) {
3012
0
                    unsigned ue_id, id, alg;
3013
0
                    if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId=   %u;setThreadCryptKey: RRC id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
3014
0
                        char *key = g_strdup(strstr(string, "key: ")+5);
3015
0
                        set_pdcp_nr_rrc_ciphering_key(ue_id, key, pinfo->num);
3016
0
                        g_free(key);
3017
0
                    }
3018
0
                    else if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId=   %u;setThreadCryptKey: UP id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
3019
0
                        char *key = g_strdup(strstr(string, "key: ")+5);
3020
0
                        set_pdcp_nr_up_ciphering_key(ue_id, key, pinfo->num);
3021
0
                        g_free(key);
3022
0
                    }
3023
0
                }
3024
3025
                /* 'raw' (ethernet) frames logged as text comments */
3026
0
                int raw_interface;
3027
0
                char raw_direction;
3028
0
                if (sscanf(string, "RawTraffic: Interface: %d %c $",
3029
0
                           &raw_interface, &raw_direction) == 2)
3030
0
                {
3031
                    /* Interface */
3032
0
                    proto_tree_add_uint(tree, hf_catapult_dct2000_rawtraffic_interface,
3033
0
                                        tvb, 0, 0, raw_interface);
3034
3035
                    /* Direction */
3036
0
                    proto_tree_add_uint(tree, hf_catapult_dct2000_rawtraffic_direction,
3037
0
                                        tvb, 0, 0, raw_direction == 'r');
3038
3039
                    /* Payload is from $ to end of string */
3040
0
                    int data_offset = 0;
3041
0
                    for (unsigned int n=0; n < strlen(string); n++) {
3042
0
                        if (string[n] == '$') {
3043
0
                            data_offset = n;
3044
0
                            break;
3045
0
                        }
3046
0
                    }
3047
3048
                    /* Convert data to hex. */
3049
0
                    static uint8_t eth_data[36000];
3050
0
                    int idx, m;
3051
0
                    for (idx=0, m=data_offset+1; idx<36000 && string[m] != '\0'; m+=2, idx++) {
3052
0
                        eth_data[idx] = (hex_from_char(string[m]) << 4) + hex_from_char(string[m+1]);
3053
0
                    }
3054
3055
                    /* Create tvb */
3056
0
                    tvbuff_t *raw_traffic_tvb = tvb_new_child_real_data(tvb, eth_data, idx, idx);
3057
0
                    add_new_data_source(pinfo, raw_traffic_tvb, "Raw-Traffic Payload");
3058
3059
                    /* PDU */
3060
0
                    proto_tree_add_item(tree, hf_catapult_dct2000_rawtraffic_pdu, raw_traffic_tvb,
3061
0
                                        0, tvb_reported_length(raw_traffic_tvb), ENC_NA);
3062
3063
                    /* Call the dissector! */
3064
0
                   call_dissector_only(eth_handle, raw_traffic_tvb, pinfo, tree, NULL);
3065
0
                }
3066
3067
0
                return tvb_captured_length(tvb);
3068
0
            }
3069
3070
0
            else
3071
0
            if (strcmp(protocol_name, "sprint") == 0) {
3072
                /* Extract & add the string. */
3073
0
                const char *string;
3074
3075
                /* Show sprint string */
3076
0
                proto_tree_add_item_ret_string(dct2000_tree, hf_catapult_dct2000_sprint, tvb,
3077
0
                                                offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)&string);
3078
0
                col_append_str(pinfo->cinfo, COL_INFO, string);
3079
3080
0
                return tvb_captured_length(tvb);
3081
0
            }
3082
3083
            /* RRC (LTE or NR).
3084
               Dissect proprietary header, then pass remainder
3085
               to RRC dissector (depending upon direction and channel type) */
3086
0
            else
3087
0
            if (catapult_dct2000_dissect_lte_rrc &&
3088
0
                ((strcmp(protocol_name, "rrc_r8_lte") == 0) ||
3089
0
                 (strcmp(protocol_name, "rrcpdcpprim_r8_lte") == 0) ||
3090
0
                 (strcmp(protocol_name, "rrc_r9_lte") == 0) ||
3091
0
                 (strcmp(protocol_name, "rrcpdcpprim_r9_lte") == 0) ||
3092
0
                 (strcmp(protocol_name, "rrc_r10_lte") == 0) ||
3093
0
                 (strcmp(protocol_name, "rrc_r11_lte") == 0) ||
3094
0
                 (strcmp(protocol_name, "rrc_r12_lte") == 0) ||
3095
0
                 (strcmp(protocol_name, "rrc_r13_lte") == 0) ||
3096
0
                 (strcmp(protocol_name, "rrc_r15_lte") == 0) ||
3097
0
                 (strcmp(protocol_name, "rrc_r16_lte") == 0) ||
3098
0
                 (strcmp(protocol_name, "rrcpdcpprim_r15_lte") == 0))) {
3099
3100
0
                dissect_rrc_lte_nr(tvb, offset, pinfo, tree, LTE);
3101
0
                return tvb_captured_length(tvb);
3102
0
            }
3103
0
            else if ((strcmp(protocol_name, "rrc_r15_5g") == 0) ||
3104
0
                     (strcmp(protocol_name, "rrc_r16_5g") == 0)) {
3105
0
                dissect_rrc_lte_nr(tvb, offset, pinfo, tree, NR);
3106
0
                return tvb_captured_length(tvb);
3107
0
            }
3108
3109
0
            else
3110
0
            if ((strcmp(protocol_name, "ccpri_r8_lte") == 0) ||
3111
0
                (strcmp(protocol_name, "ccpri_r9_lte") == 0)) {
3112
3113
                /* Dissect proprietary header, then pass remainder to lapb */
3114
0
                dissect_ccpri_lte(tvb, offset, pinfo, tree);
3115
0
                return tvb_captured_length(tvb);
3116
0
            }
3117
3118
            /* Many DCT2000 protocols have at least one IPPrim variant. If the
3119
               protocol name can be matched to a dissector, try to find the
3120
               UDP/TCP data inside and dissect it.
3121
            */
3122
3123
0
            if (!protocol_handle && catapult_dct2000_try_ipprim_heuristic) {
3124
0
                uint32_t     source_addr_offset = 0, dest_addr_offset = 0;
3125
0
                uint8_t      source_addr_length = 0, dest_addr_length = 0;
3126
0
                uint32_t     source_port_offset = 0, dest_port_offset = 0;
3127
0
                port_type    type_of_port = PT_NONE;
3128
0
                uint16_t     conn_id_offset = 0;
3129
0
                int          offset_before_ipprim_header = offset;
3130
3131
                /* For ipprim, want to show ipprim header even if can't find dissector to call for payload.. */
3132
0
                if (find_ipprim_data_offset(tvb, &offset, direction,
3133
0
                                            &source_addr_offset, &source_addr_length,
3134
0
                                            &dest_addr_offset, &dest_addr_length,
3135
0
                                            &source_port_offset, &dest_port_offset,
3136
0
                                            &type_of_port,
3137
0
                                            &conn_id_offset)) {
3138
3139
0
                    proto_tree *ipprim_tree;
3140
0
                    proto_item *ipprim_ti;
3141
0
                    struct     e_in6_addr sourcev6, destv6;
3142
3143
                    /* Fetch IPv6 addresses */
3144
0
                    if (source_addr_length != 4) {
3145
0
                        tvb_get_ipv6(tvb, source_addr_offset, &sourcev6);
3146
0
                    }
3147
0
                    if (dest_addr_length != 4) {
3148
0
                        tvb_get_ipv6(tvb, dest_addr_offset, &destv6);
3149
0
                    }
3150
3151
3152
                    /* Will use this dissector then. */
3153
0
                    heur_protocol_handle = look_for_dissector(protocol_name);
3154
0
                    protocol_handle = heur_protocol_handle;
3155
3156
                    /* Add address parameters to tree */
3157
                    /* Unfortunately can't automatically create a conversation filter for this...
3158
                       I *could* create a fake IP header from these details, but then it would be tricky
3159
                       to get the FP dissector called as it has no well-known ports or heuristics... */
3160
0
                    ipprim_ti =  proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_ipprim_addresses,
3161
0
                                                       tvb, offset_before_ipprim_header, 0,
3162
0
                                                       "", "IPPrim transport (%s): %s:%u -> %s:%u",
3163
0
                                                       (type_of_port == PT_UDP) ? "UDP" : "TCP",
3164
0
                                                       (source_addr_offset) ?
3165
0
                                                           ((source_addr_length == 4) ?
3166
0
                                                              get_hostname(tvb_get_ipv4(tvb, source_addr_offset)) :
3167
0
                                                              get_hostname6(&sourcev6)
3168
0
                                                            ) :
3169
0
                                                           "0.0.0.0",
3170
0
                                                       (source_port_offset) ?
3171
0
                                                           tvb_get_ntohs(tvb, source_port_offset) :
3172
0
                                                           0,
3173
0
                                                       (dest_addr_offset) ?
3174
0
                                                         ((dest_addr_length == 4) ?
3175
0
                                                              get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
3176
0
                                                              get_hostname6(&destv6)
3177
0
                                                            ) :
3178
0
                                                           "0.0.0.0",
3179
0
                                                       (dest_port_offset) ?
3180
0
                                                           tvb_get_ntohs(tvb, dest_port_offset) :
3181
0
                                                           0);
3182
0
                    if ((type_of_port == PT_TCP) && (conn_id_offset != 0)) {
3183
0
                        proto_item_append_text(ipprim_ti, " (conn_id=%u)", tvb_get_ntohs(tvb, conn_id_offset));
3184
0
                    }
3185
3186
                    /* Add these IPPRIM fields inside an IPPRIM subtree */
3187
0
                    ipprim_tree = proto_item_add_subtree(ipprim_ti, ett_catapult_dct2000_ipprim);
3188
3189
                    /* Try to add right stuff to pinfo so conversation stuff works... */
3190
0
                    pinfo->ptype = type_of_port;
3191
3192
                    /* Add addresses & ports into ipprim tree.
3193
                       Also set address info in pinfo for conversations... */
3194
0
                    if (source_addr_offset != 0) {
3195
0
                        proto_item *addr_ti;
3196
3197
0
                        set_address_tvb(&pinfo->net_src,
3198
0
                                    (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
3199
0
                                    source_addr_length, tvb, source_addr_offset);
3200
0
                        copy_address_shallow(&pinfo->src, &pinfo->net_src);
3201
3202
0
                        proto_tree_add_item(ipprim_tree,
3203
0
                                            (source_addr_length == 4) ?
3204
0
                                                hf_catapult_dct2000_ipprim_src_addr_v4 :
3205
0
                                                hf_catapult_dct2000_ipprim_src_addr_v6,
3206
0
                                            tvb, source_addr_offset, source_addr_length,
3207
0
                                            ENC_NA);
3208
3209
                        /* Add hidden item for "side-less" addr */
3210
0
                        addr_ti = proto_tree_add_item(ipprim_tree,
3211
0
                                                      (source_addr_length == 4) ?
3212
0
                                                          hf_catapult_dct2000_ipprim_addr_v4 :
3213
0
                                                          hf_catapult_dct2000_ipprim_addr_v6,
3214
0
                                                      tvb, source_addr_offset, source_addr_length,
3215
0
                                                      ENC_NA);
3216
0
                        proto_item_set_hidden(addr_ti);
3217
0
                    }
3218
0
                    if (source_port_offset != 0) {
3219
0
                        proto_item *port_ti;
3220
3221
0
                        pinfo->srcport = tvb_get_ntohs(tvb, source_port_offset);
3222
3223
0
                        proto_tree_add_item(ipprim_tree,
3224
0
                                            (type_of_port == PT_UDP) ?
3225
0
                                               hf_catapult_dct2000_ipprim_udp_src_port :
3226
0
                                               hf_catapult_dct2000_ipprim_tcp_src_port,
3227
0
                                            tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
3228
0
                        port_ti = proto_tree_add_item(ipprim_tree,
3229
0
                                                      (type_of_port == PT_UDP) ?
3230
0
                                                          hf_catapult_dct2000_ipprim_udp_port :
3231
0
                                                          hf_catapult_dct2000_ipprim_tcp_port,
3232
0
                                                      tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
3233
0
                        proto_item_set_hidden(port_ti);
3234
0
                    }
3235
0
                    if (dest_addr_offset != 0) {
3236
0
                        proto_item *addr_ti;
3237
3238
0
                        set_address_tvb(&pinfo->net_dst,
3239
0
                                    (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
3240
0
                                    dest_addr_length, tvb, dest_addr_offset);
3241
0
                        copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
3242
0
                        proto_tree_add_item(ipprim_tree,
3243
0
                                            (dest_addr_length == 4) ?
3244
0
                                                hf_catapult_dct2000_ipprim_dst_addr_v4 :
3245
0
                                                hf_catapult_dct2000_ipprim_dst_addr_v6,
3246
0
                                            tvb, dest_addr_offset, dest_addr_length,
3247
0
                                            ENC_NA);
3248
3249
                        /* Add hidden item for "side-less" addr */
3250
0
                        addr_ti = proto_tree_add_item(ipprim_tree,
3251
0
                                                      (dest_addr_length == 4) ?
3252
0
                                                          hf_catapult_dct2000_ipprim_addr_v4 :
3253
0
                                                          hf_catapult_dct2000_ipprim_addr_v6,
3254
0
                                                      tvb, dest_addr_offset, dest_addr_length,
3255
0
                                                      ENC_NA);
3256
0
                        proto_item_set_hidden(addr_ti);
3257
0
                    }
3258
0
                    if (dest_port_offset != 0) {
3259
0
                        proto_item *port_ti;
3260
3261
0
                        pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
3262
3263
0
                        proto_tree_add_item(ipprim_tree,
3264
0
                                            (type_of_port == PT_UDP) ?
3265
0
                                               hf_catapult_dct2000_ipprim_udp_dst_port :
3266
0
                                               hf_catapult_dct2000_ipprim_tcp_dst_port,
3267
0
                                            tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
3268
0
                        port_ti = proto_tree_add_item(ipprim_tree,
3269
0
                                                      (type_of_port == PT_UDP) ?
3270
0
                                                          hf_catapult_dct2000_ipprim_udp_port :
3271
0
                                                          hf_catapult_dct2000_ipprim_tcp_port,
3272
0
                                                      tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
3273
0
                        proto_item_set_hidden(port_ti);
3274
0
                    }
3275
0
                    if (conn_id_offset != 0) {
3276
0
                        proto_tree_add_item(ipprim_tree,
3277
0
                                            hf_catapult_dct2000_ipprim_conn_id,
3278
0
                                            tvb, conn_id_offset, 2, ENC_BIG_ENDIAN);
3279
0
                    }
3280
3281
3282
                    /* Set source and dest columns now (will be overwritten if
3283
                       src and dst IP addresses set) */
3284
0
                    if (source_addr_offset) {
3285
0
                        col_append_fstr(pinfo->cinfo, COL_DEF_SRC,
3286
0
                                        "(%s:%u)",
3287
0
                                        get_hostname(tvb_get_ipv4(tvb, source_addr_offset)),
3288
0
                                        tvb_get_ntohs(tvb, source_port_offset));
3289
0
                    }
3290
0
                    if (dest_addr_offset) {
3291
0
                        col_append_fstr(pinfo->cinfo, COL_DEF_DST,
3292
0
                                        "(%s:%u)",
3293
0
                                        get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)),
3294
0
                                        tvb_get_ntohs(tvb, dest_port_offset));
3295
0
                    }
3296
3297
                    /* Set length for IPPrim tree */
3298
0
                    proto_item_set_len(ipprim_tree, offset - offset_before_ipprim_header);
3299
0
                }
3300
0
            }
3301
3302
3303
            /* Try SCTP Prim heuristic if configured to */
3304
0
            if (!protocol_handle && catapult_dct2000_try_sctpprim_heuristic) {
3305
0
                uint32_t     dest_addr_offset = 0;
3306
0
                uint16_t     dest_addr_length = 0;
3307
0
                uint32_t     dest_port_offset = 0;
3308
0
                int          offset_before_sctpprim_header = offset;
3309
3310
0
                heur_protocol_handle = look_for_dissector(protocol_name);
3311
0
                if ((heur_protocol_handle != 0) &&
3312
0
                    (find_sctpprim_variant1_data_offset(tvb, &offset,
3313
0
                                                        &dest_addr_offset,
3314
0
                                                        &dest_addr_length,
3315
0
                                                        &dest_port_offset) ||
3316
0
                     find_sctpprim_variant3_data_offset(tvb, &offset,
3317
0
                                                        &dest_addr_offset,
3318
0
                                                        &dest_addr_length,
3319
0
                                                        &dest_port_offset))) {
3320
3321
0
                    proto_tree *sctpprim_tree;
3322
0
                    proto_item *ti_local;
3323
3324
                    /* Will use this dissector then. */
3325
0
                    protocol_handle = heur_protocol_handle;
3326
3327
0
                    ti_local =  proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_sctpprim_addresses,
3328
0
                                                       tvb, offset_before_sctpprim_header, 0,
3329
0
                                                       "", "SCTPPrim transport:  -> %s:%u",
3330
0
                                                       (dest_addr_offset) ?
3331
0
                                                         ((dest_addr_length == 4) ?
3332
0
                                                              get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
3333
0
                                                              "<ipv6-address>"
3334
0
                                                            ) :
3335
0
                                                           "0.0.0.0",
3336
0
                                                       (dest_port_offset) ?
3337
0
                                                         tvb_get_ntohs(tvb, dest_port_offset) :
3338
0
                                                         0);
3339
3340
                    /* Add these SCTPPRIM fields inside an SCTPPRIM subtree */
3341
0
                    sctpprim_tree = proto_item_add_subtree(ti_local, ett_catapult_dct2000_sctpprim);
3342
3343
                    /* Destination address */
3344
0
                    if (dest_addr_offset != 0) {
3345
0
                        proto_item *addr_ti;
3346
3347
0
                        set_address_tvb(&pinfo->net_dst,
3348
0
                                    (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
3349
0
                                    dest_addr_length, tvb, dest_addr_offset);
3350
0
                        copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
3351
0
                        proto_tree_add_item(sctpprim_tree,
3352
0
                                            (dest_addr_length == 4) ?
3353
0
                                                hf_catapult_dct2000_sctpprim_dst_addr_v4 :
3354
0
                                                hf_catapult_dct2000_sctpprim_dst_addr_v6,
3355
0
                                            tvb, dest_addr_offset, dest_addr_length,
3356
0
                                            ENC_NA);
3357
3358
                        /* Add hidden item for "side-less" addr */
3359
0
                        addr_ti = proto_tree_add_item(sctpprim_tree,
3360
0
                                                      (dest_addr_length == 4) ?
3361
0
                                                          hf_catapult_dct2000_sctpprim_addr_v4 :
3362
0
                                                          hf_catapult_dct2000_sctpprim_addr_v6,
3363
0
                                                      tvb, dest_addr_offset, dest_addr_length,
3364
0
                                                      ENC_NA);
3365
0
                        proto_item_set_hidden(addr_ti);
3366
0
                    }
3367
3368
0
                    if (dest_port_offset != 0) {
3369
0
                        pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
3370
3371
0
                        proto_tree_add_item(sctpprim_tree,
3372
0
                                            hf_catapult_dct2000_sctpprim_dst_port,
3373
0
                                            tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
3374
0
                    }
3375
3376
                    /* Set length for SCTPPrim tree */
3377
0
                    proto_item_set_len(sctpprim_tree, offset - offset_before_sctpprim_header);
3378
0
                }
3379
0
            }
3380
3381
            /* Next chance: is there a (private) registered protocol of the form
3382
               "dct2000.protocol" ? */
3383
0
            if (protocol_handle == 0) {
3384
                /* TODO: only look inside if a preference enabled? */
3385
0
                char dotted_protocol_name[128];
3386
                /* N.B. avoiding snprintf(), which was slow */
3387
0
                (void) g_strlcpy(dotted_protocol_name, "dct2000.", 128);
3388
0
                (void) g_strlcpy(dotted_protocol_name+8, protocol_name, 128-8);
3389
0
                protocol_handle = find_dissector(dotted_protocol_name);
3390
0
            }
3391
3392
            /* Last resort: Allow any PDU to be dissected if the protocol matches with
3393
               a dissector name */
3394
0
            if ( !protocol_handle && catapult_dct2000_use_protocol_name_as_dissector_name) {
3395
0
                protocol_handle = find_dissector(protocol_name);
3396
0
            }
3397
3398
3399
0
            break;
3400
3401
0
        default:
3402
            /* !! If get here, there is a mismatch between
3403
               this dissector and the wiretap module catapult_dct2000.c !!
3404
            */
3405
0
            DISSECTOR_ASSERT_NOT_REACHED();
3406
0
            return 0;
3407
0
    }
3408
3409
    /* Set selection length of dct2000 tree */
3410
0
    proto_item_set_len(dct2000_tree, offset);
3411
3412
    /* Try appropriate dissector, if one has been selected */
3413
0
    if (protocol_handle != 0) {
3414
        /* Dissect the remainder of the frame using chosen protocol handle */
3415
0
        next_tvb = tvb_new_subset_remaining(tvb, offset);
3416
0
        sub_dissector_result = call_dissector_only(protocol_handle, next_tvb, pinfo, tree, protocol_data);
3417
0
    }
3418
3419
3420
0
    if (protocol_handle == 0 || sub_dissector_result == 0) {
3421
        /* Could get here because:
3422
           - encap is DCT2000_ENCAP_UNHANDLED and we still didn't handle it, OR
3423
           - desired protocol is unavailable (probably disabled), OR
3424
           - protocol rejected our data
3425
           Show remaining bytes as unparsed data */
3426
0
        proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_unparsed_data,
3427
0
                            tvb, offset, -1, ENC_NA);
3428
3429
0
        col_add_fstr(pinfo->cinfo, COL_INFO,
3430
0
                     "Not dissected  (context=%s.%u   t=%s   %c   prot=%s (v=%s))",
3431
0
                     context_name,
3432
0
                     port_number,
3433
0
                     timestamp_string,
3434
0
                     (direction == 0) ? 'S' : 'R',
3435
0
                     protocol_name,
3436
0
                     variant_string);
3437
0
    }
3438
0
    else {
3439
        /* Show number of dissected bytes */
3440
0
        if (dct2000_tree) {
3441
0
            proto_item *ti_local = proto_tree_add_uint(dct2000_tree,
3442
0
                                                 hf_catapult_dct2000_dissected_length,
3443
0
                                                 tvb, 0, 0, tvb_reported_length(tvb)-offset);
3444
0
            proto_item_set_generated(ti_local);
3445
0
        }
3446
0
    }
3447
3448
0
    return tvb_captured_length(tvb);
3449
0
}
3450
3451
3452
3453
/******************************************************************************/
3454
/* Associate this protocol with the Catapult DCT2000 file encapsulation type. */
3455
/******************************************************************************/
3456
void proto_reg_handoff_catapult_dct2000(void)
3457
16
{
3458
16
    dissector_add_uint("wtap_encap", WTAP_ENCAP_CATAPULT_DCT2000, catapult_dct2000_handle);
3459
3460
16
    mac_lte_handle = find_dissector("mac-lte");
3461
16
    rlc_lte_handle = find_dissector("rlc-lte");
3462
16
    pdcp_lte_handle = find_dissector("pdcp-lte");
3463
3464
16
    mac_nr_handle = find_dissector("mac-nr");
3465
16
    nrup_handle = find_dissector("nrup");
3466
16
    eth_handle = find_dissector("eth_withoutfcs");
3467
16
    nrup_handle = find_dissector("nrup");
3468
3469
16
    proto_fp = proto_get_id_by_filter_name("fp");
3470
16
    proto_umts_rlc = proto_get_id_by_filter_name("rlc");
3471
16
    proto_rlc_lte = proto_get_id_by_filter_name("rlc-lte");
3472
16
    proto_pdcp_lte = proto_get_id_by_filter_name("pdcp-lte");
3473
16
}
3474
3475
/****************************************/
3476
/* Register the protocol                */
3477
/****************************************/
3478
void proto_register_catapult_dct2000(void)
3479
16
{
3480
16
    static hf_register_info hf[] =
3481
16
    {
3482
16
        { &hf_catapult_dct2000_context,
3483
16
            { "Context",
3484
16
              "dct2000.context", FT_STRING, BASE_NONE, NULL, 0x0,
3485
16
              "Context name", HFILL
3486
16
            }
3487
16
        },
3488
16
        { &hf_catapult_dct2000_port_number,
3489
16
            { "Context Port number",
3490
16
              "dct2000.context_port", FT_UINT8, BASE_DEC, NULL, 0x0,
3491
16
              NULL, HFILL
3492
16
            }
3493
16
        },
3494
16
        { &hf_catapult_dct2000_timestamp,
3495
16
            { "Timestamp",
3496
16
              "dct2000.timestamp", FT_DOUBLE, BASE_NONE, NULL, 0x0,
3497
16
              "File timestamp", HFILL
3498
16
            }
3499
16
        },
3500
16
        { &hf_catapult_dct2000_protocol,
3501
16
            { "DCT2000 protocol",
3502
16
              "dct2000.protocol", FT_STRING, BASE_NONE, NULL, 0x0,
3503
16
              "Original (DCT2000) protocol name", HFILL
3504
16
            }
3505
16
        },
3506
16
        { &hf_catapult_dct2000_variant,
3507
16
            { "Protocol variant",
3508
16
              "dct2000.variant", FT_STRING, BASE_NONE, NULL, 0x0,
3509
16
              "DCT2000 protocol variant", HFILL
3510
16
            }
3511
16
        },
3512
16
        { &hf_catapult_dct2000_outhdr,
3513
16
            { "Out-header",
3514
16
              "dct2000.outhdr", FT_STRING, BASE_NONE, NULL, 0x0,
3515
16
              "DCT2000 protocol outhdr", HFILL
3516
16
            }
3517
16
        },
3518
16
        { &hf_catapult_dct2000_direction,
3519
16
            { "Direction",
3520
16
              "dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3521
16
              "Frame direction (Sent or Received)", HFILL
3522
16
            }
3523
16
        },
3524
16
        { &hf_catapult_dct2000_encap,
3525
16
            { "Wireshark encapsulation",
3526
16
              "dct2000.encapsulation", FT_UINT8, BASE_DEC, VALS(encap_vals), 0x0,
3527
16
              "Wireshark frame encapsulation used", HFILL
3528
16
            }
3529
16
        },
3530
16
        { &hf_catapult_dct2000_unparsed_data,
3531
16
            { "Unparsed protocol data",
3532
16
              "dct2000.unparsed_data", FT_BYTES, BASE_NONE, NULL, 0x0,
3533
16
              "Unparsed DCT2000 protocol data", HFILL
3534
16
            }
3535
16
        },
3536
16
        { &hf_catapult_dct2000_comment,
3537
16
            { "Comment",
3538
16
              "dct2000.comment", FT_STRING, BASE_NONE, NULL, 0x0,
3539
16
              NULL, HFILL
3540
16
            }
3541
16
        },
3542
16
        { &hf_catapult_dct2000_sprint,
3543
16
            { "Sprint text",
3544
16
              "dct2000.sprint", FT_STRING, BASE_NONE, NULL, 0x0,
3545
16
              NULL, HFILL
3546
16
            }
3547
16
        },
3548
16
        { &hf_catapult_dct2000_error_comment,
3549
16
            { "Error comment",
3550
16
              "dct2000.error-comment", FT_NONE, BASE_NONE, NULL, 0x0,
3551
16
              NULL, HFILL
3552
16
            }
3553
16
        },
3554
16
        { &hf_catapult_dct2000_dissected_length,
3555
16
            { "Dissected length",
3556
16
              "dct2000.dissected-length", FT_UINT16, BASE_DEC, NULL, 0x0,
3557
16
              "Number of bytes dissected by subdissector(s)", HFILL
3558
16
            }
3559
16
        },
3560
3561
16
        { &hf_catapult_dct2000_ipprim_addresses,
3562
16
            { "IPPrim Addresses",
3563
16
              "dct2000.ipprim", FT_STRING, BASE_NONE, NULL, 0x0,
3564
16
              NULL, HFILL
3565
16
            }
3566
16
        },
3567
16
        { &hf_catapult_dct2000_ipprim_src_addr_v4,
3568
16
            { "Source Address",
3569
16
              "dct2000.ipprim.src", FT_IPv4, BASE_NONE, NULL, 0x0,
3570
16
              "IPPrim IPv4 Source Address", HFILL
3571
16
            }
3572
16
        },
3573
16
        { &hf_catapult_dct2000_ipprim_src_addr_v6,
3574
16
            { "Source Address",
3575
16
              "dct2000.ipprim.srcv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3576
16
              "IPPrim IPv6 Source Address", HFILL
3577
16
            }
3578
16
        },
3579
16
        { &hf_catapult_dct2000_ipprim_dst_addr_v4,
3580
16
            { "Destination Address",
3581
16
              "dct2000.ipprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3582
16
              "IPPrim IPv4 Destination Address", HFILL
3583
16
            }
3584
16
        },
3585
16
        { &hf_catapult_dct2000_ipprim_dst_addr_v6,
3586
16
            { "Destination Address",
3587
16
              "dct2000.ipprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3588
16
              "IPPrim IPv6 Destination Address", HFILL
3589
16
            }
3590
16
        },
3591
16
        { &hf_catapult_dct2000_ipprim_addr_v4,
3592
16
            { "Address",
3593
16
              "dct2000.ipprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3594
16
              "IPPrim IPv4 Address", HFILL
3595
16
            }
3596
16
        },
3597
16
        { &hf_catapult_dct2000_ipprim_addr_v6,
3598
16
            { "Address",
3599
16
              "dct2000.ipprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3600
16
              "IPPrim IPv6 Address", HFILL
3601
16
            }
3602
16
        },
3603
16
        { &hf_catapult_dct2000_ipprim_udp_src_port,
3604
16
            { "UDP Source Port",
3605
16
              "dct2000.ipprim.udp.srcport", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
3606
16
              "IPPrim UDP Source Port", HFILL
3607
16
            }
3608
16
        },
3609
16
        { &hf_catapult_dct2000_ipprim_udp_dst_port,
3610
16
            { "UDP Destination Port",
3611
16
              "dct2000.ipprim.udp.dstport", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
3612
16
              "IPPrim UDP Destination Port", HFILL
3613
16
            }
3614
16
        },
3615
16
        { &hf_catapult_dct2000_ipprim_udp_port,
3616
16
            { "UDP Port",
3617
16
              "dct2000.ipprim.udp.port", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
3618
16
              "IPPrim UDP Port", HFILL
3619
16
            }
3620
16
        },
3621
16
        { &hf_catapult_dct2000_ipprim_tcp_src_port,
3622
16
            { "TCP Source Port",
3623
16
              "dct2000.ipprim.tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
3624
16
              "IPPrim TCP Source Port", HFILL
3625
16
            }
3626
16
        },
3627
16
        { &hf_catapult_dct2000_ipprim_tcp_dst_port,
3628
16
            { "TCP Destination Port",
3629
16
              "dct2000.ipprim.tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
3630
16
              "IPPrim TCP Destination Port", HFILL
3631
16
            }
3632
16
        },
3633
16
        { &hf_catapult_dct2000_ipprim_tcp_port,
3634
16
            { "TCP Port",
3635
16
              "dct2000.ipprim.tcp.port", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
3636
16
              "IPPrim TCP Port", HFILL
3637
16
            }
3638
16
        },
3639
16
        { &hf_catapult_dct2000_ipprim_conn_id,
3640
16
            { "Conn Id",
3641
16
              "dct2000.ipprim.conn-id", FT_UINT16, BASE_DEC, NULL, 0x0,
3642
16
              "IPPrim TCP Connection ID", HFILL
3643
16
            }
3644
16
        },
3645
3646
16
        { &hf_catapult_dct2000_sctpprim_addresses,
3647
16
            { "SCTPPrim Addresses",
3648
16
              "dct2000.sctpprim", FT_STRING, BASE_NONE, NULL, 0x0,
3649
16
              NULL, HFILL
3650
16
            }
3651
16
        },
3652
16
        { &hf_catapult_dct2000_sctpprim_dst_addr_v4,
3653
16
            { "Destination Address",
3654
16
              "dct2000.sctpprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3655
16
              "SCTPPrim IPv4 Destination Address", HFILL
3656
16
            }
3657
16
        },
3658
16
        { &hf_catapult_dct2000_sctpprim_dst_addr_v6,
3659
16
            { "Destination Address",
3660
16
              "dct2000.sctpprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3661
16
              "SCTPPrim IPv6 Destination Address", HFILL
3662
16
            }
3663
16
        },
3664
16
        { &hf_catapult_dct2000_sctpprim_addr_v4,
3665
16
            { "Address",
3666
16
              "dct2000.sctpprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3667
16
              "SCTPPrim IPv4 Address", HFILL
3668
16
            }
3669
16
        },
3670
16
        { &hf_catapult_dct2000_sctpprim_addr_v6,
3671
16
            { "Address",
3672
16
              "dct2000.sctpprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3673
16
              "SCTPPrim IPv6 Address", HFILL
3674
16
            }
3675
16
        },
3676
16
        { &hf_catapult_dct2000_sctpprim_dst_port,
3677
16
            { "UDP Destination Port",
3678
16
              "dct2000.sctprim.dstport", FT_UINT16, BASE_PT_SCTP, NULL, 0x0,
3679
16
              "SCTPPrim Destination Port", HFILL
3680
16
            }
3681
16
        },
3682
3683
16
        { &hf_catapult_dct2000_tty,
3684
16
            { "tty contents",
3685
16
              "dct2000.tty", FT_NONE, BASE_NONE, NULL, 0x0,
3686
16
              NULL, HFILL
3687
16
            }
3688
16
        },
3689
16
        { &hf_catapult_dct2000_tty_line,
3690
16
            { "tty line",
3691
16
              "dct2000.tty-line", FT_STRING, BASE_NONE, NULL, 0x0,
3692
16
              NULL, HFILL
3693
16
            }
3694
16
        },
3695
3696
16
        { &hf_catapult_dct2000_ueid,
3697
16
            { "UE Id",
3698
16
              "dct2000.ueid", FT_UINT16, BASE_DEC, NULL, 0x0,
3699
16
              "User Equipment Identifier", HFILL
3700
16
            }
3701
16
        },
3702
16
        { &hf_catapult_dct2000_srbid,
3703
16
            { "srbid",
3704
16
              "dct2000.srbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3705
16
              "Signalling Radio Bearer Identifier", HFILL
3706
16
            }
3707
16
        },
3708
16
        { &hf_catapult_dct2000_drbid,
3709
16
            { "drbid",
3710
16
              "dct2000.drbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3711
16
              "Data Radio Bearer Identifier", HFILL
3712
16
            }
3713
16
        },
3714
16
        { &hf_catapult_dct2000_cellid,
3715
16
            { "Cell-Id",
3716
16
              "dct2000.cellid", FT_UINT16, BASE_DEC, NULL, 0x0,
3717
16
              "Cell Identifier", HFILL
3718
16
            }
3719
16
        },
3720
16
        { &hf_catapult_dct2000_bcch_transport,
3721
16
            { "BCCH Transport",
3722
16
              "dct2000.bcch-transport", FT_UINT16, BASE_DEC, VALS(bcch_transport_vals), 0x0,
3723
16
              "BCCH Transport Channel", HFILL
3724
16
            }
3725
16
        },
3726
16
        { &hf_catapult_dct2000_rlc_op,
3727
16
            { "RLC Op",
3728
16
              "dct2000.rlc-op", FT_UINT8, BASE_DEC, VALS(rlc_op_vals), 0x0,
3729
16
              "RLC top-level op", HFILL
3730
16
            }
3731
16
        },
3732
16
        { &hf_catapult_dct2000_rlc_channel_type,
3733
16
            { "RLC Logical Channel Type",
3734
16
              "dct2000.rlc-logchan-type", FT_UINT8, BASE_DEC, VALS(rlc_logical_channel_vals), 0x0,
3735
16
              NULL, HFILL
3736
16
            }
3737
16
        },
3738
16
        { &hf_catapult_dct2000_rlc_mui,
3739
16
            { "MUI",
3740
16
              "dct2000.rlc-mui", FT_UINT16, BASE_DEC, NULL, 0x0,
3741
16
              "RLC MUI", HFILL
3742
16
            }
3743
16
        },
3744
16
        { &hf_catapult_dct2000_rlc_cnf,
3745
16
            { "CNF",
3746
16
              "dct2000.rlc-cnf", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3747
16
              "RLC CNF", HFILL
3748
16
            }
3749
16
        },
3750
16
        { &hf_catapult_dct2000_rlc_discard_req,
3751
16
            { "Discard Req",
3752
16
              "dct2000.rlc-discard-req", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3753
16
              "RLC Discard Req", HFILL
3754
16
            }
3755
16
        },
3756
16
        { &hf_catapult_dct2000_carrier_type,
3757
16
            { "Carrier Type",
3758
16
              "dct2000.carrier-type", FT_UINT8, BASE_DEC, VALS(carrier_type_vals), 0x0,
3759
16
              NULL, HFILL
3760
16
            }
3761
16
        },
3762
16
        { &hf_catapult_dct2000_cell_group,
3763
16
            { "Cell Group",
3764
16
              "dct2000.cell-group", FT_UINT8, BASE_DEC, NULL, 0x0,
3765
16
              NULL, HFILL
3766
16
            }
3767
16
        },
3768
16
        { &hf_catapult_dct2000_carrier_id,
3769
16
            { "Carrier Id",
3770
16
              "dct2000.carrier-id", FT_UINT8, BASE_DEC, NULL, 0x0,
3771
16
              NULL, HFILL
3772
16
            }
3773
16
        },
3774
3775
16
        { &hf_catapult_dct2000_security_mode_params,
3776
16
            { "Security Mode Params",
3777
16
              "dct2000.security-mode-params", FT_NONE, BASE_NONE, NULL, 0x0,
3778
16
              NULL, HFILL
3779
16
            }
3780
16
        },
3781
16
        { &hf_catapult_dct2000_uplink_sec_mode,
3782
16
            { "Uplink Security Mode",
3783
16
              "dct2000.uplink-security-mode", FT_UINT8, BASE_DEC, VALS(security_mode_vals), 0x0,
3784
16
              NULL, HFILL
3785
16
            }
3786
16
        },
3787
16
        { &hf_catapult_dct2000_downlink_sec_mode,
3788
16
            { "Downlink Security Mode",
3789
16
              "dct2000.downlink-security-mode", FT_UINT8, BASE_DEC, VALS(security_mode_vals), 0x0,
3790
16
              NULL, HFILL
3791
16
            }
3792
16
        },
3793
16
        { &hf_catapult_dct2000_ciphering_algorithm,
3794
16
            { "Ciphering Algorithm",
3795
16
              "dct2000.ciphering-algorithm", FT_UINT8, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
3796
16
              NULL, HFILL
3797
16
            }
3798
16
        },
3799
16
        { &hf_catapult_dct2000_ciphering_key,
3800
16
            { "Ciphering Key",
3801
16
              "dct2000.ciphering-key", FT_BYTES, BASE_NONE, NULL, 0x0,
3802
16
              NULL, HFILL
3803
16
            }
3804
16
        },
3805
16
        { &hf_catapult_dct2000_integrity_algorithm,
3806
16
            { "Integrity Algorithm",
3807
16
              "dct2000.integrity-algorithm", FT_UINT8, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
3808
16
              NULL, HFILL
3809
16
            }
3810
16
        },
3811
16
        { &hf_catapult_dct2000_integrity_key,
3812
16
            { "Integrity Key",
3813
16
              "dct2000.integrity-key", FT_BYTES, BASE_NONE, NULL, 0x0,
3814
16
              NULL, HFILL
3815
16
            }
3816
16
        },
3817
3818
16
        { &hf_catapult_dct2000_lte_ccpri_opcode,
3819
16
            { "CCPRI opcode",
3820
16
              "dct2000.lte.ccpri.opcode", FT_UINT8, BASE_DEC, VALS(ccpri_opcode_vals), 0x0,
3821
16
              NULL, HFILL
3822
16
            }
3823
16
        },
3824
16
        { &hf_catapult_dct2000_lte_ccpri_status,
3825
16
            { "Status",
3826
16
              "dct2000.lte.ccpri.status", FT_BOOLEAN, BASE_NONE, TFS(&tfs_error_ok), 0x0,
3827
16
              NULL, HFILL
3828
16
            }
3829
16
        },
3830
16
        { &hf_catapult_dct2000_lte_ccpri_channel,
3831
16
            { "Channel",
3832
16
              "dct2000.lte.ccpri.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
3833
16
              NULL, HFILL
3834
16
            }
3835
16
        },
3836
3837
16
        { &hf_catapult_dct2000_lte_nas_rrc_opcode,
3838
16
            { "NAS RRC Opcode",
3839
16
              "dct2000.lte.nas-rrc.opcode", FT_UINT8, BASE_DEC, VALS(lte_nas_rrc_opcode_vals), 0x0,
3840
16
              NULL, HFILL
3841
16
            }
3842
16
        },
3843
16
        { &hf_catapult_dct2000_lte_nas_rrc_establish_cause,
3844
16
            { "Establish Cause",
3845
16
              "dct2000.lte.nas-rrc.establish-cause", FT_UINT8, BASE_DEC, NULL, 0x0,
3846
16
              NULL, HFILL
3847
16
            }
3848
16
        },
3849
16
        { &hf_catapult_dct2000_lte_nas_rrc_priority,
3850
16
            { "Priority",
3851
16
              "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3852
16
              NULL, HFILL
3853
16
            }
3854
16
        },
3855
16
        { &hf_catapult_dct2000_lte_nas_rrc_release_cause,
3856
16
            { "Priority",
3857
16
              "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3858
16
              NULL, HFILL
3859
16
            }
3860
16
        },
3861
16
        { &hf_catapult_dct2000_nr_nas_s1ap_opcode,
3862
16
            { "NAS S1AP Opcode",
3863
16
              "dct2000.nas-s1ap.opcode", FT_UINT8, BASE_DEC, VALS(nas_s1ap_opcode_vals), 0x0,
3864
16
              NULL, HFILL
3865
16
            }
3866
16
        },
3867
3868
16
        { &hf_catapult_dct2000_rbid,
3869
16
            { "Channel",
3870
16
              "dct2000.rbid", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &rlc_rbid_vals_ext, 0x0,
3871
16
              "Channel (rbid)", HFILL
3872
16
            }
3873
16
        },
3874
16
        { &hf_catapult_dct2000_ccch_id,
3875
16
            { "CCCH Id",
3876
16
              "dct2000.ccch-id", FT_UINT8, BASE_DEC, NULL, 0x0,
3877
16
              "CCCH Identifier", HFILL
3878
16
            }
3879
16
        },
3880
16
        { &hf_catapult_dct2000_no_crc_error,
3881
16
            { "No CRC Error",
3882
16
              "dct2000.no-crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3883
16
              NULL, HFILL
3884
16
            }
3885
16
        },
3886
16
        { &hf_catapult_dct2000_crc_error,
3887
16
            { "CRC Error",
3888
16
              "dct2000.crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3889
16
              NULL, HFILL
3890
16
            }
3891
16
        },
3892
16
        { &hf_catapult_dct2000_clear_tx_buffer,
3893
16
            { "Clear Tx Buffer",
3894
16
              "dct2000.clear-tx-buffer", FT_NONE, BASE_NONE, NULL, 0x0,
3895
16
              NULL, HFILL
3896
16
            }
3897
16
        },
3898
16
        { &hf_catapult_dct2000_buffer_occupancy,
3899
16
            { "Buffer Occupancy",
3900
16
              "dct2000.buffer-occupancy", FT_UINT8, BASE_DEC, NULL, 0x0,
3901
16
              NULL, HFILL
3902
16
            }
3903
16
        },
3904
16
        { &hf_catapult_dct2000_pdu_size,
3905
16
            { "PDU Size",
3906
16
              "dct2000.pdu-size", FT_UINT16, BASE_DEC, NULL, 0x0,
3907
16
              NULL, HFILL
3908
16
            }
3909
16
        },
3910
16
        { &hf_catapult_dct2000_ueid_type,
3911
16
            { "UEId Type",
3912
16
              "dct2000.ueid-type", FT_UINT8, BASE_DEC, VALS(ueid_type_vals), 0x0,
3913
16
              NULL, HFILL
3914
16
            }
3915
16
        },
3916
16
        { &hf_catapult_dct2000_tx_priority,
3917
16
            { "Tx Priority",
3918
16
              "dct2000.tx-priority", FT_BOOLEAN, BASE_NONE, TFS(&tfs_high_normal), 0x0,
3919
16
              NULL, HFILL
3920
16
            }
3921
16
        },
3922
16
        { &hf_catapult_dct2000_last_in_seg_set,
3923
16
            { "Last in seg set",
3924
16
              "dct2000.last-in-seg-set", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3925
16
              NULL, HFILL
3926
16
            }
3927
16
        },
3928
16
        { &hf_catapult_dct2000_rx_timing_deviation,
3929
16
            { "Tx Timing Deviation",
3930
16
              "dct2000.rx-timing-deviation", FT_UINT32, BASE_DEC, NULL, 0x0,
3931
16
              NULL, HFILL
3932
16
            }
3933
16
        },
3934
16
        { &hf_catapult_dct2000_transport_channel_type,
3935
16
            { "Transport Channel Type",
3936
16
              "dct2000.transport_channel_type", FT_UINT8, BASE_DEC, VALS(transport_channel_type_vals), 0x0,
3937
16
              NULL, HFILL
3938
16
            }
3939
16
        },
3940
16
        { &hf_catapult_dct2000_no_padding_bits,
3941
16
            { "Number of padding bits",
3942
16
              "dct2000.number-of-padding-bits", FT_UINT8, BASE_DEC, NULL, 0x0,
3943
16
              NULL, HFILL
3944
16
            }
3945
16
        },
3946
3947
16
        { &hf_catapult_dct2000_rawtraffic_interface,
3948
16
            { "Interface",
3949
16
              "dct2000.rawtraffic.interface", FT_UINT8, BASE_DEC, NULL, 0x0,
3950
16
              NULL, HFILL
3951
16
            }
3952
16
        },
3953
16
        { &hf_catapult_dct2000_rawtraffic_direction,
3954
16
            { "Direction",
3955
16
              "dct2000.rawtraffic.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3956
16
              NULL, HFILL
3957
16
            }
3958
16
        },
3959
16
        { &hf_catapult_dct2000_rawtraffic_pdu,
3960
16
            { "PDU",
3961
16
              "dct2000.rawtraffic.pdu", FT_BYTES, BASE_NONE, NULL, 0x0,
3962
16
              NULL, HFILL
3963
16
            }
3964
16
        }
3965
16
    };
3966
3967
16
    static int *ett[] =
3968
16
    {
3969
16
        &ett_catapult_dct2000,
3970
16
        &ett_catapult_dct2000_ipprim,
3971
16
        &ett_catapult_dct2000_sctpprim,
3972
16
        &ett_catapult_dct2000_tty,
3973
16
        &ett_catapult_dct2000_security_mode_params
3974
16
    };
3975
3976
16
    static ei_register_info ei[] = {
3977
16
        { &ei_catapult_dct2000_lte_ccpri_status_error, { "dct2000.lte.ccpri.status.error", PI_SEQUENCE, PI_ERROR, "CCPRI Indication has error status", EXPFILL }},
3978
16
        { &ei_catapult_dct2000_error_comment_expert, { "dct2000.error-comment.expert", PI_SEQUENCE, PI_ERROR, "Formatted expert comment", EXPFILL }},
3979
16
        { &ei_catapult_dct2000_string_invalid, { "dct2000.string.invalid", PI_MALFORMED, PI_ERROR, "String must contain an integer", EXPFILL }}
3980
16
    };
3981
3982
16
    module_t *catapult_dct2000_module;
3983
16
    expert_module_t* expert_catapult_dct2000;
3984
3985
    /* Register protocol. */
3986
16
    proto_catapult_dct2000 = proto_register_protocol("Catapult DCT2000 packet",
3987
16
                                                     "DCT2000",
3988
16
                                                     "dct2000");
3989
16
    proto_register_field_array(proto_catapult_dct2000, hf, array_length(hf));
3990
16
    proto_register_subtree_array(ett, array_length(ett));
3991
16
    expert_catapult_dct2000 = expert_register_protocol(proto_catapult_dct2000);
3992
16
    expert_register_field_array(expert_catapult_dct2000, ei, array_length(ei));
3993
3994
    /* Allow dissector to find be found by name. */
3995
16
    catapult_dct2000_handle = register_dissector("dct2000", dissect_catapult_dct2000, proto_catapult_dct2000);
3996
3997
    /* Preferences */
3998
16
    catapult_dct2000_module = prefs_register_protocol(proto_catapult_dct2000, NULL);
3999
4000
    /* This preference no longer supported (introduces linkage dependency between
4001
       dissectors and wiretap) */
4002
16
    prefs_register_obsolete_preference(catapult_dct2000_module, "board_ports_only");
4003
16
    prefs_register_obsolete_preference(catapult_dct2000_module, "decode_lte_s1ap");
4004
4005
    /* Determines whether for not-handled protocols we should try to parse it if:
4006
       - it looks like it's embedded in an ipprim message, AND
4007
       - the DCT2000 protocol name can be matched to a Wireshark dissector name */
4008
16
    prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
4009
16
                                   "Use IP Primitive heuristic",
4010
16
                                   "If a payload looks like it's embedded in an "
4011
16
                                   "IP primitive message, and there is a Wireshark "
4012
16
                                   "dissector matching the DCT2000 protocol name, "
4013
16
                                   "try parsing the payload using that dissector",
4014
16
                                   &catapult_dct2000_try_ipprim_heuristic);
4015
4016
    /* Determines whether for not-handled protocols we should try to parse it if:
4017
       - it looks like it's embedded in an sctpprim message, AND
4018
       - the DCT2000 protocol name can be matched to a Wireshark dissector name */
4019
16
    prefs_register_bool_preference(catapult_dct2000_module, "sctpprim_heuristic",
4020
16
                                   "Use SCTP Primitive heuristic",
4021
16
                                   "If a payload looks like it's embedded in an "
4022
16
                                   "SCTP primitive message, and there is a Wireshark "
4023
16
                                   "dissector matching the DCT2000 protocol name, "
4024
16
                                   "try parsing the payload using that dissector",
4025
16
                                   &catapult_dct2000_try_sctpprim_heuristic);
4026
4027
    /* Determines whether LTE RRC messages should be dissected */
4028
16
    prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_rrc",
4029
16
                                   "Attempt to decode LTE RRC frames",
4030
16
                                   "When set, attempt to decode LTE RRC frames. "
4031
16
                                   "Note that this won't affect other protocols "
4032
16
                                   "that also call the LTE RRC dissector",
4033
16
                                   &catapult_dct2000_dissect_lte_rrc);
4034
4035
    /* Determines whether out-of-band messages should dissected */
4036
16
    prefs_register_bool_preference(catapult_dct2000_module, "decode_mac_lte_oob_messages",
4037
16
                                   "Look for out-of-band LTE MAC events messages in comments",
4038
16
                                   "When set, look for formatted messages indicating "
4039
16
                                   "specific events.  This may be quite slow, so should "
4040
16
                                   "be disabled if LTE MAC is not being analysed",
4041
16
                                   &catapult_dct2000_dissect_mac_lte_oob_messages);
4042
4043
    /* Whether old protocol names conversions should be checked */
4044
16
    prefs_register_bool_preference(catapult_dct2000_module, "convert_old_protocol_names",
4045
16
                                   "Convert old protocol names to wireshark dissector names",
4046
16
                                   "When set, look for some older protocol names so that"
4047
16
                                   "they may be matched with wireshark dissectors.",
4048
16
                                   &catapult_dct2000_dissect_old_protocol_names);
4049
4050
    /* Determines if the protocol field in the DCT2000 shall be used to lookup for dissector */
4051
16
    prefs_register_bool_preference(catapult_dct2000_module, "use_protocol_name_as_dissector_name",
4052
16
                                   "Look for a dissector using the protocol name in the "
4053
16
                                   "DCT2000 record",
4054
16
                                   "When set, if there is a Wireshark dissector matching "
4055
16
                                   "the protocol name, it will parse the PDU using "
4056
16
                                   "that dissector. This may be slow, so should be "
4057
16
                                   "disabled unless you are using this feature.",
4058
16
                                   &catapult_dct2000_use_protocol_name_as_dissector_name);
4059
16
}
4060
4061
/*
4062
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
4063
 *
4064
 * Local variables:
4065
 * c-basic-offset: 4
4066
 * tab-width: 8
4067
 * indent-tabs-mode: nil
4068
 * End:
4069
 *
4070
 * vi: set shiftwidth=4 tabstop=8 expandtab:
4071
 * :indentSize=4:tabSize=8:noTabs=true:
4072
 */