1 /* packet-catapult-dct2000.c
2 * Routines for Catapult DCT2000 packet stub header disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <epan/packet.h>
28 #include <epan/conversation.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
31 #include <epan/addr_resolv.h>
32 #include <epan/proto_data.h>
34 #include <wsutil/strtoi.h>
36 #include <wiretap/catapult_dct2000.h>
37 #include "packet-umts_fp.h"
38 #include "packet-umts_rlc.h"
40 #include "packet-mac-lte.h"
41 #include "packet-rlc-lte.h"
42 #include "packet-pdcp-lte.h"
44 void proto_reg_handoff_catapult_dct2000(void);
45 void proto_register_catapult_dct2000(void);
47 /* Protocol and registered fields. */
48 static int proto_catapult_dct2000 = -1;
50 static int hf_catapult_dct2000_context = -1;
51 static int hf_catapult_dct2000_port_number = -1;
52 static int hf_catapult_dct2000_timestamp = -1;
53 static int hf_catapult_dct2000_protocol = -1;
54 static int hf_catapult_dct2000_variant = -1;
55 static int hf_catapult_dct2000_outhdr = -1;
56 static int hf_catapult_dct2000_direction = -1;
57 static int hf_catapult_dct2000_encap = -1;
58 static int hf_catapult_dct2000_unparsed_data = -1;
59 static int hf_catapult_dct2000_comment = -1;
60 static int hf_catapult_dct2000_sprint = -1;
61 static int hf_catapult_dct2000_error_comment = -1;
62 static int hf_catapult_dct2000_tty = -1;
63 static int hf_catapult_dct2000_tty_line = -1;
64 static int hf_catapult_dct2000_dissected_length = -1;
66 static int hf_catapult_dct2000_ipprim_addresses = -1;
67 static int hf_catapult_dct2000_ipprim_src_addr_v4 = -1;
68 static int hf_catapult_dct2000_ipprim_src_addr_v6 = -1;
69 static int hf_catapult_dct2000_ipprim_dst_addr_v4 = -1;
70 static int hf_catapult_dct2000_ipprim_dst_addr_v6 = -1;
71 static int hf_catapult_dct2000_ipprim_addr_v4 = -1;
72 static int hf_catapult_dct2000_ipprim_addr_v6 = -1;
73 static int hf_catapult_dct2000_ipprim_udp_src_port = -1;
74 static int hf_catapult_dct2000_ipprim_udp_dst_port = -1;
75 static int hf_catapult_dct2000_ipprim_udp_port = -1;
76 static int hf_catapult_dct2000_ipprim_tcp_src_port = -1;
77 static int hf_catapult_dct2000_ipprim_tcp_dst_port = -1;
78 static int hf_catapult_dct2000_ipprim_tcp_port = -1;
79 static int hf_catapult_dct2000_ipprim_conn_id = -1;
81 static int hf_catapult_dct2000_sctpprim_addresses = -1;
82 static int hf_catapult_dct2000_sctpprim_dst_addr_v4 = -1;
83 static int hf_catapult_dct2000_sctpprim_dst_addr_v6 = -1;
84 static int hf_catapult_dct2000_sctpprim_addr_v4 = -1;
85 static int hf_catapult_dct2000_sctpprim_addr_v6 = -1;
86 static int hf_catapult_dct2000_sctpprim_dst_port = -1;
88 static int hf_catapult_dct2000_lte_ueid = -1;
89 static int hf_catapult_dct2000_lte_srbid = -1;
90 static int hf_catapult_dct2000_lte_drbid = -1;
91 static int hf_catapult_dct2000_lte_cellid = -1;
92 static int hf_catapult_dct2000_lte_bcch_transport = -1;
93 static int hf_catapult_dct2000_lte_rlc_op = -1;
94 static int hf_catapult_dct2000_lte_rlc_channel_type = -1;
95 static int hf_catapult_dct2000_lte_rlc_mui = -1;
96 static int hf_catapult_dct2000_lte_rlc_cnf = -1;
97 static int hf_catapult_dct2000_lte_rlc_discard_req = -1;
99 static int hf_catapult_dct2000_lte_ccpri_opcode = -1;
100 static int hf_catapult_dct2000_lte_ccpri_status = -1;
101 static int hf_catapult_dct2000_lte_ccpri_channel = -1;
103 static int hf_catapult_dct2000_lte_nas_rrc_opcode = -1;
104 static int hf_catapult_dct2000_lte_nas_rrc_establish_cause = -1;
105 static int hf_catapult_dct2000_lte_nas_rrc_priority = -1;
106 static int hf_catapult_dct2000_lte_nas_rrc_release_cause = -1;
109 /* UMTS RLC fields */
110 static int hf_catapult_dct2000_ueid = -1;
111 static int hf_catapult_dct2000_rbid = -1;
112 static int hf_catapult_dct2000_ccch_id = -1;
113 static int hf_catapult_dct2000_no_crc_error = -1;
114 static int hf_catapult_dct2000_crc_error = -1;
115 static int hf_catapult_dct2000_clear_tx_buffer = -1;
116 static int hf_catapult_dct2000_buffer_occupancy = -1;
117 static int hf_catapult_dct2000_pdu_size = -1;
118 static int hf_catapult_dct2000_ueid_type = -1;
119 static int hf_catapult_dct2000_tx_priority = -1;
120 static int hf_catapult_dct2000_last_in_seg_set = -1;
121 static int hf_catapult_dct2000_rx_timing_deviation = -1;
122 static int hf_catapult_dct2000_transport_channel_type = -1;
123 static int hf_catapult_dct2000_no_padding_bits = -1;
125 /* Variables used for preferences */
126 static gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
127 static gboolean catapult_dct2000_try_sctpprim_heuristic = TRUE;
128 static gboolean catapult_dct2000_dissect_lte_rrc = TRUE;
129 static gboolean catapult_dct2000_dissect_lte_s1ap = TRUE;
130 static gboolean catapult_dct2000_dissect_mac_lte_oob_messages = TRUE;
132 /* Protocol subtree. */
133 static int ett_catapult_dct2000 = -1;
134 static int ett_catapult_dct2000_ipprim = -1;
135 static int ett_catapult_dct2000_sctpprim = -1;
136 static int ett_catapult_dct2000_tty = -1;
138 static expert_field ei_catapult_dct2000_lte_ccpri_status_error = EI_INIT;
139 static expert_field ei_catapult_dct2000_error_comment_expert = EI_INIT;
140 static expert_field ei_catapult_dct2000_string_invalid = EI_INIT;
142 static const value_string direction_vals[] = {
148 static const value_string encap_vals[] = {
149 { WTAP_ENCAP_RAW_IP, "Raw IP" },
150 { WTAP_ENCAP_ETHERNET, "Ethernet" },
151 { WTAP_ENCAP_ISDN, "LAPD" },
152 { WTAP_ENCAP_ATM_PDUS_UNTRUNCATED, "ATM (PDUs untruncated)" },
153 { WTAP_ENCAP_PPP, "PPP" },
154 { DCT2000_ENCAP_SSCOP, "SSCOP" },
155 { WTAP_ENCAP_FRELAY, "Frame Relay" },
156 { WTAP_ENCAP_MTP2, "MTP2" },
157 { DCT2000_ENCAP_NBAP, "NBAP" },
158 { DCT2000_ENCAP_UNHANDLED, "No Direct Encapsulation" },
162 static const value_string bcch_transport_vals[] = {
163 { BCH_TRANSPORT, "BCH" },
164 { DLSCH_TRANSPORT, "DLSCH" },
169 #define RLC_MGMT_ASSIGN 0x41
170 #define RLC_AM_DATA_REQ 0x60
171 #define RLC_AM_DATA_IND 0x61
172 #define RLC_AM_DATA_CONF 0x62
173 #define RLC_UM_DATA_REQ 0x70
174 #define RLC_UM_DATA_IND 0x71
175 #define RLC_UM_DATA_CONF 0x74
176 #define RLC_TR_DATA_REQ 0x80
177 #define RLC_TR_DATA_IND 0x81
178 #define RLC_TR_DATA_CONF 0x83
180 static const value_string rlc_op_vals[] = {
181 { RLC_AM_DATA_REQ, "[UL] [AM]" },
182 { RLC_AM_DATA_IND, "[DL] [AM]" },
183 { RLC_UM_DATA_REQ, "[UL] [UM]"},
184 { RLC_UM_DATA_IND, "[DL] [UM]"},
185 { RLC_TR_DATA_REQ, "[UL] [TM]"},
186 { RLC_TR_DATA_IND, "[DL] [TM]"},
191 static const value_string rlc_logical_channel_vals[] = {
192 { Channel_DCCH, "DCCH"},
193 { Channel_BCCH, "BCCH"},
194 { Channel_CCCH, "CCCH"},
195 { Channel_PCCH, "PCCH"},
203 static const value_string ccpri_opcode_vals[] = {
204 { CCPRI_REQ, "REQUEST"},
205 { CCPRI_IND, "INDICATION"},
209 static const value_string ccpri_status_vals[] = {
215 static const value_string rlc_rbid_vals[] = {
241 static value_string_ext rlc_rbid_vals_ext = VALUE_STRING_EXT_INIT(rlc_rbid_vals);
243 static const value_string ueid_type_vals[] = {
249 static const value_string tx_priority_vals[] = {
255 static const value_string transport_channel_type_vals[] = {
268 #define LTE_NAS_RRC_DATA_IND 0x02
269 #define LTE_NAS_RRC_DATA_REQ 0x03
270 #define LTE_NAS_RRC_ESTABLISH_REQ 0x06
271 #define LTE_NAS_RRC_RELEASE_IND 0x08
273 static const value_string lte_nas_rrc_opcode_vals[] = {
274 { LTE_NAS_RRC_DATA_IND, "Data-Ind"},
275 { LTE_NAS_RRC_DATA_REQ, "Data-Req"},
276 { LTE_NAS_RRC_ESTABLISH_REQ, "Establish-Req"},
277 { LTE_NAS_RRC_RELEASE_IND, "Release-Ind"},
283 #define MAX_OUTHDR_VALUES 32
286 extern int proto_rlc;
288 extern int proto_rlc_lte;
289 extern int proto_pdcp_lte;
291 static dissector_handle_t mac_lte_handle;
292 static dissector_handle_t rlc_lte_handle;
293 static dissector_handle_t pdcp_lte_handle;
294 static dissector_handle_t catapult_dct2000_handle;
296 static dissector_handle_t look_for_dissector(const char *protocol_name);
297 static guint parse_outhdr_string(const guchar *outhdr_string, gint outhdr_length, guint *outhdr_values);
299 static void attach_fp_info(packet_info *pinfo, gboolean received,
300 const char *protocol_name, int variant,
301 guint *outhdr_values, guint outhdr_values_found);
302 static void attach_rlc_info(packet_info *pinfo, guint32 urnti, guint8 rbid,
303 gboolean is_sent, guint *outhdr_values,
304 guint outhdr_values_found);
306 static void attach_mac_lte_info(packet_info *pinfo, guint *outhdr_values,
307 guint outhdr_values_found);
308 static void attach_rlc_lte_info(packet_info *pinfo, guint *outhdr_values,
309 guint outhdr_values_found);
310 static void attach_pdcp_lte_info(packet_info *pinfo, guint *outhdr_values,
311 guint outhdr_values_found);
315 /* Return the number of bytes used to encode the length field
316 (we're not interested in the length value itself) */
317 static int skipASNLength(guint8 value)
319 if ((value & 0x80) == 0)
325 return ((value & 0x03) == 1) ? 2 : 3;
330 /* Look for the protocol data within an ipprim packet.
331 Only set *data_offset if data field found. */
332 static gboolean find_ipprim_data_offset(tvbuff_t *tvb, int *data_offset, guint8 direction,
333 guint32 *source_addr_offset, guint8 *source_addr_length,
334 guint32 *dest_addr_offset, guint8 *dest_addr_length,
335 guint32 *source_port_offset, guint32 *dest_port_offset,
336 port_type *type_of_port,
337 guint16 *conn_id_offset)
340 int offset = *data_offset;
342 /* Get the ipprim command code. */
343 guint8 tag = tvb_get_guint8(tvb, offset++);
345 /* Only accept UDP or TCP data request or indication */
347 case 0x23: /* UDP data request */
348 case 0x24: /* UDP data indication */
349 *type_of_port = PT_UDP;
351 case 0x45: /* TCP data request */
352 case 0x46: /* TCP data indication */
353 *type_of_port = PT_TCP;
359 /* Skip any other TLC fields before reach payload */
360 while (tvb_reported_length_remaining(tvb, offset) > 2) {
361 /* Look at next tag */
362 tag = tvb_get_guint8(tvb, offset++);
364 /* Is this the data payload we're expecting? */
365 if (((tag == 0x34) && (*type_of_port == PT_UDP)) ||
366 ((tag == 0x48) && (*type_of_port == PT_TCP))) {
368 *data_offset = offset;
372 /* Read length in next byte */
373 length = tvb_get_guint8(tvb, offset++);
375 if (tag == 0x31 && length >=4) {
376 /* Remote IP address */
377 if (direction == 0) {
378 /* Sent *to* remote, so dest */
379 *dest_addr_offset = offset;
380 *dest_addr_length = (length/4) * 4;
383 *source_addr_offset = offset;
384 *source_addr_length = (length/4) * 4;
387 /* Remote port follows (if present) */
388 if ((length % 4) == 2) {
389 if (direction == 0) {
390 *dest_port_offset = offset + *dest_addr_length;
393 *source_port_offset = offset + *source_addr_length;
399 if (length == 4 || length == 16) {
400 /* Local IP address */
401 if (direction == 0) {
402 /* Sent *from* local, so source */
403 *source_addr_offset = offset;
404 *source_addr_length = length;
407 *dest_addr_offset = offset;
408 *dest_addr_length = length;
413 if (tag == 0x33 && length == 2) {
415 if (direction == 0) {
416 /* Sent from local, so source */
417 *source_port_offset = offset;
420 *dest_port_offset = offset;
424 if (tag == 0x36 && length == 2) {
426 *conn_id_offset = offset;
429 /* Skip the length of the indicated value */
434 /* No data found... */
440 /* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
441 Only set *data_offset if data field found. */
442 static gboolean find_sctpprim_variant1_data_offset(tvbuff_t *tvb, int *data_offset,
443 guint32 *dest_addr_offset,
444 guint16 *dest_addr_length,
445 guint32 *dest_port_offset)
447 int offset = *data_offset;
449 /* Get the sctpprim command code. */
450 guint8 first_tag = tvb_get_guint8(tvb, offset++);
452 guint8 first_length_byte;
454 /* Only accept interested in data requests or indications */
456 case 0x04: /* data request */
457 case 0x62: /* data indication */
463 first_length_byte = tvb_get_guint8(tvb, offset);
464 offset += skipASNLength(first_length_byte);
466 /* Skip any other fields before reach payload */
467 while (tvb_reported_length_remaining(tvb, offset) > 2) {
468 /* Look at next tag */
469 tag = tvb_get_guint8(tvb, offset++);
471 /* Is this the data payload we're expecting? */
473 *data_offset = offset;
477 /* Skip length field */
480 case 0x0a: /* destPort */
481 *dest_port_offset = offset;
485 case 0x01: /* sctpInstanceNum */
486 case 0x1e: /* strseqnum */
487 case 0x0d: /* streamnum */
491 case 0x09: /* ipv4Address */
492 *dest_addr_offset = offset;
493 *dest_addr_length = 4;
498 case 0x0c: /* payloadType */
503 /* Fail if not a known header field */
509 /* No data found... */
513 /* Look for the protocol data within an sctpprim (variant 3) packet.
514 Return value indicates whether this header found.
515 Only set *data_offset if data field found. */
516 static gboolean find_sctpprim_variant3_data_offset(tvbuff_t *tvb, int *data_offset,
517 guint32 *dest_addr_offset,
518 guint16 *dest_addr_length,
519 guint32 *dest_port_offset)
523 int offset = *data_offset;
525 /* Get the sctpprim (2 byte) command code. */
526 guint16 top_tag = tvb_get_ntohs(tvb, offset);
529 /* Only interested in data requests or indications */
530 if ((top_tag != 0x0400) && /* SendDataReq */
531 (top_tag != 0x6200)) { /* DataInd */
535 /* Overall length field is next 2 bytes */
538 /* Rx/Tx ops have different formats */
542 if (top_tag == 0x6200) {
543 /* Next 2 bytes are associate ID */
546 /* Next 2 bytes are destination port */
547 *dest_port_offset = offset;
550 /* Destination address should follow - check tag */
551 tag = tvb_get_ntohs(tvb, offset);
560 length = tvb_get_ntohs(tvb, offset) / 2;
561 if ((length != 4) && (length != 16))
567 /* Address data is here */
568 *dest_addr_offset = offset;
569 *dest_addr_length = length;
574 /* Not interested in remaining (fixed) fields */
575 if (tvb_reported_length_remaining(tvb, offset) > (4 + 2 + 2 + 4)) {
576 offset += (4 + 2 + 2 + 4);
582 /* Data should now be here */
583 tag = tvb_get_ntohs(tvb, offset);
586 /* 2-byte length field */
589 /* Data is here!!! */
590 *data_offset = offset;
598 /***********************************/
599 /* SendDataReq (top_tag == 0x0400) */
601 /* AssociateId should follow - check tag */
602 tag = tvb_get_ntohs(tvb, offset);
610 /* Skip 2-byte value */
615 tag = tvb_get_ntohs(tvb, offset);
618 /* Some optional params */
619 while ((tag != 0x0c00) && (tvb_reported_length_remaining(tvb, offset) > 4)) {
621 case 0x0900: /* Dest address */
623 length = tvb_get_ntohs(tvb, offset) / 2;
624 if ((length != 4) && (length != 16)) {
629 /* Address data is here */
630 *dest_addr_offset = offset;
631 *dest_addr_length = length;
636 case 0x0a00: /* Dest port number */
637 *dest_port_offset = offset;
641 case 0x0d00: /* StreamNum */
642 *dest_port_offset = offset;
651 /* Get the next tag */
652 tag = tvb_get_ntohs(tvb, offset);
657 /* Mandatory payload type */
661 length = tvb_get_ntohs(tvb, offset) / 2;
666 /* Optional options */
667 tag = tvb_get_ntohs(tvb, offset);
670 length = tvb_get_ntohs(tvb, offset) / 2;
676 tag = tvb_get_ntohs(tvb, offset);
681 /* Data should now be here!! */
683 /* 2-byte length field */
686 /* Data is here!!! */
687 *data_offset = offset;
697 /* Dissect a UMTS RLC frame by:
698 - parsing the primitive header
699 - passing those values + outhdeader to dissector
700 - calling the UMTS RLC dissector */
701 static void dissect_rlc_umts(tvbuff_t *tvb, gint offset,
702 packet_info *pinfo, proto_tree *tree,
703 gboolean is_sent, guint *outhdr_values,
704 guint outhdr_values_found)
707 gboolean ueid_set = FALSE, rbid_set=FALSE;
712 dissector_handle_t rlc_umts_handle = 0;
714 /* Top-level opcode */
715 tag = tvb_get_guint8(tvb, offset++);
717 case 0xc0: /* mac data request */
718 case 0xc1: /* mac data indication */
722 /* No data to dissect */
726 /* Keep going until reach data tag or end of frame */
727 while ((tag != 0x41) && tvb_reported_length_remaining(tvb, offset)) { /* i.e. Data */
728 tag = tvb_get_guint8(tvb, offset++);
730 case 0x72: /* UE Id */
731 ueid = tvb_get_ntohl(tvb, offset);
732 proto_tree_add_item(tree, hf_catapult_dct2000_ueid, tvb, offset, 4, ENC_BIG_ENDIAN);
736 case 0xa2: /* RBID */
737 offset++; /* skip length */
738 rbid = tvb_get_guint8(tvb, offset);
739 proto_tree_add_item(tree, hf_catapult_dct2000_rbid, tvb, offset, 1, ENC_BIG_ENDIAN);
743 case 0x22: /* CCCH-id setting rbid to CCCH! */
744 offset++; /* skip length */
745 proto_tree_add_item(tree, hf_catapult_dct2000_ccch_id, tvb, offset, 1, ENC_BIG_ENDIAN);
749 case 0xc4: /* No CRC error */
750 proto_tree_add_item(tree, hf_catapult_dct2000_no_crc_error, tvb, offset-1, 1, ENC_NA);
752 case 0xc5: /* CRC error */
753 proto_tree_add_item(tree, hf_catapult_dct2000_crc_error, tvb, offset-1, 1, ENC_NA);
755 case 0xf7: /* Clear Tx Buffer */
756 proto_tree_add_item(tree, hf_catapult_dct2000_clear_tx_buffer, tvb, offset-1, 1, ENC_NA);
759 case 0x41: /* Data !!! */
760 offset += skipASNLength(tvb_get_guint8(tvb, offset));
764 /* For other fields, just skip length and following data */
765 length = tvb_get_guint8(tvb, offset++);
767 case 0x42: /* Buffer Occupancy */
768 proto_tree_add_item(tree, hf_catapult_dct2000_buffer_occupancy, tvb, offset, length, ENC_BIG_ENDIAN);
770 case 0x49: /* PDU Size */
771 proto_tree_add_item(tree, hf_catapult_dct2000_pdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
773 case 0x47: /* UEId type */
774 proto_tree_add_item(tree, hf_catapult_dct2000_ueid_type, tvb, offset, 1, ENC_BIG_ENDIAN);
776 case 0x4e: /* Tx Priority */
777 proto_tree_add_item(tree, hf_catapult_dct2000_tx_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
779 case 0x4c: /* Last in seg set */
780 proto_tree_add_item(tree, hf_catapult_dct2000_last_in_seg_set, tvb, offset, 1, ENC_BIG_ENDIAN);
782 case 0x43: /* Rx timing deviation */
783 proto_tree_add_item(tree, hf_catapult_dct2000_rx_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN);
785 case 0x46: /* Transport channel type */
786 proto_tree_add_item(tree, hf_catapult_dct2000_transport_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
788 case 0xc2: /* Number of padding bits */
789 proto_tree_add_item(tree, hf_catapult_dct2000_no_padding_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
801 /* Have we got enough info to call dissector */
802 if ((tag == 0x41) && ueid_set && rbid_set) {
803 attach_rlc_info(pinfo, ueid, rbid, is_sent, outhdr_values,
804 outhdr_values_found);
806 /* Set appropriate RLC dissector handle */
808 case 1: case 2: case 3: case 4: case 5:
809 case 6: case 7: case 8: case 9: case 10:
810 case 11: case 12: case 13: case 14: case 15:
812 /* TODO: can't really tell if these are control or transport...
813 maybe control with preferences (UAT?) between "rlc.ps_dtch" and "rlc.dcch" ? */
814 rlc_umts_handle = find_dissector("rlc.dch_unknown");
817 rlc_umts_handle = find_dissector("rlc.ccch");
820 rlc_umts_handle = find_dissector("rlc.ctch");
828 /* Call UMTS RLC dissector */
829 if (rlc_umts_handle != 0) {
830 rlc_tvb = tvb_new_subset_remaining(tvb, offset);
831 call_dissector_only(rlc_umts_handle, rlc_tvb, pinfo, tree, NULL);
838 /* Dissect an RRC LTE frame by first parsing the header entries then passing
839 the data to the RRC dissector, according to direction and channel type.
840 TODO: factor out common code between this function and dissect_pdcp_lte() */
841 static void dissect_rrc_lte(tvbuff_t *tvb, gint offset,
842 packet_info *pinfo, proto_tree *tree)
845 dissector_handle_t protocol_handle = 0;
846 gboolean isUplink = FALSE;
847 LogicalChannelType logicalChannelType;
849 guint8 bcch_transport = 0;
852 /* Top-level opcode */
853 tag = tvb_get_guint8(tvb, offset++);
855 case 0x00: /* Data_Req_UE */
856 case 0x04: /* Data_Ind_eNodeB */
860 case 0x02: /* Data_Req_eNodeB */
861 case 0x03: /* Data_Ind_UE */
866 /* Unexpected opcode tag! */
871 offset += skipASNLength(tvb_get_guint8(tvb, offset));
874 tag = tvb_get_guint8(tvb, offset++);
876 case 0x12: /* UE_Id_LCId */
878 /* Dedicated channel info */
880 /* Length will fit in one byte here */
883 logicalChannelType = Channel_DCCH;
886 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, ENC_BIG_ENDIAN);
889 /* Get tag of channel type */
890 tag = tvb_get_guint8(tvb, offset++);
895 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
896 tvb_get_guint8(tvb, offset));
897 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
898 tvb, offset, 1, ENC_BIG_ENDIAN);
903 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
904 tvb_get_guint8(tvb, offset));
905 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
906 tvb, offset, 1, ENC_BIG_ENDIAN);
911 /* Unexpected channel type */
916 case 0x1a: /* Cell_LCId */
918 /* Common channel info */
924 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
925 tvb, offset, 2, ENC_BIG_ENDIAN);
926 cell_id = tvb_get_ntohs(tvb, offset);
929 /* Logical channel type */
930 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
931 tvb, offset, 1, ENC_BIG_ENDIAN);
932 logicalChannelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
935 /* Won't be seen if RRC decoder is called... */
936 col_append_fstr(pinfo->cinfo, COL_INFO, " cell-id=%u %s",
938 val_to_str_const(logicalChannelType, rlc_logical_channel_vals,
942 switch (logicalChannelType) {
947 /* Transport channel type */
948 bcch_transport = tvb_get_guint8(tvb, offset);
949 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
950 tvb, offset, 1, ENC_BIG_ENDIAN);
959 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
960 tvb, offset, 2, ENC_BIG_ENDIAN);
974 /* Data tag should follow */
975 tag = tvb_get_guint8(tvb, offset++);
981 offset += skipASNLength(tvb_get_guint8(tvb, offset));
983 /* Look up dissector handle corresponding to direction and channel type */
986 /* Uplink channel types */
987 switch (logicalChannelType) {
989 protocol_handle = find_dissector("lte_rrc.ul_dcch");
992 protocol_handle = find_dissector("lte_rrc.ul_ccch");
996 /* Unknown Uplink channel type */
1001 /* Downlink channel types */
1002 switch (logicalChannelType) {
1004 protocol_handle = find_dissector("lte_rrc.dl_dcch");
1007 protocol_handle = find_dissector("lte_rrc.dl_ccch");
1010 protocol_handle = find_dissector("lte_rrc.pcch");
1013 if (bcch_transport == 1) {
1014 protocol_handle = find_dissector("lte_rrc.bcch_bch");
1017 protocol_handle = find_dissector("lte_rrc.bcch_dl_sch");
1022 /* Unknown Downlink channel type */
1027 /* Send to RRC dissector, if got here, have sub-dissector and some data left */
1028 if ((protocol_handle != NULL) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
1029 rrc_tvb = tvb_new_subset_remaining(tvb, offset);
1030 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
1035 /* Dissect an CCPRI LTE frame by first parsing the header entries then passing
1036 the data to the CPRI C&M dissector
1038 XXX - is this the Common Public Radio Interface? If so, what's the extra
1039 "C" in "CCPRI"? And why is the LAPB dissector involved here? The CPRI
1040 spec just speaks of HDLC; LAPB is certainly a HDLC-based protocol, but
1041 that doesn't mean every HDLC-based protocol is LAPB. */
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(pinfo, ti, &ei_catapult_dct2000_lte_ccpri_status_error);
1078 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ccpri_channel,
1079 tvb, offset, 1, ENC_BIG_ENDIAN);
1082 /* Data tag must follow */
1083 tag = tvb_get_guint8(tvb, offset++);
1089 length = tvb_get_ntohs(tvb, offset);
1092 /* Send remainder to lapb dissector; I assume "CPRI" is the Common
1093 Public Radio Interface, in which case the "lapb" dissector is
1094 being used to dissect the HDLC used by CPRI, and in which case
1095 we should really have a CPRI dissector that dissects its HDLC
1096 and then hands off to a CPRI C&M dissector. */
1097 protocol_handle = find_dissector("lapb");
1098 if ((protocol_handle != NULL) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
1099 ccpri_tvb = tvb_new_subset_length(tvb, offset, length);
1100 call_dissector_only(protocol_handle, ccpri_tvb, pinfo, tree, NULL);
1107 /* Dissect a PDCP LTE frame by first parsing the RLCPrim header then passing
1108 the data to the PDCP LTE dissector */
1109 static void dissect_pdcp_lte(tvbuff_t *tvb, gint offset,
1110 packet_info *pinfo, proto_tree *tree)
1114 struct pdcp_lte_info *p_pdcp_lte_info = NULL;
1115 tvbuff_t *pdcp_lte_tvb;
1119 /* Look this up so can update channel info */
1120 p_pdcp_lte_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1121 if (p_pdcp_lte_info == NULL) {
1122 /* This really should be set...can't dissect anything without it */
1126 /* Top-level opcode */
1127 opcode = tvb_get_guint8(tvb, offset);
1129 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_op, tvb, offset, 1, ENC_BIG_ENDIAN);
1133 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, rlc_op_vals, "Unknown"));
1135 /* Assume UE side, so REQ is UL, IND is DL */
1137 case RLC_AM_DATA_REQ:
1138 case RLC_UM_DATA_REQ:
1139 case RLC_TR_DATA_REQ:
1140 p_pdcp_lte_info->direction = DIRECTION_UPLINK;
1144 p_pdcp_lte_info->direction = DIRECTION_DOWNLINK;
1149 case RLC_AM_DATA_REQ:
1150 case RLC_AM_DATA_IND:
1151 case RLC_UM_DATA_REQ:
1152 case RLC_UM_DATA_IND:
1153 case RLC_TR_DATA_REQ:
1154 case RLC_TR_DATA_IND:
1157 tag = tvb_get_guint8(tvb, offset++);
1159 case 0x10: /* UE_Id_LCId */
1161 /* Dedicated channel info */
1163 /* Length will fit in one byte here */
1166 p_pdcp_lte_info->channelType = Channel_DCCH;
1169 ueid = tvb_get_ntohs(tvb, offset);
1170 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, ENC_BIG_ENDIAN);
1171 col_append_fstr(pinfo->cinfo, COL_INFO,
1173 p_pdcp_lte_info->ueid = ueid;
1176 /* Get tag of channel type */
1177 tag = tvb_get_guint8(tvb, offset++);
1182 channelId = tvb_get_guint8(tvb, offset);
1183 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
1185 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
1186 tvb, offset++, 1, ENC_BIG_ENDIAN);
1187 p_pdcp_lte_info->channelId = channelId;
1191 channelId = tvb_get_guint8(tvb, offset);
1192 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
1194 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
1195 tvb, offset++, 1, ENC_BIG_ENDIAN);
1196 p_pdcp_lte_info->channelId = channelId;
1200 /* Unexpected channel type */
1205 case 0x1a: /* Cell_LCId */
1207 /* Common channel info */
1213 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
1214 tvb, offset, 2, ENC_BIG_ENDIAN);
1217 /* Logical channel type */
1218 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
1219 tvb, offset, 1, ENC_BIG_ENDIAN);
1220 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_guint8(tvb, offset++);
1221 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1222 val_to_str_const(p_pdcp_lte_info->channelType, rlc_logical_channel_vals,
1223 "UNKNOWN-CHANNEL"));
1225 switch (p_pdcp_lte_info->channelType) {
1230 /* Transport channel type */
1231 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_guint8(tvb, offset);
1232 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
1233 tvb, offset, 1, ENC_BIG_ENDIAN);
1242 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
1243 tvb, offset, 2, ENC_BIG_ENDIAN);
1244 ueid = tvb_get_ntohs(tvb, offset);
1247 col_append_fstr(pinfo->cinfo, COL_INFO, " UEId=%u", ueid);
1256 /* Unexpected tag */
1260 /* Other optional fields may follow */
1261 tag = tvb_get_guint8(tvb, offset++);
1262 while ((tag != 0x41) && (tvb_reported_length_remaining(tvb, offset) > 2)) {
1267 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_mui,
1268 tvb, offset, 2, ENC_BIG_ENDIAN);
1271 /* CNF follows MUI in AM */
1272 if ((opcode == RLC_AM_DATA_REQ) || (opcode == RLC_AM_DATA_IND)) {
1273 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_cnf,
1274 tvb, offset, 1, ENC_NA);
1278 else if (tag == 0x45) {
1281 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_discard_req,
1282 tvb, offset, 1, ENC_NA);
1286 tag = tvb_get_guint8(tvb, offset++);
1290 /********************************/
1291 /* Should be at data tag now */
1293 /* Call PDCP LTE dissector */
1294 pdcp_lte_tvb = tvb_new_subset_remaining(tvb, offset);
1295 call_dissector_only(pdcp_lte_handle, pdcp_lte_tvb, pinfo, tree, NULL);
1308 /* Look up dissector by protocol name. Fix up known name mis-matches.
1309 This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */
1310 static dissector_handle_t look_for_dissector(const char *protocol_name)
1312 /* Use known aliases and protocol name prefixes */
1313 if (strcmp(protocol_name, "tbcp") == 0) {
1314 return find_dissector("rtcp");
1317 if (strncmp(protocol_name, "diameter", strlen("diameter")) == 0) {
1318 return find_dissector("diameter");
1321 if ((strcmp(protocol_name, "xcap_caps") == 0) ||
1322 (strcmp(protocol_name, "soap") == 0) ||
1323 (strcmp(protocol_name, "mm1") == 0) ||
1324 (strcmp(protocol_name, "mm3") == 0) ||
1325 (strcmp(protocol_name, "mm7") == 0)) {
1327 return find_dissector("http");
1330 if ((strcmp(protocol_name, "fp") == 0) ||
1331 (strncmp(protocol_name, "fp_r", 4) == 0) ||
1332 (strcmp(protocol_name, "fpiur_r5") == 0)) {
1334 return find_dissector("fp");
1337 if ((strcmp(protocol_name, "iuup_rtp_r5") == 0) ||
1338 (strcmp(protocol_name, "iuup_rtp_r6") == 0)) {
1340 return find_dissector("rtp");
1343 if (strcmp(protocol_name, "sipt") == 0) {
1344 return find_dissector("sip");
1347 if (strncmp(protocol_name, "nbap_sctp", strlen("nbap_sctp")) == 0) {
1348 return find_dissector("nbap");
1351 if (strncmp(protocol_name, "gtp", strlen("gtp")) == 0) {
1352 return find_dissector("gtp");
1355 if (strcmp(protocol_name, "dhcpv4") == 0) {
1356 return find_dissector("bootp");
1359 if (strcmp(protocol_name, "wimax") == 0) {
1360 return find_dissector("wimaxasncp");
1363 if (strncmp(protocol_name, "sabp", strlen("sabp")) == 0) {
1364 return find_dissector("sabp");
1367 if (strcmp(protocol_name, "wtp") == 0) {
1368 return find_dissector("wtp-udp");
1371 /* Only match with s1ap if preference turned on */
1372 if (catapult_dct2000_dissect_lte_s1ap &&
1373 strncmp(protocol_name, "s1ap", strlen("s1ap")) == 0) {
1375 return find_dissector("s1ap");
1378 /* Always try lookup for now */
1379 if ((strncmp(protocol_name, "x2ap_r8_lte", strlen("x2ap_r8_lte")) == 0) ||
1380 (strncmp(protocol_name, "x2ap_r9_lte", strlen("x2ap_r9_lte")) == 0)) {
1382 return find_dissector("x2ap");
1386 if ((strcmp(protocol_name, "gtpv2_r8_lte") == 0) ||
1387 (strcmp(protocol_name, "gtpv2_r9_lte") == 0)) {
1388 return find_dissector("gtpv2");
1392 /* Try for an exact match */
1394 return find_dissector(protocol_name);
1399 /* Populate outhdr_values array with numbers found in outhdr_string */
1400 static guint parse_outhdr_string(const guchar *outhdr_string, gint outhdr_string_len, guint *outhdr_values)
1403 int outhdr_values_found;
1405 /* Populate values array */
1406 for (outhdr_values_found=0; outhdr_values_found < MAX_OUTHDR_VALUES; ) {
1408 guint digit_array[MAX_OUTHDR_VALUES];
1409 guint number_digits = 0;
1412 guint multiplier = 1;
1416 for ( ; (n < outhdr_string_len) && (number_digits < MAX_OUTHDR_VALUES); n++) {
1417 if (!g_ascii_isdigit(outhdr_string[n])) {
1421 digit_array[number_digits++] = outhdr_string[n] - '0';
1425 if (number_digits == 0) {
1426 /* No more numbers left */
1430 /* Convert digits into value (much faster than format_text() + atoi()) */
1431 for (d=number_digits; d > 0; d--) {
1432 number += ((digit_array[d-1]) * multiplier);
1435 outhdr_values[outhdr_values_found++] = number;
1440 return outhdr_values_found;
1445 /* Fill in an FP packet info struct and attach it to the packet for the FP
1447 static void attach_fp_info(packet_info *pinfo, gboolean received,
1448 const char *protocol_name, int variant,
1449 guint *outhdr_values, guint outhdr_values_found)
1453 guint tf_start, num_chans_start;
1455 int calculated_variant;
1457 /* Only need to set info once per session. */
1458 struct fp_info *p_fp_info = (struct fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1459 if (p_fp_info != NULL) {
1463 /* Allocate struct */
1464 p_fp_info = wmem_new0(wmem_file_scope(), struct fp_info);
1466 /* Check that the number of outhdr values looks sensible */
1467 if (((strcmp(protocol_name, "fpiur_r5") == 0) && (outhdr_values_found != 2)) ||
1468 (outhdr_values_found < 5)) {
1473 /* 3gpp release (99, 4, 5, 6, 7) */
1474 if (strcmp(protocol_name, "fp") == 0) {
1475 p_fp_info->release = 99;
1477 else if (strcmp(protocol_name, "fp_r4") == 0) {
1478 p_fp_info->release = 4;
1480 else if (strcmp(protocol_name, "fp_r5") == 0) {
1481 p_fp_info->release = 5;
1483 else if (strcmp(protocol_name, "fp_r6") == 0) {
1484 p_fp_info->release = 6;
1486 else if (strcmp(protocol_name, "fp_r7") == 0) {
1487 p_fp_info->release = 7;
1489 else if (strcmp(protocol_name, "fp_r8") == 0) {
1490 p_fp_info->release = 8;
1492 else if (strcmp(protocol_name, "fpiur_r5") == 0) {
1493 p_fp_info->release = 5;
1496 /* Really shouldn't get here */
1497 DISSECTOR_ASSERT_NOT_REACHED();
1501 /* Release date is derived from variant number */
1502 /* Only R6 sub-versions currently influence format within a release */
1503 switch (p_fp_info->release) {
1505 if (variant < 256) {
1506 calculated_variant = variant;
1509 calculated_variant = variant / 256;
1512 switch (calculated_variant) {
1514 p_fp_info->release_year = 2005;
1515 p_fp_info->release_month = 6;
1518 p_fp_info->release_year = 2005;
1519 p_fp_info->release_month = 9;
1523 p_fp_info->release_year = 2006;
1524 p_fp_info->release_month = 3;
1529 p_fp_info->release_year = 2008;
1530 p_fp_info->release_month = 3;
1534 p_fp_info->release_year = 2010;
1535 p_fp_info->release_month = 6;
1540 p_fp_info->release_year = 0;
1541 p_fp_info->release_month = 0;
1546 p_fp_info->channel = outhdr_values[i++];
1547 /* Sad hack until this value is filled in properly */
1548 if (p_fp_info->channel == 0) {
1549 p_fp_info->channel = CHANNEL_DCH;
1552 /* Derive direction from node type/side */
1553 node_type = outhdr_values[i++];
1554 p_fp_info->is_uplink = (( received && (node_type == 2)) ||
1555 (!received && (node_type == 1)));
1557 /* Division type introduced for R7 */
1558 if ((p_fp_info->release == 7) ||
1559 (p_fp_info->release == 8)) {
1560 p_fp_info->division = (enum division_type)outhdr_values[i++];
1563 /* HS-DSCH config */
1564 if (p_fp_info->channel == CHANNEL_HSDSCH) {
1565 if ((p_fp_info->release == 7) ||
1566 (p_fp_info->release == 8)) {
1567 /* Entity (MAC-hs or MAC-ehs) used */
1568 if (outhdr_values[i++]) {
1569 p_fp_info->hsdsch_entity = ehs;
1573 /* This is the pre-R7 default */
1574 p_fp_info->hsdsch_entity = hs;
1579 /* IUR only uses the above... */
1580 if (strcmp(protocol_name, "fpiur_r5") == 0) {
1581 /* Store info in packet */
1582 p_fp_info->iface_type = IuR_Interface;
1583 p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1587 /* DCH CRC present... */
1588 p_fp_info->dch_crc_present = outhdr_values[i++];
1590 /* ... but don't trust for edch */
1591 if (p_fp_info->channel == CHANNEL_EDCH) {
1592 p_fp_info->dch_crc_present = 2; /* unknown */
1595 /* How many paging indications (if PCH data) */
1596 p_fp_info->paging_indications = outhdr_values[i++];
1598 /* Number of channels (for coordinated channels) */
1599 p_fp_info->num_chans = outhdr_values[i++];
1600 if (p_fp_info->num_chans > MAX_FP_CHANS) {
1601 p_fp_info->num_chans = MAX_FP_CHANS;
1604 /* EDCH-Common is always T2 */
1605 if (p_fp_info->channel == CHANNEL_EDCH_COMMON) {
1606 p_fp_info->edch_type = 1;
1609 if (p_fp_info->channel != CHANNEL_EDCH) {
1610 /* TF size for each channel */
1612 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1613 if (outhdr_values_found > tf_start+chan) {
1614 p_fp_info->chan_tf_size[chan] = outhdr_values[tf_start+chan];
1616 p_fp_info->chan_tf_size[chan] = 0;
1620 /* Number of TBs for each channel */
1621 num_chans_start = tf_start + p_fp_info->num_chans;
1622 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1623 if (outhdr_values_found > num_chans_start+chan) {
1624 p_fp_info->chan_num_tbs[chan] = outhdr_values[num_chans_start+chan];
1626 p_fp_info->chan_num_tbs[chan] = 0;
1634 p_fp_info->no_ddi_entries = outhdr_values[i++];
1637 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1638 if (outhdr_values_found > i) {
1639 p_fp_info->edch_ddi[n] = outhdr_values[i++];
1641 p_fp_info->edch_ddi[n] = 0;
1645 /* Corresponding MAC-d sizes */
1646 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1647 if (outhdr_values_found > i) {
1648 p_fp_info->edch_macd_pdu_size[n] = outhdr_values[i++];
1650 p_fp_info->edch_macd_pdu_size[n] = 0;
1654 if (strcmp(protocol_name, "fp_r8") == 0) {
1655 if (outhdr_values_found > i) {
1656 p_fp_info->edch_type = outhdr_values[i];
1658 p_fp_info->edch_type = 0;
1662 p_fp_info->edch_type = 0;
1666 /* Interface must be IuB */
1667 p_fp_info->iface_type = IuB_Interface;
1669 /* Store info in packet */
1670 p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1674 /* Fill in an RLC packet info struct and attach it to the packet for the RLC
1676 static void attach_rlc_info(packet_info *pinfo, guint32 urnti, guint8 rbid,
1677 gboolean is_sent, guint *outhdr_values,
1678 guint outhdr_values_found)
1680 /* Only need to set info once per session. */
1681 struct fp_info *p_fp_info;
1682 struct rlc_info *p_rlc_info = (struct rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
1684 if (p_rlc_info != NULL) {
1688 /* Check that the number of outhdr values looks correct */
1689 if (outhdr_values_found != 2) {
1693 /* Allocate structs */
1694 p_rlc_info = wmem_new(wmem_file_scope(), struct rlc_info);
1695 p_fp_info = wmem_new(wmem_file_scope(), struct fp_info);
1697 /* Fill in struct fields for first (only) PDU in this frame */
1699 /* Urnti. Just use UEId */
1700 p_rlc_info->urnti[0] = urnti;
1702 /* ciphered (off by default) */
1703 p_rlc_info->ciphered[0] = FALSE;
1705 /* deciphered (off by default) */
1706 p_rlc_info->deciphered[0] = FALSE;
1709 switch (outhdr_values[1]) {
1711 p_rlc_info->mode[0] = RLC_TM;
1714 p_rlc_info->mode[0] = RLC_UM;
1717 p_rlc_info->mode[0] = RLC_AM;
1720 p_rlc_info->mode[0] = RLC_UM;
1721 p_rlc_info->ciphered[0] = TRUE;
1724 p_rlc_info->mode[0] = RLC_AM;
1725 p_rlc_info->ciphered[0] = TRUE;
1731 /* rbid. TODO: does this need conversion? */
1732 p_rlc_info->rbid[0] = rbid;
1735 p_rlc_info->li_size[0] = (enum rlc_li_size)outhdr_values[0];
1737 /* Store info in packet */
1738 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0, p_rlc_info);
1740 /* Also store minimal FP info consulted by RLC dissector
1741 TODO: Don't really know direction, but use S/R flag to make
1742 logs in same context consistent. Will be correct for NodeB logs,
1743 but RLC dissector seems to not use anyway... */
1744 p_fp_info->is_uplink = is_sent;
1745 p_fp_info->cur_tb = 0; /* Always the first/only one */
1746 p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, p_fp_info);
1750 /* Fill in a MAC LTE packet info struct and attach it to the packet for that
1752 static void attach_mac_lte_info(packet_info *pinfo, guint *outhdr_values, guint outhdr_values_found)
1754 struct mac_lte_info *p_mac_lte_info;
1757 /* Only need to set info once per session. */
1758 p_mac_lte_info = get_mac_lte_proto_data(pinfo);
1759 if (p_mac_lte_info != NULL) {
1763 /* Allocate & zero struct */
1764 p_mac_lte_info = wmem_new0(wmem_file_scope(), struct mac_lte_info);
1766 /* Populate the struct from outhdr values */
1767 p_mac_lte_info->crcStatusValid = FALSE; /* not set yet */
1769 p_mac_lte_info->radioType = outhdr_values[i++] + 1;
1770 p_mac_lte_info->rntiType = outhdr_values[i++];
1771 p_mac_lte_info->direction = outhdr_values[i++];
1772 /* Set these extra PHY present flags to FALSE by default */
1773 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1774 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
1777 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
1780 p_mac_lte_info->subframeNumber = outhdr_values[i++];
1781 p_mac_lte_info->isPredefinedData = outhdr_values[i++];
1782 p_mac_lte_info->rnti = outhdr_values[i++];
1783 p_mac_lte_info->ueid = outhdr_values[i++];
1784 p_mac_lte_info->length = outhdr_values[i++];
1785 if (outhdr_values_found > 8) {
1786 p_mac_lte_info->reTxCount = outhdr_values[i++];
1788 if (outhdr_values_found == 10) {
1789 /* CRC only valid for Downlink */
1790 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1791 p_mac_lte_info->crcStatusValid = TRUE;
1792 p_mac_lte_info->crcStatus = (mac_lte_crc_status)outhdr_values[i++];
1799 p_mac_lte_info->dl_retx = dl_retx_unknown;
1801 if (outhdr_values_found > 10) {
1802 /* Extra PHY parameters */
1803 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1804 p_mac_lte_info->detailed_phy_info.dl_info.present = outhdr_values[i++];
1805 p_mac_lte_info->detailed_phy_info.dl_info.dci_format = outhdr_values[i++];
1806 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type = outhdr_values[i++];
1807 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level = outhdr_values[i++];
1808 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index = outhdr_values[i++];
1809 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index = outhdr_values[i++];
1810 if (outhdr_values[i++]) {
1811 p_mac_lte_info->dl_retx = dl_retx_yes;
1814 p_mac_lte_info->dl_retx = dl_retx_no;
1816 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length = outhdr_values[i++];
1817 p_mac_lte_info->crcStatusValid = TRUE;
1818 p_mac_lte_info->crcStatus = (mac_lte_crc_status)outhdr_values[i++];
1819 if (outhdr_values_found > 18) {
1820 p_mac_lte_info->detailed_phy_info.dl_info.harq_id = outhdr_values[i++];
1821 p_mac_lte_info->detailed_phy_info.dl_info.ndi = outhdr_values[i++];
1823 if (outhdr_values_found > 20) {
1824 p_mac_lte_info->detailed_phy_info.dl_info.transport_block = outhdr_values[i++];
1829 p_mac_lte_info->detailed_phy_info.ul_info.present = outhdr_values[i++];
1830 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type = outhdr_values[i++];
1831 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index = outhdr_values[i++];
1832 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length = outhdr_values[i++];
1833 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start = outhdr_values[i++];
1834 /* Skip retx flag */
1837 if (outhdr_values_found == 16) {
1838 p_mac_lte_info->subframeNumberOfGrantPresent = TRUE;
1839 p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];
1841 if (outhdr_values_found > 16) {
1842 p_mac_lte_info->detailed_phy_info.ul_info.harq_id = outhdr_values[i++];
1843 p_mac_lte_info->detailed_phy_info.ul_info.ndi = outhdr_values[i++];
1845 p_mac_lte_info->subframeNumberOfGrantPresent = TRUE;
1846 p_mac_lte_info->subframeNumberOfGrant = outhdr_values[i++];
1851 /* System frame number */
1852 if (i < outhdr_values_found) {
1853 p_mac_lte_info->sysframeNumber = outhdr_values[i++];
1856 if ((p_mac_lte_info->direction == DIRECTION_UPLINK) &&
1857 (i < outhdr_values_found)) {
1859 p_mac_lte_info->isPHICHNACK = outhdr_values[i];
1862 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1863 /* R10 parameter not set yet */
1864 p_mac_lte_info->isExtendedBSRSizes = FALSE;
1867 /* Store info in packet */
1868 set_mac_lte_proto_data(pinfo, p_mac_lte_info);
1872 /* Fill in a RLC LTE packet info struct and attach it to the packet for that
1874 static void attach_rlc_lte_info(packet_info *pinfo, guint *outhdr_values,
1875 guint outhdr_values_found _U_)
1877 struct rlc_lte_info *p_rlc_lte_info;
1880 /* Only need to set info once per session. */
1881 p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
1882 if (p_rlc_lte_info != NULL) {
1886 /* Allocate & zero struct */
1887 p_rlc_lte_info = wmem_new0(wmem_file_scope(), rlc_lte_info);
1889 p_rlc_lte_info->rlcMode = outhdr_values[i++];
1890 p_rlc_lte_info->direction = outhdr_values[i++];
1891 p_rlc_lte_info->priority = outhdr_values[i++];
1892 p_rlc_lte_info->sequenceNumberLength = outhdr_values[i++];
1893 p_rlc_lte_info->channelId = outhdr_values[i++];
1894 p_rlc_lte_info->channelType = outhdr_values[i++];
1895 p_rlc_lte_info->ueid = outhdr_values[i++];
1896 p_rlc_lte_info->pduLength = outhdr_values[i];
1898 /* Store info in packet */
1899 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
1902 /* Fill in a PDCP LTE packet info struct and attach it to the packet for the PDCP LTE
1904 static void attach_pdcp_lte_info(packet_info *pinfo, guint *outhdr_values,
1905 guint outhdr_values_found _U_)
1907 struct pdcp_lte_info *p_pdcp_lte_info;
1910 /* Only need to set info once per session. */
1911 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1912 if (p_pdcp_lte_info != NULL) {
1916 /* Allocate & zero struct */
1917 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1919 p_pdcp_lte_info->no_header_pdu = outhdr_values[i++];
1920 p_pdcp_lte_info->plane = (enum pdcp_plane)outhdr_values[i++];
1921 if (p_pdcp_lte_info->plane != USER_PLANE) {
1922 p_pdcp_lte_info->plane = SIGNALING_PLANE;
1924 p_pdcp_lte_info->seqnum_length = outhdr_values[i++];
1926 p_pdcp_lte_info->rohc.rohc_compression = outhdr_values[i++];
1927 p_pdcp_lte_info->rohc.rohc_ip_version = outhdr_values[i++];
1928 p_pdcp_lte_info->rohc.cid_inclusion_info = outhdr_values[i++];
1929 p_pdcp_lte_info->rohc.large_cid_present = outhdr_values[i++];
1930 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)outhdr_values[i++];
1931 p_pdcp_lte_info->rohc.rnd = outhdr_values[i++];
1932 p_pdcp_lte_info->rohc.udp_checksum_present = outhdr_values[i++];
1933 p_pdcp_lte_info->rohc.profile = outhdr_values[i];
1935 /* Remaining 2 (fixed) fields are ah_length and gre_checksum */
1937 /* Store info in packet */
1938 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1942 /* Attempt to show tty (raw character messages) as text lines. */
1943 static void dissect_tty_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1946 proto_tree *tty_tree;
1950 /* Create tty tree. */
1951 ti = proto_tree_add_item(tree, hf_catapult_dct2000_tty, tvb, offset, -1, ENC_NA);
1952 tty_tree = proto_item_add_subtree(ti, ett_catapult_dct2000_tty);
1954 /* Show the tty lines one at a time. */
1955 while (tvb_offset_exists(tvb, offset)) {
1956 /* Find the end of the line. */
1957 int linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1959 /* Extract & add the string. */
1960 char *string = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, linelen, ENC_ASCII);
1961 if (g_ascii_isprint(string[0])) {
1962 /* If the first byte of the string is printable ASCII treat as string... */
1963 proto_tree_add_string_format(tty_tree, hf_catapult_dct2000_tty_line,
1969 /* Otherwise show as $hex */
1972 int tty_string_length = tvb_reported_length_remaining(tvb, offset);
1973 int hex_string_length = 1+(2*tty_string_length)+1;
1974 hex_string = (char *)wmem_alloc(wmem_packet_scope(), hex_string_length);
1976 idx = g_snprintf(hex_string, hex_string_length, "$");
1978 /* Write hex out to new string */
1979 for (n=0; n < tty_string_length; n++) {
1980 idx += g_snprintf(hex_string+idx, 3, "%02x",
1981 tvb_get_guint8(tvb, offset+n));
1983 string = hex_string;
1987 /* Show first line in info column */
1989 col_append_fstr(pinfo->cinfo, COL_INFO, "tty (%s", string);
1990 proto_item_append_text(ti, " (%s)", string);
1993 /* Move onto next line. */
1994 offset = next_offset;
1997 /* Close off summary of tty message in info column */
1999 col_append_str(pinfo->cinfo, COL_INFO, (lines > 1) ? "...)" : ")");
2004 /* Scan the log comment looking for notable out-of-band MAC events that should
2005 be sent to the MAC dissector */
2006 static void check_for_oob_mac_lte_events(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
2009 guint number_of_ues;
2010 guint ueids[MAX_SRs];
2011 guint rntis[MAX_SRs];
2013 guint rach_attempt_number;
2015 mac_lte_oob_event oob_event;
2016 struct mac_lte_info *p_mac_lte_info;
2019 /* Look for strings matching expected formats */
2020 if (sscanf(string, ">> RACH Preamble Request[UE = %u] [RAPID = %u] [Attempt = %u]",
2021 &ueids[0], &rapid, &rach_attempt_number) == 3) {
2022 oob_event = ltemac_send_preamble;
2025 if (sscanf(string, ">> Schedule Requests (%u) [UE=%u][RNTI=%u]",
2026 &number_of_ues, &ueids[0], &rntis[0]) == 3) {
2027 const char *current_position;
2029 /* Newer, multi-UE format */
2030 oob_event = ltemac_send_sr;
2032 /* Parse other ueid/rnti pairs */
2033 number_of_ues = MIN(number_of_ues, MAX_SRs);
2034 if (number_of_ues > 1) {
2035 current_position = string;
2037 for (n=1; n < number_of_ues; n++) {
2039 /* Find the start of the next entry */
2040 current_position = strstr(current_position, "] ");
2041 if (current_position != NULL) {
2042 current_position += 2;
2045 /* This is an error - shouldn't happen */
2049 /* Read this entry */
2050 if (sscanf(current_position, "[UE=%u][RNTI=%u]", &ueids[n], &rntis[n]) != 2) {
2051 /* Assuming that if we can't read this one there is no point trying others */
2059 /* Support both old and new formats of SR failure */
2060 if ((sscanf(string, ">> INFO (inst %u) MAC: [UE = %u] SR failed (CRNTI=%u)",
2061 &temp, &ueids[0], &rntis[0]) == 3) ||
2062 (sscanf(string, ">> INFO MAC: SR failed for UE %u (CRNTI=%u",
2063 &ueids[0], &rntis[0]) == 2))
2065 oob_event = ltemac_sr_failure;
2068 /* No events found */
2072 /* We have an event */
2073 /* Only need to set info once per session. */
2074 p_mac_lte_info = get_mac_lte_proto_data(pinfo);
2075 if (p_mac_lte_info == NULL) {
2077 /* Allocate & zero struct */
2078 p_mac_lte_info = wmem_new0(wmem_file_scope(), mac_lte_info);
2080 /* This indicates to MAC dissector that it has an oob event */
2081 p_mac_lte_info->length = 0;
2083 switch (oob_event) {
2084 case ltemac_send_preamble:
2085 p_mac_lte_info->ueid = ueids[0];
2086 p_mac_lte_info->rapid = rapid;
2087 p_mac_lte_info->rach_attempt_number = rach_attempt_number;
2088 p_mac_lte_info->direction = DIRECTION_UPLINK;
2090 case ltemac_send_sr:
2091 for (n=0; n < number_of_ues; n++) {
2092 p_mac_lte_info->oob_ueid[n] = ueids[n];
2093 p_mac_lte_info->oob_rnti[n] = rntis[n];
2095 p_mac_lte_info->number_of_srs = number_of_ues;
2096 p_mac_lte_info->direction = DIRECTION_UPLINK;
2098 case ltemac_sr_failure:
2099 p_mac_lte_info->rnti = rntis[0];
2100 p_mac_lte_info->ueid = ueids[0];
2101 p_mac_lte_info->direction = DIRECTION_DOWNLINK;
2105 p_mac_lte_info->radioType = FDD_RADIO; /* TODO: will be the same as rest of log... */
2106 p_mac_lte_info->oob_event = oob_event;
2108 /* Store info in packet */
2109 set_mac_lte_proto_data(pinfo, p_mac_lte_info);
2112 /* Call MAC dissector */
2113 call_dissector_only(mac_lte_handle, tvb, pinfo, tree, NULL);
2117 /*****************************************/
2118 /* Main dissection function. */
2119 /*****************************************/
2121 dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2123 proto_tree *dct2000_tree = NULL;
2124 proto_item *ti = NULL;
2126 gint context_length;
2127 const char *context_name;
2129 gint protocol_length;
2130 gint timestamp_length;
2131 const char *timestamp_string;
2132 gint variant_length;
2133 const char *variant_string;
2136 const char *outhdr_string;
2140 dissector_handle_t protocol_handle = 0;
2141 dissector_handle_t heur_protocol_handle = 0;
2142 void *protocol_data = 0;
2143 int sub_dissector_result = 0;
2144 const char *protocol_name;
2145 gboolean is_comment, is_sprint = FALSE;
2146 guint outhdr_values[MAX_OUTHDR_VALUES];
2147 guint outhdr_values_found;
2150 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCT2000");
2153 col_clear(pinfo->cinfo, COL_INFO);
2155 /* Create root (protocol) tree. */
2157 ti = proto_tree_add_item(tree, proto_catapult_dct2000, tvb, offset, -1, ENC_NA);
2158 dct2000_tree = proto_item_add_subtree(ti, ett_catapult_dct2000);
2161 /*********************************************************************/
2162 /* Note that these are the fields of the stub header as written out */
2163 /* by the wiretap module */
2166 context_name = tvb_get_const_stringz(tvb, offset, &context_length);
2168 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_context, tvb,
2169 offset, context_length, ENC_ASCII|ENC_NA);
2171 offset += context_length;
2173 /* Context port number */
2174 port_number = tvb_get_guint8(tvb, offset);
2176 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_port_number, tvb,
2177 offset, 1, ENC_BIG_ENDIAN);
2181 /* Timestamp in file */
2182 timestamp_string = tvb_get_const_stringz(tvb, offset, ×tamp_length);
2184 /* TODO: this is *very* slow, but float version adds trailing digits when
2185 displayed as a custom column... */
2186 proto_tree_add_double(dct2000_tree, hf_catapult_dct2000_timestamp, tvb,
2187 offset, timestamp_length,
2188 g_ascii_strtod(timestamp_string, NULL));
2190 offset += timestamp_length;
2193 /* DCT2000 protocol name */
2194 protocol_name = tvb_get_const_stringz(tvb, offset, &protocol_length);
2196 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_protocol, tvb,
2197 offset, protocol_length, ENC_ASCII|ENC_NA);
2199 is_comment = (strcmp(protocol_name, "comment") == 0);
2201 is_sprint = (strcmp(protocol_name, "sprint") == 0);
2203 offset += protocol_length;
2206 /* Protocol Variant */
2207 variant_string = tvb_get_const_stringz(tvb, offset, &variant_length);
2208 if (!is_comment && !is_sprint) {
2209 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_variant, tvb,
2210 offset, variant_length, ENC_ASCII|ENC_NA);
2212 offset += variant_length;
2214 /* Outhdr (shown as string) */
2215 outhdr_string = tvb_get_const_stringz(tvb, offset, &outhdr_length);
2216 if (!is_comment && !is_sprint && (outhdr_length > 1)) {
2217 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_outhdr, tvb,
2218 offset, outhdr_length, ENC_ASCII|ENC_NA);
2220 offset += outhdr_length;
2224 direction = tvb_get_guint8(tvb, offset);
2226 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
2227 offset, 1, ENC_BIG_ENDIAN);
2231 /* Read frame encapsulation set by wiretap */
2232 if (!is_comment && !is_sprint) {
2233 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_encap, tvb, offset, 1, ENC_BIG_ENDIAN);
2235 encap = tvb_get_guint8(tvb, offset);
2238 /* Add useful details to protocol tree label */
2239 proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s (v=%s)",
2243 (direction == 0) ? 'S' : 'R',
2248 memset(outhdr_values, 0, sizeof outhdr_values);
2249 outhdr_values_found = 0;
2251 /* FP protocols need info from outhdr attached */
2252 if ((strcmp(protocol_name, "fp") == 0) ||
2253 (strncmp(protocol_name, "fp_r", 4) == 0) ||
2254 (strcmp(protocol_name, "fpiur_r5") == 0)) {
2256 outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2258 if (ws_strtou32(variant_string, NULL, &variant))
2259 attach_fp_info(pinfo, direction, protocol_name, variant,
2260 outhdr_values, outhdr_values_found);
2262 expert_add_info(pinfo, ti, &ei_catapult_dct2000_string_invalid);
2265 /* RLC protocols need info from outhdr attached */
2266 else if ((strcmp(protocol_name, "rlc") == 0) ||
2267 (strcmp(protocol_name, "rlc_r4") == 0) ||
2268 (strcmp(protocol_name, "rlc_r5") == 0) ||
2269 (strcmp(protocol_name, "rlc_r6") == 0) ||
2270 (strcmp(protocol_name, "rlc_r7") == 0) ||
2271 (strcmp(protocol_name, "rlc_r8") == 0) ||
2272 (strcmp(protocol_name, "rlc_r9") == 0)) {
2274 outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2276 /* Can't attach info yet. Need combination of outheader values
2277 and fields parsed from primitive header... */
2280 /* LTE MAC needs info attached */
2281 else if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2282 (strcmp(protocol_name, "mac_r9_lte") == 0) ||
2283 (strcmp(protocol_name, "mac_r10_lte") == 0)) {
2284 outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2286 attach_mac_lte_info(pinfo, outhdr_values, outhdr_values_found);
2289 /* LTE RLC needs info attached */
2290 else if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2291 (strcmp(protocol_name, "rlc_r9_lte") == 0) ||
2292 (strcmp(protocol_name, "rlc_r10_lte") == 0)) {
2293 outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2295 attach_rlc_lte_info(pinfo, outhdr_values, outhdr_values_found);
2298 /* LTE PDCP needs info attached */
2299 else if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2300 (strcmp(protocol_name, "pdcp_r9_lte") == 0) ||
2301 (strcmp(protocol_name, "pdcp_r10_lte") == 0)) {
2302 outhdr_values_found = parse_outhdr_string(outhdr_string, outhdr_length,
2304 attach_pdcp_lte_info(pinfo, outhdr_values, outhdr_values_found);
2308 else if ((strcmp(protocol_name, "nas_rrc_r8_lte") == 0) ||
2309 (strcmp(protocol_name, "nas_rrc_r9_lte") == 0) ||
2310 (strcmp(protocol_name, "nas_rrc_r10_lte") == 0)) {
2311 gboolean nas_body_found = TRUE;
2312 guint8 opcode = tvb_get_guint8(tvb, offset);
2313 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_opcode,
2314 tvb, offset++, 1, ENC_BIG_ENDIAN);
2316 offset++; /* Skip overall length */
2319 case LTE_NAS_RRC_DATA_IND:
2320 case LTE_NAS_RRC_DATA_REQ:
2323 offset += 2; /* 2 wasted bytes of UEId*/
2324 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2325 tvb, offset, 2, ENC_BIG_ENDIAN);
2328 case LTE_NAS_RRC_ESTABLISH_REQ:
2331 offset += 2; /* 2 wasted bytes of UEId*/
2332 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2333 tvb, offset, 2, ENC_BIG_ENDIAN);
2336 /* Establish cause. TODO: value_string */
2337 offset += 2; /* tag + length */
2338 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_establish_cause,
2339 tvb, offset++, 1, ENC_BIG_ENDIAN);
2341 /* Priority. TODO: Vals are low | high */
2342 offset += 2; /* tag + length */
2343 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_priority,
2344 tvb, offset++, 1, ENC_BIG_ENDIAN);
2346 case LTE_NAS_RRC_RELEASE_IND:
2349 offset += 2; /* 2 wasted bytes of UEId*/
2350 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
2351 tvb, offset, 2, ENC_BIG_ENDIAN);
2354 /* Release cause. TODO: value_string */
2355 offset += 2; /* tag + length */
2356 proto_tree_add_item(tree, hf_catapult_dct2000_lte_nas_rrc_release_cause,
2357 tvb, offset++, 1, ENC_BIG_ENDIAN);
2361 nas_body_found = FALSE;
2365 /* Look up dissector if if looks right */
2366 if (nas_body_found) {
2367 offset += 2; /* L3 tag + len */
2368 protocol_handle = find_dissector("nas-eps");
2372 /* Note that the first item of pinfo->pseudo_header->dct2000 will contain
2373 the pseudo-header needed (in some cases) by the Wireshark dissector that
2374 this packet data will be handed off to. */
2377 /***********************************************************************/
2378 /* Now hand off to the dissector of intended packet encapsulation type */
2380 /* Get protocol handle, and set p2p_dir where necessary.
2381 (packet-frame.c won't copy it from pseudo-header because it doesn't
2382 know about Catapult DCT2000 encap type...)
2385 case WTAP_ENCAP_RAW_IP:
2386 protocol_handle = find_dissector("ip");
2388 /* TODO: this doesn't work yet.
2389 pseudo_header isn't copied from wtap to pinfo... */
2390 if ((pinfo->pseudo_header != NULL) &&
2391 (pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid != 0)) {
2395 /* Add PDCP thread info as generated fields */
2396 ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_ueid, tvb, 0, 0,
2397 pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.ueid);
2398 PROTO_ITEM_SET_GENERATED(ti);
2399 ti = proto_tree_add_uint(dct2000_tree, hf_catapult_dct2000_lte_drbid, tvb, 0, 0,
2400 pinfo->pseudo_header->dct2000.inner_pseudo_header.pdcp.drbid);
2401 PROTO_ITEM_SET_GENERATED(ti);
2405 case WTAP_ENCAP_ETHERNET:
2406 protocol_handle = find_dissector("eth_withoutfcs");
2408 case WTAP_ENCAP_ISDN:
2409 protocol_handle = find_dissector("lapd");
2410 pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton;
2412 case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
2413 protocol_handle = find_dissector("atm_untruncated");
2414 protocol_data = &pinfo->pseudo_header->dct2000.inner_pseudo_header.atm;
2416 case WTAP_ENCAP_PPP:
2417 protocol_handle = find_dissector("ppp_hdlc");
2418 pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent;
2420 case DCT2000_ENCAP_SSCOP:
2421 protocol_handle = find_dissector("sscop");
2423 case WTAP_ENCAP_FRELAY:
2424 protocol_handle = find_dissector("fr");
2426 case DCT2000_ENCAP_MTP2:
2427 protocol_handle = find_dissector("mtp2");
2429 case DCT2000_ENCAP_NBAP:
2430 protocol_handle = find_dissector("nbap");
2433 case DCT2000_ENCAP_UNHANDLED:
2434 /**********************************************************/
2435 /* The wiretap module wasn't able to set an encapsulation */
2436 /* type, but it may still be possible to dissect the data */
2437 /* if we know about the protocol or if we can recognise */
2438 /* and parse or skip a primitive header */
2439 /**********************************************************/
2441 /* Show context.port in src or dest column as appropriate */
2442 if (direction == 0) {
2443 col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
2449 if (direction == 1) {
2450 col_add_fstr(pinfo->cinfo, COL_DEF_DST,
2457 /**************************************************************************/
2458 /* These protocols have no encapsulation type, just look them up directly */
2460 if ((strcmp(protocol_name, "rlc") == 0) ||
2461 (strcmp(protocol_name, "rlc_r4") == 0) ||
2462 (strcmp(protocol_name, "rlc_r5") == 0) ||
2463 (strcmp(protocol_name, "rlc_r6") == 0) ||
2464 (strcmp(protocol_name, "rlc_r7") == 0) ||
2465 (strcmp(protocol_name, "rlc_r8") == 0) ||
2466 (strcmp(protocol_name, "rlc_r9") == 0)) {
2468 dissect_rlc_umts(tvb, offset, pinfo, tree, direction,
2469 outhdr_values, outhdr_values_found);
2470 return tvb_captured_length(tvb);
2474 if ((strcmp(protocol_name, "mac_r8_lte") == 0) ||
2475 (strcmp(protocol_name, "mac_r9_lte") == 0) ||
2476 (strcmp(protocol_name, "mac_r10_lte") == 0)) {
2477 protocol_handle = mac_lte_handle;
2481 if ((strcmp(protocol_name, "rlc_r8_lte") == 0) ||
2482 (strcmp(protocol_name, "rlc_r9_lte") == 0) ||
2483 (strcmp(protocol_name, "rlc_r10_lte") == 0)) {
2484 protocol_handle = rlc_lte_handle;
2488 if ((strcmp(protocol_name, "pdcp_r8_lte") == 0) ||
2489 (strcmp(protocol_name, "pdcp_r9_lte") == 0) ||
2490 (strcmp(protocol_name, "pdcp_r10_lte") == 0)) {
2491 /* Dissect proprietary header, then pass remainder to PDCP */
2492 dissect_pdcp_lte(tvb, offset, pinfo, tree);
2493 return tvb_captured_length(tvb);
2497 /* Work with generic XML protocol. */
2499 if (strcmp(protocol_name, "xml") == 0) {
2500 protocol_handle = find_dissector("xml");
2504 /* Attempt to show tty messages as raw text */
2506 if (strcmp(protocol_name, "tty") == 0) {
2507 dissect_tty_lines(tvb, pinfo, dct2000_tree, offset);
2508 return tvb_captured_length(tvb);
2512 if (strcmp(protocol_name, "sipprim") == 0) {
2513 protocol_handle = find_dissector("sipprim");
2517 if (strcmp(protocol_name, "comment") == 0) {
2518 /* Extract & add the string. */
2519 proto_item *string_ti;
2520 const guint8 *string;
2522 /* Show comment string */
2523 string_ti = proto_tree_add_item_ret_string(dct2000_tree, hf_catapult_dct2000_comment, tvb,
2524 offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA, wmem_packet_scope(), &string);
2525 col_append_str(pinfo->cinfo, COL_INFO, string);
2527 if (catapult_dct2000_dissect_mac_lte_oob_messages) {
2528 /* Look into string for out-of-band MAC events, such as SRReq, SRInd */
2529 check_for_oob_mac_lte_events(pinfo, tvb, tree, string);
2532 /* Look for and flag generic error messages */
2533 if (strncmp(string, ">> ERR", 6) == 0) {
2534 proto_item *error_ti = proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_error_comment, tvb,
2535 offset, -1, ENC_NA);
2536 PROTO_ITEM_SET_GENERATED(error_ti);
2537 expert_add_info_format(pinfo, string_ti, &ei_catapult_dct2000_error_comment_expert,
2541 return tvb_captured_length(tvb);
2545 if (strcmp(protocol_name, "sprint") == 0) {
2546 /* Extract & add the string. */
2547 const guint8 *string;
2549 /* Show sprint string */
2550 proto_tree_add_item_ret_string(dct2000_tree, hf_catapult_dct2000_sprint, tvb,
2551 offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA, wmem_packet_scope(), &string);
2552 col_append_str(pinfo->cinfo, COL_INFO, string);
2554 return tvb_captured_length(tvb);
2559 if (catapult_dct2000_dissect_lte_rrc &&
2560 ((strcmp(protocol_name, "rrc_r8_lte") == 0) ||
2561 (strcmp(protocol_name, "rrcpdcpprim_r8_lte") == 0) ||
2562 (strcmp(protocol_name, "rrc_r9_lte") == 0) ||
2563 (strcmp(protocol_name, "rrcpdcpprim_r9_lte") == 0) ||
2564 (strcmp(protocol_name, "rrc_r10_lte") == 0))) {
2566 /* Dissect proprietary header, then pass remainder
2567 to RRC (depending upon direction and channel type) */
2568 dissect_rrc_lte(tvb, offset, pinfo, tree);
2569 return tvb_captured_length(tvb);
2573 if ((strcmp(protocol_name, "ccpri_r8_lte") == 0) ||
2574 (strcmp(protocol_name, "ccpri_r9_lte") == 0)) {
2576 /* Dissect proprietary header, then pass remainder to lapb */
2577 dissect_ccpri_lte(tvb, offset, pinfo, tree);
2578 return tvb_captured_length(tvb);
2581 /* Many DCT2000 protocols have at least one IPPrim variant. If the
2582 protocol name can be matched to a dissector, try to find the
2583 UDP/TCP data inside and dissect it.
2586 if (!protocol_handle && catapult_dct2000_try_ipprim_heuristic) {
2587 guint32 source_addr_offset = 0, dest_addr_offset = 0;
2588 guint8 source_addr_length = 0, dest_addr_length = 0;
2589 guint32 source_port_offset = 0, dest_port_offset = 0;
2590 port_type type_of_port = PT_NONE;
2591 guint16 conn_id_offset = 0;
2592 int offset_before_ipprim_header = offset;
2594 /* Will give up if couldn't match protocol anyway... */
2595 heur_protocol_handle = look_for_dissector(protocol_name);
2596 if ((heur_protocol_handle != 0) &&
2597 find_ipprim_data_offset(tvb, &offset, direction,
2598 &source_addr_offset, &source_addr_length,
2599 &dest_addr_offset, &dest_addr_length,
2600 &source_port_offset, &dest_port_offset,
2604 proto_tree *ipprim_tree;
2605 proto_item *ipprim_ti;
2606 struct e_in6_addr sourcev6, destv6;
2608 /* Fetch IPv6 addresses */
2609 if (source_addr_length != 4) {
2610 tvb_get_ipv6(tvb, source_addr_offset, &sourcev6);
2612 if (dest_addr_length != 4) {
2613 tvb_get_ipv6(tvb, dest_addr_offset, &destv6);
2617 /* Will use this dissector then. */
2618 protocol_handle = heur_protocol_handle;
2620 /* Add address parameters to tree */
2621 /* Unfortunately can't automatically create a conversation filter for this...
2622 I *could* create a fake IP header from these details, but then it would be tricky
2623 to get the FP dissector called as it has no well-known ports or heuristics... */
2624 ipprim_ti = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_ipprim_addresses,
2625 tvb, offset_before_ipprim_header, 0,
2626 "", "IPPrim transport (%s): %s:%u -> %s:%u",
2627 (type_of_port == PT_UDP) ? "UDP" : "TCP",
2628 (source_addr_offset) ?
2629 ((source_addr_length == 4) ?
2630 get_hostname(tvb_get_ipv4(tvb, source_addr_offset)) :
2631 get_hostname6(&sourcev6)
2634 (source_port_offset) ?
2635 tvb_get_ntohs(tvb, source_port_offset) :
2637 (dest_addr_offset) ?
2638 ((source_addr_length == 4) ?
2639 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
2640 get_hostname6(&destv6)
2643 (dest_port_offset) ?
2644 tvb_get_ntohs(tvb, dest_port_offset) :
2646 if ((type_of_port == PT_TCP) && (conn_id_offset != 0)) {
2647 proto_item_append_text(ipprim_ti, " (conn_id=%u)", tvb_get_ntohs(tvb, conn_id_offset));
2650 /* Add these IPPRIM fields inside an IPPRIM subtree */
2651 ipprim_tree = proto_item_add_subtree(ipprim_ti, ett_catapult_dct2000_ipprim);
2653 /* Try to add right stuff to pinfo so conversation stuff works... */
2654 pinfo->ptype = type_of_port;
2656 /* Add addresses & ports into ipprim tree.
2657 Also set address info in pinfo for conversations... */
2658 if (source_addr_offset != 0) {
2659 proto_item *addr_ti;
2661 set_address_tvb(&pinfo->net_src,
2662 (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2663 source_addr_length, tvb, source_addr_offset);
2664 copy_address_shallow(&pinfo->src, &pinfo->net_src);
2666 proto_tree_add_item(ipprim_tree,
2667 (source_addr_length == 4) ?
2668 hf_catapult_dct2000_ipprim_src_addr_v4 :
2669 hf_catapult_dct2000_ipprim_src_addr_v6,
2670 tvb, source_addr_offset, source_addr_length,
2673 /* Add hidden item for "side-less" addr */
2674 addr_ti = proto_tree_add_item(ipprim_tree,
2675 (source_addr_length == 4) ?
2676 hf_catapult_dct2000_ipprim_addr_v4 :
2677 hf_catapult_dct2000_ipprim_addr_v6,
2678 tvb, source_addr_offset, source_addr_length,
2680 PROTO_ITEM_SET_HIDDEN(addr_ti);
2682 if (source_port_offset != 0) {
2683 proto_item *port_ti;
2685 pinfo->srcport = tvb_get_ntohs(tvb, source_port_offset);
2687 proto_tree_add_item(ipprim_tree,
2688 (type_of_port == PT_UDP) ?
2689 hf_catapult_dct2000_ipprim_udp_src_port :
2690 hf_catapult_dct2000_ipprim_tcp_src_port,
2691 tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
2692 port_ti = proto_tree_add_item(ipprim_tree,
2693 (type_of_port == PT_UDP) ?
2694 hf_catapult_dct2000_ipprim_udp_port :
2695 hf_catapult_dct2000_ipprim_tcp_port,
2696 tvb, source_port_offset, 2, ENC_BIG_ENDIAN);
2697 PROTO_ITEM_SET_HIDDEN(port_ti);
2699 if (dest_addr_offset != 0) {
2700 proto_item *addr_ti;
2702 set_address_tvb(&pinfo->net_dst,
2703 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2704 dest_addr_length, tvb, dest_addr_offset);
2705 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
2706 proto_tree_add_item(ipprim_tree,
2707 (dest_addr_length == 4) ?
2708 hf_catapult_dct2000_ipprim_dst_addr_v4 :
2709 hf_catapult_dct2000_ipprim_dst_addr_v6,
2710 tvb, dest_addr_offset, dest_addr_length,
2713 /* Add hidden item for "side-less" addr */
2714 addr_ti = proto_tree_add_item(ipprim_tree,
2715 (dest_addr_length == 4) ?
2716 hf_catapult_dct2000_ipprim_addr_v4 :
2717 hf_catapult_dct2000_ipprim_addr_v6,
2718 tvb, dest_addr_offset, dest_addr_length,
2720 PROTO_ITEM_SET_HIDDEN(addr_ti);
2722 if (dest_port_offset != 0) {
2723 proto_item *port_ti;
2725 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
2727 proto_tree_add_item(ipprim_tree,
2728 (type_of_port == PT_UDP) ?
2729 hf_catapult_dct2000_ipprim_udp_dst_port :
2730 hf_catapult_dct2000_ipprim_tcp_dst_port,
2731 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2732 port_ti = proto_tree_add_item(ipprim_tree,
2733 (type_of_port == PT_UDP) ?
2734 hf_catapult_dct2000_ipprim_udp_port :
2735 hf_catapult_dct2000_ipprim_tcp_port,
2736 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2737 PROTO_ITEM_SET_HIDDEN(port_ti);
2739 if (conn_id_offset != 0) {
2740 proto_tree_add_item(ipprim_tree,
2741 hf_catapult_dct2000_ipprim_conn_id,
2742 tvb, conn_id_offset, 2, ENC_BIG_ENDIAN);
2746 /* Set source and dest columns now (will be overwriiten if
2747 src and dst IP addresses set) */
2748 if (source_addr_offset) {
2749 col_append_fstr(pinfo->cinfo, COL_DEF_SRC,
2751 get_hostname(tvb_get_ipv4(tvb, source_addr_offset)),
2752 tvb_get_ntohs(tvb, source_port_offset));
2754 if (dest_addr_offset) {
2755 col_append_fstr(pinfo->cinfo, COL_DEF_DST,
2757 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)),
2758 tvb_get_ntohs(tvb, dest_port_offset));
2761 /* Set length for IPPrim tree */
2762 proto_item_set_len(ipprim_tree, offset - offset_before_ipprim_header);
2767 /* Try SCTP Prim heuristic if configured to */
2768 if (!protocol_handle && catapult_dct2000_try_sctpprim_heuristic) {
2769 guint32 dest_addr_offset = 0;
2770 guint16 dest_addr_length = 0;
2771 guint32 dest_port_offset = 0;
2772 int offset_before_sctpprim_header = offset;
2774 heur_protocol_handle = look_for_dissector(protocol_name);
2775 if ((heur_protocol_handle != 0) &&
2776 (find_sctpprim_variant1_data_offset(tvb, &offset,
2779 &dest_port_offset) ||
2780 find_sctpprim_variant3_data_offset(tvb, &offset,
2783 &dest_port_offset))) {
2785 proto_tree *sctpprim_tree;
2786 proto_item *ti_local;
2788 /* Will use this dissector then. */
2789 protocol_handle = heur_protocol_handle;
2791 ti_local = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_sctpprim_addresses,
2792 tvb, offset_before_sctpprim_header, 0,
2793 "", "SCTPPrim transport: -> %s:%u",
2794 (dest_addr_offset) ?
2795 ((dest_addr_length == 4) ?
2796 get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
2800 (dest_port_offset) ?
2801 tvb_get_ntohs(tvb, dest_port_offset) :
2804 /* Add these SCTPPRIM fields inside an SCTPPRIM subtree */
2805 sctpprim_tree = proto_item_add_subtree(ti_local, ett_catapult_dct2000_sctpprim);
2807 /* Destination address */
2808 if (dest_addr_offset != 0) {
2809 proto_item *addr_ti;
2811 set_address_tvb(&pinfo->net_dst,
2812 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2813 dest_addr_length, tvb, dest_addr_offset);
2814 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
2815 proto_tree_add_item(sctpprim_tree,
2816 (dest_addr_length == 4) ?
2817 hf_catapult_dct2000_sctpprim_dst_addr_v4 :
2818 hf_catapult_dct2000_sctpprim_dst_addr_v6,
2819 tvb, dest_addr_offset, dest_addr_length,
2822 /* Add hidden item for "side-less" addr */
2823 addr_ti = proto_tree_add_item(sctpprim_tree,
2824 (dest_addr_length == 4) ?
2825 hf_catapult_dct2000_sctpprim_addr_v4 :
2826 hf_catapult_dct2000_sctpprim_addr_v6,
2827 tvb, dest_addr_offset, dest_addr_length,
2829 PROTO_ITEM_SET_HIDDEN(addr_ti);
2832 if (dest_port_offset != 0) {
2833 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
2835 proto_tree_add_item(sctpprim_tree,
2836 hf_catapult_dct2000_sctpprim_dst_port,
2837 tvb, dest_port_offset, 2, ENC_BIG_ENDIAN);
2840 /* Set length for SCTPPrim tree */
2841 proto_item_set_len(sctpprim_tree, offset - offset_before_sctpprim_header);
2845 /* Last chance: is there a (private) registered protocol of the form
2846 "dct2000.protocol" ? */
2847 if (protocol_handle == 0) {
2848 /* TODO: only look inside preference? */
2849 char dotted_protocol_name[64+128];
2850 g_snprintf(dotted_protocol_name, 64+128, "dct2000.%s", protocol_name);
2851 protocol_handle = find_dissector(dotted_protocol_name);
2857 /* !! If get here, there is a mismatch between
2858 this dissector and the wiretap module catapult_dct2000.c !!
2860 DISSECTOR_ASSERT_NOT_REACHED();
2864 /* Set selection length of dct2000 tree */
2865 proto_item_set_len(dct2000_tree, offset);
2867 /* Try appropriate dissector, if one has been selected */
2868 if (protocol_handle != 0) {
2869 /* Dissect the remainder of the frame using chosen protocol handle */
2870 next_tvb = tvb_new_subset_remaining(tvb, offset);
2871 sub_dissector_result = call_dissector_only(protocol_handle, next_tvb, pinfo, tree, protocol_data);
2875 if (protocol_handle == 0 || sub_dissector_result == 0) {
2876 /* Could get here because:
2877 - encap is DCT2000_ENCAP_UNHANDLED and we still didn't handle it, OR
2878 - desired protocol is unavailable (probably disabled), OR
2879 - protocol rejected our data
2880 Show remaining bytes as unparsed data */
2881 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_unparsed_data,
2882 tvb, offset, -1, ENC_NA);
2884 col_add_fstr(pinfo->cinfo, COL_INFO,
2885 "Not dissected (context=%s.%u t=%s %c prot=%s (v=%s))",
2889 (direction == 0) ? 'S' : 'R',
2894 /* Show number of dissected bytes */
2896 proto_item *ti_local = proto_tree_add_uint(dct2000_tree,
2897 hf_catapult_dct2000_dissected_length,
2898 tvb, 0, 0, tvb_reported_length(tvb)-offset);
2899 PROTO_ITEM_SET_GENERATED(ti_local);
2903 return tvb_captured_length(tvb);
2908 /******************************************************************************/
2909 /* Associate this protocol with the Catapult DCT2000 file encapsulation type. */
2910 /******************************************************************************/
2911 void proto_reg_handoff_catapult_dct2000(void)
2913 dissector_add_uint("wtap_encap", WTAP_ENCAP_CATAPULT_DCT2000, catapult_dct2000_handle);
2915 mac_lte_handle = find_dissector("mac-lte");
2916 rlc_lte_handle = find_dissector("rlc-lte");
2917 pdcp_lte_handle = find_dissector("pdcp-lte");
2920 /****************************************/
2921 /* Register the protocol */
2922 /****************************************/
2923 void proto_register_catapult_dct2000(void)
2925 static hf_register_info hf[] =
2927 { &hf_catapult_dct2000_context,
2929 "dct2000.context", FT_STRING, BASE_NONE, NULL, 0x0,
2930 "Context name", HFILL
2933 { &hf_catapult_dct2000_port_number,
2934 { "Context Port number",
2935 "dct2000.context_port", FT_UINT8, BASE_DEC, NULL, 0x0,
2939 { &hf_catapult_dct2000_timestamp,
2941 "dct2000.timestamp", FT_DOUBLE, BASE_NONE, NULL, 0x0,
2942 "File timestamp", HFILL
2945 { &hf_catapult_dct2000_protocol,
2946 { "DCT2000 protocol",
2947 "dct2000.protocol", FT_STRING, BASE_NONE, NULL, 0x0,
2948 "Original (DCT2000) protocol name", HFILL
2951 { &hf_catapult_dct2000_variant,
2952 { "Protocol variant",
2953 "dct2000.variant", FT_STRING, BASE_NONE, NULL, 0x0,
2954 "DCT2000 protocol variant", HFILL
2957 { &hf_catapult_dct2000_outhdr,
2959 "dct2000.outhdr", FT_STRING, BASE_NONE, NULL, 0x0,
2960 "DCT2000 protocol outhdr", HFILL
2963 { &hf_catapult_dct2000_direction,
2965 "dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2966 "Frame direction (Sent or Received)", HFILL
2969 { &hf_catapult_dct2000_encap,
2970 { "Wireshark encapsulation",
2971 "dct2000.encapsulation", FT_UINT8, BASE_DEC, VALS(encap_vals), 0x0,
2972 "Wireshark frame encapsulation used", HFILL
2975 { &hf_catapult_dct2000_unparsed_data,
2976 { "Unparsed protocol data",
2977 "dct2000.unparsed_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2978 "Unparsed DCT2000 protocol data", HFILL
2981 { &hf_catapult_dct2000_comment,
2983 "dct2000.comment", FT_STRING, BASE_NONE, NULL, 0x0,
2987 { &hf_catapult_dct2000_sprint,
2989 "dct2000.sprint", FT_STRING, BASE_NONE, NULL, 0x0,
2993 { &hf_catapult_dct2000_error_comment,
2995 "dct2000.error-comment", FT_NONE, BASE_NONE, NULL, 0x0,
2999 { &hf_catapult_dct2000_dissected_length,
3000 { "Dissected length",
3001 "dct2000.dissected-length", FT_UINT16, BASE_DEC, NULL, 0x0,
3002 "Number of bytes dissected by subdissector(s)", HFILL
3006 { &hf_catapult_dct2000_ipprim_addresses,
3007 { "IPPrim Addresses",
3008 "dct2000.ipprim", FT_STRING, BASE_NONE, NULL, 0x0,
3012 { &hf_catapult_dct2000_ipprim_src_addr_v4,
3014 "dct2000.ipprim.src", FT_IPv4, BASE_NONE, NULL, 0x0,
3015 "IPPrim IPv4 Source Address", HFILL
3018 { &hf_catapult_dct2000_ipprim_src_addr_v6,
3020 "dct2000.ipprim.srcv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3021 "IPPrim IPv6 Source Address", HFILL
3024 { &hf_catapult_dct2000_ipprim_dst_addr_v4,
3025 { "Destination Address",
3026 "dct2000.ipprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3027 "IPPrim IPv4 Destination Address", HFILL
3030 { &hf_catapult_dct2000_ipprim_dst_addr_v6,
3031 { "Destination Address",
3032 "dct2000.ipprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3033 "IPPrim IPv6 Destination Address", HFILL
3036 { &hf_catapult_dct2000_ipprim_addr_v4,
3038 "dct2000.ipprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3039 "IPPrim IPv4 Address", HFILL
3042 { &hf_catapult_dct2000_ipprim_addr_v6,
3044 "dct2000.ipprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3045 "IPPrim IPv6 Address", HFILL
3048 { &hf_catapult_dct2000_ipprim_udp_src_port,
3049 { "UDP Source Port",
3050 "dct2000.ipprim.udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3051 "IPPrim UDP Source Port", HFILL
3054 { &hf_catapult_dct2000_ipprim_udp_dst_port,
3055 { "UDP Destination Port",
3056 "dct2000.ipprim.udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3057 "IPPrim UDP Destination Port", HFILL
3060 { &hf_catapult_dct2000_ipprim_udp_port,
3062 "dct2000.ipprim.udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3063 "IPPrim UDP Port", HFILL
3066 { &hf_catapult_dct2000_ipprim_tcp_src_port,
3067 { "TCP Source Port",
3068 "dct2000.ipprim.tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3069 "IPPrim TCP Source Port", HFILL
3072 { &hf_catapult_dct2000_ipprim_tcp_dst_port,
3073 { "TCP Destination Port",
3074 "dct2000.ipprim.tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3075 "IPPrim TCP Destination Port", HFILL
3078 { &hf_catapult_dct2000_ipprim_tcp_port,
3080 "dct2000.ipprim.tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3081 "IPPrim TCP Port", HFILL
3084 { &hf_catapult_dct2000_ipprim_conn_id,
3086 "dct2000.ipprim.conn-id", FT_UINT16, BASE_DEC, NULL, 0x0,
3087 "IPPrim TCP Connection ID", HFILL
3091 { &hf_catapult_dct2000_sctpprim_addresses,
3092 { "SCTPPrim Addresses",
3093 "dct2000.sctpprim", FT_STRING, BASE_NONE, NULL, 0x0,
3097 { &hf_catapult_dct2000_sctpprim_dst_addr_v4,
3098 { "Destination Address",
3099 "dct2000.sctpprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
3100 "SCTPPrim IPv4 Destination Address", HFILL
3103 { &hf_catapult_dct2000_sctpprim_dst_addr_v6,
3104 { "Destination Address",
3105 "dct2000.sctpprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3106 "SCTPPrim IPv6 Destination Address", HFILL
3109 { &hf_catapult_dct2000_sctpprim_addr_v4,
3111 "dct2000.sctpprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
3112 "SCTPPrim IPv4 Address", HFILL
3115 { &hf_catapult_dct2000_sctpprim_addr_v6,
3117 "dct2000.sctpprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3118 "SCTPPrim IPv6 Address", HFILL
3121 { &hf_catapult_dct2000_sctpprim_dst_port,
3122 { "UDP Destination Port",
3123 "dct2000.sctprim.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3124 "SCTPPrim Destination Port", HFILL
3128 { &hf_catapult_dct2000_tty,
3130 "dct2000.tty", FT_NONE, BASE_NONE, NULL, 0x0,
3134 { &hf_catapult_dct2000_tty_line,
3136 "dct2000.tty-line", FT_STRING, BASE_NONE, NULL, 0x0,
3141 { &hf_catapult_dct2000_lte_ueid,
3143 "dct2000.lte.ueid", FT_UINT16, BASE_DEC, NULL, 0x0,
3144 "User Equipment Identifier", HFILL
3147 { &hf_catapult_dct2000_lte_srbid,
3149 "dct2000.lte.srbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3150 "Signalling Radio Bearer Identifier", HFILL
3153 { &hf_catapult_dct2000_lte_drbid,
3155 "dct2000.lte.drbid", FT_UINT8, BASE_DEC, NULL, 0x0,
3156 "Data Radio Bearer Identifier", HFILL
3159 { &hf_catapult_dct2000_lte_cellid,
3161 "dct2000.lte.cellid", FT_UINT16, BASE_DEC, NULL, 0x0,
3162 "Cell Identifier", HFILL
3165 { &hf_catapult_dct2000_lte_bcch_transport,
3167 "dct2000.lte.bcch-transport", FT_UINT16, BASE_DEC, VALS(bcch_transport_vals), 0x0,
3168 "BCCH Transport Channel", HFILL
3171 { &hf_catapult_dct2000_lte_rlc_op,
3173 "dct2000.lte.rlc-op", FT_UINT8, BASE_DEC, VALS(rlc_op_vals), 0x0,
3174 "RLC top-level op", HFILL
3177 { &hf_catapult_dct2000_lte_rlc_channel_type,
3178 { "RLC Logical Channel Type",
3179 "dct2000.lte.rlc-logchan-type", FT_UINT8, BASE_DEC, VALS(rlc_logical_channel_vals), 0x0,
3183 { &hf_catapult_dct2000_lte_rlc_mui,
3185 "dct2000.lte.rlc-mui", FT_UINT16, BASE_DEC, NULL, 0x0,
3189 { &hf_catapult_dct2000_lte_rlc_cnf,
3191 "dct2000.lte.rlc-cnf", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3195 { &hf_catapult_dct2000_lte_rlc_discard_req,
3197 "dct2000.lte.rlc-discard-req", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3198 "RLC Discard Req", HFILL
3202 { &hf_catapult_dct2000_lte_ccpri_opcode,
3204 "dct2000.lte.ccpri.opcode", FT_UINT8, BASE_DEC, VALS(ccpri_opcode_vals), 0x0,
3208 { &hf_catapult_dct2000_lte_ccpri_status,
3210 "dct2000.lte.ccpri.status", FT_UINT8, BASE_DEC, VALS(ccpri_status_vals), 0x0,
3214 { &hf_catapult_dct2000_lte_ccpri_channel,
3216 "dct2000.lte.ccpri.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
3221 { &hf_catapult_dct2000_lte_nas_rrc_opcode,
3223 "dct2000.lte.nas-rrc.opcode", FT_UINT8, BASE_DEC, VALS(lte_nas_rrc_opcode_vals), 0x0,
3227 { &hf_catapult_dct2000_lte_nas_rrc_establish_cause,
3228 { "Establish Cause",
3229 "dct2000.lte.nas-rrc.establish-cause", FT_UINT8, BASE_DEC, NULL, 0x0,
3233 { &hf_catapult_dct2000_lte_nas_rrc_priority,
3235 "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3239 { &hf_catapult_dct2000_lte_nas_rrc_release_cause,
3241 "dct2000.lte.nas-rrc.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
3247 { &hf_catapult_dct2000_ueid,
3249 "dct2000.ueid", FT_UINT32, BASE_DEC, NULL, 0x0,
3250 "User Equipment Identifier", HFILL
3253 { &hf_catapult_dct2000_rbid,
3255 "dct2000.rbid", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &rlc_rbid_vals_ext, 0x0,
3256 "Channel (rbid)", HFILL
3259 { &hf_catapult_dct2000_ccch_id,
3261 "dct2000.ccch-id", FT_UINT8, BASE_DEC, NULL, 0x0,
3262 "CCCH Identifier", HFILL
3265 { &hf_catapult_dct2000_no_crc_error,
3267 "dct2000.no-crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3271 { &hf_catapult_dct2000_crc_error,
3273 "dct2000.crc-error", FT_NONE, BASE_NONE, NULL, 0x0,
3277 { &hf_catapult_dct2000_clear_tx_buffer,
3278 { "Clear Tx Buffer",
3279 "dct2000.clear-tx-buffer", FT_NONE, BASE_NONE, NULL, 0x0,
3283 { &hf_catapult_dct2000_buffer_occupancy,
3284 { "Buffer Occupancy",
3285 "dct2000.buffer-occupancy", FT_UINT8, BASE_DEC, NULL, 0x0,
3289 { &hf_catapult_dct2000_pdu_size,
3291 "dct2000.pdu-size", FT_UINT16, BASE_DEC, NULL, 0x0,
3295 { &hf_catapult_dct2000_ueid_type,
3297 "dct2000.ueid-type", FT_UINT8, BASE_DEC, VALS(ueid_type_vals), 0x0,
3301 { &hf_catapult_dct2000_tx_priority,
3303 "dct2000.tx-priority", FT_UINT8, BASE_DEC, VALS(tx_priority_vals), 0x0,
3307 { &hf_catapult_dct2000_last_in_seg_set,
3308 { "Last in seg set",
3309 "dct2000.last-in-seg-set", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
3313 { &hf_catapult_dct2000_rx_timing_deviation,
3314 { "Tx Timing Deviation",
3315 "dct2000.rx-timing-deviation", FT_UINT32, BASE_DEC, NULL, 0x0,
3319 { &hf_catapult_dct2000_transport_channel_type,
3320 { "Transport Channel Type",
3321 "dct2000.transport_channel_type", FT_UINT8, BASE_DEC, VALS(transport_channel_type_vals), 0x0,
3325 { &hf_catapult_dct2000_no_padding_bits,
3326 { "Number of padding bits",
3327 "dct2000.number-of-padding-bits", FT_UINT8, BASE_DEC, NULL, 0x0,
3334 static gint *ett[] =
3336 &ett_catapult_dct2000,
3337 &ett_catapult_dct2000_ipprim,
3338 &ett_catapult_dct2000_sctpprim,
3339 &ett_catapult_dct2000_tty
3342 static ei_register_info ei[] = {
3343 { &ei_catapult_dct2000_lte_ccpri_status_error, { "dct2000.lte.ccpri.status.error", PI_SEQUENCE, PI_ERROR, "CCPRI Indication has error status", EXPFILL }},
3344 { &ei_catapult_dct2000_error_comment_expert, { "dct2000.error-comment.expert", PI_SEQUENCE, PI_ERROR, "Formatted expert comment", EXPFILL }},
3345 { &ei_catapult_dct2000_string_invalid, { "dct2000.string.invalid", PI_MALFORMED, PI_ERROR, "String must contain an integer", EXPFILL }}
3348 module_t *catapult_dct2000_module;
3349 expert_module_t* expert_catapult_dct2000;
3351 /* Register protocol. */
3352 proto_catapult_dct2000 = proto_register_protocol("Catapult DCT2000 packet",
3355 proto_register_field_array(proto_catapult_dct2000, hf, array_length(hf));
3356 proto_register_subtree_array(ett, array_length(ett));
3357 expert_catapult_dct2000 = expert_register_protocol(proto_catapult_dct2000);
3358 expert_register_field_array(expert_catapult_dct2000, ei, array_length(ei));
3360 /* Allow dissector to find be found by name. */
3361 catapult_dct2000_handle = register_dissector("dct2000", dissect_catapult_dct2000, proto_catapult_dct2000);
3364 catapult_dct2000_module = prefs_register_protocol(proto_catapult_dct2000, NULL);
3366 /* This preference no longer supported (introduces linkage dependency between
3367 dissectors and wiretap) */
3368 prefs_register_obsolete_preference(catapult_dct2000_module, "board_ports_only");
3370 /* Determines whether for not-handled protocols we should try to parse it if:
3371 - it looks like it's embedded in an ipprim message, AND
3372 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3373 prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
3374 "Use IP Primitive heuristic",
3375 "If a payload looks like it's embedded in an "
3376 "IP primitive message, and there is a Wireshark "
3377 "dissector matching the DCT2000 protocol name, "
3378 "try parsing the payload using that dissector",
3379 &catapult_dct2000_try_ipprim_heuristic);
3381 /* Determines whether for not-handled protocols we should try to parse it if:
3382 - it looks like it's embedded in an sctpprim message, AND
3383 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3384 prefs_register_bool_preference(catapult_dct2000_module, "sctpprim_heuristic",
3385 "Use SCTP Primitive heuristic",
3386 "If a payload looks like it's embedded in an "
3387 "SCTP primitive message, and there is a Wireshark "
3388 "dissector matching the DCT2000 protocol name, "
3389 "try parsing the payload using that dissector",
3390 &catapult_dct2000_try_sctpprim_heuristic);
3392 /* Determines whether LTE RRC messages should be dissected */
3393 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_rrc",
3394 "Attempt to decode LTE RRC frames",
3395 "When set, attempt to decode LTE RRC frames. "
3396 "Note that this won't affect other protocols "
3397 "that also call the LTE RRC dissector",
3398 &catapult_dct2000_dissect_lte_rrc);
3400 /* Determines whether LTE S1AP messages should be dissected */
3401 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_s1ap",
3402 "Attempt to decode LTE S1AP frames",
3403 "When set, attempt to decode LTE S1AP frames. "
3404 "Note that this won't affect other protocols "
3405 "that also call the LTE S1AP dissector",
3406 &catapult_dct2000_dissect_lte_s1ap);
3408 /* Determines whether out-of-band messages should dissected */
3409 prefs_register_bool_preference(catapult_dct2000_module, "decode_mac_lte_oob_messages",
3410 "Look for out-of-band LTE MAC events messages in comments",
3411 "When set, look for formatted messages indicating "
3412 "specific events. This may be quite slow, so should "
3413 "be disabled if LTE MAC is not being analysed",
3414 &catapult_dct2000_dissect_mac_lte_oob_messages);
3418 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3423 * indent-tabs-mode: nil
3426 * vi: set shiftwidth=4 tabstop=8 expandtab:
3427 * :indentSize=4:tabSize=8:noTabs=true: