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/wmem/wmem.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_sprint
= -1;
63 static int hf_catapult_dct2000_error_comment
= -1;
64 static int hf_catapult_dct2000_tty
= -1;
65 static int hf_catapult_dct2000_tty_line
= -1;
66 static int hf_catapult_dct2000_dissected_length
= -1;
68 static int hf_catapult_dct2000_ipprim_addresses
= -1;
69 static int hf_catapult_dct2000_ipprim_src_addr_v4
= -1;
70 static int hf_catapult_dct2000_ipprim_src_addr_v6
= -1;
71 static int hf_catapult_dct2000_ipprim_dst_addr_v4
= -1;
72 static int hf_catapult_dct2000_ipprim_dst_addr_v6
= -1;
73 static int hf_catapult_dct2000_ipprim_addr_v4
= -1;
74 static int hf_catapult_dct2000_ipprim_addr_v6
= -1;
75 static int hf_catapult_dct2000_ipprim_udp_src_port
= -1;
76 static int hf_catapult_dct2000_ipprim_udp_dst_port
= -1;
77 static int hf_catapult_dct2000_ipprim_udp_port
= -1;
78 static int hf_catapult_dct2000_ipprim_tcp_src_port
= -1;
79 static int hf_catapult_dct2000_ipprim_tcp_dst_port
= -1;
80 static int hf_catapult_dct2000_ipprim_tcp_port
= -1;
81 static int hf_catapult_dct2000_ipprim_conn_id
= -1;
83 static int hf_catapult_dct2000_sctpprim_addresses
= -1;
84 static int hf_catapult_dct2000_sctpprim_dst_addr_v4
= -1;
85 static int hf_catapult_dct2000_sctpprim_dst_addr_v6
= -1;
86 static int hf_catapult_dct2000_sctpprim_addr_v4
= -1;
87 static int hf_catapult_dct2000_sctpprim_addr_v6
= -1;
88 static int hf_catapult_dct2000_sctpprim_dst_port
= -1;
90 static int hf_catapult_dct2000_lte_ueid
= -1;
91 static int hf_catapult_dct2000_lte_srbid
= -1;
92 static int hf_catapult_dct2000_lte_drbid
= -1;
93 static int hf_catapult_dct2000_lte_cellid
= -1;
94 static int hf_catapult_dct2000_lte_bcch_transport
= -1;
95 static int hf_catapult_dct2000_lte_rlc_op
= -1;
96 static int hf_catapult_dct2000_lte_rlc_channel_type
= -1;
97 static int hf_catapult_dct2000_lte_rlc_mui
= -1;
98 static int hf_catapult_dct2000_lte_rlc_cnf
= -1;
99 static int hf_catapult_dct2000_lte_rlc_discard_req
= -1;
101 static int hf_catapult_dct2000_lte_ccpri_opcode
= -1;
102 static int hf_catapult_dct2000_lte_ccpri_status
= -1;
103 static int hf_catapult_dct2000_lte_ccpri_channel
= -1;
105 static int hf_catapult_dct2000_lte_nas_rrc_opcode
= -1;
106 static int hf_catapult_dct2000_lte_nas_rrc_establish_cause
= -1;
107 static int hf_catapult_dct2000_lte_nas_rrc_priority
= -1;
108 static int hf_catapult_dct2000_lte_nas_rrc_release_cause
= -1;
111 /* UMTS RLC fields */
112 static int hf_catapult_dct2000_ueid
= -1;
113 static int hf_catapult_dct2000_rbid
= -1;
114 static int hf_catapult_dct2000_ccch_id
= -1;
115 static int hf_catapult_dct2000_no_crc_error
= -1;
116 static int hf_catapult_dct2000_crc_error
= -1;
117 static int hf_catapult_dct2000_clear_tx_buffer
= -1;
118 static int hf_catapult_dct2000_buffer_occupancy
= -1;
119 static int hf_catapult_dct2000_pdu_size
= -1;
120 static int hf_catapult_dct2000_ueid_type
= -1;
121 static int hf_catapult_dct2000_tx_priority
= -1;
122 static int hf_catapult_dct2000_last_in_seg_set
= -1;
123 static int hf_catapult_dct2000_rx_timing_deviation
= -1;
124 static int hf_catapult_dct2000_transport_channel_type
= -1;
125 static int hf_catapult_dct2000_no_padding_bits
= -1;
127 /* Variables used for preferences */
128 static gboolean catapult_dct2000_try_ipprim_heuristic
= TRUE
;
129 static gboolean catapult_dct2000_try_sctpprim_heuristic
= TRUE
;
130 static gboolean catapult_dct2000_dissect_lte_rrc
= TRUE
;
131 static gboolean catapult_dct2000_dissect_lte_s1ap
= TRUE
;
132 static gboolean catapult_dct2000_dissect_mac_lte_oob_messages
= TRUE
;
134 /* Protocol subtree. */
135 static int ett_catapult_dct2000
= -1;
136 static int ett_catapult_dct2000_ipprim
= -1;
137 static int ett_catapult_dct2000_sctpprim
= -1;
138 static int ett_catapult_dct2000_tty
= -1;
140 static expert_field ei_catapult_dct2000_lte_ccpri_status_error
= EI_INIT
;
141 static expert_field ei_catapult_dct2000_error_comment_expert
= EI_INIT
;
143 static const value_string direction_vals
[] = {
149 static const value_string encap_vals
[] = {
150 { WTAP_ENCAP_RAW_IP
, "Raw IP" },
151 { WTAP_ENCAP_ETHERNET
, "Ethernet" },
152 { WTAP_ENCAP_ISDN
, "LAPD" },
153 { WTAP_ENCAP_ATM_PDUS_UNTRUNCATED
, "ATM (PDUs untruncated)" },
154 { WTAP_ENCAP_PPP
, "PPP" },
155 { DCT2000_ENCAP_SSCOP
, "SSCOP" },
156 { WTAP_ENCAP_FRELAY
, "Frame Relay" },
157 { WTAP_ENCAP_MTP2
, "MTP2" },
158 { DCT2000_ENCAP_NBAP
, "NBAP" },
159 { DCT2000_ENCAP_UNHANDLED
, "No Direct Encapsulation" },
163 static const value_string bcch_transport_vals
[] = {
164 { BCH_TRANSPORT
, "BCH" },
165 { DLSCH_TRANSPORT
, "DLSCH" },
170 #define RLC_MGMT_ASSIGN 0x41
171 #define RLC_AM_DATA_REQ 0x60
172 #define RLC_AM_DATA_IND 0x61
173 #define RLC_AM_DATA_CONF 0x62
174 #define RLC_UM_DATA_REQ 0x70
175 #define RLC_UM_DATA_IND 0x71
176 #define RLC_UM_DATA_CONF 0x74
177 #define RLC_TR_DATA_REQ 0x80
178 #define RLC_TR_DATA_IND 0x81
179 #define RLC_TR_DATA_CONF 0x83
181 static const value_string rlc_op_vals
[] = {
182 { RLC_AM_DATA_REQ
, "[UL] [AM]" },
183 { RLC_AM_DATA_IND
, "[DL] [AM]" },
184 { RLC_UM_DATA_REQ
, "[UL] [UM]"},
185 { RLC_UM_DATA_IND
, "[DL] [UM]"},
186 { RLC_TR_DATA_REQ
, "[UL] [TM]"},
187 { RLC_TR_DATA_IND
, "[DL] [TM]"},
192 static const value_string rlc_logical_channel_vals
[] = {
193 { Channel_DCCH
, "DCCH"},
194 { Channel_BCCH
, "BCCH"},
195 { Channel_CCCH
, "CCCH"},
196 { Channel_PCCH
, "PCCH"},
204 static const value_string ccpri_opcode_vals
[] = {
205 { CCPRI_REQ
, "REQUEST"},
206 { CCPRI_IND
, "INDICATION"},
210 static const value_string ccpri_status_vals
[] = {
216 static const value_string 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
285 static guint outhdr_values
[MAX_OUTHDR_VALUES
];
286 static guint outhdr_values_found
= 0;
289 extern int proto_rlc
;
291 extern int proto_rlc_lte
;
292 extern int proto_pdcp_lte
;
294 static dissector_handle_t mac_lte_handle
;
295 static dissector_handle_t rlc_lte_handle
;
296 static dissector_handle_t pdcp_lte_handle
;
298 void proto_register_catapult_dct2000(void);
300 static dissector_handle_t
look_for_dissector(const char *protocol_name
);
301 static void parse_outhdr_string(const guchar
*outhdr_string
, gint outhdr_length
);
303 static void attach_fp_info(packet_info
*pinfo
, gboolean received
,
304 const char *protocol_name
, int variant
);
305 static void attach_rlc_info(packet_info
*pinfo
, guint32 urnti
, guint8 rbid
,
308 static void attach_mac_lte_info(packet_info
*pinfo
);
309 static void attach_rlc_lte_info(packet_info
*pinfo
);
310 static void attach_pdcp_lte_info(packet_info
*pinfo
);
314 /* Return the number of bytes used to encode the length field
315 (we're not interested in the length value itself) */
316 static int skipASNLength(guint8 value
)
318 if ((value
& 0x80) == 0)
324 return ((value
& 0x03) == 1) ? 2 : 3;
329 /* Look for the protocol data within an ipprim packet.
330 Only set *data_offset if data field found. */
331 static gboolean
find_ipprim_data_offset(tvbuff_t
*tvb
, int *data_offset
, guint8 direction
,
332 guint32
*source_addr_offset
, guint8
*source_addr_length
,
333 guint32
*dest_addr_offset
, guint8
*dest_addr_length
,
334 guint32
*source_port_offset
, guint32
*dest_port_offset
,
335 port_type
*type_of_port
,
336 guint16
*conn_id_offset
)
339 int offset
= *data_offset
;
341 /* Get the ipprim command code. */
342 guint8 tag
= tvb_get_guint8(tvb
, offset
++);
344 /* Only accept UDP or TCP data request or indication */
346 case 0x23: /* UDP data request */
347 case 0x24: /* UDP data indication */
348 *type_of_port
= PT_UDP
;
350 case 0x45: /* TCP data request */
351 case 0x46: /* TCP data indication */
352 *type_of_port
= PT_TCP
;
358 /* Skip any other TLC fields before reach payload */
359 while (tvb_length_remaining(tvb
, offset
) > 2) {
360 /* Look at next tag */
361 tag
= tvb_get_guint8(tvb
, offset
++);
363 /* Is this the data payload we're expecting? */
364 if (((tag
== 0x34) && (*type_of_port
== PT_UDP
)) ||
365 ((tag
== 0x48) && (*type_of_port
== PT_TCP
))) {
367 *data_offset
= offset
;
371 /* Read length in next byte */
372 length
= tvb_get_guint8(tvb
, offset
++);
374 if (tag
== 0x31 && length
>=4) {
375 /* Remote IP address */
376 if (direction
== 0) {
377 /* Sent *to* remote, so dest */
378 *dest_addr_offset
= offset
;
379 *dest_addr_length
= (length
/4) * 4;
382 *source_addr_offset
= offset
;
383 *source_addr_length
= (length
/4) * 4;
386 /* Remote port follows (if present) */
387 if ((length
% 4) == 2) {
388 if (direction
== 0) {
389 *dest_port_offset
= offset
+ *dest_addr_length
;
392 *source_port_offset
= offset
+ *source_addr_length
;
398 if (length
== 4 || length
== 16) {
399 /* Local IP address */
400 if (direction
== 0) {
401 /* Sent *from* local, so source */
402 *source_addr_offset
= offset
;
403 *source_addr_length
= length
;
406 *dest_addr_offset
= offset
;
407 *dest_addr_length
= length
;
412 if (tag
== 0x33 && length
== 2) {
414 if (direction
== 0) {
415 /* Sent from local, so source */
416 *source_port_offset
= offset
;
419 *dest_port_offset
= offset
;
423 if (tag
== 0x36 && length
== 2) {
425 *conn_id_offset
= offset
;
428 /* Skip the length of the indicated value */
433 /* No data found... */
439 /* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
440 Only set *data_offset if data field found. */
441 static gboolean
find_sctpprim_variant1_data_offset(tvbuff_t
*tvb
, int *data_offset
,
442 guint32
*dest_addr_offset
,
443 guint16
*dest_addr_length
,
444 guint32
*dest_port_offset
)
446 int offset
= *data_offset
;
448 /* Get the sctpprim command code. */
449 guint8 first_tag
= tvb_get_guint8(tvb
, offset
++);
451 guint8 first_length_byte
;
453 /* Only accept interested in data requests or indications */
455 case 0x04: /* data request */
456 case 0x62: /* data indication */
462 first_length_byte
= tvb_get_guint8(tvb
, offset
);
463 offset
+= skipASNLength(first_length_byte
);
465 /* Skip any other fields before reach payload */
466 while (tvb_length_remaining(tvb
, offset
) > 2) {
467 /* Look at next tag */
468 tag
= tvb_get_guint8(tvb
, offset
++);
470 /* Is this the data payload we're expecting? */
472 *data_offset
= offset
;
476 /* Skip length field */
479 case 0x0a: /* destPort */
480 *dest_port_offset
= offset
;
484 case 0x01: /* sctpInstanceNum */
485 case 0x1e: /* strseqnum */
486 case 0x0d: /* streamnum */
490 case 0x09: /* ipv4Address */
491 *dest_addr_offset
= offset
;
492 *dest_addr_length
= 4;
497 case 0x0c: /* payloadType */
502 /* Fail if not a known header field */
508 /* No data found... */
512 /* Look for the protocol data within an sctpprim (variant 3) packet.
513 Only set *data_offset if data field found. */
514 static gboolean
find_sctpprim_variant3_data_offset(tvbuff_t
*tvb
, int *data_offset
,
515 guint32
*dest_addr_offset
,
516 guint16
*dest_addr_length
,
517 guint32
*dest_port_offset
)
521 int offset
= *data_offset
;
523 /* Get the sctpprim (2 byte) command code. */
524 guint16 top_tag
= tvb_get_ntohs(tvb
, offset
);
527 /* Only interested in data requests or indications */
529 case 0x0400: /* SendDataReq */
530 case 0x6200: /* DataInd */
537 /* Overall length field is next 2 bytes */
540 /* Rx/Tx ops have different formats */
544 if (top_tag
== 0x6200) {
545 /* Next 2 bytes are associate ID */
548 /* Next 2 bytes are destination port */
549 *dest_port_offset
= offset
;
552 /* Destination address should follow - check tag */
553 tag
= tvb_get_ntohs(tvb
, offset
);
562 length
= tvb_get_ntohs(tvb
, offset
) / 2;
563 if ((length
!= 4) && (length
!= 16))
569 /* Address data is here */
570 *dest_addr_offset
= offset
;
571 *dest_addr_length
= length
;
576 /* Not interested in remaining (fixed) fields */
577 if (tvb_reported_length_remaining(tvb
, offset
) > (4 + 2 + 2 + 4)) {
578 offset
+= (4 + 2 + 2 + 4);
584 /* Data should now be here */
585 tag
= tvb_get_ntohs(tvb
, offset
);
588 /* 2-byte length field */
591 /* Data is here!!! */
592 *data_offset
= offset
;
602 else if (top_tag
== 0x0400) {
603 /* AssociateId should follow - check tag */
604 tag
= tvb_get_ntohs(tvb
, offset
);
612 /* Skip 2-byte value */
617 tag
= tvb_get_ntohs(tvb
, offset
);
620 /* Some optional params */
621 while ((tag
!= 0x0c00) && (tvb_length_remaining(tvb
, offset
) > 4)) {
623 case 0x0900: /* Dest address */
625 length
= tvb_get_ntohs(tvb
, offset
) / 2;
626 if ((length
!= 4) && (length
!= 16)) {
631 /* Address data is here */
632 *dest_addr_offset
= offset
;
633 *dest_addr_length
= length
;
638 case 0x0a00: /* Dest port number */
639 *dest_port_offset
= offset
;
643 case 0x0d00: /* StreamNum */
644 *dest_port_offset
= offset
;
653 /* Get the next tag */
654 tag
= tvb_get_ntohs(tvb
, offset
);
659 /* Mandatory payload type */
663 length
= tvb_get_ntohs(tvb
, offset
) / 2;
668 /* Optional options */
669 tag
= tvb_get_ntohs(tvb
, offset
);
672 length
= tvb_get_ntohs(tvb
, offset
) / 2;
678 tag
= tvb_get_ntohs(tvb
, offset
);
683 /* Data should now be here!! */
685 /* 2-byte length field */
688 /* Data is here!!! */
689 *data_offset
= offset
;
701 /* Dissect a UMTS RLC frame by:
702 - parsing the primitive header
703 - passing those values + outhdeader to dissector
704 - calling the UMTS RLC dissector */
705 static void dissect_rlc_umts(tvbuff_t
*tvb
, gint offset
,
706 packet_info
*pinfo
, proto_tree
*tree
,
710 gboolean ueid_set
= FALSE
, rbid_set
=FALSE
;
715 dissector_handle_t rlc_umts_handle
= 0;
717 /* Top-level opcode */
718 tag
= tvb_get_guint8(tvb
, offset
++);
720 case 0xc0: /* mac data request */
721 case 0xc1: /* mac data indication */
725 /* No data to dissect */
729 /* Keep going until reach data tag or end of frame */
730 while ((tag
!= 0x41) && tvb_length_remaining(tvb
, offset
)) { /* i.e. Data */
731 tag
= tvb_get_guint8(tvb
, offset
++);
733 case 0x72: /* UE Id */
734 ueid
= tvb_get_ntohl(tvb
, offset
);
735 proto_tree_add_item(tree
, hf_catapult_dct2000_ueid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
739 case 0xa2: /* RBID */
740 offset
++; /* skip length */
741 rbid
= tvb_get_guint8(tvb
, offset
);
742 proto_tree_add_item(tree
, hf_catapult_dct2000_rbid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
746 case 0x22: /* CCCH-id setting rbid to CCCH! */
747 offset
++; /* skip length */
748 proto_tree_add_item(tree
, hf_catapult_dct2000_ccch_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
752 case 0xc4: /* No CRC error */
753 proto_tree_add_item(tree
, hf_catapult_dct2000_no_crc_error
, tvb
, offset
-1, 1, ENC_NA
);
755 case 0xc5: /* CRC error */
756 proto_tree_add_item(tree
, hf_catapult_dct2000_crc_error
, tvb
, offset
-1, 1, ENC_NA
);
758 case 0xf7: /* Clear Tx Buffer */
759 proto_tree_add_item(tree
, hf_catapult_dct2000_clear_tx_buffer
, tvb
, offset
-1, 1, ENC_NA
);
762 case 0x41: /* Data !!! */
763 offset
+= skipASNLength(tvb_get_guint8(tvb
, offset
));
767 /* For other fields, just skip length and following data */
768 length
= tvb_get_guint8(tvb
, offset
++);
770 case 0x42: /* Buffer Occupancy */
771 proto_tree_add_item(tree
, hf_catapult_dct2000_buffer_occupancy
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
773 case 0x49: /* PDU Size */
774 proto_tree_add_item(tree
, hf_catapult_dct2000_pdu_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
776 case 0x47: /* UEId type */
777 proto_tree_add_item(tree
, hf_catapult_dct2000_ueid_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
779 case 0x4e: /* Tx Priority */
780 proto_tree_add_item(tree
, hf_catapult_dct2000_tx_priority
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
782 case 0x4c: /* Last in seg set */
783 proto_tree_add_item(tree
, hf_catapult_dct2000_last_in_seg_set
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
785 case 0x43: /* Rx timing deviation */
786 proto_tree_add_item(tree
, hf_catapult_dct2000_rx_timing_deviation
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
788 case 0x46: /* Transport channel type */
789 proto_tree_add_item(tree
, hf_catapult_dct2000_transport_channel_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
791 case 0xc2: /* Number of padding bits */
792 proto_tree_add_item(tree
, hf_catapult_dct2000_no_padding_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
804 /* Have we got enough info to call dissector */
805 if ((tag
== 0x41) && ueid_set
&& rbid_set
) {
806 attach_rlc_info(pinfo
, ueid
, rbid
, is_sent
);
808 /* Set appropriate RLC dissector handle */
810 case 1: case 2: case 3: case 4: case 5:
811 case 6: case 7: case 8: case 9: case 10:
812 case 11: case 12: case 13: case 14: case 15:
814 /* TODO: can't really tell if these are control or transport...
815 maybe control with preferences (UAT?) between "rlc.ps_dtch" and "rlc.dcch" ? */
816 rlc_umts_handle
= find_dissector("rlc.dch_unknown");
819 rlc_umts_handle
= find_dissector("rlc.ccch");
822 rlc_umts_handle
= find_dissector("rlc.ctch");
830 /* Call UMTS RLC dissector */
831 if (rlc_umts_handle
!= 0) {
832 rlc_tvb
= tvb_new_subset_remaining(tvb
, offset
);
833 call_dissector_only(rlc_umts_handle
, rlc_tvb
, pinfo
, tree
, NULL
);
840 /* Dissect an RRC LTE frame by first parsing the header entries then passing
841 the data to the RRC dissector, according to direction and channel type.
842 TODO: factor out common code between this function and dissect_pdcp_lte() */
843 static void dissect_rrc_lte(tvbuff_t
*tvb
, gint offset
,
844 packet_info
*pinfo
, proto_tree
*tree
)
847 dissector_handle_t protocol_handle
= 0;
848 gboolean isUplink
= FALSE
;
849 LogicalChannelType logicalChannelType
;
851 guint8 bcch_transport
= 0;
854 /* Top-level opcode */
855 tag
= tvb_get_guint8(tvb
, offset
++);
857 case 0x00: /* Data_Req_UE */
858 case 0x04: /* Data_Ind_eNodeB */
862 case 0x02: /* Data_Req_eNodeB */
863 case 0x03: /* Data_Ind_UE */
868 /* Unexpected opcode tag! */
873 offset
+= skipASNLength(tvb_get_guint8(tvb
, offset
));
876 tag
= tvb_get_guint8(tvb
, offset
++);
878 case 0x12: /* UE_Id_LCId */
880 /* Dedicated channel info */
882 /* Length will fit in one byte here */
885 logicalChannelType
= Channel_DCCH
;
888 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
891 /* Get tag of channel type */
892 tag
= tvb_get_guint8(tvb
, offset
++);
897 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " SRB:%u",
898 tvb_get_guint8(tvb
, offset
));
899 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_srbid
,
900 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
905 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " DRB:%u",
906 tvb_get_guint8(tvb
, offset
));
907 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_drbid
,
908 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
913 /* Unexpected channel type */
918 case 0x1a: /* Cell_LCId */
920 /* Common channel info */
926 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_cellid
,
927 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
928 cell_id
= tvb_get_ntohs(tvb
, offset
);
931 /* Logical channel type */
932 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_rlc_channel_type
,
933 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
934 logicalChannelType
= (LogicalChannelType
)tvb_get_guint8(tvb
, offset
);
937 /* Won't be seen if RRC decoder is called... */
938 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " cell-id=%u %s",
940 val_to_str_const(logicalChannelType
, rlc_logical_channel_vals
,
944 switch (logicalChannelType
) {
949 /* Transport channel type */
950 bcch_transport
= tvb_get_guint8(tvb
, offset
);
951 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_bcch_transport
,
952 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
961 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
,
962 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
976 /* Data tag should follow */
977 tag
= tvb_get_guint8(tvb
, offset
++);
983 offset
+= skipASNLength(tvb_get_guint8(tvb
, offset
));
985 /* Look up dissector handle corresponding to direction and channel type */
988 /* Uplink channel types */
989 switch (logicalChannelType
) {
991 protocol_handle
= find_dissector("lte_rrc.ul_dcch");
994 protocol_handle
= find_dissector("lte_rrc.ul_ccch");
998 /* Unknown Uplink channel type */
1003 /* Downlink channel types */
1004 switch (logicalChannelType
) {
1006 protocol_handle
= find_dissector("lte_rrc.dl_dcch");
1009 protocol_handle
= find_dissector("lte_rrc.dl_ccch");
1012 protocol_handle
= find_dissector("lte_rrc.pcch");
1015 if (bcch_transport
== 1) {
1016 protocol_handle
= find_dissector("lte_rrc.bcch_bch");
1019 protocol_handle
= find_dissector("lte_rrc.bcch_dl_sch");
1024 /* Unknown Downlink channel type */
1029 /* Send to RRC dissector, if got here, have sub-dissector and some data left */
1030 if ((protocol_handle
!= NULL
) && (tvb_length_remaining(tvb
, offset
) > 0)) {
1031 rrc_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1032 call_dissector_only(protocol_handle
, rrc_tvb
, pinfo
, tree
, NULL
);
1037 /* Dissect an CCPRI LTE frame by first parsing the header entries then passing
1038 the data to the CPRI C&M dissector */
1039 static void dissect_ccpri_lte(tvbuff_t
*tvb
, gint offset
,
1040 packet_info
*pinfo
, proto_tree
*tree
)
1044 tvbuff_t
*ccpri_tvb
;
1045 dissector_handle_t protocol_handle
= 0;
1048 /* Top-level opcode */
1049 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ccpri_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1050 opcode
= tvb_get_guint8(tvb
, offset
++);
1052 /* Skip 2-byte length field */
1056 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_cellid
,
1057 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1060 /* Status (ind only) */
1063 guint8 status
= tvb_get_guint8(tvb
, offset
);
1064 ti
= proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ccpri_status
,
1065 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1069 expert_add_info(pinfo
, ti
, &ei_catapult_dct2000_lte_ccpri_status_error
);
1075 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ccpri_channel
,
1076 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1079 /* Data tag must follow */
1080 tag
= tvb_get_guint8(tvb
, offset
++);
1086 length
= tvb_get_ntohs(tvb
, offset
);
1089 /* Send remainder to lapb dissector (lapb needs patch with preference
1090 set to call cpri C&M dissector instead of X.25) */
1091 protocol_handle
= find_dissector("lapb");
1092 if ((protocol_handle
!= NULL
) && (tvb_length_remaining(tvb
, offset
) > 0)) {
1093 ccpri_tvb
= tvb_new_subset(tvb
, offset
, length
, length
);
1094 call_dissector_only(protocol_handle
, ccpri_tvb
, pinfo
, tree
, NULL
);
1101 /* Dissect a PDCP LTE frame by first parsing the RLCPrim header then passing
1102 the data to the PDCP LTE dissector */
1103 static void dissect_pdcp_lte(tvbuff_t
*tvb
, gint offset
,
1104 packet_info
*pinfo
, proto_tree
*tree
)
1108 struct pdcp_lte_info
*p_pdcp_lte_info
= NULL
;
1109 tvbuff_t
*pdcp_lte_tvb
;
1113 /* Look this up so can update channel info */
1114 p_pdcp_lte_info
= (struct pdcp_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_pdcp_lte
, 0);
1115 if (p_pdcp_lte_info
== NULL
) {
1116 /* This really should be set...can't dissect anything without it */
1120 /* Top-level opcode */
1121 opcode
= tvb_get_guint8(tvb
, offset
);
1123 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_rlc_op
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1127 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(opcode
, rlc_op_vals
, "Unknown"));
1129 /* Assume UE side, so REQ is UL, IND is DL */
1131 case RLC_AM_DATA_REQ
:
1132 case RLC_UM_DATA_REQ
:
1133 case RLC_TR_DATA_REQ
:
1134 p_pdcp_lte_info
->direction
= DIRECTION_UPLINK
;
1138 p_pdcp_lte_info
->direction
= DIRECTION_DOWNLINK
;
1143 case RLC_AM_DATA_REQ
:
1144 case RLC_AM_DATA_IND
:
1145 case RLC_UM_DATA_REQ
:
1146 case RLC_UM_DATA_IND
:
1147 case RLC_TR_DATA_REQ
:
1148 case RLC_TR_DATA_IND
:
1151 tag
= tvb_get_guint8(tvb
, offset
++);
1153 case 0x10: /* UE_Id_LCId */
1155 /* Dedicated channel info */
1157 /* Length will fit in one byte here */
1160 p_pdcp_lte_info
->channelType
= Channel_DCCH
;
1163 ueid
= tvb_get_ntohs(tvb
, offset
);
1164 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1165 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1167 p_pdcp_lte_info
->ueid
= ueid
;
1170 /* Get tag of channel type */
1171 tag
= tvb_get_guint8(tvb
, offset
++);
1176 channelId
= tvb_get_guint8(tvb
, offset
);
1177 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " SRB:%u",
1179 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_srbid
,
1180 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
1181 p_pdcp_lte_info
->channelId
= channelId
;
1185 channelId
= tvb_get_guint8(tvb
, offset
);
1186 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " DRB:%u",
1188 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_drbid
,
1189 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
1190 p_pdcp_lte_info
->channelId
= channelId
;
1194 /* Unexpected channel type */
1199 case 0x1a: /* Cell_LCId */
1201 /* Common channel info */
1207 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_cellid
,
1208 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1211 /* Logical channel type */
1212 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_rlc_channel_type
,
1213 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1214 p_pdcp_lte_info
->channelType
= (LogicalChannelType
)tvb_get_guint8(tvb
, offset
++);
1215 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s",
1216 val_to_str_const(p_pdcp_lte_info
->channelType
, rlc_logical_channel_vals
,
1217 "UNKNOWN-CHANNEL"));
1219 switch (p_pdcp_lte_info
->channelType
) {
1224 /* Transport channel type */
1225 p_pdcp_lte_info
->BCCHTransport
= (BCCHTransportType
)tvb_get_guint8(tvb
, offset
);
1226 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_bcch_transport
,
1227 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1236 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
,
1237 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1238 ueid
= tvb_get_ntohs(tvb
, offset
);
1241 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " UEId=%u", ueid
);
1250 /* Unexpected tag */
1254 /* Other optional fields may follow */
1255 tag
= tvb_get_guint8(tvb
, offset
++);
1256 while ((tag
!= 0x41) && (tvb_length_remaining(tvb
, offset
) > 2)) {
1261 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_rlc_mui
,
1262 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1265 /* CNF follows MUI in AM */
1266 if ((opcode
== RLC_AM_DATA_REQ
) || (opcode
== RLC_AM_DATA_IND
)) {
1267 proto_tree_add_boolean(tree
, hf_catapult_dct2000_lte_rlc_cnf
,
1268 tvb
, offset
, 1, tvb_get_guint8(tvb
, offset
));
1272 else if (tag
== 0x45) {
1275 proto_tree_add_boolean(tree
, hf_catapult_dct2000_lte_rlc_discard_req
,
1276 tvb
, offset
, 1, tvb_get_guint8(tvb
, offset
));
1280 tag
= tvb_get_guint8(tvb
, offset
++);
1284 /********************************/
1285 /* Should be at data tag now */
1287 /* Call PDCP LTE dissector */
1288 pdcp_lte_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1289 call_dissector_only(pdcp_lte_handle
, pdcp_lte_tvb
, pinfo
, tree
, NULL
);
1302 /* Look up dissector by protocol name. Fix up known name mis-matches.
1303 This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */
1304 static dissector_handle_t
look_for_dissector(const char *protocol_name
)
1306 /* Use known aliases and protocol name prefixes */
1307 if (strcmp(protocol_name
, "tbcp") == 0) {
1308 return find_dissector("rtcp");
1311 if (strncmp(protocol_name
, "diameter", strlen("diameter")) == 0) {
1312 return find_dissector("diameter");
1315 if ((strcmp(protocol_name
, "xcap_caps") == 0) ||
1316 (strcmp(protocol_name
, "soap") == 0) ||
1317 (strcmp(protocol_name
, "mm1") == 0) ||
1318 (strcmp(protocol_name
, "mm3") == 0) ||
1319 (strcmp(protocol_name
, "mm7") == 0)) {
1321 return find_dissector("http");
1324 if ((strcmp(protocol_name
, "fp") == 0) ||
1325 (strncmp(protocol_name
, "fp_r", 4) == 0) ||
1326 (strcmp(protocol_name
, "fpiur_r5") == 0)) {
1328 return find_dissector("fp");
1331 if ((strcmp(protocol_name
, "iuup_rtp_r5") == 0) ||
1332 (strcmp(protocol_name
, "iuup_rtp_r6") == 0)) {
1334 return find_dissector("rtp");
1337 if (strcmp(protocol_name
, "sipt") == 0) {
1338 return find_dissector("sip");
1341 if (strncmp(protocol_name
, "nbap_sctp", strlen("nbap_sctp")) == 0) {
1342 return find_dissector("nbap");
1345 if (strncmp(protocol_name
, "gtp", strlen("gtp")) == 0) {
1346 return find_dissector("gtp");
1349 if (strcmp(protocol_name
, "dhcpv4") == 0) {
1350 return find_dissector("bootp");
1353 if (strcmp(protocol_name
, "wimax") == 0) {
1354 return find_dissector("wimaxasncp");
1357 if (strncmp(protocol_name
, "sabp", strlen("sabp")) == 0) {
1358 return find_dissector("sabp");
1361 if (strcmp(protocol_name
, "wtp") == 0) {
1362 return find_dissector("wtp-udp");
1365 /* Only match with s1ap if preference turned on */
1366 if (catapult_dct2000_dissect_lte_s1ap
&&
1367 strncmp(protocol_name
, "s1ap", strlen("s1ap")) == 0) {
1369 return find_dissector("s1ap");
1372 /* Always try lookup for now */
1373 if ((strncmp(protocol_name
, "x2ap_r8_lte", strlen("x2ap_r8_lte")) == 0) ||
1374 (strncmp(protocol_name
, "x2ap_r9_lte", strlen("x2ap_r9_lte")) == 0)) {
1376 return find_dissector("x2ap");
1380 if ((strcmp(protocol_name
, "gtpv2_r8_lte") == 0) ||
1381 (strcmp(protocol_name
, "gtpv2_r9_lte") == 0)) {
1382 return find_dissector("gtpv2");
1386 /* Try for an exact match */
1388 return find_dissector(protocol_name
);
1393 /* Populate outhdr_values array with numbers found in outhdr_string */
1394 static void parse_outhdr_string(const guchar
*outhdr_string
, gint outhdr_string_len
)
1398 /* Populate values array */
1399 for (outhdr_values_found
=0; outhdr_values_found
< MAX_OUTHDR_VALUES
; ) {
1401 guint digit_array
[MAX_OUTHDR_VALUES
];
1402 guint number_digits
= 0;
1405 guint multiplier
= 1;
1409 for ( ; n
< outhdr_string_len
; n
++) {
1410 if (!isdigit(outhdr_string
[n
])) {
1414 digit_array
[number_digits
++] = outhdr_string
[n
] - '0';
1418 if (number_digits
== 0) {
1419 /* No more numbers left */
1423 /* Convert digits into value (much faster than format_text() + atoi()) */
1424 for (d
=number_digits
; d
> 0; d
--) {
1425 number
+= ((digit_array
[d
-1]) * multiplier
);
1428 outhdr_values
[outhdr_values_found
++] = number
;
1437 /* Fill in an FP packet info struct and attach it to the packet for the FP
1439 static void attach_fp_info(packet_info
*pinfo
, gboolean received
, const char *protocol_name
, int variant
)
1443 int tf_start
, num_chans_start
;
1445 int calculated_variant
;
1447 /* Only need to set info once per session. */
1448 struct fp_info
*p_fp_info
= (struct fp_info
*)p_get_proto_data(pinfo
->fd
, proto_fp
, 0);
1449 if (p_fp_info
!= NULL
) {
1453 /* Allocate struct */
1454 p_fp_info
= wmem_new0(wmem_file_scope(), struct fp_info
);
1456 /* Check that the number of outhdr values looks sensible */
1457 if (((strcmp(protocol_name
, "fpiur_r5") == 0) && (outhdr_values_found
!= 2)) ||
1458 (outhdr_values_found
< 5)) {
1463 /* 3gpp release (99, 4, 5, 6, 7) */
1464 if (strcmp(protocol_name
, "fp") == 0) {
1465 p_fp_info
->release
= 99;
1467 else if (strcmp(protocol_name
, "fp_r4") == 0) {
1468 p_fp_info
->release
= 4;
1470 else if (strcmp(protocol_name
, "fp_r5") == 0) {
1471 p_fp_info
->release
= 5;
1473 else if (strcmp(protocol_name
, "fp_r6") == 0) {
1474 p_fp_info
->release
= 6;
1476 else if (strcmp(protocol_name
, "fp_r7") == 0) {
1477 p_fp_info
->release
= 7;
1479 else if (strcmp(protocol_name
, "fp_r8") == 0) {
1480 p_fp_info
->release
= 8;
1482 else if (strcmp(protocol_name
, "fpiur_r5") == 0) {
1483 p_fp_info
->release
= 5;
1486 /* Really shouldn't get here */
1487 DISSECTOR_ASSERT_NOT_REACHED();
1491 /* Release date is derived from variant number */
1492 /* Only R6 sub-versions currently influence format within a release */
1493 switch (p_fp_info
->release
) {
1495 if (variant
< 256) {
1496 calculated_variant
= variant
;
1499 calculated_variant
= variant
/ 256;
1502 switch (calculated_variant
) {
1504 p_fp_info
->release_year
= 2005;
1505 p_fp_info
->release_month
= 6;
1508 p_fp_info
->release_year
= 2005;
1509 p_fp_info
->release_month
= 9;
1513 p_fp_info
->release_year
= 2006;
1514 p_fp_info
->release_month
= 3;
1519 p_fp_info
->release_year
= 2008;
1520 p_fp_info
->release_month
= 3;
1524 p_fp_info
->release_year
= 2010;
1525 p_fp_info
->release_month
= 6;
1530 p_fp_info
->release_year
= 0;
1531 p_fp_info
->release_month
= 0;
1536 p_fp_info
->channel
= outhdr_values
[i
++];
1537 /* Sad hack until this value is filled in properly */
1538 if (p_fp_info
->channel
== 0) {
1539 p_fp_info
->channel
= CHANNEL_DCH
;
1542 /* Derive direction from node type/side */
1543 node_type
= outhdr_values
[i
++];
1544 p_fp_info
->is_uplink
= (( received
&& (node_type
== 2)) ||
1545 (!received
&& (node_type
== 1)));
1547 /* Division type introduced for R7 */
1548 if ((p_fp_info
->release
== 7) ||
1549 (p_fp_info
->release
== 8)) {
1550 p_fp_info
->division
= (enum division_type
)outhdr_values
[i
++];
1553 /* HS-DSCH config */
1554 if (p_fp_info
->channel
== CHANNEL_HSDSCH
) {
1555 if ((p_fp_info
->release
== 7) ||
1556 (p_fp_info
->release
== 8)) {
1557 /* Entity (MAC-hs or MAC-ehs) used */
1558 if (outhdr_values
[i
++]) {
1559 p_fp_info
->hsdsch_entity
= ehs
;
1563 /* This is the pre-R7 default */
1564 p_fp_info
->hsdsch_entity
= hs
;
1569 /* IUR only uses the above... */
1570 if (strcmp(protocol_name
, "fpiur_r5") == 0) {
1571 /* Store info in packet */
1572 p_fp_info
->iface_type
= IuR_Interface
;
1573 p_add_proto_data(pinfo
->fd
, proto_fp
, 0, p_fp_info
);
1577 /* DCH CRC present... */
1578 p_fp_info
->dch_crc_present
= outhdr_values
[i
++];
1580 /* ... but don't trust for edch */
1581 if (p_fp_info
->channel
== CHANNEL_EDCH
) {
1582 p_fp_info
->dch_crc_present
= 2; /* unknown */
1585 /* How many paging indications (if PCH data) */
1586 p_fp_info
->paging_indications
= outhdr_values
[i
++];
1588 /* Number of channels (for coordinated channels) */
1589 p_fp_info
->num_chans
= outhdr_values
[i
++];
1591 /* EDCH-Common is always T2 */
1592 if (p_fp_info
->channel
== CHANNEL_EDCH_COMMON
) {
1593 p_fp_info
->edch_type
= 1;
1596 if (p_fp_info
->channel
!= CHANNEL_EDCH
) {
1597 /* TF size for each channel */
1599 for (chan
=0; chan
< p_fp_info
->num_chans
; chan
++) {
1600 p_fp_info
->chan_tf_size
[chan
] = outhdr_values
[tf_start
+chan
];
1603 /* Number of TBs for each channel */
1604 num_chans_start
= tf_start
+ p_fp_info
->num_chans
;
1605 for (chan
=0; chan
< p_fp_info
->num_chans
; chan
++) {
1606 p_fp_info
->chan_num_tbs
[chan
] = outhdr_values
[num_chans_start
+chan
];
1613 p_fp_info
->no_ddi_entries
= outhdr_values
[i
++];
1616 for (n
=0; n
< p_fp_info
->no_ddi_entries
; n
++) {
1617 p_fp_info
->edch_ddi
[n
] = outhdr_values
[i
++];
1620 /* Corresponding MAC-d sizes */
1621 for (n
=0; n
< p_fp_info
->no_ddi_entries
; n
++) {
1622 p_fp_info
->edch_macd_pdu_size
[n
] = outhdr_values
[i
++];
1625 if (strcmp(protocol_name
, "fp_r8") == 0) {
1626 p_fp_info
->edch_type
= outhdr_values
[i
];
1629 p_fp_info
->edch_type
= 0;
1633 /* Interface must be IuB */
1634 p_fp_info
->iface_type
= IuB_Interface
;
1636 /* Store info in packet */
1637 p_add_proto_data(pinfo
->fd
, proto_fp
, 0, p_fp_info
);
1641 /* Fill in an RLC packet info struct and attach it to the packet for the RLC
1643 static void attach_rlc_info(packet_info
*pinfo
, guint32 urnti
, guint8 rbid
, gboolean is_sent
)
1645 /* Only need to set info once per session. */
1646 struct fp_info
*p_fp_info
;
1647 struct rlc_info
*p_rlc_info
= (struct rlc_info
*)p_get_proto_data(pinfo
->fd
, proto_rlc
, 0);
1649 if (p_rlc_info
!= NULL
) {
1653 /* Check that the number of outhdr values looks correct */
1654 if (outhdr_values_found
!= 2) {
1658 /* Allocate structs */
1659 p_rlc_info
= wmem_new(wmem_file_scope(), struct rlc_info
);
1660 p_fp_info
= wmem_new(wmem_file_scope(), struct fp_info
);
1662 /* Fill in struct fields for first (only) PDU in this frame */
1664 /* Urnti. Just use UEId */
1665 p_rlc_info
->urnti
[0] = urnti
;
1667 /* ciphered (off by default) */
1668 p_rlc_info
->ciphered
[0] = FALSE
;
1670 /* deciphered (off by default) */
1671 p_rlc_info
->deciphered
[0] = FALSE
;
1674 switch (outhdr_values
[1]) {
1676 p_rlc_info
->mode
[0] = RLC_TM
;
1679 p_rlc_info
->mode
[0] = RLC_UM
;
1682 p_rlc_info
->mode
[0] = RLC_AM
;
1685 p_rlc_info
->mode
[0] = RLC_UM
;
1686 p_rlc_info
->ciphered
[0] = TRUE
;
1689 p_rlc_info
->mode
[0] = RLC_AM
;
1690 p_rlc_info
->ciphered
[0] = TRUE
;
1696 /* rbid. TODO: does this need conversion? */
1697 p_rlc_info
->rbid
[0] = rbid
;
1700 p_rlc_info
->li_size
[0] = (enum rlc_li_size
)outhdr_values
[0];
1702 /* Store info in packet */
1703 p_add_proto_data(pinfo
->fd
, proto_rlc
, 0, p_rlc_info
);
1705 /* Also store minimal FP info consulted by RLC dissector
1706 TODO: Don't really know direction, but use S/R flag to make
1707 logs in same context consistent. Will be correct for NodeB logs,
1708 but RLC dissector seems to not use anyway... */
1709 p_fp_info
->is_uplink
= is_sent
;
1710 p_fp_info
->cur_tb
= 0; /* Always the first/only one */
1711 p_add_proto_data(pinfo
->fd
, proto_fp
, 0, p_fp_info
);
1715 /* Fill in a MAC LTE packet info struct and attach it to the packet for that
1717 static void attach_mac_lte_info(packet_info
*pinfo
)
1719 struct mac_lte_info
*p_mac_lte_info
;
1722 /* Only need to set info once per session. */
1723 p_mac_lte_info
= get_mac_lte_proto_data(pinfo
);
1724 if (p_mac_lte_info
!= NULL
) {
1728 /* Allocate & zero struct */
1729 p_mac_lte_info
= wmem_new0(wmem_file_scope(), struct mac_lte_info
);
1731 /* Populate the struct from outhdr values */
1732 p_mac_lte_info
->crcStatusValid
= crc_fail
; /* not set yet */
1734 p_mac_lte_info
->radioType
= outhdr_values
[i
++] + 1;
1735 p_mac_lte_info
->rntiType
= outhdr_values
[i
++];
1736 p_mac_lte_info
->direction
= outhdr_values
[i
++];
1737 /* Set these extra PHY present flags to FALSE by default */
1738 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
1739 p_mac_lte_info
->detailed_phy_info
.ul_info
.present
= FALSE
;
1742 p_mac_lte_info
->detailed_phy_info
.dl_info
.present
= FALSE
;
1745 p_mac_lte_info
->subframeNumber
= outhdr_values
[i
++];
1746 p_mac_lte_info
->isPredefinedData
= outhdr_values
[i
++];
1747 p_mac_lte_info
->rnti
= outhdr_values
[i
++];
1748 p_mac_lte_info
->ueid
= outhdr_values
[i
++];
1749 p_mac_lte_info
->length
= outhdr_values
[i
++];
1750 if (outhdr_values_found
> 8) {
1751 p_mac_lte_info
->reTxCount
= outhdr_values
[i
++];
1753 if (outhdr_values_found
== 10) {
1754 /* CRC only valid for Downlink */
1755 if (p_mac_lte_info
->direction
== DIRECTION_DOWNLINK
) {
1756 p_mac_lte_info
->crcStatusValid
= crc_success
;
1757 p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
= (mac_lte_crc_status
)outhdr_values
[i
++];
1764 p_mac_lte_info
->dl_retx
= dl_retx_unknown
;
1766 if (outhdr_values_found
> 10) {
1767 /* Extra PHY parameters */
1768 if (p_mac_lte_info
->direction
== DIRECTION_DOWNLINK
) {
1769 p_mac_lte_info
->detailed_phy_info
.dl_info
.present
= outhdr_values
[i
++];
1770 p_mac_lte_info
->detailed_phy_info
.dl_info
.dci_format
= outhdr_values
[i
++];
1771 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_allocation_type
= outhdr_values
[i
++];
1772 p_mac_lte_info
->detailed_phy_info
.dl_info
.aggregation_level
= outhdr_values
[i
++];
1773 p_mac_lte_info
->detailed_phy_info
.dl_info
.mcs_index
= outhdr_values
[i
++];
1774 p_mac_lte_info
->detailed_phy_info
.dl_info
.redundancy_version_index
= outhdr_values
[i
++];
1775 if (outhdr_values
[i
++]) {
1776 p_mac_lte_info
->dl_retx
= dl_retx_yes
;
1779 p_mac_lte_info
->dl_retx
= dl_retx_no
;
1781 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_block_length
= outhdr_values
[i
++];
1782 p_mac_lte_info
->crcStatusValid
= crc_success
;
1783 p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
= (mac_lte_crc_status
)outhdr_values
[i
++];
1784 if (outhdr_values_found
> 18) {
1785 p_mac_lte_info
->detailed_phy_info
.dl_info
.harq_id
= outhdr_values
[i
++];
1786 p_mac_lte_info
->detailed_phy_info
.dl_info
.ndi
= outhdr_values
[i
++];
1788 if (outhdr_values_found
> 20) {
1789 p_mac_lte_info
->detailed_phy_info
.dl_info
.transport_block
= outhdr_values
[i
++];
1794 p_mac_lte_info
->detailed_phy_info
.ul_info
.present
= outhdr_values
[i
++];
1795 p_mac_lte_info
->detailed_phy_info
.ul_info
.modulation_type
= outhdr_values
[i
++];
1796 p_mac_lte_info
->detailed_phy_info
.ul_info
.tbs_index
= outhdr_values
[i
++];
1797 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_length
= outhdr_values
[i
++];
1798 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_start
= outhdr_values
[i
++];
1799 /* Skip retx flag */
1802 if (outhdr_values_found
== 16) {
1803 p_mac_lte_info
->subframeNumberOfGrantPresent
= TRUE
;
1804 p_mac_lte_info
->subframeNumberOfGrant
= outhdr_values
[i
++];
1806 if (outhdr_values_found
> 16) {
1807 p_mac_lte_info
->detailed_phy_info
.ul_info
.harq_id
= outhdr_values
[i
++];
1808 p_mac_lte_info
->detailed_phy_info
.ul_info
.ndi
= outhdr_values
[i
++];
1810 p_mac_lte_info
->subframeNumberOfGrantPresent
= TRUE
;
1811 p_mac_lte_info
->subframeNumberOfGrant
= outhdr_values
[i
++];
1816 /* System frame number */
1817 if (i
< outhdr_values_found
) {
1818 p_mac_lte_info
->sysframeNumber
= outhdr_values
[i
++];
1821 if ((p_mac_lte_info
->direction
== DIRECTION_UPLINK
) &&
1822 (i
< outhdr_values_found
)) {
1824 p_mac_lte_info
->isPHICHNACK
= outhdr_values
[i
];
1827 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
1828 /* R10 parameter not set yet */
1829 p_mac_lte_info
->isExtendedBSRSizes
= FALSE
;
1832 /* Store info in packet */
1833 set_mac_lte_proto_data(pinfo
, p_mac_lte_info
);
1837 /* Fill in a RLC LTE packet info struct and attach it to the packet for that
1839 static void attach_rlc_lte_info(packet_info
*pinfo
)
1841 struct rlc_lte_info
*p_rlc_lte_info
;
1844 /* Only need to set info once per session. */
1845 p_rlc_lte_info
= (rlc_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_rlc_lte
, 0);
1846 if (p_rlc_lte_info
!= NULL
) {
1850 /* Allocate & zero struct */
1851 p_rlc_lte_info
= wmem_new0(wmem_file_scope(), rlc_lte_info
);
1853 p_rlc_lte_info
->rlcMode
= outhdr_values
[i
++];
1854 p_rlc_lte_info
->direction
= outhdr_values
[i
++];
1855 p_rlc_lte_info
->priority
= outhdr_values
[i
++];
1856 p_rlc_lte_info
->UMSequenceNumberLength
= outhdr_values
[i
++];
1857 p_rlc_lte_info
->channelId
= outhdr_values
[i
++];
1858 p_rlc_lte_info
->channelType
= outhdr_values
[i
++];
1859 p_rlc_lte_info
->ueid
= outhdr_values
[i
++];
1860 p_rlc_lte_info
->pduLength
= outhdr_values
[i
];
1862 /* Store info in packet */
1863 p_add_proto_data(pinfo
->fd
, proto_rlc_lte
, 0, p_rlc_lte_info
);
1866 /* Fill in a PDCP LTE packet info struct and attach it to the packet for the PDCP LTE
1868 static void attach_pdcp_lte_info(packet_info
*pinfo
)
1870 struct pdcp_lte_info
*p_pdcp_lte_info
;
1873 /* Only need to set info once per session. */
1874 p_pdcp_lte_info
= (pdcp_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_pdcp_lte
, 0);
1875 if (p_pdcp_lte_info
!= NULL
) {
1879 /* Allocate & zero struct */
1880 p_pdcp_lte_info
= wmem_new0(wmem_file_scope(), pdcp_lte_info
);
1882 p_pdcp_lte_info
->no_header_pdu
= outhdr_values
[i
++];
1883 p_pdcp_lte_info
->plane
= (enum pdcp_plane
)outhdr_values
[i
++];
1884 if (p_pdcp_lte_info
->plane
!= USER_PLANE
) {
1885 p_pdcp_lte_info
->plane
= SIGNALING_PLANE
;
1887 p_pdcp_lte_info
->seqnum_length
= outhdr_values
[i
++];
1889 p_pdcp_lte_info
->rohc
.rohc_compression
= outhdr_values
[i
++];
1890 p_pdcp_lte_info
->rohc
.rohc_ip_version
= outhdr_values
[i
++];
1891 p_pdcp_lte_info
->rohc
.cid_inclusion_info
= outhdr_values
[i
++];
1892 p_pdcp_lte_info
->rohc
.large_cid_present
= outhdr_values
[i
++];
1893 p_pdcp_lte_info
->rohc
.mode
= (enum rohc_mode
)outhdr_values
[i
++];
1894 p_pdcp_lte_info
->rohc
.rnd
= outhdr_values
[i
++];
1895 p_pdcp_lte_info
->rohc
.udp_checksum_present
= outhdr_values
[i
++];
1896 p_pdcp_lte_info
->rohc
.profile
= outhdr_values
[i
];
1898 /* Remaining 2 (fixed) fields are ah_length and gre_checksum */
1900 /* Store info in packet */
1901 p_add_proto_data(pinfo
->fd
, proto_pdcp_lte
, 0, p_pdcp_lte_info
);
1905 /* Attempt to show tty (raw character messages) as text lines. */
1906 static void dissect_tty_lines(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1909 proto_tree
*tty_tree
;
1913 /* Create tty tree. */
1914 ti
= proto_tree_add_item(tree
, hf_catapult_dct2000_tty
, tvb
, offset
, -1, ENC_NA
);
1915 tty_tree
= proto_item_add_subtree(ti
, ett_catapult_dct2000_tty
);
1917 /* Show the tty lines one at a time. */
1918 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1919 /* Find the end of the line. */
1920 int linelen
= tvb_find_line_end_unquoted(tvb
, offset
, -1, &next_offset
);
1922 /* Extract & add the string. */
1923 char *string
= (char*)tvb_get_string(wmem_packet_scope(), tvb
, offset
, linelen
);
1924 if (isascii(string
[0])) {
1925 /* If looks printable treat as string... */
1926 proto_tree_add_string_format(tty_tree
, hf_catapult_dct2000_tty_line
,
1932 /* Otherwise show as $hex */
1935 int tty_string_length
= tvb_length_remaining(tvb
, offset
);
1936 int hex_string_length
= 1+(2*tty_string_length
)+1;
1937 hex_string
= (char *)wmem_alloc(wmem_packet_scope(), hex_string_length
);
1939 idx
= g_snprintf(hex_string
, hex_string_length
, "$");
1941 /* Write hex out to new string */
1942 for (n
=0; n
< tty_string_length
; n
++) {
1943 idx
+= g_snprintf(hex_string
+idx
, 3, "%02x",
1944 tvb_get_guint8(tvb
, offset
+n
));
1946 string
= hex_string
;
1950 /* Show first line in info column */
1952 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "tty (%s", string
);
1953 proto_item_append_text(ti
, " (%s)", string
);
1956 /* Move onto next line. */
1957 offset
= next_offset
;
1960 /* Close off summary of tty message in info column */
1962 col_append_str(pinfo
->cinfo
, COL_INFO
, (lines
> 1) ? "...)" : ")");
1967 /* Scan the log comment looking for notable out-of-band MAC events that should
1968 be sent to the MAC dissector */
1969 static void check_for_oob_mac_lte_events(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tree
,
1972 guint number_of_ues
;
1973 guint ueids
[MAX_SRs
];
1974 guint rntis
[MAX_SRs
];
1976 guint rach_attempt_number
;
1978 mac_lte_oob_event oob_event
;
1979 struct mac_lte_info
*p_mac_lte_info
;
1980 tvbuff_t
*mac_lte_tvb
= NULL
;
1983 /* Look for strings matching expected formats */
1984 if (sscanf(string
, ">> RACH Preamble Request[UE = %u] [RAPID = %u] [Attempt = %u]",
1985 &ueids
[0], &rapid
, &rach_attempt_number
) == 3) {
1986 oob_event
= ltemac_send_preamble
;
1989 if (sscanf(string
, ">> Schedule Requests (%u) [UE=%u][RNTI=%u]",
1990 &number_of_ues
, &ueids
[0], &rntis
[0]) == 3) {
1991 const char *current_position
;
1993 /* Newer, multi-UE format */
1994 oob_event
= ltemac_send_sr
;
1996 /* Parse other ueid/rnti pairs */
1997 number_of_ues
= MIN(number_of_ues
, MAX_SRs
);
1998 if (number_of_ues
> 1) {
1999 current_position
= string
;
2001 for (n
=1; n
< number_of_ues
; n
++) {
2003 /* Find the start of the next entry */
2004 current_position
= strstr(current_position
, "] ");
2005 if (current_position
!= NULL
) {
2006 current_position
+= 2;
2009 /* This is an error - shouldn't happen */
2013 /* Read this entry */
2014 if (sscanf(current_position
, "[UE=%u][RNTI=%u]", &ueids
[n
], &rntis
[n
]) != 2) {
2015 /* Assuming that if we can't read this one there is no point trying others */
2023 /* Support both old and new formats of SR failure */
2024 if ((sscanf(string
, ">> INFO (inst %u) MAC: [UE = %u] SR failed (CRNTI=%u)",
2025 &temp
, &ueids
[0], &rntis
[0]) == 3) ||
2026 (sscanf(string
, ">> INFO MAC: SR failed for UE %u (CRNTI=%u",
2027 &ueids
[0], &rntis
[0]) == 2))
2029 oob_event
= ltemac_sr_failure
;
2032 /* No events found */
2036 /* We have an event */
2037 /* Only need to set info once per session. */
2038 p_mac_lte_info
= get_mac_lte_proto_data(pinfo
);
2039 if (p_mac_lte_info
== NULL
) {
2041 /* Allocate & zero struct */
2042 p_mac_lte_info
= wmem_new0(wmem_file_scope(), mac_lte_info
);
2044 /* This indicates to MAC dissector that it has an oob event */
2045 p_mac_lte_info
->length
= 0;
2047 switch (oob_event
) {
2048 case ltemac_send_preamble
:
2049 p_mac_lte_info
->ueid
= ueids
[0];
2050 p_mac_lte_info
->rapid
= rapid
;
2051 p_mac_lte_info
->rach_attempt_number
= rach_attempt_number
;
2052 p_mac_lte_info
->direction
= DIRECTION_UPLINK
;
2054 case ltemac_send_sr
:
2055 for (n
=0; n
< number_of_ues
; n
++) {
2056 p_mac_lte_info
->oob_ueid
[n
] = ueids
[n
];
2057 p_mac_lte_info
->oob_rnti
[n
] = rntis
[n
];
2059 p_mac_lte_info
->number_of_srs
= number_of_ues
;
2060 p_mac_lte_info
->direction
= DIRECTION_UPLINK
;
2062 case ltemac_sr_failure
:
2063 p_mac_lte_info
->rnti
= rntis
[0];
2064 p_mac_lte_info
->ueid
= ueids
[0];
2065 p_mac_lte_info
->direction
= DIRECTION_DOWNLINK
;
2069 p_mac_lte_info
->radioType
= FDD_RADIO
; /* TODO: will be the same as rest of log... */
2070 p_mac_lte_info
->oob_event
= oob_event
;
2072 /* Store info in packet */
2073 set_mac_lte_proto_data(pinfo
, p_mac_lte_info
);
2076 /* Call MAC dissector */
2077 mac_lte_tvb
= tvb_new_subset(tvb
, 0, 0, 0);
2078 call_dissector_only(mac_lte_handle
, mac_lte_tvb
, pinfo
, tree
, NULL
);
2082 /*****************************************/
2083 /* Main dissection function. */
2084 /*****************************************/
2086 dissect_catapult_dct2000(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2088 proto_tree
*dct2000_tree
= NULL
;
2089 proto_item
*ti
= NULL
;
2091 gint context_length
;
2092 const char *context_name
;
2094 gint protocol_length
;
2095 gint timestamp_length
;
2096 const char *timestamp_string
;
2097 gint variant_length
;
2098 const char *variant_string
;
2100 const char *outhdr_string
;
2104 dissector_handle_t protocol_handle
= 0;
2105 dissector_handle_t heur_protocol_handle
= 0;
2106 int sub_dissector_result
= 0;
2107 const char *protocol_name
;
2108 gboolean is_comment
, is_sprint
= FALSE
;
2111 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCT2000");
2114 col_clear(pinfo
->cinfo
, COL_INFO
);
2116 /* Create root (protocol) tree. */
2118 ti
= proto_tree_add_item(tree
, proto_catapult_dct2000
, tvb
, offset
, -1, ENC_NA
);
2119 dct2000_tree
= proto_item_add_subtree(ti
, ett_catapult_dct2000
);
2122 /*********************************************************************/
2123 /* Note that these are the fields of the stub header as written out */
2124 /* by the wiretap module */
2127 context_name
= tvb_get_const_stringz(tvb
, offset
, &context_length
);
2129 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_context
, tvb
,
2130 offset
, context_length
, ENC_ASCII
|ENC_NA
);
2132 offset
+= context_length
;
2134 /* Context port number */
2135 port_number
= tvb_get_guint8(tvb
, offset
);
2137 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_port_number
, tvb
,
2138 offset
, 1, ENC_BIG_ENDIAN
);
2142 /* Timestamp in file */
2143 timestamp_string
= tvb_get_const_stringz(tvb
, offset
, ×tamp_length
);
2145 /* TODO: this is *very* slow, but float version adds trailing digits when
2146 displayed as a custom column... */
2147 proto_tree_add_double(dct2000_tree
, hf_catapult_dct2000_timestamp
, tvb
,
2148 offset
, timestamp_length
,
2149 atof(timestamp_string
));
2151 offset
+= timestamp_length
;
2154 /* DCT2000 protocol name */
2155 protocol_name
= tvb_get_const_stringz(tvb
, offset
, &protocol_length
);
2157 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_protocol
, tvb
,
2158 offset
, protocol_length
, ENC_ASCII
|ENC_NA
);
2160 is_comment
= (strcmp(protocol_name
, "comment") == 0);
2162 is_sprint
= (strcmp(protocol_name
, "sprint") == 0);
2164 offset
+= protocol_length
;
2167 /* Protocol Variant */
2168 variant_string
= tvb_get_const_stringz(tvb
, offset
, &variant_length
);
2169 if (!is_comment
&& !is_sprint
) {
2170 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_variant
, tvb
,
2171 offset
, variant_length
, ENC_ASCII
|ENC_NA
);
2173 offset
+= variant_length
;
2175 /* Outhdr (shown as string) */
2176 outhdr_string
= tvb_get_const_stringz(tvb
, offset
, &outhdr_length
);
2177 if (!is_comment
&& !is_sprint
&& (outhdr_length
> 1)) {
2178 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_outhdr
, tvb
,
2179 offset
, outhdr_length
, ENC_ASCII
|ENC_NA
);
2181 offset
+= outhdr_length
;
2185 direction
= tvb_get_guint8(tvb
, offset
);
2187 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_direction
, tvb
,
2188 offset
, 1, ENC_BIG_ENDIAN
);
2192 /* Read frame encapsulation set by wiretap */
2193 if (!is_comment
&& !is_sprint
) {
2194 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_encap
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2196 encap
= tvb_get_guint8(tvb
, offset
);
2199 /* Add useful details to protocol tree label */
2200 proto_item_append_text(ti
, " context=%s.%u t=%s %c prot=%s (v=%s)",
2204 (direction
== 0) ? 'S' : 'R',
2210 /* FP protocols need info from outhdr attached */
2211 if ((strcmp(protocol_name
, "fp") == 0) ||
2212 (strncmp(protocol_name
, "fp_r", 4) == 0) ||
2213 (strcmp(protocol_name
, "fpiur_r5") == 0)) {
2215 parse_outhdr_string(outhdr_string
, outhdr_length
);
2216 attach_fp_info(pinfo
, direction
, protocol_name
, atoi(variant_string
));
2219 /* RLC protocols need info from outhdr attached */
2220 else if ((strcmp(protocol_name
, "rlc") == 0) ||
2221 (strcmp(protocol_name
, "rlc_r4") == 0) ||
2222 (strcmp(protocol_name
, "rlc_r5") == 0) ||
2223 (strcmp(protocol_name
, "rlc_r6") == 0) ||
2224 (strcmp(protocol_name
, "rlc_r7") == 0) ||
2225 (strcmp(protocol_name
, "rlc_r8") == 0) ||
2226 (strcmp(protocol_name
, "rlc_r9") == 0)) {
2228 parse_outhdr_string(outhdr_string
, outhdr_length
);
2229 /* Can't attach info yet. Need combination of outheader values
2230 and fields parsed from primitive header... */
2233 /* LTE MAC needs info attached */
2234 else if ((strcmp(protocol_name
, "mac_r8_lte") == 0) ||
2235 (strcmp(protocol_name
, "mac_r9_lte") == 0) ||
2236 (strcmp(protocol_name
, "mac_r10_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 (strcmp(protocol_name
, "rlc_r10_lte") == 0)) {
2245 parse_outhdr_string(outhdr_string
, outhdr_length
);
2246 attach_rlc_lte_info(pinfo
);
2249 /* LTE PDCP needs info attached */
2250 else if ((strcmp(protocol_name
, "pdcp_r8_lte") == 0) ||
2251 (strcmp(protocol_name
, "pdcp_r9_lte") == 0) ||
2252 (strcmp(protocol_name
, "pdcp_r10_lte") == 0)) {
2253 parse_outhdr_string(outhdr_string
, outhdr_length
);
2254 attach_pdcp_lte_info(pinfo
);
2258 else if ((strcmp(protocol_name
, "nas_rrc_r8_lte") == 0) ||
2259 (strcmp(protocol_name
, "nas_rrc_r9_lte") == 0) ||
2260 (strcmp(protocol_name
, "nas_rrc_r10_lte") == 0)) {
2261 gboolean nas_body_found
= TRUE
;
2262 guint8 opcode
= tvb_get_guint8(tvb
, offset
);
2263 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_nas_rrc_opcode
,
2264 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
2266 offset
++; /* Skip overall length */
2269 case LTE_NAS_RRC_DATA_IND
:
2270 case LTE_NAS_RRC_DATA_REQ
:
2273 offset
+= 2; /* 2 wasted bytes of UEId*/
2274 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
,
2275 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2278 case LTE_NAS_RRC_ESTABLISH_REQ
:
2281 offset
+= 2; /* 2 wasted bytes of UEId*/
2282 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
,
2283 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2286 /* Establish cause. TODO: value_string */
2287 offset
+= 2; /* tag + length */
2288 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_nas_rrc_establish_cause
,
2289 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
2291 /* Priority. TODO: Vals are low | high */
2292 offset
+= 2; /* tag + length */
2293 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_nas_rrc_priority
,
2294 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
2296 case LTE_NAS_RRC_RELEASE_IND
:
2299 offset
+= 2; /* 2 wasted bytes of UEId*/
2300 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_ueid
,
2301 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2304 /* Release cause. TODO: value_string */
2305 offset
+= 2; /* tag + length */
2306 proto_tree_add_item(tree
, hf_catapult_dct2000_lte_nas_rrc_release_cause
,
2307 tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
2311 nas_body_found
= FALSE
;
2315 /* Look up dissector if if looks right */
2316 if (nas_body_found
) {
2317 offset
+= 2; /* L3 tag + len */
2318 protocol_handle
= find_dissector("nas-eps");
2322 /* Note that the first item of pinfo->pseudo_header->dct2000 will contain
2323 the pseudo-header needed (in some cases) by the Wireshark dissector that
2324 this packet data will be handed off to. */
2327 /***********************************************************************/
2328 /* Now hand off to the dissector of intended packet encapsulation type */
2330 /* Get protocol handle, and set p2p_dir where necessary.
2331 (packet-frame.c won't copy it from pseudo-header because it doesn't
2332 know about Catapult DCT2000 encap type...)
2335 case WTAP_ENCAP_RAW_IP
:
2336 protocol_handle
= find_dissector("ip");
2338 /* TODO: this doesn't work yet.
2339 pseudo_header isn't copied from wtap to pinfo... */
2340 if ((pinfo
->pseudo_header
!= NULL
) &&
2341 (pinfo
->pseudo_header
->dct2000
.inner_pseudo_header
.pdcp
.ueid
!= 0)) {
2345 /* Add PDCP thread info as generated fields */
2346 ti
= proto_tree_add_uint(dct2000_tree
, hf_catapult_dct2000_lte_ueid
, tvb
, 0, 0,
2347 pinfo
->pseudo_header
->dct2000
.inner_pseudo_header
.pdcp
.ueid
);
2348 PROTO_ITEM_SET_GENERATED(ti
);
2349 ti
= proto_tree_add_uint(dct2000_tree
, hf_catapult_dct2000_lte_drbid
, tvb
, 0, 0,
2350 pinfo
->pseudo_header
->dct2000
.inner_pseudo_header
.pdcp
.drbid
);
2351 PROTO_ITEM_SET_GENERATED(ti
);
2355 case WTAP_ENCAP_ETHERNET
:
2356 protocol_handle
= find_dissector("eth_withoutfcs");
2358 case WTAP_ENCAP_ISDN
:
2359 protocol_handle
= find_dissector("lapd");
2360 pinfo
->p2p_dir
= pinfo
->pseudo_header
->isdn
.uton
;
2362 case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED
:
2363 protocol_handle
= find_dissector("atm_untruncated");
2365 case WTAP_ENCAP_PPP
:
2366 protocol_handle
= find_dissector("ppp_hdlc");
2367 pinfo
->p2p_dir
= pinfo
->pseudo_header
->p2p
.sent
;
2369 case DCT2000_ENCAP_SSCOP
:
2370 protocol_handle
= find_dissector("sscop");
2372 case WTAP_ENCAP_FRELAY
:
2373 protocol_handle
= find_dissector("fr");
2375 case DCT2000_ENCAP_MTP2
:
2376 protocol_handle
= find_dissector("mtp2");
2378 case DCT2000_ENCAP_NBAP
:
2379 protocol_handle
= find_dissector("nbap");
2382 case DCT2000_ENCAP_UNHANDLED
:
2383 /**********************************************************/
2384 /* The wiretap module wasn't able to set an encapsulation */
2385 /* type, but it may still be possible to dissect the data */
2386 /* if we know about the protocol or if we can recognise */
2387 /* and parse or skip a primitive header */
2388 /**********************************************************/
2390 /* Show context.port in src or dest column as appropriate */
2391 if (direction
== 0) {
2392 col_add_fstr(pinfo
->cinfo
, COL_DEF_SRC
,
2398 if (direction
== 1) {
2399 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
,
2406 /**************************************************************************/
2407 /* These protocols have no encapsulation type, just look them up directly */
2409 if ((strcmp(protocol_name
, "rlc") == 0) ||
2410 (strcmp(protocol_name
, "rlc_r4") == 0) ||
2411 (strcmp(protocol_name
, "rlc_r5") == 0) ||
2412 (strcmp(protocol_name
, "rlc_r6") == 0) ||
2413 (strcmp(protocol_name
, "rlc_r7") == 0) ||
2414 (strcmp(protocol_name
, "rlc_r8") == 0) ||
2415 (strcmp(protocol_name
, "rlc_r9") == 0)) {
2417 dissect_rlc_umts(tvb
, offset
, pinfo
, tree
, direction
);
2422 if ((strcmp(protocol_name
, "mac_r8_lte") == 0) ||
2423 (strcmp(protocol_name
, "mac_r9_lte") == 0) ||
2424 (strcmp(protocol_name
, "mac_r10_lte") == 0)) {
2425 protocol_handle
= mac_lte_handle
;
2429 if ((strcmp(protocol_name
, "rlc_r8_lte") == 0) ||
2430 (strcmp(protocol_name
, "rlc_r9_lte") == 0) ||
2431 (strcmp(protocol_name
, "rlc_r10_lte") == 0)) {
2432 protocol_handle
= rlc_lte_handle
;
2436 if ((strcmp(protocol_name
, "pdcp_r8_lte") == 0) ||
2437 (strcmp(protocol_name
, "pdcp_r9_lte") == 0) ||
2438 (strcmp(protocol_name
, "pdcp_r10_lte") == 0)) {
2439 /* Dissect proprietary header, then pass remainder to PDCP */
2440 dissect_pdcp_lte(tvb
, offset
, pinfo
, tree
);
2445 /* Work with generic XML protocol. */
2447 if (strcmp(protocol_name
, "xml") == 0) {
2448 protocol_handle
= find_dissector("xml");
2452 /* Attempt to show tty messages as raw text */
2454 if (strcmp(protocol_name
, "tty") == 0) {
2455 dissect_tty_lines(tvb
, pinfo
, dct2000_tree
, offset
);
2460 if (strcmp(protocol_name
, "sipprim") == 0) {
2461 protocol_handle
= find_dissector("sipprim");
2465 if (strcmp(protocol_name
, "comment") == 0) {
2466 /* Extract & add the string. */
2467 proto_item
*string_ti
;
2468 char *string
= (char*)tvb_get_string(wmem_packet_scope(), tvb
, offset
, tvb_length_remaining(tvb
, offset
));
2470 /* Show comment string */
2471 string_ti
= proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_comment
, tvb
,
2472 offset
, -1, ENC_ASCII
|ENC_NA
);
2473 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", string
);
2475 if (catapult_dct2000_dissect_mac_lte_oob_messages
) {
2476 /* Look into string for out-of-band MAC events, such as SRReq, SRInd */
2477 check_for_oob_mac_lte_events(pinfo
, tvb
, tree
, string
);
2480 /* Look for and flag generic error messages */
2481 if (strncmp(string
, ">> ERR", 6) == 0) {
2482 proto_item
*error_ti
= proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_error_comment
, tvb
,
2483 offset
, -1, ENC_NA
);
2484 PROTO_ITEM_SET_GENERATED(error_ti
);
2485 expert_add_info_format(pinfo
, string_ti
, &ei_catapult_dct2000_error_comment_expert
,
2493 if (strcmp(protocol_name
, "sprint") == 0) {
2494 /* Extract & add the string. */
2495 char *string
= (char*)tvb_get_string(wmem_packet_scope(), tvb
, offset
, tvb_length_remaining(tvb
, offset
));
2497 /* Show sprint string */
2498 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_sprint
, tvb
,
2499 offset
, -1, ENC_ASCII
|ENC_NA
);
2500 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", string
);
2507 if (catapult_dct2000_dissect_lte_rrc
&&
2508 ((strcmp(protocol_name
, "rrc_r8_lte") == 0) ||
2509 (strcmp(protocol_name
, "rrcpdcpprim_r8_lte") == 0) ||
2510 (strcmp(protocol_name
, "rrc_r9_lte") == 0) ||
2511 (strcmp(protocol_name
, "rrcpdcpprim_r9_lte") == 0) ||
2512 (strcmp(protocol_name
, "rrc_r10_lte") == 0))) {
2514 /* Dissect proprietary header, then pass remainder
2515 to RRC (depending upon direction and channel type) */
2516 dissect_rrc_lte(tvb
, offset
, pinfo
, tree
);
2521 if ((strcmp(protocol_name
, "ccpri_r8_lte") == 0) ||
2522 (strcmp(protocol_name
, "ccpri_r9_lte") == 0)) {
2524 /* Dissect proprietary header, then pass remainder to lapb */
2525 dissect_ccpri_lte(tvb
, offset
, pinfo
, tree
);
2529 /* Many DCT2000 protocols have at least one IPPrim variant. If the
2530 protocol name can be matched to a dissector, try to find the
2531 UDP/TCP data inside and dissect it.
2534 if (!protocol_handle
&& catapult_dct2000_try_ipprim_heuristic
) {
2535 guint32 source_addr_offset
= 0, dest_addr_offset
= 0;
2536 guint8 source_addr_length
= 0, dest_addr_length
= 0;
2537 guint32 source_port_offset
= 0, dest_port_offset
= 0;
2538 port_type type_of_port
= PT_NONE
;
2539 guint16 conn_id_offset
= 0;
2540 int offset_before_ipprim_header
= offset
;
2542 /* Will give up if couldn't match protocol anyway... */
2543 heur_protocol_handle
= look_for_dissector(protocol_name
);
2544 if ((heur_protocol_handle
!= 0) &&
2545 find_ipprim_data_offset(tvb
, &offset
, direction
,
2546 &source_addr_offset
, &source_addr_length
,
2547 &dest_addr_offset
, &dest_addr_length
,
2548 &source_port_offset
, &dest_port_offset
,
2552 proto_tree
*ipprim_tree
;
2553 proto_item
*ipprim_ti
;
2554 struct e_in6_addr sourcev6
, destv6
;
2556 /* Fetch IPv6 addresses */
2557 if (source_addr_length
!= 4) {
2558 tvb_get_ipv6(tvb
, source_addr_offset
, &sourcev6
);
2560 if (dest_addr_length
!= 4) {
2561 tvb_get_ipv6(tvb
, dest_addr_offset
, &destv6
);
2565 /* Will use this dissector then. */
2566 protocol_handle
= heur_protocol_handle
;
2568 /* Add address parameters to tree */
2569 /* Unfortunately can't automatically create a conversation filter for this...
2570 I *could* create a fake IP header from these details, but then it would be tricky
2571 to get the FP dissector called as it has no well-known ports or heuristics... */
2572 ipprim_ti
= proto_tree_add_string_format(dct2000_tree
, hf_catapult_dct2000_ipprim_addresses
,
2573 tvb
, offset_before_ipprim_header
, 0,
2574 "", "IPPrim transport (%s): %s:%u -> %s:%u",
2575 (type_of_port
== PT_UDP
) ? "UDP" : "TCP",
2576 (source_addr_offset
) ?
2577 ((source_addr_length
== 4) ?
2578 get_hostname(tvb_get_ipv4(tvb
, source_addr_offset
)) :
2579 get_hostname6(&sourcev6
)
2582 (source_port_offset
) ?
2583 tvb_get_ntohs(tvb
, source_port_offset
) :
2585 (dest_addr_offset
) ?
2586 ((source_addr_length
== 4) ?
2587 get_hostname(tvb_get_ipv4(tvb
, dest_addr_offset
)) :
2588 get_hostname6(&destv6
)
2591 (dest_port_offset
) ?
2592 tvb_get_ntohs(tvb
, dest_port_offset
) :
2594 if ((type_of_port
== PT_TCP
) && (conn_id_offset
!= 0)) {
2595 proto_item_append_text(ipprim_ti
, " (conn_id=%u)", tvb_get_ntohs(tvb
, conn_id_offset
));
2598 /* Add these IPPRIM fields inside an IPPRIM subtree */
2599 ipprim_tree
= proto_item_add_subtree(ipprim_ti
, ett_catapult_dct2000_ipprim
);
2601 /* Try to add right stuff to pinfo so conversation stuff works... */
2602 pinfo
->ptype
= type_of_port
;
2603 switch (type_of_port
) {
2605 pinfo
->ipproto
= IP_PROTO_UDP
;
2608 pinfo
->ipproto
= IP_PROTO_TCP
;
2611 pinfo
->ipproto
= IP_PROTO_NONE
;
2614 /* Add addresses & ports into ipprim tree.
2615 Also set address info in pinfo for conversations... */
2616 if (source_addr_offset
!= 0) {
2617 proto_item
*addr_ti
;
2619 TVB_SET_ADDRESS(&pinfo
->net_src
,
2620 (source_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2621 tvb
, source_addr_offset
, source_addr_length
);
2622 TVB_SET_ADDRESS(&pinfo
->src
,
2623 (source_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2624 tvb
, source_addr_offset
, source_addr_length
);
2626 proto_tree_add_item(ipprim_tree
,
2627 (source_addr_length
== 4) ?
2628 hf_catapult_dct2000_ipprim_src_addr_v4
:
2629 hf_catapult_dct2000_ipprim_src_addr_v6
,
2630 tvb
, source_addr_offset
, source_addr_length
,
2631 (source_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2633 /* Add hidden item for "side-less" addr */
2634 addr_ti
= proto_tree_add_item(ipprim_tree
,
2635 (source_addr_length
== 4) ?
2636 hf_catapult_dct2000_ipprim_addr_v4
:
2637 hf_catapult_dct2000_ipprim_addr_v6
,
2638 tvb
, source_addr_offset
, source_addr_length
,
2639 (source_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2640 PROTO_ITEM_SET_HIDDEN(addr_ti
);
2642 if (source_port_offset
!= 0) {
2643 proto_item
*port_ti
;
2645 pinfo
->srcport
= tvb_get_ntohs(tvb
, source_port_offset
);
2647 proto_tree_add_item(ipprim_tree
,
2648 (type_of_port
== PT_UDP
) ?
2649 hf_catapult_dct2000_ipprim_udp_src_port
:
2650 hf_catapult_dct2000_ipprim_tcp_src_port
,
2651 tvb
, source_port_offset
, 2, ENC_BIG_ENDIAN
);
2652 port_ti
= proto_tree_add_item(ipprim_tree
,
2653 (type_of_port
== PT_UDP
) ?
2654 hf_catapult_dct2000_ipprim_udp_port
:
2655 hf_catapult_dct2000_ipprim_tcp_port
,
2656 tvb
, source_port_offset
, 2, ENC_BIG_ENDIAN
);
2657 PROTO_ITEM_SET_HIDDEN(port_ti
);
2659 if (dest_addr_offset
!= 0) {
2660 proto_item
*addr_ti
;
2662 TVB_SET_ADDRESS(&pinfo
->net_dst
,
2663 (dest_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2664 tvb
, dest_addr_offset
, dest_addr_length
);
2665 TVB_SET_ADDRESS(&pinfo
->dst
,
2666 (dest_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2667 tvb
, dest_addr_offset
, dest_addr_length
);
2668 proto_tree_add_item(ipprim_tree
,
2669 (dest_addr_length
== 4) ?
2670 hf_catapult_dct2000_ipprim_dst_addr_v4
:
2671 hf_catapult_dct2000_ipprim_dst_addr_v6
,
2672 tvb
, dest_addr_offset
, dest_addr_length
,
2673 (dest_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2675 /* Add hidden item for "side-less" addr */
2676 addr_ti
= proto_tree_add_item(ipprim_tree
,
2677 (dest_addr_length
== 4) ?
2678 hf_catapult_dct2000_ipprim_addr_v4
:
2679 hf_catapult_dct2000_ipprim_addr_v6
,
2680 tvb
, dest_addr_offset
, dest_addr_length
,
2681 (dest_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2682 PROTO_ITEM_SET_HIDDEN(addr_ti
);
2684 if (dest_port_offset
!= 0) {
2685 proto_item
*port_ti
;
2687 pinfo
->destport
= tvb_get_ntohs(tvb
, dest_port_offset
);
2689 proto_tree_add_item(ipprim_tree
,
2690 (type_of_port
== PT_UDP
) ?
2691 hf_catapult_dct2000_ipprim_udp_dst_port
:
2692 hf_catapult_dct2000_ipprim_tcp_dst_port
,
2693 tvb
, dest_port_offset
, 2, ENC_BIG_ENDIAN
);
2694 port_ti
= proto_tree_add_item(ipprim_tree
,
2695 (type_of_port
== PT_UDP
) ?
2696 hf_catapult_dct2000_ipprim_udp_port
:
2697 hf_catapult_dct2000_ipprim_tcp_port
,
2698 tvb
, dest_port_offset
, 2, ENC_BIG_ENDIAN
);
2699 PROTO_ITEM_SET_HIDDEN(port_ti
);
2701 if (conn_id_offset
!= 0) {
2702 proto_tree_add_item(ipprim_tree
,
2703 hf_catapult_dct2000_ipprim_conn_id
,
2704 tvb
, conn_id_offset
, 2, ENC_BIG_ENDIAN
);
2708 /* Set source and dest columns now (will be overwriiten if
2709 src and dst IP addresses set) */
2710 if (source_addr_offset
) {
2711 col_append_fstr(pinfo
->cinfo
, COL_DEF_SRC
,
2713 get_hostname(tvb_get_ipv4(tvb
, source_addr_offset
)),
2714 tvb_get_ntohs(tvb
, source_port_offset
));
2716 if (dest_addr_offset
) {
2717 col_append_fstr(pinfo
->cinfo
, COL_DEF_DST
,
2719 get_hostname(tvb_get_ipv4(tvb
, dest_addr_offset
)),
2720 tvb_get_ntohs(tvb
, dest_port_offset
));
2723 /* Set length for IPPrim tree */
2724 proto_item_set_len(ipprim_tree
, offset
- offset_before_ipprim_header
);
2729 /* Try SCTP Prim heuristic if configured to */
2730 if (!protocol_handle
&& catapult_dct2000_try_sctpprim_heuristic
) {
2731 guint32 dest_addr_offset
= 0;
2732 guint16 dest_addr_length
= 0;
2733 guint32 dest_port_offset
= 0;
2734 int offset_before_sctpprim_header
= offset
;
2736 heur_protocol_handle
= look_for_dissector(protocol_name
);
2737 if ((heur_protocol_handle
!= 0) &&
2738 (find_sctpprim_variant1_data_offset(tvb
, &offset
,
2741 &dest_port_offset
) ||
2742 find_sctpprim_variant3_data_offset(tvb
, &offset
,
2745 &dest_port_offset
))) {
2747 proto_tree
*sctpprim_tree
;
2748 proto_item
*ti_local
;
2750 /* Will use this dissector then. */
2751 protocol_handle
= heur_protocol_handle
;
2753 ti_local
= proto_tree_add_string_format(dct2000_tree
, hf_catapult_dct2000_sctpprim_addresses
,
2754 tvb
, offset_before_sctpprim_header
, 0,
2755 "", "SCTPPrim transport: -> %s:%u",
2756 (dest_addr_offset
) ?
2757 ((dest_addr_length
== 4) ?
2758 get_hostname(tvb_get_ipv4(tvb
, dest_addr_offset
)) :
2762 (dest_port_offset
) ?
2763 tvb_get_ntohs(tvb
, dest_port_offset
) :
2766 /* Add these SCTPPRIM fields inside an SCTPPRIM subtree */
2767 sctpprim_tree
= proto_item_add_subtree(ti_local
, ett_catapult_dct2000_sctpprim
);
2769 pinfo
->ipproto
= IP_PROTO_SCTP
;
2771 /* Destination address */
2772 if (dest_addr_offset
!= 0) {
2773 proto_item
*addr_ti
;
2775 TVB_SET_ADDRESS(&pinfo
->net_dst
,
2776 (dest_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2777 tvb
, dest_addr_offset
, dest_addr_length
);
2778 TVB_SET_ADDRESS(&pinfo
->dst
,
2779 (dest_addr_length
== 4) ? AT_IPv4
: AT_IPv6
,
2780 tvb
, dest_addr_offset
, dest_addr_length
);
2781 proto_tree_add_item(sctpprim_tree
,
2782 (dest_addr_length
== 4) ?
2783 hf_catapult_dct2000_sctpprim_dst_addr_v4
:
2784 hf_catapult_dct2000_sctpprim_dst_addr_v6
,
2785 tvb
, dest_addr_offset
, dest_addr_length
,
2786 (dest_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2788 /* Add hidden item for "side-less" addr */
2789 addr_ti
= proto_tree_add_item(sctpprim_tree
,
2790 (dest_addr_length
== 4) ?
2791 hf_catapult_dct2000_sctpprim_addr_v4
:
2792 hf_catapult_dct2000_sctpprim_addr_v6
,
2793 tvb
, dest_addr_offset
, dest_addr_length
,
2794 (dest_addr_length
== 4) ? ENC_BIG_ENDIAN
: ENC_NA
);
2795 PROTO_ITEM_SET_HIDDEN(addr_ti
);
2798 if (dest_port_offset
!= 0) {
2799 pinfo
->destport
= tvb_get_ntohs(tvb
, dest_port_offset
);
2801 proto_tree_add_item(sctpprim_tree
,
2802 hf_catapult_dct2000_sctpprim_dst_port
,
2803 tvb
, dest_port_offset
, 2, ENC_BIG_ENDIAN
);
2806 /* Set length for SCTPPrim tree */
2807 proto_item_set_len(sctpprim_tree
, offset
- offset_before_sctpprim_header
);
2811 /* Last chance: is there a (private) registered protocol of the form
2812 "dct2000.protocol" ? */
2813 if (protocol_handle
== 0) {
2814 /* TODO: only look inside preference? */
2815 char dotted_protocol_name
[64+128];
2816 g_snprintf(dotted_protocol_name
, 64+128, "dct2000.%s", protocol_name
);
2817 protocol_handle
= find_dissector(dotted_protocol_name
);
2823 /* !! If get here, there is a mismatch between
2824 this dissector and the wiretap module catapult_dct2000.c !!
2826 DISSECTOR_ASSERT_NOT_REACHED();
2830 /* Set selection length of dct2000 tree */
2831 proto_item_set_len(dct2000_tree
, offset
);
2833 /* Try appropriate dissector, if one has been selected */
2834 if (protocol_handle
!= 0) {
2835 /* Dissect the remainder of the frame using chosen protocol handle */
2836 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2837 sub_dissector_result
= call_dissector_only(protocol_handle
, next_tvb
, pinfo
, tree
, NULL
);
2841 if (protocol_handle
== 0 || sub_dissector_result
== 0) {
2842 /* Could get here because:
2843 - encap is DCT2000_ENCAP_UNHANDLED and we still didn't handle it, OR
2844 - desired protocol is unavailable (probably disabled), OR
2845 - protocol rejected our data
2846 Show remaining bytes as unparsed data */
2847 proto_tree_add_item(dct2000_tree
, hf_catapult_dct2000_unparsed_data
,
2848 tvb
, offset
, -1, ENC_NA
);
2850 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
2851 "Not dissected (context=%s.%u t=%s %c prot=%s (v=%s))",
2855 (direction
== 0) ? 'S' : 'R',
2860 /* Show number of dissected bytes */
2862 proto_item
*ti_local
= proto_tree_add_uint(dct2000_tree
,
2863 hf_catapult_dct2000_dissected_length
,
2864 tvb
, 0, 0, tvb_reported_length(tvb
)-offset
);
2865 PROTO_ITEM_SET_GENERATED(ti_local
);
2872 /******************************************************************************/
2873 /* Associate this protocol with the Catapult DCT2000 file encapsulation type. */
2874 /******************************************************************************/
2875 void proto_reg_handoff_catapult_dct2000(void)
2877 dissector_handle_t catapult_dct2000_handle
= find_dissector("dct2000");
2879 dissector_add_uint("wtap_encap", WTAP_ENCAP_CATAPULT_DCT2000
, catapult_dct2000_handle
);
2881 mac_lte_handle
= find_dissector("mac-lte");
2882 rlc_lte_handle
= find_dissector("rlc-lte");
2883 pdcp_lte_handle
= find_dissector("pdcp-lte");
2886 /****************************************/
2887 /* Register the protocol */
2888 /****************************************/
2889 void proto_register_catapult_dct2000(void)
2891 static hf_register_info hf
[] =
2893 { &hf_catapult_dct2000_context
,
2895 "dct2000.context", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2896 "Context name", HFILL
2899 { &hf_catapult_dct2000_port_number
,
2900 { "Context Port number",
2901 "dct2000.context_port", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2905 { &hf_catapult_dct2000_timestamp
,
2907 "dct2000.timestamp", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
2908 "File timestamp", HFILL
2911 { &hf_catapult_dct2000_protocol
,
2912 { "DCT2000 protocol",
2913 "dct2000.protocol", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2914 "Original (DCT2000) protocol name", HFILL
2917 { &hf_catapult_dct2000_variant
,
2918 { "Protocol variant",
2919 "dct2000.variant", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2920 "DCT2000 protocol variant", HFILL
2923 { &hf_catapult_dct2000_outhdr
,
2925 "dct2000.outhdr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2926 "DCT2000 protocol outhdr", HFILL
2929 { &hf_catapult_dct2000_direction
,
2931 "dct2000.direction", FT_UINT8
, BASE_DEC
, VALS(direction_vals
), 0x0,
2932 "Frame direction (Sent or Received)", HFILL
2935 { &hf_catapult_dct2000_encap
,
2936 { "Wireshark encapsulation",
2937 "dct2000.encapsulation", FT_UINT8
, BASE_DEC
, VALS(encap_vals
), 0x0,
2938 "Wireshark frame encapsulation used", HFILL
2941 { &hf_catapult_dct2000_unparsed_data
,
2942 { "Unparsed protocol data",
2943 "dct2000.unparsed_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2944 "Unparsed DCT2000 protocol data", HFILL
2947 { &hf_catapult_dct2000_comment
,
2949 "dct2000.comment", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2953 { &hf_catapult_dct2000_sprint
,
2955 "dct2000.sprint", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2959 { &hf_catapult_dct2000_error_comment
,
2961 "dct2000.error-comment", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2965 { &hf_catapult_dct2000_dissected_length
,
2966 { "Dissected length",
2967 "dct2000.dissected-length", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2968 "Number of bytes dissected by subdissector(s)", HFILL
2972 { &hf_catapult_dct2000_ipprim_addresses
,
2973 { "IPPrim Addresses",
2974 "dct2000.ipprim", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2978 { &hf_catapult_dct2000_ipprim_src_addr_v4
,
2980 "dct2000.ipprim.src", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
2981 "IPPrim IPv4 Source Address", HFILL
2984 { &hf_catapult_dct2000_ipprim_src_addr_v6
,
2986 "dct2000.ipprim.srcv6", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2987 "IPPrim IPv6 Source Address", HFILL
2990 { &hf_catapult_dct2000_ipprim_dst_addr_v4
,
2991 { "Destination Address",
2992 "dct2000.ipprim.dst", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
2993 "IPPrim IPv4 Destination Address", HFILL
2996 { &hf_catapult_dct2000_ipprim_dst_addr_v6
,
2997 { "Destination Address",
2998 "dct2000.ipprim.dstv6", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2999 "IPPrim IPv6 Destination Address", HFILL
3002 { &hf_catapult_dct2000_ipprim_addr_v4
,
3004 "dct2000.ipprim.addr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
3005 "IPPrim IPv4 Address", HFILL
3008 { &hf_catapult_dct2000_ipprim_addr_v6
,
3010 "dct2000.ipprim.addrv6", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
3011 "IPPrim IPv6 Address", HFILL
3014 { &hf_catapult_dct2000_ipprim_udp_src_port
,
3015 { "UDP Source Port",
3016 "dct2000.ipprim.udp.srcport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3017 "IPPrim UDP Source Port", HFILL
3020 { &hf_catapult_dct2000_ipprim_udp_dst_port
,
3021 { "UDP Destination Port",
3022 "dct2000.ipprim.udp.dstport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3023 "IPPrim UDP Destination Port", HFILL
3026 { &hf_catapult_dct2000_ipprim_udp_port
,
3028 "dct2000.ipprim.udp.port", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3029 "IPPrim UDP Port", HFILL
3032 { &hf_catapult_dct2000_ipprim_tcp_src_port
,
3033 { "TCP Source Port",
3034 "dct2000.ipprim.tcp.srcport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3035 "IPPrim TCP Source Port", HFILL
3038 { &hf_catapult_dct2000_ipprim_tcp_dst_port
,
3039 { "TCP Destination Port",
3040 "dct2000.ipprim.tcp.dstport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3041 "IPPrim TCP Destination Port", HFILL
3044 { &hf_catapult_dct2000_ipprim_tcp_port
,
3046 "dct2000.ipprim.tcp.port", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3047 "IPPrim TCP Port", HFILL
3050 { &hf_catapult_dct2000_ipprim_conn_id
,
3052 "dct2000.ipprim.conn-id", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3053 "IPPrim TCP Connection ID", HFILL
3057 { &hf_catapult_dct2000_sctpprim_addresses
,
3058 { "SCTPPrim Addresses",
3059 "dct2000.sctpprim", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3063 { &hf_catapult_dct2000_sctpprim_dst_addr_v4
,
3064 { "Destination Address",
3065 "dct2000.sctpprim.dst", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
3066 "SCTPPrim IPv4 Destination Address", HFILL
3069 { &hf_catapult_dct2000_sctpprim_dst_addr_v6
,
3070 { "Destination Address",
3071 "dct2000.sctpprim.dstv6", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
3072 "SCTPPrim IPv6 Destination Address", HFILL
3075 { &hf_catapult_dct2000_sctpprim_addr_v4
,
3077 "dct2000.sctpprim.addr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
3078 "SCTPPrim IPv4 Address", HFILL
3081 { &hf_catapult_dct2000_sctpprim_addr_v6
,
3083 "dct2000.sctpprim.addrv6", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
3084 "SCTPPrim IPv6 Address", HFILL
3087 { &hf_catapult_dct2000_sctpprim_dst_port
,
3088 { "UDP Destination Port",
3089 "dct2000.sctprim.dstport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3090 "SCTPPrim Destination Port", HFILL
3094 { &hf_catapult_dct2000_tty
,
3096 "dct2000.tty", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3100 { &hf_catapult_dct2000_tty_line
,
3102 "dct2000.tty-line", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3107 { &hf_catapult_dct2000_lte_ueid
,
3109 "dct2000.lte.ueid", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3110 "User Equipment Identifier", HFILL
3113 { &hf_catapult_dct2000_lte_srbid
,
3115 "dct2000.lte.srbid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3116 "Signalling Radio Bearer Identifier", HFILL
3119 { &hf_catapult_dct2000_lte_drbid
,
3121 "dct2000.lte.drbid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3122 "Data Radio Bearer Identifier", HFILL
3125 { &hf_catapult_dct2000_lte_cellid
,
3127 "dct2000.lte.cellid", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3128 "Cell Identifier", HFILL
3131 { &hf_catapult_dct2000_lte_bcch_transport
,
3133 "dct2000.lte.bcch-transport", FT_UINT16
, BASE_DEC
, VALS(bcch_transport_vals
), 0x0,
3134 "BCCH Transport Channel", HFILL
3137 { &hf_catapult_dct2000_lte_rlc_op
,
3139 "dct2000.lte.rlc-op", FT_UINT8
, BASE_DEC
, VALS(rlc_op_vals
), 0x0,
3140 "RLC top-level op", HFILL
3143 { &hf_catapult_dct2000_lte_rlc_channel_type
,
3144 { "RLC Logical Channel Type",
3145 "dct2000.lte.rlc-logchan-type", FT_UINT8
, BASE_DEC
, VALS(rlc_logical_channel_vals
), 0x0,
3149 { &hf_catapult_dct2000_lte_rlc_mui
,
3151 "dct2000.lte.rlc-mui", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3155 { &hf_catapult_dct2000_lte_rlc_cnf
,
3157 "dct2000.lte.rlc-cnf", FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_yes_no
), 0x0,
3161 { &hf_catapult_dct2000_lte_rlc_discard_req
,
3163 "dct2000.lte.rlc-discard-req", FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_yes_no
), 0x0,
3164 "RLC Discard Req", HFILL
3168 { &hf_catapult_dct2000_lte_ccpri_opcode
,
3170 "dct2000.lte.ccpri.opcode", FT_UINT8
, BASE_DEC
, VALS(ccpri_opcode_vals
), 0x0,
3174 { &hf_catapult_dct2000_lte_ccpri_status
,
3176 "dct2000.lte.ccpri.status", FT_UINT8
, BASE_DEC
, VALS(ccpri_status_vals
), 0x0,
3180 { &hf_catapult_dct2000_lte_ccpri_channel
,
3182 "dct2000.lte.ccpri.channel", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3187 { &hf_catapult_dct2000_lte_nas_rrc_opcode
,
3189 "dct2000.lte.nas-rrc.opcode", FT_UINT8
, BASE_DEC
, VALS(lte_nas_rrc_opcode_vals
), 0x0,
3193 { &hf_catapult_dct2000_lte_nas_rrc_establish_cause
,
3194 { "Establish Cause",
3195 "dct2000.lte.nas-rrc.establish-cause", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3199 { &hf_catapult_dct2000_lte_nas_rrc_priority
,
3201 "dct2000.lte.nas-rrc.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3205 { &hf_catapult_dct2000_lte_nas_rrc_release_cause
,
3207 "dct2000.lte.nas-rrc.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3213 { &hf_catapult_dct2000_ueid
,
3215 "dct2000.ueid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3216 "User Equipment Identifier", HFILL
3219 { &hf_catapult_dct2000_rbid
,
3221 "dct2000.rbid", FT_UINT8
, BASE_DEC
, VALS(rlc_rbid_vals
), 0x0,
3222 "Channel (rbid)", HFILL
3225 { &hf_catapult_dct2000_ccch_id
,
3227 "dct2000.ccch-id", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3228 "CCCH Identifier", HFILL
3231 { &hf_catapult_dct2000_no_crc_error
,
3233 "dct2000.no-crc-error", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3237 { &hf_catapult_dct2000_crc_error
,
3239 "dct2000.crc-error", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3243 { &hf_catapult_dct2000_clear_tx_buffer
,
3244 { "Clear Tx Buffer",
3245 "dct2000.clear-tx-buffer", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3249 { &hf_catapult_dct2000_buffer_occupancy
,
3250 { "Buffer Occupancy",
3251 "dct2000.buffer-occupancy", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3255 { &hf_catapult_dct2000_pdu_size
,
3257 "dct2000.pdu-size", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3261 { &hf_catapult_dct2000_ueid_type
,
3263 "dct2000.ueid-type", FT_UINT8
, BASE_DEC
, VALS(ueid_type_vals
), 0x0,
3267 { &hf_catapult_dct2000_tx_priority
,
3269 "dct2000.tx-priority", FT_UINT8
, BASE_DEC
, VALS(tx_priority_vals
), 0x0,
3273 { &hf_catapult_dct2000_last_in_seg_set
,
3274 { "Last in seg set",
3275 "dct2000.last-in-seg-set", FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_yes_no
), 0x0,
3279 { &hf_catapult_dct2000_rx_timing_deviation
,
3280 { "Tx Timing Deviation",
3281 "dct2000.rx-timing-deviation", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3285 { &hf_catapult_dct2000_transport_channel_type
,
3286 { "Transport Channel Type",
3287 "dct2000.transport_channel_type", FT_UINT8
, BASE_DEC
, VALS(transport_channel_type_vals
), 0x0,
3291 { &hf_catapult_dct2000_no_padding_bits
,
3292 { "Number of padding bits",
3293 "dct2000.number-of-padding-bits", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3300 static gint
*ett
[] =
3302 &ett_catapult_dct2000
,
3303 &ett_catapult_dct2000_ipprim
,
3304 &ett_catapult_dct2000_sctpprim
,
3305 &ett_catapult_dct2000_tty
3308 static ei_register_info ei
[] = {
3309 { &ei_catapult_dct2000_lte_ccpri_status_error
, { "dct2000.lte.ccpri.status.error", PI_SEQUENCE
, PI_ERROR
, "CCPRI Indication has error status", EXPFILL
}},
3310 { &ei_catapult_dct2000_error_comment_expert
, { "dct2000.error-comment.expert", PI_SEQUENCE
, PI_ERROR
, "Formatted expert comment", EXPFILL
}},
3313 module_t
*catapult_dct2000_module
;
3314 expert_module_t
* expert_catapult_dct2000
;
3316 /* Register protocol. */
3317 proto_catapult_dct2000
= proto_register_protocol("Catapult DCT2000 packet",
3320 proto_register_field_array(proto_catapult_dct2000
, hf
, array_length(hf
));
3321 proto_register_subtree_array(ett
, array_length(ett
));
3322 expert_catapult_dct2000
= expert_register_protocol(proto_catapult_dct2000
);
3323 expert_register_field_array(expert_catapult_dct2000
, ei
, array_length(ei
));
3325 /* Allow dissector to find be found by name. */
3326 register_dissector("dct2000", dissect_catapult_dct2000
, proto_catapult_dct2000
);
3329 catapult_dct2000_module
= prefs_register_protocol(proto_catapult_dct2000
, NULL
);
3331 /* This preference no longer supported (introduces linkage dependency between
3332 dissectors and wiretap) */
3333 prefs_register_obsolete_preference(catapult_dct2000_module
, "board_ports_only");
3335 /* Determines whether for not-handled protocols we should try to parse it if:
3336 - it looks like it's embedded in an ipprim message, AND
3337 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3338 prefs_register_bool_preference(catapult_dct2000_module
, "ipprim_heuristic",
3339 "Use IP Primitive heuristic",
3340 "If a payload looks like it's embedded in an "
3341 "IP primitive message, and there is a Wireshark "
3342 "dissector matching the DCT2000 protocol name, "
3343 "try parsing the payload using that dissector",
3344 &catapult_dct2000_try_ipprim_heuristic
);
3346 /* Determines whether for not-handled protocols we should try to parse it if:
3347 - it looks like it's embedded in an sctpprim message, AND
3348 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
3349 prefs_register_bool_preference(catapult_dct2000_module
, "sctpprim_heuristic",
3350 "Use SCTP Primitive heuristic",
3351 "If a payload looks like it's embedded in an "
3352 "SCTP primitive message, and there is a Wireshark "
3353 "dissector matching the DCT2000 protocol name, "
3354 "try parsing the payload using that dissector",
3355 &catapult_dct2000_try_sctpprim_heuristic
);
3357 /* Determines whether LTE RRC messages should be dissected */
3358 prefs_register_bool_preference(catapult_dct2000_module
, "decode_lte_rrc",
3359 "Attempt to decode LTE RRC frames",
3360 "When set, attempt to decode LTE RRC frames. "
3361 "Note that this won't affect other protocols "
3362 "that also call the LTE RRC dissector",
3363 &catapult_dct2000_dissect_lte_rrc
);
3365 /* Determines whether LTE S1AP messages should be dissected */
3366 prefs_register_bool_preference(catapult_dct2000_module
, "decode_lte_s1ap",
3367 "Attempt to decode LTE S1AP frames",
3368 "When set, attempt to decode LTE S1AP frames. "
3369 "Note that this won't affect other protocols "
3370 "that also call the LTE S1AP dissector",
3371 &catapult_dct2000_dissect_lte_s1ap
);
3373 /* Determines whether out-of-band messages should dissected */
3374 prefs_register_bool_preference(catapult_dct2000_module
, "decode_mac_lte_oob_messages",
3375 "Look for out-of-band LTE MAC events messages in comments",
3376 "When set, look for formatted messages indicating "
3377 "specific events. This may be quite slow, so should "
3378 "be disabled if LTE MAC is not being analysed",
3379 &catapult_dct2000_dissect_mac_lte_oob_messages
);