1 /* packet-catapult-dct2000.c
2 * Routines for Catapult DCT2000 packet stub header disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <epan/conversation.h>
34 #include <epan/expert.h>
35 #include <epan/emem.h>
36 #include <epan/ipproto.h>
37 #include <epan/prefs.h>
38 #include <epan/strutil.h>
39 #include <epan/addr_resolv.h>
41 #include <wiretap/catapult_dct2000.h>
42 #include "packet-umts_fp.h"
43 #include "packet-rlc.h"
45 #include "packet-mac-lte.h"
46 #include "packet-rlc-lte.h"
47 #include "packet-pdcp-lte.h"
49 /* Protocol and registered fields. */
50 static int proto_catapult_dct2000 = -1;
52 static int hf_catapult_dct2000_context = -1;
53 static int hf_catapult_dct2000_port_number = -1;
54 static int hf_catapult_dct2000_timestamp = -1;
55 static int hf_catapult_dct2000_protocol = -1;
56 static int hf_catapult_dct2000_variant = -1;
57 static int hf_catapult_dct2000_outhdr = -1;
58 static int hf_catapult_dct2000_direction = -1;
59 static int hf_catapult_dct2000_encap = -1;
60 static int hf_catapult_dct2000_unparsed_data = -1;
61 static int hf_catapult_dct2000_comment = -1;
62 static int hf_catapult_dct2000_error_comment = -1;
63 static int hf_catapult_dct2000_tty = -1;
64 static int hf_catapult_dct2000_tty_line = -1;
65 static int hf_catapult_dct2000_dissected_length = -1;
67 static int hf_catapult_dct2000_ipprim_addresses = -1;
68 static int hf_catapult_dct2000_ipprim_src_addr_v4 = -1;
69 static int hf_catapult_dct2000_ipprim_src_addr_v6 = -1;
70 static int hf_catapult_dct2000_ipprim_dst_addr_v4 = -1;
71 static int hf_catapult_dct2000_ipprim_dst_addr_v6 = -1;
72 static int hf_catapult_dct2000_ipprim_addr_v4 = -1;
73 static int hf_catapult_dct2000_ipprim_addr_v6 = -1;
74 static int hf_catapult_dct2000_ipprim_udp_src_port = -1;
75 static int hf_catapult_dct2000_ipprim_udp_dst_port = -1;
76 static int hf_catapult_dct2000_ipprim_udp_port = -1;
77 static int hf_catapult_dct2000_ipprim_tcp_src_port = -1;
78 static int hf_catapult_dct2000_ipprim_tcp_dst_port = -1;
79 static int hf_catapult_dct2000_ipprim_tcp_port = -1;
80 static int hf_catapult_dct2000_ipprim_conn_id = -1;
82 static int hf_catapult_dct2000_sctpprim_addresses = -1;
83 static int hf_catapult_dct2000_sctpprim_dst_addr_v4 = -1;
84 static int hf_catapult_dct2000_sctpprim_dst_addr_v6 = -1;
85 static int hf_catapult_dct2000_sctpprim_addr_v4 = -1;
86 static int hf_catapult_dct2000_sctpprim_addr_v6 = -1;
87 static int hf_catapult_dct2000_sctpprim_dst_port = -1;
89 static int hf_catapult_dct2000_lte_ueid = -1;
90 static int hf_catapult_dct2000_lte_srbid = -1;
91 static int hf_catapult_dct2000_lte_drbid = -1;
92 static int hf_catapult_dct2000_lte_cellid = -1;
93 static int hf_catapult_dct2000_lte_bcch_transport = -1;
94 static int hf_catapult_dct2000_lte_rlc_op = -1;
95 static int hf_catapult_dct2000_lte_rlc_channel_type = -1;
96 static int hf_catapult_dct2000_lte_rlc_mui = -1;
97 static int hf_catapult_dct2000_lte_rlc_cnf = -1;
98 static int hf_catapult_dct2000_lte_rlc_discard_req = -1;
100 static int hf_catapult_dct2000_lte_ccpri_opcode = -1;
101 static int hf_catapult_dct2000_lte_ccpri_status = -1;
102 static int hf_catapult_dct2000_lte_ccpri_channel = -1;
104 static int hf_catapult_dct2000_lte_monitor_cpu_user = -1;
105 static int hf_catapult_dct2000_lte_monitor_cpu_sys = -1;
106 static int hf_catapult_dct2000_lte_monitor_cpu_load = -1;
107 static int hf_catapult_dct2000_lte_monitor_lte_scs_cpu_user = -1;
108 static int hf_catapult_dct2000_lte_monitor_lte_scs_cpu_sys = -1;
111 static int hf_catapult_dct2000_lte_nas_rrc_opcode = -1;
112 static int hf_catapult_dct2000_lte_nas_rrc_establish_cause = -1;
113 static int hf_catapult_dct2000_lte_nas_rrc_priority = -1;
114 static int hf_catapult_dct2000_lte_nas_rrc_release_cause = -1;
117 /* UMTS RLC fields */
118 static int hf_catapult_dct2000_ueid = -1;
119 static int hf_catapult_dct2000_rbid = -1;
120 static int hf_catapult_dct2000_ccch_id = -1;
121 static int hf_catapult_dct2000_no_crc_error = -1;
122 static int hf_catapult_dct2000_crc_error = -1;
123 static int hf_catapult_dct2000_clear_tx_buffer = -1;
124 static int hf_catapult_dct2000_buffer_occupancy = -1;
125 static int hf_catapult_dct2000_pdu_size = -1;
126 static int hf_catapult_dct2000_ueid_type = -1;
127 static int hf_catapult_dct2000_tx_priority = -1;
128 static int hf_catapult_dct2000_last_in_seg_set = -1;
129 static int hf_catapult_dct2000_rx_timing_deviation = -1;
130 static int hf_catapult_dct2000_transport_channel_type = -1;
131 static int hf_catapult_dct2000_no_padding_bits = -1;
133 /* Variables used for preferences */
134 static gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
135 static gboolean catapult_dct2000_try_sctpprim_heuristic = TRUE;
136 static gboolean catapult_dct2000_dissect_lte_rrc = TRUE;
137 static gboolean catapult_dct2000_dissect_lte_s1ap = TRUE;
138 static gboolean catapult_dct2000_dissect_mac_lte_oob_messages = TRUE;
140 /* Protocol subtree. */
141 static int ett_catapult_dct2000 = -1;
142 static int ett_catapult_dct2000_ipprim = -1;
143 static int ett_catapult_dct2000_sctpprim = -1;
144 static int ett_catapult_dct2000_tty = -1;
146 static const value_string direction_vals[] = {
152 static const value_string encap_vals[] = {
153 { WTAP_ENCAP_RAW_IP, "Raw IP" },
154 { WTAP_ENCAP_ETHERNET, "Ethernet" },
155 { WTAP_ENCAP_ISDN, "LAPD" },
156 { WTAP_ENCAP_ATM_PDUS_UNTRUNCATED, "ATM (PDUs untruncated)" },
157 { WTAP_ENCAP_PPP, "PPP" },
158 { DCT2000_ENCAP_SSCOP, "SSCOP" },
159 { WTAP_ENCAP_FRELAY, "Frame Relay" },
160 { WTAP_ENCAP_MTP2, "MTP2" },
161 { DCT2000_ENCAP_NBAP, "NBAP" },
162 { DCT2000_ENCAP_UNHANDLED, "No Direct Encapsulation" },
166 static const value_string bcch_transport_vals[] = {
167 { BCH_TRANSPORT, "BCH" },
168 { DLSCH_TRANSPORT, "DLSCH" },
173 #define RLC_MGMT_ASSIGN 0x41
174 #define RLC_AM_DATA_REQ 0x60
175 #define RLC_AM_DATA_IND 0x61
176 #define RLC_AM_DATA_CONF 0x62
177 #define RLC_UM_DATA_REQ 0x70
178 #define RLC_UM_DATA_IND 0x71
179 #define RLC_UM_DATA_CONF 0x74
180 #define RLC_TR_DATA_REQ 0x80
181 #define RLC_TR_DATA_IND 0x81
182 #define RLC_TR_DATA_CONF 0x83
184 static const value_string rlc_op_vals[] = {
185 { RLC_AM_DATA_REQ, "[UL] [AM]" },
186 { RLC_AM_DATA_IND, "[DL] [AM]" },
187 { RLC_UM_DATA_REQ, "[UL] [UM]"},
188 { RLC_UM_DATA_IND, "[DL] [UM]"},
189 { RLC_TR_DATA_REQ, "[UL] [TM]"},
190 { RLC_TR_DATA_IND, "[DL] [TM]"},
195 static const value_string rlc_logical_channel_vals[] = {
196 { Channel_DCCH, "DCCH"},
197 { Channel_BCCH, "BCCH"},
198 { Channel_CCCH, "CCCH"},
199 { Channel_PCCH, "PCCH"},
207 static const value_string ccpri_opcode_vals[] = {
208 { CCPRI_REQ, "REQUEST"},
209 { CCPRI_IND, "INDICATION"},
213 static const value_string ccpri_status_vals[] = {
219 static const value_string rlc_rbid_vals[] = {
246 static const value_string ueid_type_vals[] = {
252 static const value_string tx_priority_vals[] = {
258 static const value_string transport_channel_type_vals[] = {
271 #define LTE_NAS_RRC_DATA_IND 0x02
272 #define LTE_NAS_RRC_DATA_REQ 0x03
273 #define LTE_NAS_RRC_ESTABLISH_REQ 0x06
274 #define LTE_NAS_RRC_RELEASE_IND 0x08
276 static const value_string lte_nas_rrc_opcode_vals[] = {
277 { LTE_NAS_RRC_DATA_IND, "Data-Ind"},
278 { LTE_NAS_RRC_DATA_REQ, "Data-Req"},
279 { LTE_NAS_RRC_ESTABLISH_REQ, "Establish-Req"},
280 { LTE_NAS_RRC_RELEASE_IND, "Release-Ind"},
286 #define MAX_OUTHDR_VALUES 32
288 static guint outhdr_values[MAX_OUTHDR_VALUES];
289 static guint outhdr_values_found = 0;
292 extern int proto_rlc;
294 extern int proto_rlc_lte;
295 extern int proto_pdcp_lte;
297 static dissector_handle_t mac_lte_handle;
298 static dissector_handle_t rlc_lte_handle;
299 static dissector_handle_t pdcp_lte_handle;
301 void proto_register_catapult_dct2000(void);
303 static dissector_handle_t look_for_dissector(const char *protocol_name);
304 static void parse_outhdr_string(const guchar *outhdr_string, gint outhdr_length);
306 static void attach_fp_info(packet_info *pinfo, gboolean received,
307 const char *protocol_name, int variant);
308 static void attach_rlc_info(packet_info *pinfo, guint32 urnti, guint8 rbid,
311 static void attach_mac_lte_info(packet_info *pinfo);
312 static void attach_rlc_lte_info(packet_info *pinfo);
313 static void attach_pdcp_lte_info(packet_info *pinfo);
317 /* Return the number of bytes used to encode the length field
318 (we're not interested in the length value itself) */
319 static int skipASNLength(guint8 value)
321 if ((value & 0x80) == 0)
327 return ((value & 0x03) == 1) ? 2 : 3;
332 /* Look for the protocol data within an ipprim packet.
333 Only set *data_offset if data field found. */
334 static gboolean find_ipprim_data_offset(tvbuff_t *tvb, int *data_offset, guint8 direction,
335 guint32 *source_addr_offset, guint8 *source_addr_length,
336 guint32 *dest_addr_offset, guint8 *dest_addr_length,
337 guint32 *source_port_offset, guint32 *dest_port_offset,
338 port_type *type_of_port,
339 guint16 *conn_id_offset)
342 int offset = *data_offset;
344 /* Get the ipprim command code. */
345 guint8 tag = tvb_get_guint8(tvb, offset++);
347 /* Only accept UDP or TCP data request or indication */
349 case 0x23: /* UDP data request */
350 case 0x24: /* UDP data indication */
351 *type_of_port = PT_UDP;
353 case 0x45: /* TCP data request */
354 case 0x46: /* TCP data indication */
355 *type_of_port = PT_TCP;
361 /* Skip any other TLC fields before reach payload */
362 while (tvb_length_remaining(tvb, offset) > 2) {
363 /* Look at next tag */
364 tag = tvb_get_guint8(tvb, offset++);
366 /* Is this the data payload we're expecting? */
367 if (((tag == 0x34) && (*type_of_port == PT_UDP)) ||
368 ((tag == 0x48) && (*type_of_port == PT_TCP))) {
370 *data_offset = offset;
374 /* Read length in next byte */
375 length = tvb_get_guint8(tvb, offset++);
377 if (tag == 0x31 && length >=4) {
378 /* Remote IP address */
379 if (direction == 0) {
380 /* Sent *to* remote, so dest */
381 *dest_addr_offset = offset;
382 *dest_addr_length = (length/4) * 4;
385 *source_addr_offset = offset;
386 *source_addr_length = (length/4) * 4;
389 /* Remote port follows (if present) */
390 if ((length % 4) == 2) {
391 if (direction == 0) {
392 *dest_port_offset = offset + *dest_addr_length;
395 *source_port_offset = offset + *source_addr_length;
401 if (length == 4 || length == 16) {
402 /* Local IP address */
403 if (direction == 0) {
404 /* Sent *from* local, so source */
405 *source_addr_offset = offset;
406 *source_addr_length = length;
409 *dest_addr_offset = offset;
410 *dest_addr_length = length;
415 if (tag == 0x33 && length == 2) {
417 if (direction == 0) {
418 /* Sent from local, so source */
419 *source_port_offset = offset;
422 *dest_port_offset = offset;
426 if (tag == 0x36 && length == 2) {
428 *conn_id_offset = offset;
431 /* Skip the length of the indicated value */
436 /* No data found... */
442 /* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
443 Only set *data_offset if data field found. */
444 static gboolean find_sctpprim_variant1_data_offset(tvbuff_t *tvb, int *data_offset,
445 guint32 *dest_addr_offset,
446 guint16 *dest_addr_length,
447 guint32 *dest_port_offset)
449 int offset = *data_offset;
451 /* Get the sctpprim command code. */
452 guint8 first_tag = tvb_get_guint8(tvb, offset++);
454 guint8 first_length_byte;
456 /* Only accept interested in data requests or indications */
458 case 0x04: /* data request */
459 case 0x62: /* data indication */
465 first_length_byte = tvb_get_guint8(tvb, offset);
466 offset += skipASNLength(first_length_byte);
468 /* Skip any other fields before reach payload */
469 while (tvb_length_remaining(tvb, offset) > 2) {
470 /* Look at next tag */
471 tag = tvb_get_guint8(tvb, offset++);
473 /* Is this the data payload we're expecting? */
475 *data_offset = offset;
479 /* Skip length field */
482 case 0x0a: /* destPort */
483 *dest_port_offset = offset;
487 case 0x01: /* sctpInstanceNum */
488 case 0x1e: /* strseqnum */
489 case 0x0d: /* streamnum */
493 case 0x09: /* ipv4Address */
494 *dest_addr_offset = offset;
495 *dest_addr_length = 4;
500 case 0x0c: /* payloadType */
505 /* Fail if not a known header field */
511 /* No data found... */
515 /* Look for the protocol data within an sctpprim (variant 3) packet.
516 Only set *data_offset if data field found. */
517 static gboolean find_sctpprim_variant3_data_offset(tvbuff_t *tvb, int *data_offset,
518 guint32 *dest_addr_offset,
519 guint16 *dest_addr_length,
520 guint32 *dest_port_offset)
524 int offset = *data_offset;
526 /* Get the sctpprim (2 byte) command code. */
527 guint16 top_tag = tvb_get_ntohs(tvb, offset);
530 /* Only interested in data requests or indications */
532 case 0x0400: /* SendDataReq */
533 case 0x6200: /* DataInd */
540 /* Overall length field is next 2 bytes */
543 /* Rx/Tx ops have different formats */
547 if (top_tag == 0x6200) {
548 /* Next 2 bytes are associate ID */
551 /* Next 2 bytes are destination port */
552 *dest_port_offset = offset;
555 /* Destination address should follow - check tag */
556 tag = tvb_get_ntohs(tvb, offset);
565 length = tvb_get_ntohs(tvb, offset) / 2;
566 if ((length != 4) && (length != 16))
572 /* Address data is here */
573 *dest_addr_offset = offset;
574 *dest_addr_length = length;
579 /* Not interested in remaining (fixed) fields */
580 if (tvb_reported_length_remaining(tvb, offset) > (4 + 2 + 2 + 4)) {
581 offset += (4 + 2 + 2 + 4);
587 /* Data should now be here */
588 tag = tvb_get_ntohs(tvb, offset);
591 /* 2-byte length field */
594 /* Data is here!!! */
595 *data_offset = offset;
605 else if (top_tag == 0x0400) {
606 /* AssociateId should follow - check tag */
607 tag = tvb_get_ntohs(tvb, offset);
615 /* Skip 2-byte value */
620 tag = tvb_get_ntohs(tvb, offset);
623 /* Some optional params */
624 while ((tag != 0x0c00) && (tvb_length_remaining(tvb, offset) > 4)) {
626 case 0x0900: /* Dest address */
628 length = tvb_get_ntohs(tvb, offset) / 2;
629 if ((length != 4) && (length != 16)) {
634 /* Address data is here */
635 *dest_addr_offset = offset;
636 *dest_addr_length = length;
641 case 0x0a00: /* Dest port number */
642 *dest_port_offset = offset;
646 case 0x0d00: /* StreamNum */
647 *dest_port_offset = offset;
656 /* Get the next tag */
657 tag = tvb_get_ntohs(tvb, offset);
662 /* Mandatory payload type */
666 length = tvb_get_ntohs(tvb, offset) / 2;
671 /* Optional options */
672 tag = tvb_get_ntohs(tvb, offset);
675 length = tvb_get_ntohs(tvb, offset) / 2;
681 tag = tvb_get_ntohs(tvb, offset);
686 /* Data should now be here!! */
688 /* 2-byte length field */
691 /* Data is here!!! */
692 *data_offset = offset;
704 /* Dissect a UMTS RLC frame by:
705 - parsing the primitive header
706 - passing those values + outhdeader to dissector
707 - calling the UMTS RLC dissector */
708 static void dissect_rlc_umts(tvbuff_t *tvb, gint offset,
709 packet_info *pinfo, proto_tree *tree,
713 gboolean ueid_set = FALSE, rbid_set=FALSE;
718 dissector_handle_t rlc_umts_handle = 0;
720 /* Top-level opcode */
721 tag = tvb_get_guint8(tvb, offset++);
723 case 0xc0: /* mac data request */
724 case 0xc1: /* mac data indication */
728 /* No data to dissect */
732 /* Keep going until reach data tag or end of frame */
733 while ((tag != 0x41) && tvb_length_remaining(tvb, offset)) { /* i.e. Data */
734 tag = tvb_get_guint8(tvb, offset++);
736 case 0x72: /* UE Id */
737 ueid = tvb_get_ntohl(tvb, offset);
738 proto_tree_add_item(tree, hf_catapult_dct2000_ueid, tvb, offset, 4, ENC_BIG_ENDIAN);
742 case 0xa2: /* RBID */
743 offset++; /* skip length */
744 rbid = tvb_get_guint8(tvb, offset);
745 proto_tree_add_item(tree, hf_catapult_dct2000_rbid, tvb, offset, 1, ENC_BIG_ENDIAN);
749 case 0x22: /* CCCH-id setting rbid to CCCH! */
750 offset++; /* skip length */
751 proto_tree_add_item(tree, hf_catapult_dct2000_ccch_id, tvb, offset, 1, ENC_BIG_ENDIAN);
755 case 0xc4: /* No CRC error */
756 proto_tree_add_item(tree, hf_catapult_dct2000_no_crc_error, tvb, offset-1, 1, ENC_NA);
758 case 0xc5: /* CRC error */
759 proto_tree_add_item(tree, hf_catapult_dct2000_crc_error, tvb, offset-1, 1, ENC_NA);
761 case 0xf7: /* Clear Tx Buffer */
762 proto_tree_add_item(tree, hf_catapult_dct2000_clear_tx_buffer, tvb, offset-1, 1, ENC_NA);
765 case 0x41: /* Data !!! */
766 offset += skipASNLength(tvb_get_guint8(tvb, offset));
770 /* For other fields, just skip length and following data */
771 length = tvb_get_guint8(tvb, offset++);
773 case 0x42: /* Buffer Occupancy */
774 proto_tree_add_item(tree, hf_catapult_dct2000_buffer_occupancy, tvb, offset, length, ENC_BIG_ENDIAN);
776 case 0x49: /* PDU Size */
777 proto_tree_add_item(tree, hf_catapult_dct2000_pdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
779 case 0x47: /* UEId type */
780 proto_tree_add_item(tree, hf_catapult_dct2000_ueid_type, tvb, offset, 1, ENC_BIG_ENDIAN);
782 case 0x4e: /* Tx Priority */
783 proto_tree_add_item(tree, hf_catapult_dct2000_tx_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
785 case 0x4c: /* Last in seg set */
786 proto_tree_add_item(tree, hf_catapult_dct2000_last_in_seg_set, tvb, offset, 1, ENC_BIG_ENDIAN);
788 case 0x43: /* Rx timing deviation */
789 proto_tree_add_item(tree, hf_catapult_dct2000_rx_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN);
791 case 0x46: /* Transport channel type */
792 proto_tree_add_item(tree, hf_catapult_dct2000_transport_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
794 case 0xc2: /* Number of padding bits */
795 proto_tree_add_item(tree, hf_catapult_dct2000_no_padding_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
807 /* Have we got enough info to call dissector */
808 if ((tag == 0x41) && ueid_set && rbid_set) {
809 attach_rlc_info(pinfo, ueid, rbid, is_sent);
811 /* Set appropriate RLC dissector handle */
813 case 1: case 2: case 3: case 4: case 5:
814 case 6: case 7: case 8: case 9: case 10:
815 case 11: case 12: case 13: case 14: case 15:
817 /* TODO: can't really tell if these are control or transport...
818 maybe control with preferences (UAT?) between "rlc.ps_dtch" and "rlc.dcch" ? */
819 rlc_umts_handle = find_dissector("rlc.dch_unknown");
822 rlc_umts_handle = find_dissector("rlc.ccch");
825 rlc_umts_handle = find_dissector("rlc.ctch");
833 /* Call UMTS RLC dissector */
834 if (rlc_umts_handle != 0) {
835 rlc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
836 call_dissector_only(rlc_umts_handle, rlc_tvb, pinfo, tree, NULL);
843 /* Dissect an RRC LTE frame by first parsing the header entries then passing
844 the data to the RRC dissector, according to direction and channel type.
845 TODO: factor out common code between this function and dissect_pdcp_lte() */
846 static void dissect_rrc_lte(tvbuff_t *tvb, gint offset,
847 packet_info *pinfo, proto_tree *tree)
850 dissector_handle_t protocol_handle = 0;
851 gboolean isUplink = FALSE;
852 LogicalChannelType logicalChannelType;
854 guint8 bcch_transport = 0;
857 /* Top-level opcode */
858 tag = tvb_get_guint8(tvb, offset++);
860 case 0x00: /* Data_Req_UE */
861 case 0x04: /* Data_Ind_eNodeB */
865 case 0x02: /* Data_Req_eNodeB */
866 case 0x03: /* Data_Ind_UE */
871 /* Unexpected opcode tag! */
876 offset += skipASNLength(tvb_get_guint8(tvb, offset));
879 tag = tvb_get_guint8(tvb, offset++);
881 case 0x12: /* UE_Id_LCId */
883 /* Dedicated channel info */
885 /* Length will fit in one byte here */
888 logicalChannelType = Channel_DCCH;
891 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, ENC_BIG_ENDIAN);
894 /* Get tag of channel type */
895 tag = tvb_get_guint8(tvb, offset++);
900 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
901 tvb_get_guint8(tvb, offset));
902 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
903 tvb, offset, 1, ENC_BIG_ENDIAN);
908 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
909 tvb_get_guint8(tvb, offset));
910 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
911 tvb, offset, 1, ENC_BIG_ENDIAN);
916 /* Unexpected channel type */
921 case 0x1a: /* Cell_LCId */
923 /* Common channel info */
929 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
930 tvb, offset, 2, ENC_BIG_ENDIAN);
931 cell_id = tvb_get_ntohs(tvb, offset);
934 /* Logical channel type */
935 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
936 tvb, offset, 1, ENC_BIG_ENDIAN);
937 logicalChannelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
940 /* Won't be seen if RRC decoder is called... */
941 col_append_fstr(pinfo->cinfo, COL_INFO, " cell-id=%u %s",
943 val_to_str_const(logicalChannelType, rlc_logical_channel_vals,
947 switch (logicalChannelType) {
952 /* Transport channel type */
953 bcch_transport = tvb_get_guint8(tvb, offset);
954 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
955 tvb, offset, 1, ENC_BIG_ENDIAN);
964 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
965 tvb, offset, 2, ENC_BIG_ENDIAN);
979 /* Data tag should follow */
980 tag = tvb_get_guint8(tvb, offset++);
986 offset += skipASNLength(tvb_get_guint8(tvb, offset));
988 /* Look up dissector handle corresponding to direction and channel type */
991 /* Uplink channel types */
992 switch (logicalChannelType) {
994 protocol_handle = find_dissector("lte_rrc.ul_dcch");
997 protocol_handle = find_dissector("lte_rrc.ul_ccch");
1001 /* Unknown Uplink channel type */
1006 /* Downlink channel types */
1007 switch (logicalChannelType) {
1009 protocol_handle = find_dissector("lte_rrc.dl_dcch");
1012 protocol_handle = find_dissector("lte_rrc.dl_ccch");
1015 protocol_handle = find_dissector("lte_rrc.pcch");
1018 if (bcch_transport == 1) {
1019 protocol_handle = find_dissector("lte_rrc.bcch_bch");
1022 protocol_handle = find_dissector("lte_rrc.bcch_dl_sch");
1027 /* Unknown Downlink channel type */
1032 /* Send to RRC dissector, if got here, have sub-dissector and some data left */
1033 if ((protocol_handle != NULL) && (tvb_length_remaining(tvb, offset) > 0)) {
1034 rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1035 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
1040 /* Dissect an CCPRI LTE frame by first parsing the header entries then passing
1041 the data to the CPRI C&M dissector */
1042 static void dissect_ccpri_lte(tvbuff_t *tvb, gint offset,
1043 packet_info *pinfo, proto_tree *tree)
1047 tvbuff_t *ccpri_tvb;
1048 dissector_handle_t protocol_handle = 0;
1051 /* Top-level opcode */
1052 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
1053 opcode = tvb_get_guint8(tvb, offset++);
1055 /* Skip 2-byte length field */
1059 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
1060 tvb, offset, 2, ENC_BIG_ENDIAN);
1063 /* Status (ind only) */
1066 guint8 status = tvb_get_guint8(tvb, offset);
1067 ti = proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_status,
1068 tvb, offset, 1, ENC_BIG_ENDIAN);
1072 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
1073 "CCPRI Indication has error status");
1079 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_channel,
1080 tvb, offset, 1, ENC_BIG_ENDIAN);
1083 /* Data tag must follow */
1084 tag = tvb_get_guint8(tvb, offset++);
1090 length = tvb_get_ntohs(tvb, offset);
1093 /* Send remainder to lapb dissector (lapb needs patch with preference
1094 set to call cpri C&M dissector instead of X.25) */
1095 protocol_handle = find_dissector("lapb");
1096 if ((protocol_handle != NULL) && (tvb_length_remaining(tvb, offset) > 0)) {
1097 ccpri_tvb = tvb_new_subset(tvb, offset, length, length);
1098 call_dissector_only(protocol_handle, ccpri_tvb, pinfo, tree, NULL);
1105 /* Dissect a PDCP LTE frame by first parsing the RLCPrim header then passing
1106 the data to the PDCP LTE dissector */
1107 static void dissect_pdcp_lte(tvbuff_t *tvb, gint offset,
1108 packet_info *pinfo, proto_tree *tree)
1112 struct pdcp_lte_info *p_pdcp_lte_info = NULL;
1113 tvbuff_t *pdcp_lte_tvb;
1117 /* Look this up so can update channel info */
1118 p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1119 if (p_pdcp_lte_info == NULL) {
1120 /* This really should be set...can't dissect anything without it */
1124 /* Top-level opcode */
1125 opcode = tvb_get_guint8(tvb, offset);
1127 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_op, tvb, offset, 1, ENC_BIG_ENDIAN);
1131 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, rlc_op_vals, "Unknown"));
1133 /* Assume UE side, so REQ is UL, IND is DL */
1135 case RLC_AM_DATA_REQ:
1136 case RLC_UM_DATA_REQ:
1137 case RLC_TR_DATA_REQ:
1138 p_pdcp_lte_info->direction = DIRECTION_UPLINK;
1142 p_pdcp_lte_info->direction = DIRECTION_DOWNLINK;
1147 case RLC_AM_DATA_REQ:
1148 case RLC_AM_DATA_IND:
1149 case RLC_UM_DATA_REQ:
1150 case RLC_UM_DATA_IND:
1151 case RLC_TR_DATA_REQ:
1152 case RLC_TR_DATA_IND:
1155 tag = tvb_get_guint8(tvb, offset++);
1157 case 0x10: /* UE_Id_LCId */
1159 /* Dedicated channel info */
1161 /* Length will fit in one byte here */
1164 p_pdcp_lte_info->channelType = Channel_DCCH;
1167 ueid = tvb_get_ntohs(tvb, offset);
1168 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, ENC_BIG_ENDIAN);
1169 col_append_fstr(pinfo->cinfo, COL_INFO,
1171 p_pdcp_lte_info->ueid = ueid;
1174 /* Get tag of channel type */
1175 tag = tvb_get_guint8(tvb, offset++);
1180 channelId = tvb_get_guint8(tvb, offset);
1181 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
1183 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
1184 tvb, offset++, 1, ENC_BIG_ENDIAN);
1185 p_pdcp_lte_info->channelId = channelId;
1189 channelId = tvb_get_guint8(tvb, offset);
1190 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
1192 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
1193 tvb, offset++, 1, ENC_BIG_ENDIAN);
1194 p_pdcp_lte_info->channelId = channelId;
1198 /* Unexpected channel type */
1203 case 0x1a: /* Cell_LCId */
1205 /* Common channel info */
1211 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
1212 tvb, offset, 2, ENC_BIG_ENDIAN);
1215 /* Logical channel type */
1216 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
1217 tvb, offset, 1, ENC_BIG_ENDIAN);
1218 p_pdcp_lte_info->channelType = tvb_get_guint8(tvb, offset++);
1219 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1220 val_to_str_const(p_pdcp_lte_info->channelType, rlc_logical_channel_vals,
1221 "UNKNOWN-CHANNEL"));
1223 switch (p_pdcp_lte_info->channelType) {
1228 /* Transport channel type */
1229 p_pdcp_lte_info->BCCHTransport = tvb_get_guint8(tvb, offset);
1230 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
1231 tvb, offset, 1, ENC_BIG_ENDIAN);
1240 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
1241 tvb, offset, 2, ENC_BIG_ENDIAN);
1242 ueid = tvb_get_ntohs(tvb, offset);
1245 col_append_fstr(pinfo->cinfo, COL_INFO, " UEId=%u", ueid);
1254 /* Unexpected tag */
1258 /* Other optional fields may follow */
1259 tag = tvb_get_guint8(tvb, offset++);
1260 while ((tag != 0x41) && (tvb_length_remaining(tvb, offset) > 2)) {
1265 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_mui,
1266 tvb, offset, 2, ENC_BIG_ENDIAN);
1269 /* CNF follows MUI in AM */
1270 if ((opcode == RLC_AM_DATA_REQ) || (opcode == RLC_AM_DATA_IND)) {
1271 proto_tree_add_boolean(tree, hf_catapult_dct2000_lte_rlc_cnf,
1272 tvb, offset, 1, tvb_get_guint8(tvb, offset));
1276 else if (tag == 0x45) {
1279 proto_tree_add_boolean(tree, hf_catapult_dct2000_lte_rlc_discard_req,
1280 tvb, offset, 1, tvb_get_guint8(tvb, offset));
1284 tag = tvb_get_guint8(tvb, offset++);
1288 /********************************/
1289 /* Should be at data tag now */
1291 /* Call PDCP LTE dissector */
1292 pdcp_lte_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1293 call_dissector_only(pdcp_lte_handle, pdcp_lte_tvb, pinfo, tree, NULL);
1306 /* Look up dissector by protocol name. Fix up known name mis-matches.
1307 This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */
1308 static dissector_handle_t look_for_dissector(const char *protocol_name)
1310 /* Use known aliases and protocol name prefixes */
1311 if (strcmp(protocol_name, "tbcp") == 0) {
1312 return find_dissector("rtcp");
1315 if (strncmp(protocol_name, "diameter", strlen("diameter")) == 0) {
1316 return find_dissector("diameter");
1319 if ((strcmp(protocol_name, "xcap_caps") == 0) ||
1320 (strcmp(protocol_name, "soap") == 0) ||
1321 (strcmp(protocol_name, "mm1") == 0) ||
1322 (strcmp(protocol_name, "mm3") == 0) ||
1323 (strcmp(protocol_name, "mm7") == 0)) {
1325 return find_dissector("http");
1328 if ((strcmp(protocol_name, "fp") == 0) ||
1329 (strncmp(protocol_name, "fp_r", 4) == 0) ||
1330 (strcmp(protocol_name, "fpiur_r5") == 0)) {
1332 return find_dissector("fp");
1335 if ((strcmp(protocol_name, "iuup_rtp_r5") == 0) ||
1336 (strcmp(protocol_name, "iuup_rtp_r6") == 0)) {
1338 return find_dissector("rtp");
1341 if (strcmp(protocol_name, "sipt") == 0) {
1342 return find_dissector("sip");
1345 if (strncmp(protocol_name, "nbap_sctp", strlen("nbap_sctp")) == 0) {
1346 return find_dissector("nbap");
1349 if (strncmp(protocol_name, "gtp", strlen("gtp")) == 0) {
1350 return find_dissector("gtp");
1353 if (strcmp(protocol_name, "dhcpv4") == 0) {
1354 return find_dissector("bootp");
1357 if (strcmp(protocol_name, "wimax") == 0) {
1358 return find_dissector("wimaxasncp");
1361 if (strncmp(protocol_name, "sabp", strlen("sabp")) == 0) {
1362 return find_dissector("sabp");
1365 if (strcmp(protocol_name, "wtp") == 0) {
1366 return find_dissector("wtp-udp");
1369 /* Only match with s1ap if preference turned on */
1370 if (catapult_dct2000_dissect_lte_s1ap &&
1371 strncmp(protocol_name, "s1ap", strlen("s1ap")) == 0) {
1373 return find_dissector("s1ap");
1376 /* Always try lookup for now */
1377 if ((strncmp(protocol_name, "x2ap_r8_lte", strlen("x2ap_r8_lte")) == 0) ||
1378 (strncmp(protocol_name, "x2ap_r9_lte", strlen("x2ap_r9_lte")) == 0)) {
1380 return find_dissector("x2ap");
1384 if ((strcmp(protocol_name, "gtpv2_r8_lte") == 0) ||
1385 (strcmp(protocol_name, "gtpv2_r9_lte") == 0)) {
1386 return find_dissector("gtpv2");
1390 /* Try for an exact match */
1392 return find_dissector(protocol_name);
1397 /* Populate outhdr_values array with numbers found in outhdr_string */
1398 static void parse_outhdr_string(const guchar *outhdr_string, gint outhdr_string_len)
1402 /* Populate values array */
1403 for (outhdr_values_found=0; outhdr_values_found < MAX_OUTHDR_VALUES; ) {
1405 guint digit_array[MAX_OUTHDR_VALUES];
1406 guint number_digits = 0;
1409 guint multiplier = 1;
1413 for ( ; n < outhdr_string_len; n++) {
1414 if (!isdigit(outhdr_string[n])) {
1418 digit_array[number_digits++] = outhdr_string[n] - '0';
1422 if (number_digits == 0) {
1423 /* No more numbers left */
1427 /* Convert digits into value (much faster than format_text() + atoi()) */
1428 for (d=number_digits; d > 0; d--) {
1429 number += ((digit_array[d-1]) * multiplier);
1432 outhdr_values[outhdr_values_found++] = number;
1441 /* Fill in an FP packet info struct and attach it to the packet for the FP
1443 static void attach_fp_info(packet_info *pinfo, gboolean received, const char *protocol_name, int variant)
1447 int tf_start, num_chans_start;
1449 int calculated_variant;
1451 /* Only need to set info once per session. */
1452 struct fp_info *p_fp_info = p_get_proto_data(pinfo->fd, proto_fp);
1453 if (p_fp_info != NULL) {
1457 /* Allocate struct */
1458 p_fp_info = se_alloc0(sizeof(struct fp_info));
1460 /* Check that the number of outhdr values looks sensible */
1461 if (((strcmp(protocol_name, "fpiur_r5") == 0) && (outhdr_values_found != 2)) ||
1462 (outhdr_values_found < 5)) {
1467 /* 3gpp release (99, 4, 5, 6, 7) */
1468 if (strcmp(protocol_name, "fp") == 0) {
1469 p_fp_info->release = 99;
1471 else if (strcmp(protocol_name, "fp_r4") == 0) {
1472 p_fp_info->release = 4;
1474 else if (strcmp(protocol_name, "fp_r5") == 0) {
1475 p_fp_info->release = 5;
1477 else if (strcmp(protocol_name, "fp_r6") == 0) {
1478 p_fp_info->release = 6;
1480 else if (strcmp(protocol_name, "fp_r7") == 0) {
1481 p_fp_info->release = 7;
1483 else if (strcmp(protocol_name, "fp_r8") == 0) {
1484 p_fp_info->release = 8;
1486 else if (strcmp(protocol_name, "fpiur_r5") == 0) {
1487 p_fp_info->release = 5;
1490 /* Really shouldn't get here */
1491 DISSECTOR_ASSERT_NOT_REACHED();
1495 /* Release date is derived from variant number */
1496 /* Only R6 sub-versions currently influence format within a release */
1497 switch (p_fp_info->release) {
1499 if (variant < 256) {
1500 calculated_variant = variant;
1503 calculated_variant = variant / 256;
1506 switch (calculated_variant) {
1508 p_fp_info->release_year = 2005;
1509 p_fp_info->release_month = 6;
1512 p_fp_info->release_year = 2005;
1513 p_fp_info->release_month = 9;
1517 p_fp_info->release_year = 2006;
1518 p_fp_info->release_month = 3;
1523 p_fp_info->release_year = 2008;
1524 p_fp_info->release_month = 3;
1528 p_fp_info->release_year = 2010;
1529 p_fp_info->release_month = 6;
1534 p_fp_info->release_year = 0;
1535 p_fp_info->release_month = 0;
1540 p_fp_info->channel = outhdr_values[i++];
1541 /* Sad hack until this value is filled in properly */
1542 if (p_fp_info->channel == 0) {
1543 p_fp_info->channel = CHANNEL_DCH;
1546 /* Derive direction from node type/side */
1547 node_type = outhdr_values[i++];
1548 p_fp_info->is_uplink = (( received && (node_type == 2)) ||
1549 (!received && (node_type == 1)));
1551 /* Division type introduced for R7 */
1552 if ((p_fp_info->release == 7) ||
1553 (p_fp_info->release == 8)) {
1554 p_fp_info->division = outhdr_values[i++];
1557 /* HS-DSCH config */
1558 if (p_fp_info->channel == CHANNEL_HSDSCH) {
1559 if ((p_fp_info->release == 7) ||
1560 (p_fp_info->release == 8)) {
1561 /* Entity (MAC-hs or MAC-ehs) used */
1562 if (outhdr_values[i++]) {
1563 p_fp_info->hsdsch_entity = ehs;
1567 /* This is the pre-R7 default */
1568 p_fp_info->hsdsch_entity = hs;
1573 /* IUR only uses the above... */
1574 if (strcmp(protocol_name, "fpiur_r5") == 0) {
1575 /* Store info in packet */
1576 p_fp_info->iface_type = IuR_Interface;
1577 p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);
1581 /* DCH CRC present... */
1582 p_fp_info->dch_crc_present = outhdr_values[i++];
1584 /* ... but don't trust for edch */
1585 if (p_fp_info->channel == CHANNEL_EDCH) {
1586 p_fp_info->dch_crc_present = 2; /* unknown */
1589 /* How many paging indications (if PCH data) */
1590 p_fp_info->paging_indications = outhdr_values[i++];
1592 /* Number of channels (for coordinated channels) */
1593 p_fp_info->num_chans = outhdr_values[i++];
1595 /* EDCH-Common is always T2 */
1596 if (p_fp_info->channel == CHANNEL_EDCH_COMMON) {
1597 p_fp_info->edch_type = 1;
1600 if (p_fp_info->channel != CHANNEL_EDCH) {
1601 /* TF size for each channel */
1603 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1604 p_fp_info->chan_tf_size[chan] = outhdr_values[tf_start+chan];
1607 /* Number of TBs for each channel */
1608 num_chans_start = tf_start + p_fp_info->num_chans;
1609 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1610 p_fp_info->chan_num_tbs[chan] = outhdr_values[num_chans_start+chan];
1617 p_fp_info->no_ddi_entries = outhdr_values[i++];
1620 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1621 p_fp_info->edch_ddi[n] = outhdr_values[i++];
1624 /* Corresponding MAC-d sizes */
1625 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1626 p_fp_info->edch_macd_pdu_size[n] = outhdr_values[i++];
1629 if (strcmp(protocol_name, "fp_r8") == 0) {
1630 p_fp_info->edch_type = outhdr_values[i];
1633 p_fp_info->edch_type = 0;
1637 /* Interface must be IuB */
1638 p_fp_info->iface_type = IuB_Interface;
1640 /* Store info in packet */
1641 p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);
1645 /* Fill in an RLC packet info struct and attach it to the packet for the RLC
1647 static void attach_rlc_info(packet_info *pinfo, guint32 urnti, guint8 rbid, gboolean is_sent)
1649 /* Only need to set info once per session. */
1650 struct fp_info *p_fp_info;
1651 struct rlc_info *p_rlc_info = p_get_proto_data(pinfo->fd, proto_rlc);
1653 if (p_rlc_info != NULL) {
1657 /* Check that the number of outhdr values looks correct */
1658 if (outhdr_values_found != 2) {
1662 /* Allocate structs */
1663 p_rlc_info = se_alloc0(sizeof(struct rlc_info));
1664 p_fp_info = se_alloc0(sizeof(struct fp_info));
1666 /* Fill in struct fields for first (only) PDU in this frame */
1668 /* Urnti. Just use UEId */
1669 p_rlc_info->urnti[0] = urnti;
1671 /* ciphered (off by default) */
1672 p_rlc_info->ciphered[0] = FALSE;
1674 /* deciphered (off by default) */
1675 p_rlc_info->deciphered[0] = FALSE;
1678 switch (outhdr_values[1]) {
1680 p_rlc_info->mode[0] = RLC_TM;
1683 p_rlc_info->mode[0] = RLC_UM;
1686 p_rlc_info->mode[0] = RLC_AM;
1689 p_rlc_info->mode[0] = RLC_UM;
1690 p_rlc_info->ciphered[0] = TRUE;
1693 p_rlc_info->mode[0] = RLC_AM;
1694 p_rlc_info->ciphered[0] = TRUE;
1700 /* rbid. TODO: does this need conversion? */
1701 p_rlc_info->rbid[0] = rbid;
1704 p_rlc_info->li_size[0] = outhdr_values[0];
1706 /* Store info in packet */
1707 p_add_proto_data(pinfo->fd, proto_rlc, p_rlc_info);
1709 /* Also store minimal FP info consulted by RLC dissector
1710 TODO: Don't really know direction, but use S/R flag to make
1711 logs in same context consistent. Will be correct for NodeB logs,
1712 but RLC dissector seems to not use anyway... */
1713 p_fp_info->is_uplink = is_sent;
1714 p_fp_info->cur_tb = 0; /* Always the first/only one */
1715 p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);
1719 /* Fill in a MAC LTE packet info struct and attach it to the packet for that
1721 static void attach_mac_lte_info(packet_info *pinfo)
1723 struct mac_lte_info *p_mac_lte_info;
1726 /* Only need to set info once per session. */
1727 p_mac_lte_info = get_mac_lte_proto_data(pinfo);
1728 if (p_mac_lte_info != NULL) {
1732 /* Allocate & zero struct */
1733 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
1735 /* Populate the struct from outhdr values */
1736 p_mac_lte_info->crcStatusValid = FALSE; /* not set yet */
1738 p_mac_lte_info->radioType = outhdr_values[i++] + 1;
1739 p_mac_lte_info->rntiType = outhdr_values[i++];
1740 p_mac_lte_info->direction = outhdr_values[i++];
1741 /* Set these extra PHY present flags to FALSE by default */
1742 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1743 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
1746 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
1749 p_mac_lte_info->subframeNumber = outhdr_values[i++];
1750 p_mac_lte_info->isPredefinedData = outhdr_values[i++];
1751 p_mac_lte_info->rnti = outhdr_values[i++];
1752 p_mac_lte_info->ueid = outhdr_values[i++];
1753 p_mac_lte_info->length = outhdr_values[i++];
1754 if (outhdr_values_found > 8) {
1755 p_mac_lte_info->reTxCount = outhdr_values[i++];
1757 if (outhdr_values_found == 10) {
1758 /* CRC only valid for Downlink */
1759 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1760 p_mac_lte_info->crcStatusValid = TRUE;
1761 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = outhdr_values[i++];
1768 p_mac_lte_info->dl_retx = dl_retx_unknown;
1770 if (outhdr_values_found > 10) {
1771 /* Extra PHY parameters */
1772 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1773 p_mac_lte_info->detailed_phy_info.dl_info.present = outhdr_values[i++];
1774 p_mac_lte_info->detailed_phy_info.dl_info.dci_format = outhdr_values[i++];
1775 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type = outhdr_values[i++];
1776 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level = outhdr_values[i++];
1777 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index = outhdr_values[i++];
1778 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index = outhdr_values[i++];
1779 if (outhdr_values[i++]) {
1780 p_mac_lte_info->dl_retx = dl_retx_yes;
1783 p_mac_lte_info->dl_retx = dl_retx_no;
1785 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length = outhdr_values[i++];
1786 p_mac_lte_info->crcStatusValid = TRUE;
1787 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = outhdr_values[i++];
1788 if (outhdr_values_found > 18) {
1789 p_mac_lte_info->detailed_phy_info.dl_info.harq_id = outhdr_values[i++];
1790 p_mac_lte_info->detailed_phy_info.dl_info.ndi = outhdr_values[i++];
1792 if (outhdr_values_found > 20) {
1793 p_mac_lte_info->detailed_phy_info.dl_info.transport_block = outhdr_values[i++];
1798 p_mac_lte_info->detailed_phy_info.ul_info.present = outhdr_values[i++];
1799 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type = outhdr_values[i++];
1800 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index = outhdr_values[i++];
1801 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length = outhdr_values[i++];
1802 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start = outhdr_values[i++];
1803 /* Skip retx flag */
1806 if (outhdr_values_found == 16) {
1807 p_mac_lte_info->subframeNumberOfGrantPresent = TRUE;
1808 p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];
1810 if (outhdr_values_found > 16) {
1811 p_mac_lte_info->detailed_phy_info.ul_info.harq_id = outhdr_values[i++];
1812 p_mac_lte_info->detailed_phy_info.ul_info.ndi = outhdr_values[i++];
1814 p_mac_lte_info->subframeNumberOfGrantPresent = TRUE;
1815 p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];
1820 /* System frame number */
1821 if (i < outhdr_values_found) {
1822 p_mac_lte_info->sysframeNumber = outhdr_values[i++];
1825 if ((p_mac_lte_info->direction == DIRECTION_UPLINK) &&
1826 (i < outhdr_values_found)) {
1828 p_mac_lte_info->isPHICHNACK = outhdr_values[i];
1831 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1832 /* R10 parameter not set yet */
1833 p_mac_lte_info->isExtendedBSRSizes = FALSE;
1836 /* Store info in packet */
1837 set_mac_lte_proto_data(pinfo, p_mac_lte_info);
1841 /* Fill in a RLC LTE packet info struct and attach it to the packet for that
1843 static void attach_rlc_lte_info(packet_info *pinfo)
1845 struct rlc_lte_info *p_rlc_lte_info;
1848 /* Only need to set info once per session. */
1849 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1850 if (p_rlc_lte_info != NULL) {
1854 /* Allocate & zero struct */
1855 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1857 p_rlc_lte_info->rlcMode = outhdr_values[i++];
1858 p_rlc_lte_info->direction = outhdr_values[i++];
1859 p_rlc_lte_info->priority = outhdr_values[i++];
1860 p_rlc_lte_info->UMSequenceNumberLength = outhdr_values[i++];
1861 p_rlc_lte_info->channelId = outhdr_values[i++];
1862 p_rlc_lte_info->channelType = outhdr_values[i++];
1863 p_rlc_lte_info->ueid = outhdr_values[i++];
1864 p_rlc_lte_info->pduLength = outhdr_values[i];
1866 /* Store info in packet */
1867 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1870 /* Fill in a PDCP LTE packet info struct and attach it to the packet for the PDCP LTE
1872 static void attach_pdcp_lte_info(packet_info *pinfo)
1874 struct pdcp_lte_info *p_pdcp_lte_info;
1877 /* Only need to set info once per session. */
1878 p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1879 if (p_pdcp_lte_info != NULL) {
1883 /* Allocate & zero struct */
1884 p_pdcp_lte_info = se_alloc0(sizeof(struct pdcp_lte_info));
1886 p_pdcp_lte_info->no_header_pdu = outhdr_values[i++];
1887 p_pdcp_lte_info->plane = outhdr_values[i++];
1888 if (p_pdcp_lte_info->plane != USER_PLANE) {
1889 p_pdcp_lte_info->plane = SIGNALING_PLANE;
1891 p_pdcp_lte_info->seqnum_length = outhdr_values[i++];
1893 p_pdcp_lte_info->rohc_compression = outhdr_values[i++];
1894 p_pdcp_lte_info->rohc_ip_version = outhdr_values[i++];
1895 p_pdcp_lte_info->cid_inclusion_info = outhdr_values[i++];
1896 p_pdcp_lte_info->large_cid_present = outhdr_values[i++];
1897 p_pdcp_lte_info->mode = outhdr_values[i++];
1898 p_pdcp_lte_info->rnd = outhdr_values[i++];
1899 p_pdcp_lte_info->udp_checkum_present = outhdr_values[i++];
1900 p_pdcp_lte_info->profile = outhdr_values[i];
1902 /* Remaining 2 (fixed) fields are ah_length and gre_checksum */
1904 /* Store info in packet */
1905 p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
1909 /* Attempt to show tty (raw character messages) as text lines. */
1910 static void dissect_tty_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1913 proto_tree *tty_tree;
1917 /* Create tty tree. */
1918 ti = proto_tree_add_item(tree, hf_catapult_dct2000_tty, tvb, offset, -1, ENC_NA);
1919 tty_tree = proto_item_add_subtree(ti, ett_catapult_dct2000_tty);
1921 /* Show the tty lines one at a time. */
1922 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1923 /* Find the end of the line. */
1924 int linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1926 /* Extract & add the string. */
1927 char *string = (char*)tvb_get_ephemeral_string(tvb, offset, linelen);
1928 if (isascii(string[0])) {
1929 /* If looks printable treat as string... */
1930 proto_tree_add_string_format(tty_tree, hf_catapult_dct2000_tty_line,
1936 /* Otherwise show as $hex */
1939 int tty_string_length = tvb_length_remaining(tvb, offset);
1940 int hex_string_length = 1+(2*tty_string_length)+1;
1941 hex_string = ep_alloc(hex_string_length);
1943 idx = g_snprintf(hex_string, hex_string_length, "$");
1945 /* Write hex out to new string */
1946 for (n=0; n < tty_string_length; n++) {
1947 idx += g_snprintf(hex_string+idx, 3, "%02x",
1948 tvb_get_guint8(tvb, offset+n));
1950 string = hex_string;
1954 /* Show first line in info column */
1956 col_append_fstr(pinfo->cinfo, COL_INFO, "tty (%s", string);
1957 proto_item_append_text(ti, " (%s)", string);
1960 /* Move onto next line. */
1961 offset = next_offset;
1964 /* Close off summary of tty message in info column */
1966 col_append_str(pinfo->cinfo, COL_INFO, (lines > 1) ? "...)" : ")");
1971 /* Scan the log comment looking for notable out-of-band MAC events that should
1972 be sent to the MAC dissector */
1973 static void check_for_oob_mac_lte_events(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1976 guint number_of_ues;
1977 guint ueids[MAX_SRs];
1978 guint rntis[MAX_SRs];
1980 guint rach_attempt_number;
1981 mac_lte_oob_event oob_event;
1982 struct mac_lte_info *p_mac_lte_info;
1983 tvbuff_t *mac_lte_tvb = NULL;
1986 /* Look for strings matching expected formats */
1987 if (sscanf(string, ">> RACH Preamble Request[UE = %u] [RAPID = %u] [Attempt = %u]",
1988 &ueids[0], &rapid, &rach_attempt_number) == 3) {
1989 oob_event = ltemac_send_preamble;
1992 if (sscanf(string, ">> Schedule Request[UE = %u] [RNTI = %u]", &ueids[0], &rntis[0]) == 2) {
1993 /* Older, single SR format */
1994 oob_event = ltemac_send_sr;
1998 if (sscanf(string, ">> Schedule Requests (%u) [UE=%u][RNTI=%u]",
1999 &number_of_ues, &ueids[0], &rntis[0]) == 3) {
2000 const char *current_position;
2002 /* Newer, multi-UE format */
2003 oob_event = ltemac_send_sr;
2005 /* Parse other ueid/rnti pairs */
2006 number_of_ues = MIN(number_of_ues, MAX_SRs);
2007 if (number_of_ues > 1) {
2008 current_position = string;
2010 for (n=1; n < number_of_ues; n++) {
2012 /* Find the start of the next entry */
2013 current_position = strstr(current_position, "] ");
2014 if (current_position != NULL) {
2015 current_position += 2;
2018 /* This is an error - shouldn't happen */
2022 /* Read this entry */
2023 if (sscanf(current_position, "[UE=%u][RNTI=%u]", &ueids[n], &rntis[n]) != 2) {
2024 /* Assuming that if we can't read this one there is no point trying others */
2032 if (sscanf(string, ">> INFO MAC: SR failed for UE %u (CRNTI=%u)", &ueids[0], &rntis[0]) == 2) {
2033 oob_event = ltemac_sr_failure;
2036 /* No events found */
2040 /* We have an event */
2041 /* Only need to set info once per session. */
2042 p_mac_lte_info = get_mac_lte_proto_data(pinfo);
2043 if (p_mac_lte_info == NULL) {
2045 /* Allocate & zero struct */
2046 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
2048 /* This indicates to MAC dissector that it has an oob event */
2049 p_mac_lte_info->length = 0;
2051 switch (oob_event) {
2052 case ltemac_send_preamble:
2053 p_mac_lte_info->ueid = ueids[0];
2054 p_mac_lte_info->rapid = rapid;
2055 p_mac_lte_info->rach_attempt_number = rach_attempt_number;
2056 p_mac_lte_info->direction = DIRECTION_UPLINK;
2058 case ltemac_send_sr:
2059 for (n=0; n < number_of_ues; n++) {
2060 p_mac_lte_info->oob_ueid[n] = ueids[n];
2061 p_mac_lte_info->oob_rnti[n] = rntis[n];
2063 p_mac_lte_info->number_of_srs = number_of_ues;
2064 p_mac_lte_info->direction = DIRECTION_UPLINK;
2066 case ltemac_sr_failure:
2067 p_mac_lte_info->rnti = rntis[0];
2068 p_mac_lte_info->ueid = ueids[0];
2069 p_mac_lte_info->direction = DIRECTION_DOWNLINK;
2073 p_mac_lte_info->radioType = FDD_RADIO; /* TODO: will be the same as rest of log... */
2074 p_mac_lte_info->oob_event = oob_event;
2076 /* Store info in packet */
2077 set_mac_lte_proto_data(pinfo, p_mac_lte_info);
2080 /* Call MAC dissector */
2081 mac_lte_tvb = tvb_new_subset(tvb, 0, 0, 0);
2082 call_dissector_only(mac_lte_handle, mac_lte_tvb, pinfo, tree, NULL);
2086 /*****************************************/
2087 /* Main dissection function. */
2088 /*****************************************/
2090 dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2092 proto_tree *dct2000_tree = NULL;
2093 proto_item *ti = NULL;
2095 gint context_length;
2096 const char *context_name;
2098 gint protocol_length;
2099 gint timestamp_length;
2100 const char *timestamp_string;
2101 gint variant_length;
2102 const char *variant_string;
2104 const char *outhdr_string;
2108 dissector_handle_t protocol_handle = 0;
2109 dissector_handle_t heur_protocol_handle = 0;
2110 int sub_dissector_result = 0;
2111 const char *protocol_name;
2112 gboolean is_comment;
2115 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCT2000");
2118 col_clear(pinfo->cinfo, COL_INFO);
2120 /* Create root (protocol) tree. */
2122 ti = proto_tree_add_item(tree, proto_catapult_dct2000, tvb, offset, -1, ENC_NA);
2123 dct2000_tree = proto_item_add_subtree(ti, ett_catapult_dct2000);
2126 /*********************************************************************/
2127 /* Note that these are the fields of the stub header as written out */
2128 /* by the wiretap module */
2131 context_name = tvb_get_stringz(tvb, offset, &context_length);
2133 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_context, tvb,
2134 offset, context_length, ENC_ASCII|ENC_NA);
2136 offset += context_length;
2138 /* Context port number */
2139 port_number = tvb_get_guint8(tvb, offset);
2141 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_port_number, tvb,
2142 offset, 1, ENC_BIG_ENDIAN);
2146 /* Timestamp in file */
2147 timestamp_string = tvb_get_stringz(tvb, offset, ×tamp_length);
2149 /* TODO: this is *very* slow, but float version adds trailing digits when
2150 displayed as a custom column... */
2151 proto_tree_add_double(dct2000_tree, hf_catapult_dct2000_timestamp, tvb,
2152 offset, timestamp_length,
2153 atof(timestamp_string));
2155 offset += timestamp_length;
2158 /* DCT2000 protocol name */
2159 protocol_name = tvb_get_stringz(tvb, offset, &protocol_length);
2161 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_protocol, tvb,
2162 offset, protocol_length, ENC_ASCII|ENC_NA);
2164 is_comment = (strcmp(protocol_name, "comment") == 0);
2165 offset += protocol_length;
2168 /* Protocol Variant */
2169 variant_string = tvb_get_stringz(tvb, offset, &variant_length);
2171 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_variant, tvb,
2172 offset, variant_length, ENC_ASCII|ENC_NA);
2174 offset += variant_length;
2176 /* Outhdr (shown as string) */
2177 outhdr_string = tvb_get_stringz(tvb, offset, &outhdr_length);
2178 if (!is_comment && (outhdr_length > 1)) {
2179 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_outhdr, tvb,
2180 offset, outhdr_length, ENC_ASCII|ENC_NA);
2182 offset += outhdr_length;
2186 direction = tvb_get_guint8(tvb, offset);
2188 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
2189 offset, 1, ENC_BIG_ENDIAN);
2193 /* Read frame encapsulation set by wiretap */
2195 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_encap, tvb, offset, 1, ENC_BIG_ENDIAN);
2197 encap = tvb_get_guint8(tvb, offset);
2200 /* Add useful details to protocol tree label */
2201 proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s (v=%s)",
2205 (direction == 0) ? 'S' : 'R',
2211 /* FP protocols need info from outhdr attached */
2212 if ((strcmp(protocol_name, "fp") == 0) ||
2213 (strncmp(protocol_name, "fp_r", 4) == 0) ||
2214 (strcmp(protocol_name, "fpiur_r5") == 0)) {
2216 parse_outhdr_string(outhdr_string, outhdr_length);
2217 attach_fp_info(pinfo, direction, protocol_name, atoi(variant_string));
2220 /* RLC protocols need info from outhdr attached */
2221 else if ((strcmp(protocol_name, "rlc") == 0) ||
2222 (strcmp(protocol_name, "rlc_r4") == 0) ||
2223 (strcmp(protocol_name, "rlc_r5") == 0) ||
2224 (strcmp(protocol_name, "rlc_r6") == 0) ||
2225 (strcmp(protocol_name, "rlc_r7") == 0) ||
2226 (strcmp(protocol_name, "rlc_r8") == 0) ||
2227 (strcmp(protocol_name, "rlc_r9") == 0)) {
2229 parse_outhdr_string(outhdr_string, outhdr_length);
2230 /* Can't attach info yet. Need combination of outheader values
2231 and fields parsed from primitive header... */
2234 /* LTE MAC needs info attached */
2235 else if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2236 (strcmp(protocol_name, "mac_r9_lte") == 0)) {
2237 parse_outhdr_string(outhdr_string, outhdr_length);
2238 attach_mac_lte_info(pinfo);
2241 /* LTE RLC needs info attached */
2242 else if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2243 (strcmp(protocol_name, "rlc_r9_lte") == 0)) {
2244 parse_outhdr_string(outhdr_string, outhdr_length);
2245 attach_rlc_lte_info(pinfo);
2248 /* LTE PDCP needs info attached */
2249 else if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2250 (strcmp(protocol_name, "pdcp_r9_lte") == 0)) {
2251 parse_outhdr_string(outhdr_string, outhdr_length);
2252 attach_pdcp_lte_info(pinfo);
2256 else if ((strcmp(protocol_name, "nas_rrc_r8_lte") == 0) ||
2257 (strcmp(protocol_name, "nas_rrc_r9_lte") == 0)) {
2258 gboolean nas_body_found = TRUE;
2259 guint8 opcode = tvb_get_guint8(tvb, offset);
2260 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_opcode,
2261 tvb, offset++, 1, ENC_BIG_ENDIAN);
2263 offset++; /* Skip overall length */
2266 case LTE_NAS_RRC_DATA_IND:
2267 case LTE_NAS_RRC_DATA_REQ:
2270 offset += 2; /* 2 wasted bytes of UEId*/
2271 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2272 tvb, offset, 2, ENC_BIG_ENDIAN);
2275 case LTE_NAS_RRC_ESTABLISH_REQ:
2278 offset += 2; /* 2 wasted bytes of UEId*/
2279 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2280 tvb, offset, 2, ENC_BIG_ENDIAN);
2283 /* Establish cause. TODO: value_string */
2284 offset += 2; /* tag + length */
2285 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_establish_cause,
2286 tvb, offset++, 1, ENC_BIG_ENDIAN);
2288 /* Priority. TODO: Vals are low | high */
2289 offset += 2; /* tag + length */
2290 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_priority,
2291 tvb, offset++, 1, ENC_BIG_ENDIAN);
2293 case LTE_NAS_RRC_RELEASE_IND:
2296 offset += 2; /* 2 wasted bytes of UEId*/
2297 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2298 tvb, offset, 2, ENC_BIG_ENDIAN);
2301 /* Release cause. TODO: value_string */
2302 offset += 2; /* tag + length */
2303 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_release_cause,
2304 tvb, offset++, 1, ENC_BIG_ENDIAN);
2308 nas_body_found = FALSE;
2312 /* Look up dissector if if looks right */
2313 if (nas_body_found) {
2314 offset += 2; /* L3 tag + len */
2315 protocol_handle = find_dissector("nas-eps");
2319 /* Note that the first item of pinfo->pseudo_header->dct2000 will contain
2320 the pseudo-header needed (in some cases) by the Wireshark dissector that
2321 this packet data will be handed off to. */
2324 /***********************************************************************/
2325 /* Now hand off to the dissector of intended packet encapsulation type */
2327 /* Get protocol handle, and set p2p_dir where necessary.
2328 (packet-frame.c won't copy it from pseudo-header because it doesn't
2329 know about Catapult DCT2000 encap type...)
2332 case WTAP_ENCAP_RAW_IP:
2333 protocol_handle = find_dissector("ip");
2335 /* TODO: this doesn't work yet.
2336 pseudo_header isn't copied from wtap to pinfo... */
2337 if ((pinfo->pseudo_header != NULL) &&
2338 (pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid != 0)) {
2342 /* Add PDCP thread info as generated fields */
2343 ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_ueid, tvb, 0, 0,
2344 pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid);
2345 PROTO_ITEM_SET_GENERATED(ti);
2346 ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_drbid, tvb, 0, 0,
2347 pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.drbid);
2348 PROTO_ITEM_SET_GENERATED(ti);
2352 case WTAP_ENCAP_ETHERNET:
2353 protocol_handle = find_dissector("eth_withoutfcs");
2355 case WTAP_ENCAP_ISDN:
2356 protocol_handle = find_dissector("lapd");
2357 pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton;
2359 case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
2360 protocol_handle = find_dissector("atm_untruncated");
2362 case WTAP_ENCAP_PPP:
2363 protocol_handle = find_dissector("ppp_hdlc");
2364 pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent;
2366 case DCT2000_ENCAP_SSCOP:
2367 protocol_handle = find_dissector("sscop");
2369 case WTAP_ENCAP_FRELAY:
2370 protocol_handle = find_dissector("fr");
2372 case DCT2000_ENCAP_MTP2:
2373 protocol_handle = find_dissector("mtp2");
2375 case DCT2000_ENCAP_NBAP:
2376 protocol_handle = find_dissector("nbap");
2379 case DCT2000_ENCAP_UNHANDLED:
2380 /**********************************************************/
2381 /* The wiretap module wasn't able to set an encapsulation */
2382 /* type, but it may still be possible to dissect the data */
2383 /* if we know about the protocol or if we can recognise */
2384 /* and parse or skip a primitive header */
2385 /**********************************************************/
2387 /* Show context.port in src or dest column as appropriate */
2388 if (direction == 0) {
2389 col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
2395 if (direction == 1) {
2396 col_add_fstr(pinfo->cinfo, COL_DEF_DST,
2403 /**************************************************************************/
2404 /* These protocols have no encapsulation type, just look them up directly */
2406 if ((strcmp(protocol_name, "rlc") == 0) ||
2407 (strcmp(protocol_name, "rlc_r4") == 0) ||
2408 (strcmp(protocol_name, "rlc_r5") == 0) ||
2409 (strcmp(protocol_name, "rlc_r6") == 0) ||
2410 (strcmp(protocol_name, "rlc_r7") == 0) ||
2411 (strcmp(protocol_name, "rlc_r8") == 0) ||
2412 (strcmp(protocol_name, "rlc_r9") == 0)) {
2414 dissect_rlc_umts(tvb, offset, pinfo, tree, direction);
2419 if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2420 (strcmp(protocol_name, "mac_r9_lte") == 0)) {
2421 protocol_handle = mac_lte_handle;
2425 if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2426 (strcmp(protocol_name, "rlc_r9_lte") == 0)) {
2427 protocol_handle = rlc_lte_handle;
2431 if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2432 (strcmp(protocol_name, "pdcp_r9_lte") == 0)) {
2433 /* Dissect proprietary header, then pass remainder to PDCP */
2434 dissect_pdcp_lte(tvb, offset, pinfo, tree);
2439 /* Work with generic XML protocol. */
2441 if (strcmp(protocol_name, "xml") == 0) {
2442 protocol_handle = find_dissector("xml");
2446 /* Attempt to show tty messages as raw text */
2448 if (strcmp(protocol_name, "tty") == 0) {
2449 dissect_tty_lines(tvb, pinfo, dct2000_tree, offset);
2454 if (strcmp(protocol_name, "sipprim") == 0) {
2455 protocol_handle = find_dissector("sipprim");
2459 if (strcmp(protocol_name, "comment") == 0) {
2460 /* Extract & add the string. */
2461 proto_item *string_ti;
2462 char *string = (char*)tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
2464 /* Show comment string */
2465 string_ti = proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_comment, tvb,
2466 offset, -1, ENC_ASCII|ENC_NA);
2467 col_append_fstr(pinfo->cinfo, COL_INFO, "%s", string);
2469 if (catapult_dct2000_dissect_mac_lte_oob_messages) {
2470 /* Look into string for out-of-band MAC events, such as SRReq, SRInd */
2471 check_for_oob_mac_lte_events(pinfo, tvb, tree, string);
2474 /* Look for and flag generic error messages */
2475 if (strncmp(string, ">> ERR", 6) == 0) {
2476 proto_item *error_ti = proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_error_comment, tvb,
2477 offset, -1, ENC_NA);
2478 PROTO_ITEM_SET_GENERATED(error_ti);
2479 expert_add_info_format(pinfo, string_ti, PI_SEQUENCE, PI_ERROR,
2483 #define MONITOR_PREFIX ">> INFO ALL: Monitor: CPU=["
2484 if (strncmp(string, MONITOR_PREFIX, strlen(MONITOR_PREFIX)) == 0) {
2485 gint user_cpu, sys_cpu, load_cpu;
2486 gint memory_free, memory_load;
2487 gint lte_scs_user_cpu, lte_scs_system_cpu;
2489 matched = sscanf(string+strlen(MONITOR_PREFIX),
2490 "User%%=%d Sys%%=%d Load%%=%d] Memory=[FreeMb=%d Load%%=%d] LTE_SCS_CPU=[User%%=%d Sys%%=%d]",
2491 &user_cpu, &sys_cpu, &load_cpu,
2492 &memory_free, &memory_load,
2493 <e_scs_user_cpu, <e_scs_system_cpu);
2496 ti = proto_tree_add_uint(tree, hf_catapult_dct2000_lte_monitor_cpu_user,
2497 tvb, 0, 0, user_cpu);
2498 PROTO_ITEM_SET_GENERATED(ti);
2500 ti = proto_tree_add_uint(tree, hf_catapult_dct2000_lte_monitor_cpu_sys,
2501 tvb, 0, 0, sys_cpu);
2502 PROTO_ITEM_SET_GENERATED(ti);
2504 ti = proto_tree_add_uint(tree, hf_catapult_dct2000_lte_monitor_cpu_load,
2505 tvb, 0, 0, load_cpu);
2506 PROTO_ITEM_SET_GENERATED(ti);
2509 ti = proto_tree_add_uint(tree, hf_catapult_dct2000_lte_monitor_lte_scs_cpu_user,
2510 tvb, 0, 0, lte_scs_user_cpu);
2511 PROTO_ITEM_SET_GENERATED(ti);
2513 ti = proto_tree_add_uint(tree, hf_catapult_dct2000_lte_monitor_lte_scs_cpu_sys,
2514 tvb, 0, 0, lte_scs_system_cpu);
2515 PROTO_ITEM_SET_GENERATED(ti);
2523 if (catapult_dct2000_dissect_lte_rrc &&
2524 ((strcmp(protocol_name, "rrc_r8_lte") == 0) ||
2525 (strcmp(protocol_name, "rrcpdcpprim_r8_lte") == 0) ||
2526 (strcmp(protocol_name, "rrc_r9_lte") == 0) ||
2527 (strcmp(protocol_name, "rrcpdcpprim_r9_lte") == 0))) {
2529 /* Dissect proprietary header, then pass remainder
2530 to RRC (depending upon direction and channel type) */
2531 dissect_rrc_lte(tvb, offset, pinfo, tree);
2536 if ((strcmp(protocol_name, "ccpri_r8_lte") == 0) ||
2537 (strcmp(protocol_name, "ccpri_r9_lte") == 0)) {
2539 /* Dissect proprietary header, then pass remainder to lapb */
2540 dissect_ccpri_lte(tvb, offset, pinfo, tree);
2544 /* Many DCT2000 protocols have at least one IPPrim variant. If the
2545 protocol name can be matched to a dissector, try to find the
2546 UDP/TCP data inside and dissect it.
2549 if (!protocol_handle && catapult_dct2000_try_ipprim_heuristic) {
2550 guint32 source_addr_offset = 0, dest_addr_offset = 0;
2551 guint8 source_addr_length = 0, dest_addr_length = 0;
2552 guint32 source_port_offset = 0, dest_port_offset = 0;
2553 port_type type_of_port = PT_NONE;
2554 guint16 conn_id_offset = 0;
2555 int offset_before_ipprim_header = offset;
2557 /* Will give up if couldn't match protocol anyway... */
2558 heur_protocol_handle = look_for_dissector(protocol_name);
2559 if ((heur_protocol_handle != 0) &&
2560 find_ipprim_data_offset(tvb, &offset, direction,
2561 &source_addr_offset, &source_addr_length,
2562 &dest_addr_offset, &dest_addr_length,
2563 &source_port_offset, &dest_port_offset,
2567 proto_tree *ipprim_tree;
2568 proto_item *ipprim_ti;
2569 struct e_in6_addr sourcev6, destv6;
2571 /* Fetch IPv6 addresses */
2572 if (source_addr_length != 4) {
2573 tvb_get_ipv6(tvb, source_addr_offset, &sourcev6);
2575 if (dest_addr_length != 4) {
2576 tvb_get_ipv6(tvb, dest_addr_offset, &destv6);
2580 /* Will use this dissector then. */
2581 protocol_handle = heur_protocol_handle;
2583 /* Add address parameters to tree */
2584 /* Unfortunately can't automatically create a conversation filter for this...
2585 I *could* create a fake IP header from these details, but then it would be tricky
2586 to get the FP dissector called as it has no well-known ports or heuristics... */
2587 ipprim_ti = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_ipprim_addresses,
2588 tvb, offset_before_ipprim_header, 0,
2589 "", "IPPrim transport (%s): %s:%u -> %s:%u",
2590 (type_of_port == PT_UDP) ? "UDP" : "TCP",
2591 (source_addr_offset) ?
2592 ((source_addr_length == 4) ?
2593 get_hostname(tvb_get_ipv4(tvb, source_addr_offset)) :
2594 get_hostname6(&sourcev6)
2597 (source_port_offset) ?
2598 tvb_get_ntohs(tvb, source_port_offset) :
2600 (dest_addr_offset) ?
2601 ((source_addr_length == 4) ?
2602 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
2603 get_hostname6(&destv6)
2606 (dest_port_offset) ?
2607 tvb_get_ntohs(tvb, dest_port_offset) :
2609 if ((type_of_port == PT_TCP) && (conn_id_offset != 0)) {
2610 proto_item_append_text(ipprim_ti, " (conn_id=%u)", tvb_get_ntohs(tvb, conn_id_offset));
2613 /* Add these IPPRIM fields inside an IPPRIM subtree */
2614 ipprim_tree = proto_item_add_subtree(ipprim_ti, ett_catapult_dct2000_ipprim);
2616 /* Try to add right stuff to pinfo so conversation stuff works... */
2617 pinfo->ptype = type_of_port;
2618 switch (type_of_port) {
2620 pinfo->ipproto = IP_PROTO_UDP;
2623 pinfo->ipproto = IP_PROTO_TCP;
2626 pinfo->ipproto = IP_PROTO_NONE;
2629 /* Add addresses & ports into ipprim tree.
2630 Also set address info in pinfo for conversations... */
2631 if (source_addr_offset != 0) {
2632 proto_item *addr_ti;
2634 SET_ADDRESS(&pinfo->net_src,
2635 (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2637 (tvb_get_ptr(tvb, source_addr_offset, source_addr_length)));
2638 SET_ADDRESS(&pinfo->src,
2639 (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2641 (tvb_get_ptr(tvb, source_addr_offset, source_addr_length)));
2643 proto_tree_add_item(ipprim_tree,
2644 (source_addr_length == 4) ?
2645 hf_catapult_dct2000_ipprim_src_addr_v4 :
2646 hf_catapult_dct2000_ipprim_src_addr_v6,
2647 tvb, source_addr_offset, source_addr_length,
2648 (source_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2650 /* Add hidden item for "side-less" addr */
2651 addr_ti = proto_tree_add_item(ipprim_tree,
2652 (source_addr_length == 4) ?
2653 hf_catapult_dct2000_ipprim_addr_v4 :
2654 hf_catapult_dct2000_ipprim_addr_v6,
2655 tvb, source_addr_offset, source_addr_length,
2656 (source_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2657 PROTO_ITEM_SET_HIDDEN(addr_ti);
2659 if (source_port_offset != 0) {
2660 proto_item *port_ti;
2662 pinfo->srcport = tvb_get_ntohs(tvb, source_port_offset);
2664 proto_tree_add_item(ipprim_tree,
2665 (type_of_port == PT_UDP) ?
2666 hf_catapult_dct2000_ipprim_udp_src_port :
2667 hf_catapult_dct2000_ipprim_tcp_src_port,
2668 tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
2669 port_ti = proto_tree_add_item(ipprim_tree,
2670 (type_of_port == PT_UDP) ?
2671 hf_catapult_dct2000_ipprim_udp_port :
2672 hf_catapult_dct2000_ipprim_tcp_port,
2673 tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
2674 PROTO_ITEM_SET_HIDDEN(port_ti);
2676 if (dest_addr_offset != 0) {
2677 proto_item *addr_ti;
2679 SET_ADDRESS(&pinfo->net_dst,
2680 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2682 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2683 SET_ADDRESS(&pinfo->dst,
2684 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2686 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2687 proto_tree_add_item(ipprim_tree,
2688 (dest_addr_length == 4) ?
2689 hf_catapult_dct2000_ipprim_dst_addr_v4 :
2690 hf_catapult_dct2000_ipprim_dst_addr_v6,
2691 tvb, dest_addr_offset, dest_addr_length,
2692 (dest_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2694 /* Add hidden item for "side-less" addr */
2695 addr_ti = proto_tree_add_item(ipprim_tree,
2696 (dest_addr_length == 4) ?
2697 hf_catapult_dct2000_ipprim_addr_v4 :
2698 hf_catapult_dct2000_ipprim_addr_v6,
2699 tvb, dest_addr_offset, dest_addr_length,
2700 (dest_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2701 PROTO_ITEM_SET_HIDDEN(addr_ti);
2703 if (dest_port_offset != 0) {
2704 proto_item *port_ti;
2706 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
2708 proto_tree_add_item(ipprim_tree,
2709 (type_of_port == PT_UDP) ?
2710 hf_catapult_dct2000_ipprim_udp_dst_port :
2711 hf_catapult_dct2000_ipprim_tcp_dst_port,
2712 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2713 port_ti = proto_tree_add_item(ipprim_tree,
2714 (type_of_port == PT_UDP) ?
2715 hf_catapult_dct2000_ipprim_udp_port :
2716 hf_catapult_dct2000_ipprim_tcp_port,
2717 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2718 PROTO_ITEM_SET_HIDDEN(port_ti);
2720 if (conn_id_offset != 0) {
2721 proto_tree_add_item(ipprim_tree,
2722 hf_catapult_dct2000_ipprim_conn_id,
2723 tvb, conn_id_offset, 2, ENC_BIG_ENDIAN);
2727 /* Set source and dest columns now (will be overwriiten if
2728 src and dst IP addresses set) */
2729 if (source_addr_offset) {
2730 col_append_fstr(pinfo->cinfo, COL_DEF_SRC,
2732 get_hostname(tvb_get_ipv4(tvb, source_addr_offset)),
2733 tvb_get_ntohs(tvb, source_port_offset));
2735 if (dest_addr_offset) {
2736 col_append_fstr(pinfo->cinfo, COL_DEF_DST,
2738 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)),
2739 tvb_get_ntohs(tvb, dest_port_offset));
2742 /* Set length for IPPrim tree */
2743 proto_item_set_len(ipprim_tree, offset - offset_before_ipprim_header);
2748 /* Try SCTP Prim heuristic if configured to */
2749 if (!protocol_handle && catapult_dct2000_try_sctpprim_heuristic) {
2750 guint32 dest_addr_offset = 0;
2751 guint16 dest_addr_length = 0;
2752 guint32 dest_port_offset = 0;
2753 int offset_before_sctpprim_header = offset;
2755 heur_protocol_handle = look_for_dissector(protocol_name);
2756 if ((heur_protocol_handle != 0) &&
2757 (find_sctpprim_variant1_data_offset(tvb, &offset,
2760 &dest_port_offset) ||
2761 find_sctpprim_variant3_data_offset(tvb, &offset,
2764 &dest_port_offset))) {
2766 proto_tree *sctpprim_tree;
2767 proto_item *ti_local;
2769 /* Will use this dissector then. */
2770 protocol_handle = heur_protocol_handle;
2772 ti_local = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_sctpprim_addresses,
2773 tvb, offset_before_sctpprim_header, 0,
2774 "", "SCTPPrim transport: -> %s:%u",
2775 (dest_addr_offset) ?
2776 ((dest_addr_length == 4) ?
2777 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
2781 (dest_port_offset) ?
2782 tvb_get_ntohs(tvb, dest_port_offset) :
2785 /* Add these SCTPPRIM fields inside an SCTPPRIM subtree */
2786 sctpprim_tree = proto_item_add_subtree(ti_local, ett_catapult_dct2000_sctpprim);
2788 pinfo->ipproto = IP_PROTO_SCTP;
2790 /* Destination address */
2791 if (dest_addr_offset != 0) {
2792 proto_item *addr_ti;
2794 SET_ADDRESS(&pinfo->net_dst,
2795 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2797 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2798 SET_ADDRESS(&pinfo->dst,
2799 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2801 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2802 proto_tree_add_item(sctpprim_tree,
2803 (dest_addr_length == 4) ?
2804 hf_catapult_dct2000_sctpprim_dst_addr_v4 :
2805 hf_catapult_dct2000_sctpprim_dst_addr_v6,
2806 tvb, dest_addr_offset, dest_addr_length,
2807 (dest_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2809 /* Add hidden item for "side-less" addr */
2810 addr_ti = proto_tree_add_item(sctpprim_tree,
2811 (dest_addr_length == 4) ?
2812 hf_catapult_dct2000_sctpprim_addr_v4 :
2813 hf_catapult_dct2000_sctpprim_addr_v6,
2814 tvb, dest_addr_offset, dest_addr_length,
2815 (dest_addr_length == 4) ? ENC_BIG_ENDIAN : ENC_NA);
2816 PROTO_ITEM_SET_HIDDEN(addr_ti);
2819 if (dest_port_offset != 0) {
2820 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
2822 proto_tree_add_item(sctpprim_tree,
2823 hf_catapult_dct2000_sctpprim_dst_port,
2824 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2827 /* Set length for SCTPPrim tree */
2828 proto_item_set_len(sctpprim_tree, offset - offset_before_sctpprim_header);
2832 /* Last chance: is there a (private) registered protocol of the form
2833 "dct2000.protocol" ? */
2834 if (protocol_handle == 0) {
2835 /* TODO: only look inside preference? */
2836 char dotted_protocol_name[64+128];
2837 g_snprintf(dotted_protocol_name, 64+128, "dct2000.%s", protocol_name);
2838 protocol_handle = find_dissector(dotted_protocol_name);
2844 /* !! If get here, there is a mismatch between
2845 this dissector and the wiretap module catapult_dct2000.c !!
2847 DISSECTOR_ASSERT_NOT_REACHED();
2851 /* Set selection length of dct2000 tree */
2852 proto_item_set_len(dct2000_tree, offset);
2854 /* Try appropriate dissector, if one has been selected */
2855 if (protocol_handle != 0) {
2856 /* Dissect the remainder of the frame using chosen protocol handle */
2857 next_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
2858 sub_dissector_result = call_dissector_only(protocol_handle, next_tvb, pinfo, tree, NULL);
2862 if (protocol_handle == 0 || sub_dissector_result == 0) {
2863 /* Could get here because:
2864 - encap is DCT2000_ENCAP_UNHANDLED and we still didn't handle it, OR
2865 - desired protocol is unavailable (probably disabled), OR
2866 - protocol rejected our data
2867 Show remaining bytes as unparsed data */
2868 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_unparsed_data,
2869 tvb, offset, -1, ENC_NA);
2871 col_add_fstr(pinfo->cinfo, COL_INFO,
2872 "Not dissected (context=%s.%u t=%s %c prot=%s (v=%s))",
2876 (direction == 0) ? 'S' : 'R',
2881 /* Show number of dissected bytes */
2883 proto_item *ti_local = proto_tree_add_uint(dct2000_tree,
2884 hf_catapult_dct2000_dissected_length,
2885 tvb, 0, 0, tvb_reported_length(tvb)-offset);
2886 PROTO_ITEM_SET_GENERATED(ti_local);
2893 /******************************************************************************/
2894 /* Associate this protocol with the Catapult DCT2000 file encapsulation type. */
2895 /******************************************************************************/
2896 void proto_reg_handoff_catapult_dct2000(void)
2898 dissector_handle_t catapult_dct2000_handle = find_dissector("dct2000");
2900 dissector_add_uint("wtap_encap", WTAP_ENCAP_CATAPULT_DCT2000, catapult_dct2000_handle);
2902 mac_lte_handle = find_dissector("mac-lte");
2903 rlc_lte_handle = find_dissector("rlc-lte");
2904 pdcp_lte_handle = find_dissector("pdcp-lte");
2907 /****************************************/
2908 /* Register the protocol */
2909 /****************************************/
2910 void proto_register_catapult_dct2000(void)
2912 static hf_register_info hf[] =
2914 { &hf_catapult_dct2000_context,
2916 "dct2000.context", FT_STRING, BASE_NONE, NULL, 0x0,
2917 "Context name", HFILL
2920 { &hf_catapult_dct2000_port_number,
2921 { "Context Port number",
2922 "dct2000.context_port", FT_UINT8, BASE_DEC, NULL, 0x0,
2926 { &hf_catapult_dct2000_timestamp,
2928 "dct2000.timestamp", FT_DOUBLE, BASE_NONE, NULL, 0x0,
2929 "File timestamp", HFILL
2932 { &hf_catapult_dct2000_protocol,
2933 { "DCT2000 protocol",
2934 "dct2000.protocol", FT_STRING, BASE_NONE, NULL, 0x0,
2935 "Original (DCT2000) protocol name", HFILL
2938 { &hf_catapult_dct2000_variant,
2939 { "Protocol variant",
2940 "dct2000.variant", FT_STRING, BASE_NONE, NULL, 0x0,
2941 "DCT2000 protocol variant", HFILL
2944 { &hf_catapult_dct2000_outhdr,
2946 "dct2000.outhdr", FT_STRING, BASE_NONE, NULL, 0x0,
2947 "DCT2000 protocol outhdr", HFILL
2950 { &hf_catapult_dct2000_direction,
2952 "dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2953 "Frame direction (Sent or Received)", HFILL
2956 { &hf_catapult_dct2000_encap,
2957 { "Wireshark encapsulation",
2958 "dct2000.encapsulation", FT_UINT8, BASE_DEC, VALS(encap_vals), 0x0,
2959 "Wireshark frame encapsulation used", HFILL
2962 { &hf_catapult_dct2000_unparsed_data,
2963 { "Unparsed protocol data",
2964 "dct2000.unparsed_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2965 "Unparsed DCT2000 protocol data", HFILL
2968 { &hf_catapult_dct2000_comment,
2970 "dct2000.comment", FT_STRING, BASE_NONE, NULL, 0x0,
2974 { &hf_catapult_dct2000_error_comment,
2976 "dct2000.error-comment", FT_NONE, BASE_NONE, NULL, 0x0,
2980 { &hf_catapult_dct2000_dissected_length,
2981 { "Dissected length",
2982 "dct2000.dissected-length", FT_UINT16, BASE_DEC, NULL, 0x0,
2983 "Number of bytes dissected by subdissector(s)", HFILL
2987 { &hf_catapult_dct2000_ipprim_addresses,
2988 { "IPPrim Addresses",
2989 "dct2000.ipprim", FT_STRING, BASE_NONE, NULL, 0x0,
2993 { &hf_catapult_dct2000_ipprim_src_addr_v4,
2995 "dct2000.ipprim.src", FT_IPv4, BASE_NONE, NULL, 0x0,
2996 "IPPrim IPv4 Source Address", HFILL
2999 { &hf_catapult_dct2000_ipprim_src_addr_v6,
3001 "dct2000.ipprim.srcv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3002 "IPPrim IPv6 Source Address", HFILL
3005 { &hf_catapult_dct2000_ipprim_dst_addr_v4,
3006 { "Destination Address",
3007 "dct2000.ipprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3008 "IPPrim IPv4 Destination Address", HFILL
3011 { &hf_catapult_dct2000_ipprim_dst_addr_v6,
3012 { "Destination Address",
3013 "dct2000.ipprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3014 "IPPrim IPv6 Destination Address", HFILL
3017 { &hf_catapult_dct2000_ipprim_addr_v4,
3019 "dct2000.ipprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3020 "IPPrim IPv4 Address", HFILL
3023 { &hf_catapult_dct2000_ipprim_addr_v6,
3025 "dct2000.ipprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3026 "IPPrim IPv6 Address", HFILL
3029 { &hf_catapult_dct2000_ipprim_udp_src_port,
3030 { "UDP Source Port",
3031 "dct2000.ipprim.udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3032 "IPPrim UDP Source Port", HFILL
3035 { &hf_catapult_dct2000_ipprim_udp_dst_port,
3036 { "UDP Destination Port",
3037 "dct2000.ipprim.udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3038 "IPPrim UDP Destination Port", HFILL
3041 { &hf_catapult_dct2000_ipprim_udp_port,
3043 "dct2000.ipprim.udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3044 "IPPrim UDP Port", HFILL
3047 { &hf_catapult_dct2000_ipprim_tcp_src_port,
3048 { "TCP Source Port",
3049 "dct2000.ipprim.tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3050 "IPPrim TCP Source Port", HFILL
3053 { &hf_catapult_dct2000_ipprim_tcp_dst_port,
3054 { "TCP Destination Port",
3055 "dct2000.ipprim.tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3056 "IPPrim TCP Destination Port", HFILL
3059 { &hf_catapult_dct2000_ipprim_tcp_port,
3061 "dct2000.ipprim.tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3062 "IPPrim TCP Port", HFILL
3065 { &hf_catapult_dct2000_ipprim_conn_id,
3067 "dct2000.ipprim.conn-id", FT_UINT16, BASE_DEC, NULL, 0x0,
3068 "IPPrim TCP Connection ID", HFILL
3072 { &hf_catapult_dct2000_sctpprim_addresses,
3073 { "SCTPPrim Addresses",
3074 "dct2000.sctpprim", FT_STRING, BASE_NONE, NULL, 0x0,
3078 { &hf_catapult_dct2000_sctpprim_dst_addr_v4,
3079 { "Destination Address",
3080 "dct2000.sctpprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3081 "SCTPPrim IPv4 Destination Address", HFILL
3084 { &hf_catapult_dct2000_sctpprim_dst_addr_v6,
3085 { "Destination Address",
3086 "dct2000.sctpprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3087 "SCTPPrim IPv6 Destination Address", HFILL
3090 { &hf_catapult_dct2000_sctpprim_addr_v4,
3092 "dct2000.sctpprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3093 "SCTPPrim IPv4 Address", HFILL
3096 { &hf_catapult_dct2000_sctpprim_addr_v6,
3098 "dct2000.sctpprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3099 "SCTPPrim IPv6 Address", HFILL
3102 { &hf_catapult_dct2000_sctpprim_dst_port,
3103 { "UDP Destination Port",
3104 "dct2000.sctprim.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3105 "SCTPPrim Destination Port", HFILL
3109 { &hf_catapult_dct2000_tty,
3111 "dct2000.tty", FT_NONE, BASE_NONE, NULL, 0x0,
3115 { &hf_catapult_dct2000_tty_line,
3117 "dct2000.tty-line", FT_STRING, BASE_NONE, NULL, 0x0,
3122 { &hf_catapult_dct2000_lte_ueid,
3124 "dct2000.lte.ueid", FT_UINT16, BASE_DEC, NULL, 0x0,
3125 "User Equipment Identifier", HFILL
3128 { &hf_catapult_dct2000_lte_srbid,
3130 "dct2000.lte.srbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3131 "Signalling Radio Bearer Identifier", HFILL
3134 { &hf_catapult_dct2000_lte_drbid,
3136 "dct2000.lte.drbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3137 "Data Radio Bearer Identifier", HFILL
3140 { &hf_catapult_dct2000_lte_cellid,
3142 "dct2000.lte.cellid", FT_UINT16, BASE_DEC, NULL, 0x0,
3143 "Cell Identifier", HFILL
3146 { &hf_catapult_dct2000_lte_bcch_transport,
3148 "dct2000.lte.bcch-transport", FT_UINT16, BASE_DEC, VALS(bcch_transport_vals), 0x0,
3149 "BCCH Transport Channel", HFILL
3152 { &hf_catapult_dct2000_lte_rlc_op,
3154 "dct2000.lte.rlc-op", FT_UINT8, BASE_DEC, VALS(rlc_op_vals), 0x0,
3155 "RLC top-level op", HFILL
3158 { &hf_catapult_dct2000_lte_rlc_channel_type,
3159 { "RLC Logical Channel Type",
3160 "dct2000.lte.rlc-logchan-type", FT_UINT8, BASE_DEC, VALS(rlc_logical_channel_vals), 0x0,
3164 { &hf_catapult_dct2000_lte_rlc_mui,
3166 "dct2000.lte.rlc-mui", FT_UINT16, BASE_DEC, NULL, 0x0,
3170 { &hf_catapult_dct2000_lte_rlc_cnf,
3172 "dct2000.lte.rlc-cnf", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3176 { &hf_catapult_dct2000_lte_rlc_discard_req,
3178 "dct2000.lte.rlc-discard-req", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3179 "RLC Discard Req", HFILL
3183 { &hf_catapult_dct2000_lte_ccpri_opcode,
3185 "dct2000.lte.ccpri.opcode", FT_UINT8, BASE_DEC, VALS(ccpri_opcode_vals), 0x0,
3189 { &hf_catapult_dct2000_lte_ccpri_status,
3191 "dct2000.lte.ccpri.status", FT_UINT8, BASE_DEC, VALS(ccpri_status_vals), 0x0,
3195 { &hf_catapult_dct2000_lte_ccpri_channel,
3197 "dct2000.lte.ccpri.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
3202 { &hf_catapult_dct2000_lte_monitor_cpu_user,
3204 "dct2000.lte.monitor.cpu.user", FT_UINT32, BASE_DEC, NULL, 0x0,
3208 { &hf_catapult_dct2000_lte_monitor_cpu_sys,
3210 "dct2000.lte.monitor.cpu.sys", FT_UINT32, BASE_DEC, NULL, 0x0,
3214 { &hf_catapult_dct2000_lte_monitor_cpu_load,
3216 "dct2000.lte.monitor.cpu.load", FT_UINT32, BASE_DEC, NULL, 0x0,
3220 { &hf_catapult_dct2000_lte_monitor_lte_scs_cpu_user,
3221 { "lte-scs User CPU",
3222 "dct2000.lte.monitor.lte-scs.cpu.user", FT_UINT32, BASE_DEC, NULL, 0x0,
3226 { &hf_catapult_dct2000_lte_monitor_lte_scs_cpu_sys,
3227 { "lte-scs Sys CPU",
3228 "dct2000.lte.monitor.lte-scs.cpu.sys", FT_UINT32, BASE_DEC, NULL, 0x0,
3233 { &hf_catapult_dct2000_lte_nas_rrc_opcode,
3235 "dct2000.lte.nas-rrc.opcode", FT_UINT8, BASE_DEC, VALS(lte_nas_rrc_opcode_vals), 0x0,
3239 { &hf_catapult_dct2000_lte_nas_rrc_establish_cause,
3240 { "Establish Cause",
3241 "dct2000.lte.nas-rrc.establish-cause", FT_UINT8, BASE_DEC, NULL, 0x0,
3245 { &hf_catapult_dct2000_lte_nas_rrc_priority,
3247 "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3251 { &hf_catapult_dct2000_lte_nas_rrc_release_cause,
3253 "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3259 { &hf_catapult_dct2000_ueid,
3261 "dct2000.ueid", FT_UINT32, BASE_DEC, NULL, 0x0,
3262 "User Equipment Identifier", HFILL
3265 { &hf_catapult_dct2000_rbid,
3267 "dct2000.rbid", FT_UINT8, BASE_DEC, VALS(rlc_rbid_vals), 0x0,
3268 "Channel (rbid)", HFILL
3271 { &hf_catapult_dct2000_ccch_id,
3273 "dct2000.ccch-id", FT_UINT8, BASE_DEC, NULL, 0x0,
3274 "CCCH Identifier", HFILL
3277 { &hf_catapult_dct2000_no_crc_error,
3279 "dct2000.no-crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3283 { &hf_catapult_dct2000_crc_error,
3285 "dct2000.crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3289 { &hf_catapult_dct2000_clear_tx_buffer,
3290 { "Clear Tx Buffer",
3291 "dct2000.clear-tx-buffer", FT_NONE, BASE_NONE, NULL, 0x0,
3295 { &hf_catapult_dct2000_buffer_occupancy,
3296 { "Buffer Occupancy",
3297 "dct2000.buffer-occupancy", FT_UINT8, BASE_DEC, NULL, 0x0,
3301 { &hf_catapult_dct2000_pdu_size,
3303 "dct2000.pdu-size", FT_UINT16, BASE_DEC, NULL, 0x0,
3307 { &hf_catapult_dct2000_ueid_type,
3309 "dct2000.ueid-type", FT_UINT8, BASE_DEC, VALS(ueid_type_vals), 0x0,
3313 { &hf_catapult_dct2000_tx_priority,
3315 "dct2000.tx-priority", FT_UINT8, BASE_DEC, VALS(tx_priority_vals), 0x0,
3319 { &hf_catapult_dct2000_last_in_seg_set,
3320 { "Last in seg set",
3321 "dct2000.last-in-seg-set", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3325 { &hf_catapult_dct2000_rx_timing_deviation,
3326 { "Tx Timing Deviation",
3327 "dct2000.rx-timing-deviation", FT_UINT32, BASE_DEC, NULL, 0x0,
3331 { &hf_catapult_dct2000_transport_channel_type,
3332 { "Transport Channel Type",
3333 "dct2000.transport_channel_type", FT_UINT8, BASE_DEC, VALS(transport_channel_type_vals), 0x0,
3337 { &hf_catapult_dct2000_no_padding_bits,
3338 { "Number of padding bits",
3339 "dct2000.number-of-padding-bits", FT_UINT8, BASE_DEC, NULL, 0x0,
3346 static gint *ett[] =
3348 &ett_catapult_dct2000,
3349 &ett_catapult_dct2000_ipprim,
3350 &ett_catapult_dct2000_sctpprim,
3351 &ett_catapult_dct2000_tty
3354 module_t *catapult_dct2000_module;
3356 /* Register protocol. */
3357 proto_catapult_dct2000 = proto_register_protocol("Catapult DCT2000 packet",
3360 proto_register_field_array(proto_catapult_dct2000, hf, array_length(hf));
3361 proto_register_subtree_array(ett, array_length(ett));
3363 /* Allow dissector to find be found by name. */
3364 register_dissector("dct2000", dissect_catapult_dct2000, proto_catapult_dct2000);
3367 catapult_dct2000_module = prefs_register_protocol(proto_catapult_dct2000, NULL);
3369 /* This preference no longer supported (introduces linkage dependency between
3370 dissectors and wiretap) */
3371 prefs_register_obsolete_preference(catapult_dct2000_module, "board_ports_only");
3373 /* Determines whether for not-handled protocols we should try to parse it if:
3374 - it looks like its embedded in an ipprim message, AND
3375 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3376 prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
3377 "Use IP Primitive heuristic",
3378 "If a payload looks like its embedded in an "
3379 "IP primitive message, and there is a Wireshark "
3380 "dissector matching the DCT2000 protocol name, "
3381 "try parsing the payload using that dissector",
3382 &catapult_dct2000_try_ipprim_heuristic);
3384 /* Determines whether for not-handled protocols we should try to parse it if:
3385 - it looks like its embedded in an sctpprim message, AND
3386 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3387 prefs_register_bool_preference(catapult_dct2000_module, "sctpprim_heuristic",
3388 "Use SCTP Primitive heuristic",
3389 "If a payload looks like its embedded in an "
3390 "SCTP primitive message, and there is a Wireshark "
3391 "dissector matching the DCT2000 protocol name, "
3392 "try parsing the payload using that dissector",
3393 &catapult_dct2000_try_sctpprim_heuristic);
3395 /* Determines whether LTE RRC messages should be dissected */
3396 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_rrc",
3397 "Attempt to decode LTE RRC frames",
3398 "When set, attempt to decode LTE RRC frames. "
3399 "Note that this won't affect other protocols "
3400 "that also call the LTE RRC dissector",
3401 &catapult_dct2000_dissect_lte_rrc);
3403 /* Determines whether LTE S1AP messages should be dissected */
3404 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_s1ap",
3405 "Attempt to decode LTE S1AP frames",
3406 "When set, attempt to decode LTE S1AP frames. "
3407 "Note that this won't affect other protocols "
3408 "that also call the LTE S1AP dissector",
3409 &catapult_dct2000_dissect_lte_s1ap);
3411 /* Determines whether out-of-band messages should dissected */
3412 prefs_register_bool_preference(catapult_dct2000_module, "decode_mac_lte_oob_messages",
3413 "Look for out-of-band LTE MAC events messages in comments",
3414 "When set, look for formatted messages indicating "
3415 "specific events. This may be quite slow, so should "
3416 "be disabled if LTE MAC is not being analysed",
3417 &catapult_dct2000_dissect_mac_lte_oob_messages);