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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
37 #include <epan/expert.h>
38 #include <epan/emem.h>
39 #include <epan/proto.h>
40 #include <epan/ipproto.h>
41 #include <epan/prefs.h>
42 #include <epan/strutil.h>
43 #include <epan/addr_resolv.h>
45 #include <wiretap/catapult_dct2000.h>
46 #include "packet-umts_fp.h"
47 #include "packet-mac-lte.h"
48 #include "packet-rlc-lte.h"
49 #include "packet-pdcp-lte.h"
51 /* Protocol and registered fields. */
52 static int proto_catapult_dct2000 = -1;
54 static int hf_catapult_dct2000_context = -1;
55 static int hf_catapult_dct2000_port_number = -1;
56 static int hf_catapult_dct2000_timestamp = -1;
57 static int hf_catapult_dct2000_protocol = -1;
58 static int hf_catapult_dct2000_variant = -1;
59 static int hf_catapult_dct2000_outhdr = -1;
60 static int hf_catapult_dct2000_direction = -1;
61 static int hf_catapult_dct2000_encap = -1;
62 static int hf_catapult_dct2000_unparsed_data = -1;
63 static int hf_catapult_dct2000_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;
102 /* Variables used for preferences */
103 static gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
104 static gboolean catapult_dct2000_try_sctpprim_heuristic = TRUE;
105 static gboolean catapult_dct2000_dissect_lte_rrc = TRUE;
106 static gboolean catapult_dct2000_dissect_lte_s1ap = TRUE;
107 static gboolean catapult_dct2000_dissect_mac_lte_oob_messages = TRUE;
109 /* Protocol subtree. */
110 static int ett_catapult_dct2000 = -1;
111 static int ett_catapult_dct2000_ipprim = -1;
112 static int ett_catapult_dct2000_sctpprim = -1;
113 static int ett_catapult_dct2000_tty = -1;
115 static const value_string direction_vals[] = {
121 static const value_string encap_vals[] = {
122 { WTAP_ENCAP_RAW_IP, "Raw IP" },
123 { WTAP_ENCAP_ETHERNET, "Ethernet" },
124 { WTAP_ENCAP_ISDN, "LAPD" },
125 { WTAP_ENCAP_ATM_PDUS_UNTRUNCATED, "ATM (PDUs untruncated)" },
126 { WTAP_ENCAP_PPP, "PPP" },
127 { DCT2000_ENCAP_SSCOP, "SSCOP" },
128 { WTAP_ENCAP_FRELAY, "Frame Relay" },
129 { WTAP_ENCAP_MTP2, "MTP2" },
130 { DCT2000_ENCAP_NBAP, "NBAP" },
131 { DCT2000_ENCAP_UNHANDLED, "No Direct Encapsulation" },
135 static const value_string bcch_transport_vals[] = {
136 { BCH_TRANSPORT, "BCH" },
137 { DLSCH_TRANSPORT, "DLSCH" },
142 #define RLC_MGMT_ASSIGN 0x41
143 #define RLC_AM_DATA_REQ 0x60
144 #define RLC_AM_DATA_IND 0x61
145 #define RLC_AM_DATA_CONF 0x62
146 #define RLC_UM_DATA_REQ 0x70
147 #define RLC_UM_DATA_IND 0x71
148 #define RLC_UM_DATA_CONF 0x74
149 #define RLC_TR_DATA_REQ 0x80
150 #define RLC_TR_DATA_IND 0x81
151 #define RLC_TR_DATA_CONF 0x83
153 static const value_string rlc_op_vals[] = {
154 { RLC_AM_DATA_REQ, "[UL] [AM]" },
155 { RLC_AM_DATA_IND, "[DL] [AM]" },
156 { RLC_UM_DATA_REQ, "[UL] [UM]"},
157 { RLC_UM_DATA_IND, "[DL] [UM]"},
158 { RLC_TR_DATA_REQ, "[UL] [TM]"},
159 { RLC_TR_DATA_IND, "[DL] [TM]"},
164 static const value_string rlc_logical_channel_vals[] = {
165 { Channel_DCCH, "DCCH"},
166 { Channel_BCCH, "BCCH"},
167 { Channel_CCCH, "CCCH"},
168 { Channel_PCCH, "PCCH"},
174 #define MAX_OUTHDR_VALUES 32
176 static guint outhdr_values[MAX_OUTHDR_VALUES];
177 static gint outhdr_values_found = 0;
180 extern int proto_mac_lte;
181 extern int proto_rlc_lte;
182 extern int proto_pdcp_lte;
184 static dissector_handle_t mac_lte_handle;
185 static dissector_handle_t rlc_lte_handle;
186 static dissector_handle_t pdcp_lte_handle;
188 void proto_register_catapult_dct2000(void);
190 static dissector_handle_t look_for_dissector(char *protocol_name);
191 static void parse_outhdr_string(const guchar *outhdr_string);
192 static void attach_fp_info(packet_info *pinfo, gboolean received,
193 const char *protocol_name, int variant);
194 static void attach_mac_lte_info(packet_info *pinfo);
195 static void attach_rlc_lte_info(packet_info *pinfo);
196 static void attach_pdcp_lte_info(packet_info *pinfo);
200 /* Return the number of bytes used to encode the length field
201 (we're not interested in the length value itself) */
202 static int skipASNLength(guint8 value)
204 if ((value & 0x80) == 0)
210 return ((value & 0x03) == 1) ? 2 : 3;
215 /* Look for the protocol data within an ipprim packet.
216 Only set *data_offset if data field found. */
217 static gboolean find_ipprim_data_offset(tvbuff_t *tvb, int *data_offset, guint8 direction,
218 guint32 *source_addr_offset, guint8 *source_addr_length,
219 guint32 *dest_addr_offset, guint8 *dest_addr_length,
220 guint32 *source_port_offset, guint32 *dest_port_offset,
221 port_type *type_of_port,
222 guint16 *conn_id_offset)
225 int offset = *data_offset;
227 /* Get the ipprim command code. */
228 guint8 tag = tvb_get_guint8(tvb, offset++);
230 /* Only accept UDP or TCP data request or indication */
232 case 0x23: /* UDP data request */
233 case 0x24: /* UDP data indication */
234 *type_of_port = PT_UDP;
236 case 0x45: /* TCP data request */
237 case 0x46: /* TCP data indication */
238 *type_of_port = PT_TCP;
244 /* Skip any other TLC fields before reach payload */
245 while (tvb_length_remaining(tvb, offset) > 2) {
246 /* Look at next tag */
247 tag = tvb_get_guint8(tvb, offset++);
249 /* Is this the data payload we're expecting? */
250 if (((tag == 0x34) && (*type_of_port == PT_UDP)) ||
251 ((tag == 0x48) && (*type_of_port == PT_TCP))) {
253 *data_offset = offset;
257 /* Read length in next byte */
258 length = tvb_get_guint8(tvb, offset++);
260 if (tag == 0x31 && length >=4) {
261 /* Remote IP address */
262 if (direction == 0) {
263 /* Sent *to* remote, so dest */
264 *dest_addr_offset = offset;
265 *dest_addr_length = (length/4) * 4;
268 *source_addr_offset = offset;
269 *source_addr_length = (length/4) * 4;
272 /* Remote port follows (if present) */
273 if ((length % 4) == 2) {
274 if (direction == 0) {
275 *dest_port_offset = offset + 4;
278 *source_port_offset = offset + 4;
284 if (length == 4 || length == 16) {
285 /* Local IP address */
286 if (direction == 0) {
287 /* Sent *from* local, so source */
288 *source_addr_offset = offset;
289 *source_addr_length = length;
292 *dest_addr_offset = offset;
293 *dest_addr_length = length;
298 if (tag == 0x33 && length == 2) {
300 if (direction == 0) {
301 /* Sent from local, so source */
302 *source_port_offset = offset;
305 *dest_port_offset = offset;
309 if (tag == 0x36 && length == 2) {
311 *conn_id_offset = offset;
314 /* Skip the length of the indicated value */
319 /* No data found... */
325 /* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
326 Only set *data_offset if data field found. */
327 static gboolean find_sctpprim_variant1_data_offset(tvbuff_t *tvb, int *data_offset,
328 guint32 *dest_addr_offset,
329 guint16 *dest_addr_length,
330 guint32 *dest_port_offset)
332 int offset = *data_offset;
334 /* Get the sctpprim command code. */
335 guint8 first_tag = tvb_get_guint8(tvb, offset++);
337 guint8 first_length_byte;
339 /* Only accept interested in data requests or indications */
341 case 0x04: /* data request */
342 case 0x62: /* data indication */
348 first_length_byte = tvb_get_guint8(tvb, offset);
349 offset += skipASNLength(first_length_byte);
351 /* Skip any other fields before reach payload */
352 while (tvb_length_remaining(tvb, offset) > 2) {
353 /* Look at next tag */
354 tag = tvb_get_guint8(tvb, offset++);
356 /* Is this the data payload we're expecting? */
358 *data_offset = offset;
362 /* Skip length field */
365 case 0x0a: /* destPort */
366 *dest_port_offset = offset;
370 case 0x01: /* sctpInstanceNum */
371 case 0x1e: /* strseqnum */
372 case 0x0d: /* streamnum */
376 case 0x09: /* ipv4Address */
377 *dest_addr_offset = offset;
378 *dest_addr_length = 4;
383 case 0x0c: /* payloadType */
388 /* Fail if not a known header field */
394 /* No data found... */
398 /* Look for the protocol data within an sctpprim (variant 3) packet.
399 Only set *data_offset if data field found. */
400 static gboolean find_sctpprim_variant3_data_offset(tvbuff_t *tvb, int *data_offset,
401 guint32 *dest_addr_offset,
402 guint16 *dest_addr_length,
403 guint32 *dest_port_offset)
407 int offset = *data_offset;
409 /* Get the sctpprim (2 byte) command code. */
410 guint16 top_tag = tvb_get_ntohs(tvb, offset);
413 /* Only interested in data requests or indications */
415 case 0x0400: /* SendDataReq */
416 case 0x6200: /* DataInd */
423 /* Overall length field is next 2 bytes */
426 /* Rx/Tx ops have different formats */
430 if (top_tag == 0x6200) {
431 /* Next 2 bytes are associate ID */
434 /* Next 2 bytes are destination port */
435 *dest_port_offset = offset;
438 /* Destination address should follow - check tag */
439 tag = tvb_get_ntohs(tvb, offset);
448 length = tvb_get_ntohs(tvb, offset) / 2;
449 if ((length != 4) && (length != 16))
455 /* Address data is here */
456 *dest_addr_offset = offset;
457 *dest_addr_length = length;
462 /* Not interested in remaining (fixed) fields */
463 if (tvb_reported_length_remaining(tvb, offset) > (4 + 2 + 2 + 4)) {
464 offset += (4 + 2 + 2 + 4);
470 /* Data should now be here */
471 tag = tvb_get_ntohs(tvb, offset);
474 /* 2-byte length field */
477 /* Data is here!!! */
478 *data_offset = offset;
488 else if (top_tag == 0x0400) {
489 /* AssociateId should follow - check tag */
490 tag = tvb_get_ntohs(tvb, offset);
498 /* Skip 2-byte value */
503 tag = tvb_get_ntohs(tvb, offset);
506 /* Some optional params */
507 while ((tag != 0x0c00) && (tvb_length_remaining(tvb, offset) > 4)) {
509 case 0x0900: /* Dest address */
511 length = tvb_get_ntohs(tvb, offset) / 2;
512 if ((length != 4) && (length != 16)) {
517 /* Address data is here */
518 *dest_addr_offset = offset;
519 *dest_addr_length = length;
524 case 0x0a00: /* Dest port number */
525 *dest_port_offset = offset;
529 case 0x0d00: /* StreamNum */
530 *dest_port_offset = offset;
539 /* Get the next tag */
540 tag = tvb_get_ntohs(tvb, offset);
545 /* Mandatory payload type */
549 length = tvb_get_ntohs(tvb, offset) / 2;
554 /* Optional options */
555 tag = tvb_get_ntohs(tvb, offset);
558 length = tvb_get_ntohs(tvb, offset) / 2;
564 tag = tvb_get_ntohs(tvb, offset);
569 /* Data should now be here!! */
571 /* 2-byte length field */
574 /* Data is here!!! */
575 *data_offset = offset;
589 /* Dissect an RRC LTE frame by first parsing the header entries then passing
590 the data to the RRC dissector, according to direction and channel type.
591 TODO: factor out common code between this function and dissect_pdcp_lte() */
592 static void dissect_rrc_lte(tvbuff_t *tvb, gint offset,
593 packet_info *pinfo, proto_tree *tree)
596 dissector_handle_t protocol_handle = 0;
597 gboolean isUplink = FALSE;
598 LogicalChannelType logicalChannelType;
599 guint8 bcch_transport = 0;
602 /* Top-level opcode */
603 tag = tvb_get_guint8(tvb, offset++);
605 case 0x00: /* Data_Req_UE */
606 case 0x04: /* Data_Ind_eNodeB */
610 case 0x02: /* Data_Req_eNodeB */
611 case 0x03: /* Data_Ind_UE */
616 /* Unexpected opcode tag! */
621 offset += skipASNLength(tvb_get_guint8(tvb, offset));
624 tag = tvb_get_guint8(tvb, offset++);
626 case 0x12: /* UE_Id_LCId */
628 /* Dedicated channel info */
630 /* Length will fit in one byte here */
633 logicalChannelType = Channel_DCCH;
636 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, FALSE);
639 /* Get tag of channel type */
640 tag = tvb_get_guint8(tvb, offset++);
645 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
646 tvb_get_guint8(tvb, offset));
647 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
648 tvb, offset, 1, FALSE);
653 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
654 tvb_get_guint8(tvb, offset));
655 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
656 tvb, offset, 1, FALSE);
660 /* Unexpected channel type */
665 case 0x1a: /* Cell_LCId */
667 /* Common channel info */
673 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
674 tvb, offset, 2, FALSE);
677 /* Logical channel type */
678 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
679 tvb, offset, 1, FALSE);
680 logicalChannelType = (LogicalChannelType)tvb_get_guint8(tvb, offset++);
681 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
682 val_to_str(logicalChannelType, rlc_logical_channel_vals,
685 switch (logicalChannelType) {
690 /* Transport channel type */
691 bcch_transport = tvb_get_guint8(tvb, offset);
692 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
693 tvb, offset, 1, FALSE);
702 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
703 tvb, offset, 2, FALSE);
717 /* Data tag should follow */
718 tag = tvb_get_guint8(tvb, offset++);
724 offset += skipASNLength(tvb_get_guint8(tvb, offset));
726 /* Look up dissector handle corresponding to direction and channel type */
729 /* Uplink channel types */
730 switch (logicalChannelType) {
732 protocol_handle = find_dissector("lte-rrc.ul.dcch");
735 protocol_handle = find_dissector("lte-rrc.ul.ccch");
739 /* Unknown Uplink channel type */
744 /* Downlink channel types */
745 switch (logicalChannelType) {
747 protocol_handle = find_dissector("lte-rrc.dl.dcch");
750 protocol_handle = find_dissector("lte-rrc.dl.ccch");
753 protocol_handle = find_dissector("lte-rrc.pcch");
756 if (bcch_transport == 1) {
757 protocol_handle = find_dissector("lte-rrc.bcch.bch");
760 protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
765 /* Unknown Downlink channel type */
770 /* Send to RRC dissector, if got here, have sub-dissector and some data left */
771 if ((protocol_handle != NULL) && (tvb_length_remaining(tvb, offset) > 0)) {
772 rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
773 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
778 /* Dissect a PDCP LTE frame by first parsing the RLCPrim header then passing
779 the data to the PDCP LTE dissector */
780 static void dissect_pdcp_lte(tvbuff_t *tvb, gint offset,
781 packet_info *pinfo, proto_tree *tree)
785 struct pdcp_lte_info *p_pdcp_lte_info = NULL;
786 tvbuff_t *pdcp_lte_tvb;
789 /* Look this up so can update channel info */
790 p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
791 if (p_pdcp_lte_info == NULL) {
792 /* This really should be set...can't dissect anything without it */
796 /* Top-level opcode */
797 opcode = tvb_get_guint8(tvb, offset);
799 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_op, tvb, offset, 1, FALSE);
803 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, rlc_op_vals, "Unknown"));
805 /* Assume UE side, so REQ is UL, IND is DL */
807 case RLC_AM_DATA_REQ:
808 case RLC_UM_DATA_REQ:
809 case RLC_TR_DATA_REQ:
810 p_pdcp_lte_info->direction = DIRECTION_UPLINK;
813 p_pdcp_lte_info->direction = DIRECTION_DOWNLINK;
818 case RLC_AM_DATA_REQ:
819 case RLC_AM_DATA_IND:
820 case RLC_UM_DATA_REQ:
821 case RLC_UM_DATA_IND:
822 case RLC_TR_DATA_REQ:
823 case RLC_TR_DATA_IND:
826 tag = tvb_get_guint8(tvb, offset++);
828 case 0x10: /* UE_Id_LCId */
830 /* Dedicated channel info */
832 /* Length will fit in one byte here */
835 p_pdcp_lte_info->channelType = Channel_DCCH;
838 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid, tvb, offset, 2, FALSE);
839 col_append_fstr(pinfo->cinfo, COL_INFO,
840 " UEId=%u", tvb_get_ntohs(tvb, offset));
843 /* Get tag of channel type */
844 tag = tvb_get_guint8(tvb, offset++);
849 col_append_fstr(pinfo->cinfo, COL_INFO, " SRB:%u",
850 tvb_get_guint8(tvb, offset));
851 proto_tree_add_item(tree, hf_catapult_dct2000_lte_srbid,
852 tvb, offset++, 1, FALSE);
856 col_append_fstr(pinfo->cinfo, COL_INFO, " DRB:%u",
857 tvb_get_guint8(tvb, offset));
858 proto_tree_add_item(tree, hf_catapult_dct2000_lte_drbid,
859 tvb, offset++, 1, FALSE);
863 /* Unexpected channel type */
868 case 0x1a: /* Cell_LCId */
870 /* Common channel info */
876 proto_tree_add_item(tree, hf_catapult_dct2000_lte_cellid,
877 tvb, offset, 2, FALSE);
880 /* Logical channel type */
881 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_channel_type,
882 tvb, offset, 1, FALSE);
883 p_pdcp_lte_info->channelType = tvb_get_guint8(tvb, offset++);
884 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
885 val_to_str(p_pdcp_lte_info->channelType, rlc_logical_channel_vals,
888 switch (p_pdcp_lte_info->channelType) {
893 /* Transport channel type */
894 p_pdcp_lte_info->BCCHTransport = (LogicalChannelType)tvb_get_guint8(tvb, offset);
895 proto_tree_add_item(tree, hf_catapult_dct2000_lte_bcch_transport,
896 tvb, offset, 1, FALSE);
905 proto_tree_add_item(tree, hf_catapult_dct2000_lte_ueid,
906 tvb, offset, 2, FALSE);
907 ueid = tvb_get_ntohs(tvb, offset);
910 col_append_fstr(pinfo->cinfo, COL_INFO, " UEId=%u", ueid);
923 /* Other optional fields may follow */
924 tag = tvb_get_guint8(tvb, offset++);
925 while ((tag != 0x41) && (tvb_length_remaining(tvb, offset) > 2)) {
930 proto_tree_add_item(tree, hf_catapult_dct2000_lte_rlc_mui,
931 tvb, offset, 2, FALSE);
934 /* CNF follows MUI in AM */
935 if ((opcode == RLC_AM_DATA_REQ) || (opcode == RLC_AM_DATA_IND)) {
936 proto_tree_add_boolean(tree, hf_catapult_dct2000_lte_rlc_cnf,
937 tvb, offset, 1, tvb_get_guint8(tvb, offset));
941 else if (tag == 0x45) {
944 proto_tree_add_boolean(tree, hf_catapult_dct2000_lte_rlc_discard_req,
945 tvb, offset, 1, tvb_get_guint8(tvb, offset));
949 tag = tvb_get_guint8(tvb, offset++);
953 /********************************/
954 /* Should be at data tag now */
956 /* Call PDCP LTE dissector */
957 pdcp_lte_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
958 call_dissector_only(pdcp_lte_handle, pdcp_lte_tvb, pinfo, tree);
971 /* Look up dissector by protocol name. Fix up known name mis-matches.
972 This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */
973 static dissector_handle_t look_for_dissector(char *protocol_name)
975 /* Use known aliases and protocol name prefixes */
976 if (strcmp(protocol_name, "tbcp") == 0) {
977 return find_dissector("rtcp");
980 if (strncmp(protocol_name, "diameter", strlen("diameter")) == 0) {
981 return find_dissector("diameter");
984 if ((strcmp(protocol_name, "xcap_caps") == 0) ||
985 (strcmp(protocol_name, "soap") == 0) ||
986 (strcmp(protocol_name, "mm1") == 0) ||
987 (strcmp(protocol_name, "mm3") == 0) ||
988 (strcmp(protocol_name, "mm7") == 0)) {
990 return find_dissector("http");
993 if ((strcmp(protocol_name, "fp") == 0) ||
994 (strcmp(protocol_name, "fp_r4") == 0) ||
995 (strcmp(protocol_name, "fp_r5") == 0) ||
996 (strcmp(protocol_name, "fp_r6") == 0) ||
997 (strcmp(protocol_name, "fp_r7") == 0) ||
998 (strcmp(protocol_name, "fpiur_r5") == 0)) {
1000 return find_dissector("fp");
1003 if ((strcmp(protocol_name, "iuup_rtp_r5") == 0) ||
1004 (strcmp(protocol_name, "iuup_rtp_r6") == 0)) {
1006 return find_dissector("rtp");
1009 if (strcmp(protocol_name, "sipt") == 0) {
1010 return find_dissector("sip");
1013 if (strncmp(protocol_name, "nbap_sctp", strlen("nbap_sctp")) == 0) {
1014 return find_dissector("nbap");
1017 if (strncmp(protocol_name, "gtp", strlen("gtp")) == 0) {
1018 return find_dissector("gtp");
1021 if (strcmp(protocol_name, "dhcpv4") == 0) {
1022 return find_dissector("bootp");
1025 if (strcmp(protocol_name, "wimax") == 0) {
1026 return find_dissector("wimaxasncp");
1029 if (strncmp(protocol_name, "sabp", strlen("sabp")) == 0) {
1030 return find_dissector("sabp");
1033 if (strcmp(protocol_name, "wtp") == 0) {
1034 return find_dissector("wtp-udp");
1037 /* Only match with s1ap if preference turned on */
1038 if (catapult_dct2000_dissect_lte_s1ap &&
1039 strncmp(protocol_name, "s1ap", strlen("s1ap")) == 0) {
1041 return find_dissector("s1ap");
1044 if (strcmp(protocol_name, "gtpv2_r8_lte") == 0) {
1045 return find_dissector("gtpv2");
1049 /* Try for an exact match */
1051 return find_dissector(protocol_name);
1056 /* Populate outhdr_values array with numbers found in outhdr_string */
1057 static void parse_outhdr_string(const guchar *outhdr_string)
1060 guint outhdr_string_len = (guint)strlen((gchar*)outhdr_string);
1062 /* Populate values array */
1063 for (outhdr_values_found=0; outhdr_values_found < MAX_OUTHDR_VALUES; ) {
1064 guint digits_start = n;
1068 for (digits = 0; digits < outhdr_string_len; digits++, n++) {
1069 if (!isdigit(outhdr_string[n])) {
1075 /* No more numbers left */
1079 /* Convert digits into value */
1080 outhdr_values[outhdr_values_found++] =
1081 atoi((char*)format_text((guchar*)outhdr_string+digits_start, digits));
1088 /* Fill in an FP packet info struct and attach it to the packet for the FP
1090 void attach_fp_info(packet_info *pinfo, gboolean received, const char *protocol_name, int variant)
1094 int tf_start, num_chans_start;
1097 /* Only need to set info once per session. */
1098 struct fp_info *p_fp_info = p_get_proto_data(pinfo->fd, proto_fp);
1099 if (p_fp_info != NULL) {
1103 /* Allocate struct */
1104 p_fp_info = se_alloc0(sizeof(struct fp_info));
1109 /* Check that the number of outhdr values looks sensible */
1110 if (((strcmp(protocol_name, "fpiur_r5") == 0) && (outhdr_values_found != 2)) ||
1111 (outhdr_values_found < 5)) {
1116 /* 3gpp release (99, 4, 5, 6, 7) */
1117 if (strcmp(protocol_name, "fp") == 0) {
1118 p_fp_info->release = 99;
1120 else if (strcmp(protocol_name, "fp_r4") == 0) {
1121 p_fp_info->release = 4;
1123 else if (strcmp(protocol_name, "fp_r5") == 0) {
1124 p_fp_info->release = 5;
1126 else if (strcmp(protocol_name, "fp_r6") == 0) {
1127 p_fp_info->release = 6;
1129 else if (strcmp(protocol_name, "fp_r7") == 0) {
1130 p_fp_info->release = 7;
1132 else if (strcmp(protocol_name, "fpiur_r5") == 0) {
1133 p_fp_info->release = 5;
1136 /* Really shouldn't get here */
1137 DISSECTOR_ASSERT_NOT_REACHED();
1141 /* Release date is derived from variant number */
1142 /* Only R6 sub-versions currently influence format within a release */
1143 switch (p_fp_info->release) {
1145 switch (variant % 256) {
1147 p_fp_info->release_year = 2005;
1148 p_fp_info->release_month = 6;
1151 p_fp_info->release_year = 2005;
1152 p_fp_info->release_month = 9;
1156 p_fp_info->release_year = 2006;
1157 p_fp_info->release_month = 3;
1162 p_fp_info->release_year = 2008;
1163 p_fp_info->release_month = 3;
1167 p_fp_info->release_year = 0;
1168 p_fp_info->release_month = 0;
1173 p_fp_info->channel = outhdr_values[i++];
1175 /* Derive direction from node type/side */
1176 node_type = outhdr_values[i++];
1177 p_fp_info->is_uplink = (( received && (node_type == 2)) ||
1178 (!received && (node_type == 1)));
1180 /* Division type introduced for R7 */
1181 if (p_fp_info->release == 7) {
1182 p_fp_info->division = outhdr_values[i++];
1185 /* HS-DSCH config */
1186 if (p_fp_info->channel == CHANNEL_HSDSCH) {
1187 if (p_fp_info->release == 7) {
1188 /* Entity (MAC-hs or MAC-ehs) used */
1189 if (outhdr_values[i++]) {
1190 p_fp_info->hsdsch_entity = ehs;
1194 /* This is the pre-R7 default */
1195 p_fp_info->hsdsch_entity = hs;
1200 /* IUR only uses the above... */
1201 if (strcmp(protocol_name, "fpiur_r5") == 0) {
1202 /* Store info in packet */
1203 p_fp_info->iface_type = IuR_Interface;
1204 p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);
1208 /* DCH CRC present... */
1209 p_fp_info->dch_crc_present = outhdr_values[i++];
1211 /* ... but don't trust for edch */
1212 if (p_fp_info->channel == CHANNEL_EDCH) {
1213 p_fp_info->dch_crc_present = 2; /* unknown */
1216 /* How many paging indications (if PCH data) */
1217 p_fp_info->paging_indications = outhdr_values[i++];
1219 /* Number of channels (for coordinated channels) */
1220 p_fp_info->num_chans = outhdr_values[i++];
1222 if (p_fp_info->channel != CHANNEL_EDCH) {
1223 /* TF size for each channel */
1225 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1226 p_fp_info->chan_tf_size[chan] = outhdr_values[tf_start+chan];
1229 /* Number of TBs for each channel */
1230 num_chans_start = tf_start + p_fp_info->num_chans;
1231 for (chan=0; chan < p_fp_info->num_chans; chan++) {
1232 p_fp_info->chan_num_tbs[chan] = outhdr_values[num_chans_start+chan];
1239 p_fp_info->no_ddi_entries = outhdr_values[i++];
1242 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1243 p_fp_info->edch_ddi[n] = outhdr_values[i++];
1246 /* Corresponding MAC-d sizes */
1247 for (n=0; n < p_fp_info->no_ddi_entries; n++) {
1248 p_fp_info->edch_macd_pdu_size[n] = outhdr_values[i++];
1252 /* Interface must be IuB */
1253 p_fp_info->iface_type = IuB_Interface;
1255 /* Store info in packet */
1256 p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);
1260 /* Fill in a MAC LTE packet info struct and attach it to the packet for that
1262 static void attach_mac_lte_info(packet_info *pinfo)
1264 struct mac_lte_info *p_mac_lte_info;
1267 /* Only need to set info once per session. */
1268 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1269 if (p_mac_lte_info != NULL) {
1273 /* Allocate & zero struct */
1274 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
1275 if (p_mac_lte_info == NULL) {
1279 /* Populate the struct from outhdr values */
1280 p_mac_lte_info->crcStatusValid = FALSE;
1282 p_mac_lte_info->radioType = outhdr_values[i++];
1283 p_mac_lte_info->rntiType = outhdr_values[i++];
1284 p_mac_lte_info->direction = outhdr_values[i++];
1285 p_mac_lte_info->subframeNumber = outhdr_values[i++];
1286 p_mac_lte_info->isPredefinedData = outhdr_values[i++];
1287 p_mac_lte_info->rnti = outhdr_values[i++];
1288 p_mac_lte_info->ueid = outhdr_values[i++];
1289 p_mac_lte_info->length = outhdr_values[i++];
1290 if (outhdr_values_found > 8) {
1291 p_mac_lte_info->reTxCount = outhdr_values[i++];
1293 if (outhdr_values_found > 9) {
1294 /* CRC only valid for Downlink */
1295 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1296 p_mac_lte_info->crcStatusValid = TRUE;
1297 p_mac_lte_info->crcStatus = outhdr_values[i++];
1304 /* Store info in packet */
1305 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
1309 /* Fill in a RLC LTE packet info struct and attach it to the packet for that
1311 static void attach_rlc_lte_info(packet_info *pinfo)
1313 struct rlc_lte_info *p_rlc_lte_info;
1316 /* Only need to set info once per session. */
1317 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1318 if (p_rlc_lte_info != NULL) {
1322 /* Allocate & zero struct */
1323 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1324 if (p_rlc_lte_info == NULL) {
1328 p_rlc_lte_info->rlcMode = outhdr_values[i++];
1329 p_rlc_lte_info->direction = outhdr_values[i++];
1330 p_rlc_lte_info->priority = outhdr_values[i++];
1331 p_rlc_lte_info->UMSequenceNumberLength = outhdr_values[i++];
1332 p_rlc_lte_info->channelId = outhdr_values[i++];
1333 p_rlc_lte_info->channelType = outhdr_values[i++];
1334 p_rlc_lte_info->ueid = outhdr_values[i++];
1335 p_rlc_lte_info->pduLength = outhdr_values[i++];
1337 /* Store info in packet */
1338 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1341 /* Fill in a PDCP LTE packet info struct and attach it to the packet for the PDCP LTE
1343 static void attach_pdcp_lte_info(packet_info *pinfo)
1345 struct pdcp_lte_info *p_pdcp_lte_info;
1348 /* Only need to set info once per session. */
1349 p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1350 if (p_pdcp_lte_info != NULL) {
1354 /* Allocate & zero struct */
1355 p_pdcp_lte_info = se_alloc0(sizeof(struct pdcp_lte_info));
1356 if (p_pdcp_lte_info == NULL) {
1360 p_pdcp_lte_info->no_header_pdu = outhdr_values[i++];
1361 p_pdcp_lte_info->plane = outhdr_values[i++];
1362 if (p_pdcp_lte_info->plane != USER_PLANE) {
1363 p_pdcp_lte_info->plane = SIGNALING_PLANE;
1365 p_pdcp_lte_info->seqnum_length = outhdr_values[i++];
1367 p_pdcp_lte_info->rohc_compression = outhdr_values[i++];
1368 p_pdcp_lte_info->rohc_ip_version = outhdr_values[i++];
1369 p_pdcp_lte_info->cid_inclusion_info = outhdr_values[i++];
1370 p_pdcp_lte_info->large_cid_present = outhdr_values[i++];
1371 p_pdcp_lte_info->mode = outhdr_values[i++];
1372 p_pdcp_lte_info->rnd = outhdr_values[i++];
1373 p_pdcp_lte_info->udp_checkum_present = outhdr_values[i++];
1374 p_pdcp_lte_info->profile = outhdr_values[i++];
1376 /* Store info in packet */
1377 p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
1381 /* Attempt to show tty (raw character messages) as text lines. */
1382 static void dissect_tty_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1385 proto_tree *tty_tree;
1389 /* Create tty tree. */
1390 ti = proto_tree_add_item(tree, hf_catapult_dct2000_tty, tvb, offset, -1, FALSE);
1391 tty_tree = proto_item_add_subtree(ti, ett_catapult_dct2000);
1393 /* Show the tty lines one at a time. */
1394 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1395 /* Find the end of the line. */
1396 int linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1398 /* Extract & add the string. */
1399 char *string = (char*)tvb_get_ephemeral_string(tvb, offset, linelen);
1400 proto_tree_add_string_format(tty_tree, hf_catapult_dct2000_tty_line,
1406 /* Show first line in info column */
1408 col_append_fstr(pinfo->cinfo, COL_INFO, "tty (%s", string);
1411 /* Move onto next line. */
1412 offset = next_offset;
1415 /* Close off summary of tty message in info column */
1417 col_append_str(pinfo->cinfo, COL_INFO, (lines > 1) ? "...)" : ")");
1422 /* Scan the log comment looking for notable out-of-band MAC events that should
1423 be sent to the MAC dissector */
1424 static void check_for_oob_mac_lte_events(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1430 guint rach_attempt_number;
1431 mac_lte_oob_event oob_event;
1432 struct mac_lte_info *p_mac_lte_info;
1433 tvbuff_t *mac_lte_tvb = NULL;
1435 /* Look for strings matching expected formats */
1436 if (sscanf(string, ">> RACH Preamble Request[UE = %u] [RAPID = %u] [Attempt = %u]",
1437 &ueid, &rapid, &rach_attempt_number) == 3) {
1438 oob_event = ltemac_send_preamble;
1441 if (sscanf(string, ">> Schedule Request[UE = %u] [RNTI = %u]", &ueid, &rnti) == 2) {
1442 oob_event = ltemac_send_sr;
1445 if (sscanf(string, ">> INFO MAC: ProcessSRInd - CRNTI=%u", &rnti) == 1) {
1446 oob_event = ltemac_sr_failure;
1449 /* No events found */
1453 /* We have an event */
1454 /* Only need to set info once per session. */
1455 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1456 if (p_mac_lte_info == NULL) {
1458 /* Allocate & zero struct */
1459 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
1460 if (p_mac_lte_info == NULL) {
1464 /* This indicates to MAC dissector that it has an oob event */
1465 p_mac_lte_info->length = 0;
1467 switch (oob_event) {
1468 case ltemac_send_preamble:
1469 p_mac_lte_info->ueid = ueid;
1470 p_mac_lte_info->rapid = rapid;
1471 p_mac_lte_info->rach_attempt_number = rach_attempt_number;
1472 p_mac_lte_info->direction = DIRECTION_UPLINK;
1474 case ltemac_send_sr:
1475 p_mac_lte_info->ueid = ueid;
1476 p_mac_lte_info->rnti = rnti;
1477 p_mac_lte_info->direction = DIRECTION_UPLINK;
1479 case ltemac_sr_failure:
1480 p_mac_lte_info->rnti = rnti;
1481 p_mac_lte_info->direction = DIRECTION_DOWNLINK;
1485 p_mac_lte_info->radioType = FDD_RADIO;
1486 p_mac_lte_info->oob_event = oob_event;
1488 /* Store info in packet */
1489 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
1492 /* Call MAC dissector */
1493 mac_lte_tvb = tvb_new_subset(tvb, 0, 0, 0);
1494 call_dissector_only(mac_lte_handle, mac_lte_tvb, pinfo, tree);
1498 /*****************************************/
1499 /* Main dissection function. */
1500 /*****************************************/
1502 dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1504 proto_tree *dct2000_tree = NULL;
1505 proto_item *ti = NULL;
1507 gint context_length;
1509 gint protocol_start;
1510 gint protocol_length;
1511 gint timestamp_start;
1512 gint timestamp_length;
1514 gint variant_length;
1520 dissector_handle_t protocol_handle = 0;
1521 dissector_handle_t heur_protocol_handle = 0;
1522 int sub_dissector_result = 0;
1523 char *protocol_name;
1524 gboolean is_comment;
1527 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCT2000");
1530 col_clear(pinfo->cinfo, COL_INFO);
1532 /* Create root (protocol) tree. */
1534 ti = proto_tree_add_item(tree, proto_catapult_dct2000, tvb, offset, -1, FALSE);
1535 dct2000_tree = proto_item_add_subtree(ti, ett_catapult_dct2000);
1538 /*********************************************************************/
1539 /* Note that these are the fields of the stub header as written out */
1540 /* by the wiretap module */
1543 context_length = tvb_strsize(tvb, offset);
1545 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_context, tvb,
1546 offset, context_length, FALSE);
1548 offset += context_length;
1550 /* Context port number */
1551 port_number = tvb_get_guint8(tvb, offset);
1553 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_port_number, tvb,
1558 /* Timestamp in file */
1559 timestamp_start = offset;
1560 timestamp_length = tvb_strsize(tvb, offset);
1562 /* TODO: this is *very* slow, but float version adds trailing digits when
1563 displayed as a custom column... */
1564 proto_tree_add_double(dct2000_tree, hf_catapult_dct2000_timestamp, tvb,
1565 offset, timestamp_length,
1566 atof(tvb_get_ptr(tvb, offset, timestamp_length)));
1568 offset += timestamp_length;
1571 /* DCT2000 protocol name */
1572 protocol_start = offset;
1573 protocol_length = tvb_strsize(tvb, offset);
1575 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_protocol, tvb,
1576 offset, protocol_length, FALSE);
1578 protocol_name = (char*)tvb_get_ptr(tvb, protocol_start, protocol_length);
1579 is_comment = (strcmp(protocol_name, "comment") == 0);
1580 offset += protocol_length;
1583 /* Protocol Variant */
1584 variant_start = offset;
1585 variant_length = tvb_strsize(tvb, offset);
1587 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_variant, tvb,
1588 offset, variant_length, FALSE);
1590 offset += variant_length;
1592 /* Outhdr (shown as string) */
1593 outhdr_start = offset;
1594 outhdr_length = tvb_strsize(tvb, offset);
1595 if (!is_comment && (outhdr_length > 1)) {
1596 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_outhdr, tvb,
1597 offset, outhdr_length, FALSE);
1599 offset += outhdr_length;
1603 direction = tvb_get_guint8(tvb, offset);
1605 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
1610 /* Read frame encapsulation set by wiretap */
1612 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_encap, tvb, offset, 1, FALSE);
1614 encap = tvb_get_guint8(tvb, offset);
1617 /* Set selection length of dct2000 tree */
1618 proto_item_set_len(dct2000_tree, offset);
1620 /* Add useful details to protocol tree label */
1621 proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s (v=%s)",
1622 tvb_get_ptr(tvb, 0, context_length),
1624 tvb_get_ptr(tvb, timestamp_start, timestamp_length),
1625 (direction == 0) ? 'S' : 'R',
1627 tvb_get_ptr(tvb, variant_start, variant_length));
1631 /* FP protocols need info from outhdr attached */
1632 if ((strcmp(protocol_name, "fp") == 0) ||
1633 (strcmp(protocol_name, "fp_r4") == 0) ||
1634 (strcmp(protocol_name, "fp_r5") == 0) ||
1635 (strcmp(protocol_name, "fp_r6") == 0) ||
1636 (strcmp(protocol_name, "fp_r7") == 0) ||
1637 (strcmp(protocol_name, "fpiur_r5") == 0)) {
1639 parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length));
1640 attach_fp_info(pinfo, direction, protocol_name,
1641 atoi((char*)tvb_get_ptr(tvb, variant_start, variant_length)));
1644 /* LTE MAC needs info attached */
1645 else if (strcmp(protocol_name, "mac_r8_lte") == 0) {
1646 parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length));
1647 attach_mac_lte_info(pinfo);
1650 /* LTE RLC needs info attached */
1651 else if (strcmp(protocol_name, "rlc_r8_lte") == 0) {
1652 parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length));
1653 attach_rlc_lte_info(pinfo);
1656 /* LTE PDCP needs info attached */
1657 else if (strcmp(protocol_name, "pdcp_r8_lte") == 0) {
1658 parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length));
1659 attach_pdcp_lte_info(pinfo);
1663 /* Note that the first item of pinfo->pseudo_header->dct2000 will contain
1664 the pseudo-header needed (in some cases) by the Wireshark dissector that
1665 this packet data will be handed off to. */
1668 /***********************************************************************/
1669 /* Now hand off to the dissector of intended packet encapsulation type */
1671 /* Get protocol handle, and set p2p_dir where necessary.
1672 (packet-frame.c won't copy it from pseudo-header because it doesn't
1673 know about Catapult DCT2000 encap type...)
1676 case WTAP_ENCAP_RAW_IP:
1677 protocol_handle = find_dissector("ip");
1679 case WTAP_ENCAP_ETHERNET:
1680 protocol_handle = find_dissector("eth_withoutfcs");
1682 case WTAP_ENCAP_ISDN:
1683 protocol_handle = find_dissector("lapd");
1684 pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton;
1686 case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
1687 protocol_handle = find_dissector("atm_untruncated");
1689 case WTAP_ENCAP_PPP:
1690 protocol_handle = find_dissector("ppp_hdlc");
1691 pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent;
1693 case DCT2000_ENCAP_SSCOP:
1694 protocol_handle = find_dissector("sscop");
1696 case WTAP_ENCAP_FRELAY:
1697 protocol_handle = find_dissector("fr");
1699 case DCT2000_ENCAP_MTP2:
1700 protocol_handle = find_dissector("mtp2");
1702 case DCT2000_ENCAP_NBAP:
1703 protocol_handle = find_dissector("nbap");
1706 case DCT2000_ENCAP_UNHANDLED:
1707 /**********************************************************/
1708 /* The wiretap module wasn't able to set an encapsulation */
1709 /* type, but it may still be possible to dissect the data */
1710 /* if we know about the protocol or if we can recognise */
1711 /* and parse or skip a primitive header */
1712 /**********************************************************/
1714 /* Show context.port in src or dest column as appropriate */
1715 if (direction == 0) {
1716 col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
1718 tvb_get_ptr(tvb, 0, context_length),
1722 if (direction == 1) {
1723 col_add_fstr(pinfo->cinfo, COL_DEF_DST,
1725 tvb_get_ptr(tvb, 0, context_length),
1730 /**************************************************************************/
1731 /* These protocols have no encapsulation type, just look them up directly */
1732 if (strcmp(protocol_name, "mac_r8_lte") == 0) {
1733 protocol_handle = mac_lte_handle;
1737 if (strcmp(protocol_name, "rlc_r8_lte") == 0) {
1738 protocol_handle = rlc_lte_handle;
1742 if (strcmp(protocol_name, "pdcp_r8_lte") == 0) {
1743 /* Dissect proprietary header, then pass remainder to PDCP */
1744 dissect_pdcp_lte(tvb, offset, pinfo, tree);
1749 /* Work with generic XML protocol. */
1751 if (strcmp(protocol_name, "xml") == 0) {
1752 protocol_handle = find_dissector("xml");
1756 /* Attempt to show tty messages as raw text */
1758 if (strcmp(protocol_name, "tty") == 0) {
1759 dissect_tty_lines(tvb, pinfo, dct2000_tree, offset);
1764 if (strcmp(protocol_name, "sipprim") == 0) {
1765 protocol_handle = find_dissector("sipprim");
1769 if (strcmp(protocol_name, "comment") == 0) {
1770 /* Extract & add the string. */
1771 proto_item *string_ti;
1772 char *string = (char*)tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
1774 /* Show comment string */
1775 string_ti = proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_comment, tvb,
1777 col_append_fstr(pinfo->cinfo, COL_INFO, "%s", string);
1779 if (catapult_dct2000_dissect_mac_lte_oob_messages) {
1780 /* Look into string for out-of-band MAC events, such as SRReq, SRInd */
1781 check_for_oob_mac_lte_events(pinfo, tvb, tree, string);
1784 /* Look for and flag generic error messages */
1785 if (strncmp(string, ">> ERR", 6) == 0) {
1786 expert_add_info_format(pinfo, string_ti, PI_SEQUENCE, PI_ERROR,
1794 if (catapult_dct2000_dissect_lte_rrc &&
1795 ((strcmp(protocol_name, "rrc_r8_lte") == 0) ||
1796 (strcmp(protocol_name, "rrcpdcpprim_r8_lte") == 0))) {
1798 /* Dissect proprietary header, then pass remainder
1799 to RRC (depending upon direction and channel type) */
1800 dissect_rrc_lte(tvb, offset, pinfo, tree);
1805 /* Many DCT2000 protocols have at least one IPPrim variant. If the
1806 protocol name can be matched to a dissector, try to find the
1807 UDP/TCP data inside and dissect it.
1810 if (!protocol_handle && catapult_dct2000_try_ipprim_heuristic) {
1811 guint32 source_addr_offset = 0, dest_addr_offset = 0;
1812 guint8 source_addr_length = 0, dest_addr_length = 0;
1813 guint32 source_port_offset = 0, dest_port_offset = 0;
1814 port_type type_of_port = PT_NONE;
1815 guint16 conn_id_offset = 0;
1816 int offset_before_ipprim_header = offset;
1818 /* Will give up if couldn't match protocol anyway... */
1819 heur_protocol_handle = look_for_dissector(protocol_name);
1820 if ((heur_protocol_handle != 0) &&
1821 find_ipprim_data_offset(tvb, &offset, direction,
1822 &source_addr_offset, &source_addr_length,
1823 &dest_addr_offset, &dest_addr_length,
1824 &source_port_offset, &dest_port_offset,
1828 proto_tree *ipprim_tree;
1829 proto_item *ipprim_ti;
1831 /* Will use this dissector then. */
1832 protocol_handle = heur_protocol_handle;
1834 /* Add address parameters to tree */
1835 /* Unfortunately can't automatically create a conversation filter for this...
1836 I *could* create a fake IP header from these details, but then it would be tricky
1837 to get the FP dissector called as it has no well-known ports or heuristics... */
1838 ipprim_ti = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_ipprim_addresses,
1839 tvb, offset_before_ipprim_header, 0,
1840 "", "IPPrim transport (%s): %s:%u -> %s:%u",
1841 (type_of_port == PT_UDP) ? "UDP" : "TCP",
1842 (source_addr_offset) ?
1843 ((source_addr_length == 4) ?
1844 (char *)get_hostname(tvb_get_ipv4(tvb, source_addr_offset)) :
1848 (source_port_offset) ?
1849 tvb_get_ntohs(tvb, source_port_offset) :
1851 (dest_addr_offset) ?
1852 ((source_addr_length == 4) ?
1853 (char *)get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
1857 (dest_port_offset) ?
1858 tvb_get_ntohs(tvb, dest_port_offset) :
1860 if ((type_of_port == PT_TCP) && (conn_id_offset != 0)) {
1861 proto_item_append_text(ipprim_ti, " (conn_id=%u)", tvb_get_ntohs(tvb, conn_id_offset));
1864 /* Add these IPPRIM fields inside an IPPRIM subtree */
1865 ipprim_tree = proto_item_add_subtree(ipprim_ti, ett_catapult_dct2000_ipprim);
1867 /* Try to add right stuff to pinfo so conversation stuff works... */
1868 pinfo->ptype = type_of_port;
1869 switch (type_of_port) {
1871 pinfo->ipproto = IP_PROTO_UDP;
1874 pinfo->ipproto = IP_PROTO_TCP;
1877 pinfo->ipproto = IP_PROTO_NONE;
1880 /* Add addresses & ports into ipprim tree.
1881 Also set address info in pinfo for conversations... */
1882 if (source_addr_offset != 0) {
1883 proto_item *addr_ti;
1885 SET_ADDRESS(&pinfo->net_src,
1886 (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
1888 (tvb_get_ptr(tvb, source_addr_offset, source_addr_length)));
1889 SET_ADDRESS(&pinfo->src,
1890 (source_addr_length == 4) ? AT_IPv4 : AT_IPv6,
1892 (tvb_get_ptr(tvb, source_addr_offset, source_addr_length)));
1894 proto_tree_add_item(ipprim_tree,
1895 (source_addr_length == 4) ?
1896 hf_catapult_dct2000_ipprim_src_addr_v4 :
1897 hf_catapult_dct2000_ipprim_src_addr_v6,
1898 tvb, source_addr_offset, source_addr_length, FALSE);
1900 /* Add hidden item for "side-less" addr */
1901 addr_ti = proto_tree_add_item(ipprim_tree,
1902 (source_addr_length == 4) ?
1903 hf_catapult_dct2000_ipprim_addr_v4 :
1904 hf_catapult_dct2000_ipprim_addr_v6,
1905 tvb, source_addr_offset,
1906 source_addr_length, FALSE);
1907 PROTO_ITEM_SET_HIDDEN(addr_ti);
1909 if (source_port_offset != 0) {
1910 proto_item *port_ti;
1912 pinfo->srcport = tvb_get_ntohs(tvb, source_port_offset);
1914 proto_tree_add_item(ipprim_tree,
1915 (type_of_port == PT_UDP) ?
1916 hf_catapult_dct2000_ipprim_udp_src_port :
1917 hf_catapult_dct2000_ipprim_tcp_src_port,
1918 tvb, source_port_offset, 2, FALSE);
1919 port_ti = proto_tree_add_item(ipprim_tree,
1920 (type_of_port == PT_UDP) ?
1921 hf_catapult_dct2000_ipprim_udp_port :
1922 hf_catapult_dct2000_ipprim_tcp_port,
1923 tvb, source_port_offset, 2, FALSE);
1924 PROTO_ITEM_SET_HIDDEN(port_ti);
1926 if (dest_addr_offset != 0) {
1927 proto_item *addr_ti;
1929 SET_ADDRESS(&pinfo->net_dst,
1930 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
1932 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
1933 SET_ADDRESS(&pinfo->dst,
1934 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
1936 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
1937 proto_tree_add_item(ipprim_tree,
1938 (dest_addr_length == 4) ?
1939 hf_catapult_dct2000_ipprim_dst_addr_v4 :
1940 hf_catapult_dct2000_ipprim_dst_addr_v6,
1941 tvb, dest_addr_offset, dest_addr_length, FALSE);
1943 /* Add hidden item for "side-less" addr */
1944 addr_ti = proto_tree_add_item(ipprim_tree,
1945 (dest_addr_length == 4) ?
1946 hf_catapult_dct2000_ipprim_addr_v4 :
1947 hf_catapult_dct2000_ipprim_addr_v6,
1948 tvb, dest_addr_offset, dest_addr_length, FALSE);
1949 PROTO_ITEM_SET_HIDDEN(addr_ti);
1951 if (dest_port_offset != 0) {
1952 proto_item *port_ti;
1954 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
1956 proto_tree_add_item(ipprim_tree,
1957 (type_of_port == PT_UDP) ?
1958 hf_catapult_dct2000_ipprim_udp_dst_port :
1959 hf_catapult_dct2000_ipprim_tcp_dst_port,
1960 tvb, dest_port_offset, 2, FALSE);
1961 port_ti = proto_tree_add_item(ipprim_tree,
1962 (type_of_port == PT_UDP) ?
1963 hf_catapult_dct2000_ipprim_udp_port :
1964 hf_catapult_dct2000_ipprim_tcp_port,
1965 tvb, dest_port_offset, 2, FALSE);
1966 PROTO_ITEM_SET_HIDDEN(port_ti);
1968 if (conn_id_offset != 0) {
1969 proto_tree_add_item(ipprim_tree,
1970 hf_catapult_dct2000_ipprim_conn_id,
1971 tvb, conn_id_offset, 2, FALSE);
1975 /* Set source and dest columns now (will be overwriiten if
1976 src and dst IP addresses set) */
1977 if (source_addr_offset) {
1978 col_append_fstr(pinfo->cinfo, COL_DEF_SRC,
1980 (char*)get_hostname(tvb_get_ipv4(tvb, source_addr_offset)),
1981 tvb_get_ntohs(tvb, source_port_offset));
1983 if (dest_addr_offset) {
1984 col_append_fstr(pinfo->cinfo, COL_DEF_DST,
1986 (char*)get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)),
1987 tvb_get_ntohs(tvb, dest_port_offset));
1990 /* Set length for IPPrim tree */
1991 proto_item_set_len(ipprim_tree, offset - offset_before_ipprim_header);
1996 /* Try SCTP Prim heuristic if configured to */
1997 if (!protocol_handle && catapult_dct2000_try_sctpprim_heuristic) {
1998 guint32 dest_addr_offset = 0;
1999 guint16 dest_addr_length = 0;
2000 guint32 dest_port_offset = 0;
2001 int offset_before_sctpprim_header = offset;
2003 heur_protocol_handle = look_for_dissector(protocol_name);
2004 if ((heur_protocol_handle != 0) &&
2005 (find_sctpprim_variant1_data_offset(tvb, &offset,
2008 &dest_port_offset) ||
2009 find_sctpprim_variant3_data_offset(tvb, &offset,
2012 &dest_port_offset))) {
2014 proto_tree *sctpprim_tree;
2015 proto_item *ti_local;
2017 /* Will use this dissector then. */
2018 protocol_handle = heur_protocol_handle;
2020 ti_local = proto_tree_add_string_format(dct2000_tree, hf_catapult_dct2000_sctpprim_addresses,
2021 tvb, offset_before_sctpprim_header, 0,
2022 "", "SCTPPrim transport: -> %s:%u",
2023 (dest_addr_offset) ?
2024 ((dest_addr_length == 4) ?
2025 (char *)get_hostname(tvb_get_ipv4(tvb, dest_addr_offset)) :
2029 (dest_port_offset) ?
2030 tvb_get_ntohs(tvb, dest_port_offset) :
2033 /* Add these SCTPPRIM fields inside an SCTPPRIM subtree */
2034 sctpprim_tree = proto_item_add_subtree(ti_local, ett_catapult_dct2000_sctpprim);
2036 pinfo->ipproto = IP_PROTO_SCTP;
2038 /* Destination address */
2039 if (dest_addr_offset != 0) {
2040 proto_item *addr_ti;
2042 SET_ADDRESS(&pinfo->net_dst,
2043 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2045 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2046 SET_ADDRESS(&pinfo->dst,
2047 (dest_addr_length == 4) ? AT_IPv4 : AT_IPv6,
2049 (tvb_get_ptr(tvb, dest_addr_offset, dest_addr_length)));
2050 proto_tree_add_item(sctpprim_tree,
2051 (dest_addr_length == 4) ?
2052 hf_catapult_dct2000_sctpprim_dst_addr_v4 :
2053 hf_catapult_dct2000_sctpprim_dst_addr_v6,
2054 tvb, dest_addr_offset, dest_addr_length, FALSE);
2056 /* Add hidden item for "side-less" addr */
2057 addr_ti = proto_tree_add_item(sctpprim_tree,
2058 (dest_addr_length == 4) ?
2059 hf_catapult_dct2000_sctpprim_addr_v4 :
2060 hf_catapult_dct2000_sctpprim_addr_v6,
2061 tvb, dest_addr_offset, dest_addr_length, FALSE);
2062 PROTO_ITEM_SET_HIDDEN(addr_ti);
2065 if (dest_port_offset != 0) {
2066 pinfo->destport = tvb_get_ntohs(tvb, dest_port_offset);
2068 proto_tree_add_item(sctpprim_tree,
2069 hf_catapult_dct2000_sctpprim_dst_port,
2070 tvb, dest_port_offset, 2, FALSE);
2073 /* Set length for SCTPPrim tree */
2074 proto_item_set_len(sctpprim_tree, offset - offset_before_sctpprim_header);
2081 /* !! If get here, there is a mismatch between
2082 this dissector and the wiretap module catapult_dct2000.c !!
2084 DISSECTOR_ASSERT_NOT_REACHED();
2089 /* Try appropriate dissector, if one has been selected */
2090 if (protocol_handle != 0) {
2091 /* Dissect the remainder of the frame using chosen protocol handle */
2092 next_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
2093 sub_dissector_result = call_dissector_only(protocol_handle, next_tvb, pinfo, tree);
2097 if (protocol_handle == 0 || sub_dissector_result == 0) {
2098 /* Could get here because:
2099 - encap is DCT2000_ENCAP_UNHANDLED and we still didn't handle it, OR
2100 - desired protocol is unavailable (probably disabled), OR
2101 - protocol rejected our data
2102 Show remaining bytes as unparsed data */
2103 proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_unparsed_data,
2104 tvb, offset, -1, FALSE);
2106 col_add_fstr(pinfo->cinfo, COL_INFO,
2107 "Not dissected (context=%s.%u t=%s %c prot=%s (v=%s))",
2108 tvb_get_ptr(tvb, 0, context_length),
2110 tvb_get_ptr(tvb, timestamp_start, timestamp_length),
2111 (direction == 0) ? 'S' : 'R',
2112 tvb_get_ptr(tvb, protocol_start, protocol_length),
2113 tvb_get_ptr(tvb, variant_start, variant_length));
2116 /* Show number of dissected bytes */
2118 proto_item *ti_local = proto_tree_add_uint(dct2000_tree,
2119 hf_catapult_dct2000_dissected_length,
2120 tvb, 0, 0, tvb_reported_length(tvb)-offset);
2121 PROTO_ITEM_SET_GENERATED(ti_local);
2128 /******************************************************************************/
2129 /* Associate this protocol with the Catapult DCT2000 file encapsulation type. */
2130 /******************************************************************************/
2131 void proto_reg_handoff_catapult_dct2000(void)
2133 dissector_handle_t catapult_dct2000_handle = find_dissector("dct2000");
2135 dissector_add("wtap_encap", WTAP_ENCAP_CATAPULT_DCT2000, catapult_dct2000_handle);
2137 mac_lte_handle = find_dissector("mac-lte");
2138 rlc_lte_handle = find_dissector("rlc-lte");
2139 pdcp_lte_handle = find_dissector("pdcp-lte");
2142 /****************************************/
2143 /* Register the protocol */
2144 /****************************************/
2145 void proto_register_catapult_dct2000(void)
2147 static hf_register_info hf[] =
2149 { &hf_catapult_dct2000_context,
2151 "dct2000.context", FT_STRING, BASE_NONE, NULL, 0x0,
2152 "Context name", HFILL
2155 { &hf_catapult_dct2000_port_number,
2156 { "Context Port number",
2157 "dct2000.context_port", FT_UINT8, BASE_DEC, NULL, 0x0,
2161 { &hf_catapult_dct2000_timestamp,
2163 "dct2000.timestamp", FT_DOUBLE, BASE_NONE, NULL, 0x0,
2164 "File timestamp", HFILL
2167 { &hf_catapult_dct2000_protocol,
2168 { "DCT2000 protocol",
2169 "dct2000.protocol", FT_STRING, BASE_NONE, NULL, 0x0,
2170 "Original (DCT2000) protocol name", HFILL
2173 { &hf_catapult_dct2000_variant,
2174 { "Protocol variant",
2175 "dct2000.variant", FT_STRING, BASE_NONE, NULL, 0x0,
2176 "DCT2000 protocol variant", HFILL
2179 { &hf_catapult_dct2000_outhdr,
2181 "dct2000.outhdr", FT_STRING, BASE_NONE, NULL, 0x0,
2182 "DCT2000 protocol outhdr", HFILL
2185 { &hf_catapult_dct2000_direction,
2187 "dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2188 "Frame direction (Sent or Received)", HFILL
2191 { &hf_catapult_dct2000_encap,
2192 { "Wireshark encapsulation",
2193 "dct2000.encapsulation", FT_UINT8, BASE_DEC, VALS(encap_vals), 0x0,
2194 "Wireshark frame encapsulation used", HFILL
2197 { &hf_catapult_dct2000_unparsed_data,
2198 { "Unparsed protocol data",
2199 "dct2000.unparsed_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2200 "Unparsed DCT2000 protocol data", HFILL
2203 { &hf_catapult_dct2000_comment,
2205 "dct2000.comment", FT_STRING, BASE_NONE, NULL, 0x0,
2209 { &hf_catapult_dct2000_dissected_length,
2210 { "Dissected length",
2211 "dct2000.dissected-length", FT_UINT16, BASE_DEC, NULL, 0x0,
2212 "Number of bytes dissected by subdissector(s)", HFILL
2216 { &hf_catapult_dct2000_ipprim_addresses,
2217 { "IPPrim Addresses",
2218 "dct2000.ipprim", FT_STRING, BASE_NONE, NULL, 0x0,
2222 { &hf_catapult_dct2000_ipprim_src_addr_v4,
2224 "dct2000.ipprim.src", FT_IPv4, BASE_NONE, NULL, 0x0,
2225 "IPPrim IPv4 Source Address", HFILL
2228 { &hf_catapult_dct2000_ipprim_src_addr_v6,
2230 "dct2000.ipprim.srcv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2231 "IPPrim IPv6 Source Address", HFILL
2234 { &hf_catapult_dct2000_ipprim_dst_addr_v4,
2235 { "Destination Address",
2236 "dct2000.ipprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2237 "IPPrim IPv4 Destination Address", HFILL
2240 { &hf_catapult_dct2000_ipprim_dst_addr_v6,
2241 { "Destination Address",
2242 "dct2000.ipprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2243 "IPPrim IPv6 Destination Address", HFILL
2246 { &hf_catapult_dct2000_ipprim_addr_v4,
2248 "dct2000.ipprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
2249 "IPPrim IPv4 Address", HFILL
2252 { &hf_catapult_dct2000_ipprim_addr_v6,
2254 "dct2000.ipprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2255 "IPPrim IPv6 Address", HFILL
2258 { &hf_catapult_dct2000_ipprim_udp_src_port,
2259 { "UDP Source Port",
2260 "dct2000.ipprim.udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
2261 "IPPrim UDP Source Port", HFILL
2264 { &hf_catapult_dct2000_ipprim_udp_dst_port,
2265 { "UDP Destination Port",
2266 "dct2000.ipprim.udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
2267 "IPPrim UDP Destination Port", HFILL
2270 { &hf_catapult_dct2000_ipprim_udp_port,
2272 "dct2000.ipprim.udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
2273 "IPPrim UDP Port", HFILL
2276 { &hf_catapult_dct2000_ipprim_tcp_src_port,
2277 { "TCP Source Port",
2278 "dct2000.ipprim.tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
2279 "IPPrim TCP Source Port", HFILL
2282 { &hf_catapult_dct2000_ipprim_tcp_dst_port,
2283 { "TCP Destination Port",
2284 "dct2000.ipprim.tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
2285 "IPPrim TCP Destination Port", HFILL
2288 { &hf_catapult_dct2000_ipprim_tcp_port,
2290 "dct2000.ipprim.tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
2291 "IPPrim TCP Port", HFILL
2294 { &hf_catapult_dct2000_ipprim_conn_id,
2296 "dct2000.ipprim.conn-id", FT_UINT16, BASE_DEC, NULL, 0x0,
2297 "IPPrim TCP Connection ID", HFILL
2301 { &hf_catapult_dct2000_sctpprim_addresses,
2302 { "SCTPPrim Addresses",
2303 "dct2000.sctpprim", FT_STRING, BASE_NONE, NULL, 0x0,
2307 { &hf_catapult_dct2000_sctpprim_dst_addr_v4,
2308 { "Destination Address",
2309 "dct2000.sctpprim.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2310 "SCTPPrim IPv4 Destination Address", HFILL
2313 { &hf_catapult_dct2000_sctpprim_dst_addr_v6,
2314 { "Destination Address",
2315 "dct2000.sctpprim.dstv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2316 "SCTPPrim IPv6 Destination Address", HFILL
2319 { &hf_catapult_dct2000_sctpprim_addr_v4,
2321 "dct2000.sctpprim.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
2322 "SCTPPrim IPv4 Address", HFILL
2325 { &hf_catapult_dct2000_sctpprim_addr_v6,
2327 "dct2000.sctpprim.addrv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2328 "SCTPPrim IPv6 Address", HFILL
2331 { &hf_catapult_dct2000_sctpprim_dst_port,
2332 { "UDP Destination Port",
2333 "dct2000.sctprim.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
2334 "SCTPPrim Destination Port", HFILL
2338 { &hf_catapult_dct2000_tty,
2340 "dct2000.tty", FT_NONE, BASE_NONE, NULL, 0x0,
2344 { &hf_catapult_dct2000_tty_line,
2346 "dct2000.tty-line", FT_STRING, BASE_NONE, NULL, 0x0,
2351 { &hf_catapult_dct2000_lte_ueid,
2353 "dct2000.lte.ueid", FT_UINT16, BASE_DEC, NULL, 0x0,
2354 "User Equipment Identifier", HFILL
2357 { &hf_catapult_dct2000_lte_srbid,
2359 "dct2000.lte.srbid", FT_UINT8, BASE_DEC, NULL, 0x0,
2360 "Signalling Radio Bearer Identifier", HFILL
2363 { &hf_catapult_dct2000_lte_drbid,
2365 "dct2000.lte.drbid", FT_UINT8, BASE_DEC, NULL, 0x0,
2366 "Data Radio Bearer Identifier", HFILL
2369 { &hf_catapult_dct2000_lte_cellid,
2371 "dct2000.lte.cellid", FT_UINT16, BASE_DEC, NULL, 0x0,
2372 "Cell Identifier", HFILL
2375 { &hf_catapult_dct2000_lte_bcch_transport,
2377 "dct2000.lte.bcch-transport", FT_UINT16, BASE_DEC, VALS(bcch_transport_vals), 0x0,
2378 "BCCH Transport Channel", HFILL
2381 { &hf_catapult_dct2000_lte_rlc_op,
2383 "dct2000.lte.rlc-op", FT_UINT8, BASE_DEC, VALS(rlc_op_vals), 0x0,
2384 "RLC top-level op", HFILL
2387 { &hf_catapult_dct2000_lte_rlc_channel_type,
2388 { "RLC Logical Channel Type",
2389 "dct2000.lte.rlc-logchan-type", FT_UINT8, BASE_DEC, VALS(rlc_logical_channel_vals), 0x0,
2393 { &hf_catapult_dct2000_lte_rlc_mui,
2395 "dct2000.lte.rlc-mui", FT_UINT16, BASE_DEC, NULL, 0x0,
2399 { &hf_catapult_dct2000_lte_rlc_cnf,
2401 "dct2000.lte.rlc-cnf", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
2405 { &hf_catapult_dct2000_lte_rlc_discard_req,
2407 "dct2000.lte.rlc-discard-req", FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
2408 "RLC Discard Req", HFILL
2413 static gint *ett[] =
2415 &ett_catapult_dct2000,
2416 &ett_catapult_dct2000_ipprim,
2417 &ett_catapult_dct2000_sctpprim,
2418 &ett_catapult_dct2000_tty
2421 module_t *catapult_dct2000_module;
2423 /* Register protocol. */
2424 proto_catapult_dct2000 = proto_register_protocol("Catapult DCT2000 packet",
2427 proto_register_field_array(proto_catapult_dct2000, hf, array_length(hf));
2428 proto_register_subtree_array(ett, array_length(ett));
2430 /* Allow dissector to find be found by name. */
2431 register_dissector("dct2000", dissect_catapult_dct2000, proto_catapult_dct2000);
2434 catapult_dct2000_module = prefs_register_protocol(proto_catapult_dct2000, NULL);
2436 /* This preference no longer supported (introduces linkage dependency between
2437 dissectors and wiretap) */
2438 prefs_register_obsolete_preference(catapult_dct2000_module, "board_ports_only");
2440 /* Determines whether for not-handled protocols we should try to parse it if:
2441 - it looks like its embedded in an ipprim message, AND
2442 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
2443 prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
2444 "Use IP Primitive heuristic",
2445 "If a payload looks like its embedded in an "
2446 "IP primitive message, and there is a Wireshark "
2447 "dissector matching the DCT2000 protocol name, "
2448 "try parsing the payload using that dissector",
2449 &catapult_dct2000_try_ipprim_heuristic);
2451 /* Determines whether for not-handled protocols we should try to parse it if:
2452 - it looks like its embedded in an sctpprim message, AND
2453 - the DCT2000 protocol name can be matched to a Wireshark dissector name */
2454 prefs_register_bool_preference(catapult_dct2000_module, "sctpprim_heuristic",
2455 "Use SCTP Primitive heuristic",
2456 "If a payload looks like its embedded in an "
2457 "SCTP primitive message, and there is a Wireshark "
2458 "dissector matching the DCT2000 protocol name, "
2459 "try parsing the payload using that dissector",
2460 &catapult_dct2000_try_sctpprim_heuristic);
2462 /* Determines whether LTE RRC messages should be dissected */
2463 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_rrc",
2464 "Attempt to decode LTE RRC frames",
2465 "When set, attempt to decode LTE RRC frames. "
2466 "Note that this won't affect other protocols "
2467 "that also call the LTE RRC dissector",
2468 &catapult_dct2000_dissect_lte_rrc);
2470 /* Determines whether LTE S1AP messages should be dissected */
2471 prefs_register_bool_preference(catapult_dct2000_module, "decode_lte_s1ap",
2472 "Attempt to decode LTE S1AP frames",
2473 "When set, attempt to decode LTE S1AP frames. "
2474 "Note that this won't affect other protocols "
2475 "that also call the LTE S1AP dissector",
2476 &catapult_dct2000_dissect_lte_s1ap);
2478 /* Determines whether out-of-band messages should dissected */
2479 prefs_register_bool_preference(catapult_dct2000_module, "decode_mac_lte_oob_messages",
2480 "Look for out-of-band LTE MAC events messages in comments",
2481 "When set, look for formatted messages indicating "
2482 "specific events. This may be quite slow, so should "
2483 "be disabled if LTE MAC is not being analysed",
2484 &catapult_dct2000_dissect_mac_lte_oob_messages);