2 * Routines for M3 Application Protocol packet dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
10 * Reference: 3GPP TS 36.444 v16.0.0
15 #include <epan/packet.h>
17 #include <epan/strutil.h>
18 #include <epan/asn1.h>
19 #include <epan/sctpppids.h>
20 #include <epan/expert.h>
21 #include <epan/proto_data.h>
22 #include <epan/unit_strings.h>
23 #include <wsutil/array.h>
25 #include "packet-ber.h"
26 #include "packet-per.h"
27 #include "packet-e212.h"
28 #include "packet-gtpv2.h"
30 #define PNAME "M3 Application Protocol"
34 void proto_register_m3ap(void);
35 void proto_reg_handoff_m3ap(void);
37 /* M3AP uses port 36444 as recommended by IANA. */
38 #define M3AP_PORT 36444
39 static dissector_handle_t m3ap_handle
;
41 #include "packet-m3ap-val.h"
43 /* Initialize the protocol and registered fields */
44 static int proto_m3ap
;
46 static int hf_m3ap_Absolute_Time_ofMBMS_Data_value
;
47 static int hf_m3ap_IPAddress_v4
;
48 static int hf_m3ap_IPAddress_v6
;
50 #include "packet-m3ap-hf.c"
52 /* Initialize the subtree pointers */
54 static int ett_m3ap_IPAddress
;
55 #include "packet-m3ap-ett.c"
57 static expert_field ei_m3ap_invalid_ip_address_len
;
59 struct m3ap_private_data
{
60 e212_number_type_t number_type
;
69 /* Global variables */
70 static uint32_t ProcedureCode
;
71 static uint32_t ProtocolIE_ID
;
72 /*static uint32_t ProtocolExtensionID; */
73 static int global_m3ap_port
= M3AP_PORT
;
74 static uint32_t message_type
;
76 /* Dissector tables */
77 static dissector_table_t m3ap_ies_dissector_table
;
78 static dissector_table_t m3ap_extension_dissector_table
;
79 static dissector_table_t m3ap_proc_imsg_dissector_table
;
80 static dissector_table_t m3ap_proc_sout_dissector_table
;
81 static dissector_table_t m3ap_proc_uout_dissector_table
;
83 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
84 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
85 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
86 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
87 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
89 static struct m3ap_private_data
*
90 m3ap_get_private_data(packet_info
*pinfo
)
92 struct m3ap_private_data
*m3ap_data
= (struct m3ap_private_data
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_m3ap
, 0);
94 m3ap_data
= wmem_new0(pinfo
->pool
, struct m3ap_private_data
);
95 p_add_proto_data(pinfo
->pool
, pinfo
, proto_m3ap
, 0, m3ap_data
);
100 #include "packet-m3ap-fn.c"
102 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
104 return (dissector_try_uint_new(m3ap_ies_dissector_table
, ProtocolIE_ID
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
107 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
109 return (dissector_try_uint_new(m3ap_extension_dissector_table
, ProtocolIE_ID
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
112 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
114 return (dissector_try_uint_new(m3ap_proc_imsg_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
117 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
119 return (dissector_try_uint_new(m3ap_proc_sout_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
122 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
124 return (dissector_try_uint_new(m3ap_proc_uout_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
129 dissect_m3ap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
131 proto_item
*m3ap_item
= NULL
;
132 proto_tree
*m3ap_tree
= NULL
;
134 /* make entry in the Protocol column on summary display */
135 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PSNAME
);
136 col_clear_fence(pinfo
->cinfo
, COL_INFO
);
137 col_clear(pinfo
->cinfo
, COL_INFO
);
139 /* create the m3ap protocol tree */
140 m3ap_item
= proto_tree_add_item(tree
, proto_m3ap
, tvb
, 0, -1, ENC_NA
);
141 m3ap_tree
= proto_item_add_subtree(m3ap_item
, ett_m3ap
);
143 dissect_M3AP_PDU_PDU(tvb
, pinfo
, m3ap_tree
, NULL
);
144 return tvb_captured_length(tvb
);
146 /*--- proto_register_m3ap -------------------------------------------*/
147 void proto_register_m3ap(void) {
150 static hf_register_info hf
[] = {
151 { &hf_m3ap_Absolute_Time_ofMBMS_Data_value
,
152 { "Absolute-Time-ofMBMS-Data-value", "m3ap.Absolute_Time_ofMBMS_Data_value",
153 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_NTP_UTC
, NULL
, 0,
156 { &hf_m3ap_IPAddress_v4
,
157 { "IPAddress", "m3ap.IPAddress_v4",
158 FT_IPv4
, BASE_NONE
, NULL
, 0,
161 { &hf_m3ap_IPAddress_v6
,
162 { "IPAddress", "m3ap.IPAddress_v6",
163 FT_IPv6
, BASE_NONE
, NULL
, 0,
167 #include "packet-m3ap-hfarr.c"
170 /* List of subtrees */
171 static int *ett
[] = {
174 #include "packet-m3ap-ettarr.c"
177 expert_module_t
* expert_m3ap
;
179 static ei_register_info ei
[] = {
180 { &ei_m3ap_invalid_ip_address_len
, { "m3ap.invalid_ip_address_len", PI_MALFORMED
, PI_ERROR
, "Invalid IP address length", EXPFILL
}}
183 /* Register protocol */
184 proto_m3ap
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
185 /* Register fields and subtrees */
186 proto_register_field_array(proto_m3ap
, hf
, array_length(hf
));
187 proto_register_subtree_array(ett
, array_length(ett
));
188 expert_m3ap
= expert_register_protocol(proto_m3ap
);
189 expert_register_field_array(expert_m3ap
, ei
, array_length(ei
));
190 /* Register dissector */
191 m3ap_handle
= register_dissector(PFNAME
, dissect_m3ap
, proto_m3ap
);
193 /* Register dissector tables */
194 m3ap_ies_dissector_table
= register_dissector_table("m3ap.ies", "M3AP-PROTOCOL-IES", proto_m3ap
, FT_UINT32
, BASE_DEC
);
195 m3ap_extension_dissector_table
= register_dissector_table("m3ap.extension", "M3AP-PROTOCOL-EXTENSION", proto_m3ap
, FT_UINT32
, BASE_DEC
);
196 m3ap_proc_imsg_dissector_table
= register_dissector_table("m3ap.proc.imsg", "M3AP-ELEMENTARY-PROCEDURE InitiatingMessage", proto_m3ap
, FT_UINT32
, BASE_DEC
);
197 m3ap_proc_sout_dissector_table
= register_dissector_table("m3ap.proc.sout", "M3AP-ELEMENTARY-PROCEDURE SuccessfulOutcome", proto_m3ap
, FT_UINT32
, BASE_DEC
);
198 m3ap_proc_uout_dissector_table
= register_dissector_table("m3ap.proc.uout", "M3AP-ELEMENTARY-PROCEDURE UnsuccessfulOutcome", proto_m3ap
, FT_UINT32
, BASE_DEC
);
202 /*--- proto_reg_handoff_m3ap ---------------------------------------*/
204 proto_reg_handoff_m3ap(void)
206 static bool inited
= false;
207 static unsigned SctpPort
;
210 dissector_add_uint("sctp.ppi", PROTO_3GPP_M3AP_PROTOCOL_ID
, m3ap_handle
);
212 #include "packet-m3ap-dis-tab.c"
213 dissector_add_uint("m3ap.extension", 17, create_dissector_handle(dissect_AllocationAndRetentionPriority_PDU
, proto_m3ap
));
217 dissector_delete_uint("sctp.port", SctpPort
, m3ap_handle
);
221 SctpPort
= global_m3ap_port
;
223 dissector_add_uint("sctp.port", SctpPort
, m3ap_handle
);