Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / asn1 / ranap / packet-ranap-template.c
blobc356a2a74b2b26de82b412a0f4ee429cfd443f8b
1 /* packet-ranap.c
2 * Routines for UMTS Node B Application Part(RANAP) packet dissection
3 * Copyright 2005 - 2010, Anders Broman <anders.broman[AT]ericsson.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * References: 3GPP TS 25.413 version 10.4.0 Release 10
14 #include "config.h"
16 #include <epan/packet.h>
18 #include <epan/strutil.h>
19 #include <epan/asn1.h>
20 #include <epan/prefs.h>
21 #include <epan/proto_data.h>
22 #include <wsutil/array.h>
24 #include "packet-ber.h"
25 #include "packet-per.h"
26 #include "packet-gsm_map.h"
27 #include "packet-ranap.h"
28 #include "packet-e212.h"
29 #include "packet-sccp.h"
30 #include "packet-gsm_a_common.h"
31 #include "packet-isup.h"
32 #include "packet-s1ap.h"
33 #include "packet-rtp.h"
35 #ifdef _MSC_VER
36 /* disable: "warning C4146: unary minus operator applied to unsigned type, result still unsigned" */
37 #pragma warning(disable:4146)
38 #endif
40 #define SCCP_SSN_RANAP 142
42 #define PNAME "Radio Access Network Application Part"
43 #define PSNAME "RANAP"
44 #define PFNAME "ranap"
46 /* Highest Ranap_ProcedureCode_value, use in heuristics */
47 #define RANAP_MAX_PC 49 /* id_RerouteNASRequest = 49 */
49 #include "packet-ranap-val.h"
51 void proto_register_ranap(void);
52 void proto_reg_handoff_ranap(void);
54 /* Initialize the protocol and registered fields */
55 static int proto_ranap;
57 /* initialise sub-dissector handles */
58 static dissector_handle_t rrc_s_to_trnc_handle;
59 static dissector_handle_t rrc_t_to_srnc_handle;
60 static dissector_handle_t rrc_ho_to_utran_cmd;
61 static dissector_handle_t bssgp_handle;
63 static int hf_ranap_transportLayerAddress_ipv4;
64 static int hf_ranap_transportLayerAddress_ipv6;
65 static int hf_ranap_transportLayerAddress_nsap;
67 #include "packet-ranap-hf.c"
69 /* Initialize the subtree pointers */
70 static int ett_ranap;
71 static int ett_ranap_transportLayerAddress;
72 static int ett_ranap_transportLayerAddress_nsap;
74 #include "packet-ranap-ett.c"
76 /*****************************************************************************/
77 /* Packet private data */
78 /* For this dissector, all access to actx->private_data should be made */
79 /* through this API, which ensures that they will not overwrite each other!! */
80 /*****************************************************************************/
83 typedef struct ranap_private_data_t
85 uint32_t transportLayerAddress_ipv4;
86 uint16_t binding_id_port;
87 e212_number_type_t number_type;
88 } ranap_private_data_t;
91 /* Helper function to get or create the private data struct */
92 static ranap_private_data_t* ranap_get_private_data(asn1_ctx_t *actx)
94 packet_info *pinfo = actx->pinfo;
95 ranap_private_data_t *private_data = (ranap_private_data_t *)p_get_proto_data(pinfo->pool, pinfo, proto_ranap, 0);
96 if(private_data == NULL ) {
97 private_data = wmem_new0(pinfo->pool, ranap_private_data_t);
98 p_add_proto_data(pinfo->pool, pinfo, proto_ranap, 0, private_data);
100 return private_data;
103 /* Helper function to reset the private data struct */
104 static void ranap_reset_private_data(packet_info *pinfo)
106 p_remove_proto_data(pinfo->pool, pinfo, proto_ranap, 0);
109 static uint32_t private_data_get_transportLayerAddress_ipv4(asn1_ctx_t *actx)
111 ranap_private_data_t *private_data = (ranap_private_data_t*)ranap_get_private_data(actx);
112 return private_data->transportLayerAddress_ipv4;
115 static void private_data_set_transportLayerAddress_ipv4(asn1_ctx_t *actx, uint32_t transportLayerAddress_ipv4)
117 ranap_private_data_t *private_data = (ranap_private_data_t*)ranap_get_private_data(actx);
118 private_data->transportLayerAddress_ipv4 = transportLayerAddress_ipv4;
121 static uint16_t private_data_get_binding_id_port(asn1_ctx_t *actx)
123 ranap_private_data_t *private_data = (ranap_private_data_t*)ranap_get_private_data(actx);
124 return private_data->binding_id_port;
127 static void private_data_set_binding_id_port(asn1_ctx_t *actx, uint16_t binding_id_port)
129 ranap_private_data_t *private_data = (ranap_private_data_t*)ranap_get_private_data(actx);
130 private_data->binding_id_port = binding_id_port;
133 /*****************************************************************************/
136 /* Global variables */
137 static uint32_t ProcedureCode;
138 static uint32_t ProtocolIE_ID;
139 static uint32_t ProtocolExtensionID;
140 static bool glbl_dissect_container;
142 static dissector_handle_t ranap_handle;
144 /* Some IE:s identities uses the same value for different IE:s
145 * depending on PDU type:
146 * InitiatingMessage
147 * SuccessfulOutcome
148 * UnsuccessfulOutcome
149 * Outcome
150 * As a workarond a value is added to the IE:id in the .cnf file.
151 * Example:
152 * ResetResourceList N rnsap.ies IMSG||id-IuSigConIdList # no spaces are allowed in value as a space is delimiter
153 * PDU type is stored in a global variable and can is used in the IE decoding section.
156 * &InitiatingMessage ,
157 * &SuccessfulOutcome OPTIONAL,
158 * &UnsuccessfulOutcome OPTIONAL,
159 * &Outcome OPTIONAL,
161 * Only these two needed currently
163 #define IMSG (1U<<16)
164 #define SOUT (2U<<16)
165 #define SPECIAL (4U<<16)
167 int pdu_type; /* 0 means wildcard */
169 /* Dissector tables */
170 static dissector_table_t ranap_ies_dissector_table;
171 static dissector_table_t ranap_ies_p1_dissector_table;
172 static dissector_table_t ranap_ies_p2_dissector_table;
173 static dissector_table_t ranap_extension_dissector_table;
174 static dissector_table_t ranap_proc_imsg_dissector_table;
175 static dissector_table_t ranap_proc_sout_dissector_table;
176 static dissector_table_t ranap_proc_uout_dissector_table;
177 static dissector_table_t ranap_proc_out_dissector_table;
178 static dissector_table_t nas_pdu_dissector_table;
180 static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
181 static int dissect_ProtocolIEFieldPairFirstValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
182 static int dissect_ProtocolIEFieldPairSecondValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
183 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
184 static int dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
185 static int dissect_SuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
186 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
187 static int dissect_OutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *);
189 static int dissect_ranap_SourceRNC_ToTargetRNC_TransparentContainer(tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index);
190 static int dissect_ranap_TargetRNC_ToSourceRNC_TransparentContainer(tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index);
193 #include "packet-ranap-fn.c"
195 static int
196 dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
199 int ret = 0;
200 int key;
202 /* Special handling, same ID used for different IE's depending on signal */
203 switch(ProcedureCode){
204 case id_RelocationPreparation:
205 if((ProtocolIE_ID == id_Source_ToTarget_TransparentContainer)||(ProtocolIE_ID == id_Target_ToSource_TransparentContainer)){
206 key = SPECIAL | ProtocolIE_ID;
207 ret = (dissector_try_uint_with_data(ranap_ies_dissector_table, key, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
208 break;
210 /* Fall through */
211 default:
212 /* no special handling */
213 ret = (dissector_try_uint_with_data(ranap_ies_dissector_table, ProtocolIE_ID, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
214 if (ret == 0) {
215 key = pdu_type | ProtocolIE_ID;
216 ret = (dissector_try_uint_with_data(ranap_ies_dissector_table, key, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
218 break;
220 return ret;
223 static int
224 dissect_ProtocolIEFieldPairFirstValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
226 return (dissector_try_uint_with_data(ranap_ies_p1_dissector_table, ProtocolIE_ID, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
229 static int
230 dissect_ProtocolIEFieldPairSecondValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
232 return (dissector_try_uint_with_data(ranap_ies_p2_dissector_table, ProtocolIE_ID, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
235 static int
236 dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
238 return (dissector_try_uint_with_data(ranap_extension_dissector_table, ProtocolExtensionID, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
241 static int
242 dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
244 bool ret;
246 pdu_type = IMSG;
247 ret = dissector_try_uint_with_data(ranap_proc_imsg_dissector_table, ProcedureCode, tvb, pinfo, tree, false, NULL);
248 pdu_type = 0;
249 return ret ? tvb_captured_length(tvb) : 0;
252 static int
253 dissect_SuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
255 bool ret;
257 pdu_type = SOUT;
258 ret = dissector_try_uint_with_data(ranap_proc_sout_dissector_table, ProcedureCode, tvb, pinfo, tree, false, NULL);
259 pdu_type = 0;
260 return ret ? tvb_captured_length(tvb) : 0;
263 static int
264 dissect_UnsuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
266 return (dissector_try_uint_with_data(ranap_proc_uout_dissector_table, ProcedureCode, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
269 static int
270 dissect_OutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
272 return (dissector_try_uint_with_data(ranap_proc_out_dissector_table, ProcedureCode, tvb, pinfo, tree, false, NULL)) ? tvb_captured_length(tvb) : 0;
275 static int
276 dissect_ranap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
278 proto_item *ranap_item = NULL;
279 proto_tree *ranap_tree = NULL;
280 sccp_msg_info_t *sccp_msg_lcl = (sccp_msg_info_t *)data;
282 pdu_type = 0;
283 ProtocolIE_ID = 0;
285 /* make entry in the Protocol column on summary display */
286 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RANAP");
288 /* create the ranap protocol tree */
289 ranap_item = proto_tree_add_item(tree, proto_ranap, tvb, 0, -1, ENC_NA);
290 ranap_tree = proto_item_add_subtree(ranap_item, ett_ranap);
292 /* Save the sccp_msg_info_t data (if present) because it can't be passed
293 through function calls */
294 p_add_proto_data(pinfo->pool, pinfo, proto_ranap, pinfo->curr_layer_num, data);
296 /* Clearing any old 'private data' stored */
297 ranap_reset_private_data(pinfo);
299 dissect_RANAP_PDU_PDU(tvb, pinfo, ranap_tree, NULL);
300 if (sccp_msg_lcl) {
302 if (sccp_msg_lcl->data.co.assoc)
303 sccp_msg_lcl->data.co.assoc->payload = SCCP_PLOAD_RANAP;
305 if (! sccp_msg_lcl->data.co.label && ProcedureCode != 0xFFFFFFFF) {
306 const char* str = val_to_str_const(ProcedureCode, ranap_ProcedureCode_vals, "Unknown RANAP");
307 sccp_msg_lcl->data.co.label = wmem_strdup(wmem_file_scope(), str);
311 return tvb_reported_length(tvb);
314 #define RANAP_MSG_MIN_LENGTH 7
315 static bool
316 dissect_sccp_ranap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
318 uint8_t temp;
319 uint16_t word;
320 unsigned length;
321 int offset;
323 /* Is it a ranap packet?
325 * 4th octet should be the length of the rest of the message.
326 * 3th octed is the Criticality field
327 * 2nd octet is the message-type e Z[0, 28]
328 * 1st octet is the PDU type (with the extension bit)
329 * (obviously there must be at least four octets)
331 * If all of them hold true we'll assume it's RANAP
334 #define LENGTH_OFFSET 3
335 #define CRIT_OFFSET 2
336 #define MSG_TYPE_OFFSET 1
337 #define PDU_TYPE_OFFSET 0
338 if (tvb_captured_length(tvb) < RANAP_MSG_MIN_LENGTH) { return false; }
340 temp = tvb_get_uint8(tvb, PDU_TYPE_OFFSET);
341 if (temp & 0x1F) {
342 /* PDU Type byte is not 0x00 (initiatingMessage), 0x20 (succesfulOutcome),
343 0x40 (unsuccesfulOutcome) or 0x60 (outcome), ignore extension bit (0x80) */
344 return false;
347 temp = tvb_get_uint8(tvb, CRIT_OFFSET);
348 if (temp == 0xC0 || temp & 0x3F) {
349 /* Criticality byte is not 0x00 (reject), 0x40 (ignore) or 0x80 (notify) */
350 return false;
353 /* compute aligned PER length determinant without calling dissect_per_length_determinant()
354 to avoid exceptions and info added to tree, info column and expert info */
355 offset = LENGTH_OFFSET;
356 length = tvb_get_uint8(tvb, offset);
357 offset += 1;
358 if ((length & 0x80) == 0x80) {
359 if ((length & 0xc0) == 0x80) {
360 length &= 0x3f;
361 length <<= 8;
362 length += tvb_get_uint8(tvb, offset);
363 offset += 1;
364 } else {
365 length = 0;
368 if (length!= (tvb_reported_length(tvb) - offset)){
369 return false;
372 temp = tvb_get_uint8(tvb, MSG_TYPE_OFFSET);
373 if (temp > RANAP_MAX_PC) { return false; }
375 /* Try to strengthen the heuristic further, by checking the byte following the length and the bitfield indicating extensions etc
376 * which usually is a sequence-of length
378 word = tvb_get_ntohs(tvb, offset + 1);
379 if (word > 0x1ff){
380 return false;
382 dissect_ranap(tvb, pinfo, tree, data);
384 return true;
387 /*--- proto_register_ranap -------------------------------------------*/
388 void proto_register_ranap(void) {
389 module_t *ranap_module;
391 /* List of fields */
393 static hf_register_info hf[] = {
394 { &hf_ranap_transportLayerAddress_ipv4,
395 { "transportLayerAddress IPv4", "ranap.transportLayerAddress_ipv4",
396 FT_IPv4, BASE_NONE, NULL, 0,
397 NULL, HFILL }},
398 { &hf_ranap_transportLayerAddress_ipv6,
399 { "transportLayerAddress IPv6", "ranap.transportLayerAddress_ipv6",
400 FT_IPv6, BASE_NONE, NULL, 0,
401 NULL, HFILL }},
402 { &hf_ranap_transportLayerAddress_nsap,
403 { "transportLayerAddress NSAP", "ranap.transportLayerAddress_NSAP",
404 FT_BYTES, BASE_NONE, NULL, 0,
405 NULL, HFILL }},
408 #include "packet-ranap-hfarr.c"
411 /* List of subtrees */
412 static int *ett[] = {
413 &ett_ranap,
414 &ett_ranap_transportLayerAddress,
415 &ett_ranap_transportLayerAddress_nsap,
416 #include "packet-ranap-ettarr.c"
420 /* Register protocol */
421 proto_ranap = proto_register_protocol(PNAME, PSNAME, PFNAME);
422 /* Register fields and subtrees */
423 proto_register_field_array(proto_ranap, hf, array_length(hf));
424 proto_register_subtree_array(ett, array_length(ett));
426 /* Register dissector */
427 ranap_handle = register_dissector("ranap", dissect_ranap, proto_ranap);
429 /* Register dissector tables */
430 ranap_ies_dissector_table = register_dissector_table("ranap.ies", "RANAP-PROTOCOL-IES", proto_ranap, FT_UINT32, BASE_DEC);
431 ranap_ies_p1_dissector_table = register_dissector_table("ranap.ies.pair.first", "RANAP-PROTOCOL-IES-PAIR FirstValue", proto_ranap, FT_UINT32, BASE_DEC);
432 ranap_ies_p2_dissector_table = register_dissector_table("ranap.ies.pair.second", "RANAP-PROTOCOL-IES-PAIR SecondValue", proto_ranap, FT_UINT32, BASE_DEC);
433 ranap_extension_dissector_table = register_dissector_table("ranap.extension", "RANAP-PROTOCOL-EXTENSION", proto_ranap, FT_UINT32, BASE_DEC);
434 ranap_proc_imsg_dissector_table = register_dissector_table("ranap.proc.imsg", "RANAP-ELEMENTARY-PROCEDURE InitiatingMessage", proto_ranap, FT_UINT32, BASE_DEC);
435 ranap_proc_sout_dissector_table = register_dissector_table("ranap.proc.sout", "RANAP-ELEMENTARY-PROCEDURE SuccessfulOutcome", proto_ranap, FT_UINT32, BASE_DEC);
436 ranap_proc_uout_dissector_table = register_dissector_table("ranap.proc.uout", "RANAP-ELEMENTARY-PROCEDURE UnsuccessfulOutcome", proto_ranap, FT_UINT32, BASE_DEC);
437 ranap_proc_out_dissector_table = register_dissector_table("ranap.proc.out", "RANAP-ELEMENTARY-PROCEDURE Outcome", proto_ranap, FT_UINT32, BASE_DEC);
439 nas_pdu_dissector_table = register_dissector_table("ranap.nas_pdu", "RANAP NAS PDU", proto_ranap, FT_UINT8, BASE_DEC);
441 ranap_module = prefs_register_protocol(proto_ranap, NULL);
442 prefs_register_bool_preference(ranap_module, "dissect_rrc_container",
443 "Attempt to dissect RRC-Container",
444 "Attempt to dissect RRC message embedded in RRC-Container IE",
445 &glbl_dissect_container);
449 /*--- proto_reg_handoff_ranap ---------------------------------------*/
450 void
451 proto_reg_handoff_ranap(void)
453 rrc_s_to_trnc_handle = find_dissector_add_dependency("rrc.s_to_trnc_cont", proto_ranap);
454 rrc_t_to_srnc_handle = find_dissector_add_dependency("rrc.t_to_srnc_cont", proto_ranap);
455 rrc_ho_to_utran_cmd = find_dissector_add_dependency("rrc.irat.ho_to_utran_cmd", proto_ranap);
456 bssgp_handle = find_dissector("bssgp");
457 heur_dissector_add("sccp", dissect_sccp_ranap_heur, "RANAP over SCCP", "ranap_sccp", proto_ranap, HEURISTIC_ENABLE);
458 heur_dissector_add("sua", dissect_sccp_ranap_heur, "RANAP over SUA", "ranap_sua", proto_ranap, HEURISTIC_ENABLE);
459 dissector_add_uint_with_preference("sccp.ssn", SCCP_SSN_RANAP, ranap_handle);
460 #include "packet-ranap-dis-tab.c"
465 * Editor modelines
467 * Local Variables:
468 * c-basic-offset: 2
469 * tab-width: 8
470 * indent-tabs-mode: nil
471 * End:
473 * ex: set shiftwidth=2 tabstop=8 expandtab:
474 * :indentSize=2:tabSize=8:noTabs=true: