1 /* packet-nbap-template.c
2 * Routines for UMTS Node B Application Part(NBAP) packet dissection
3 * Copyright 2005, 2009 Anders Broman <anders.broman@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 * Ref: 3GPP TS 25.433 version 6.6.0 Release 6
14 #define WS_LOG_DOMAIN "packet-nbap"
16 #include <wireshark.h>
18 #include <epan/to_str.h>
19 #include <epan/packet.h>
20 #include <epan/sctpppids.h>
21 #include <epan/asn1.h>
22 #include <epan/conversation.h>
23 #include <epan/expert.h>
24 #include <epan/prefs.h>
25 #include <epan/proto_data.h>
27 #include <wsutil/array.h>
29 #include "packet-per.h"
30 #include "packet-isup.h"
31 #include "packet-umts_fp.h"
32 #include "packet-umts_mac.h"
33 #include "packet-rrc.h"
34 #include "packet-umts_rlc.h"
35 #include "packet-nbap.h"
38 /* disable: "warning C4146: unary minus operator applied to unsigned type, result still unsigned" */
39 #pragma warning(disable:4146)
42 #define PNAME "UTRAN Iub interface NBAP signalling"
47 #define NBAP_IGNORE_PORT 255
49 void proto_register_nbap(void);
50 void proto_reg_handoff_nbap(void);
52 /* Protocol Handles */
53 static dissector_handle_t fp_handle
;
55 #include "packet-nbap-val.h"
57 /* Initialize the protocol and registered fields */
58 static int proto_nbap
;
59 static int hf_nbap_transportLayerAddress_ipv4
;
60 static int hf_nbap_transportLayerAddress_ipv6
;
61 static int hf_nbap_transportLayerAddress_nsap
;
62 static int hf_nbap_reassembled_information_block
;
64 #include "packet-nbap-hf.c"
66 /* Initialize the subtree pointers */
68 static int ett_nbap_TransportLayerAddress
;
69 static int ett_nbap_TransportLayerAddress_nsap
;
70 static int ett_nbap_ib_sg_data
;
72 #include "packet-nbap-ett.c"
74 static expert_field ei_nbap_no_find_port_info
;
75 static expert_field ei_nbap_no_set_comm_context_id
;
76 static expert_field ei_nbap_hsdsch_entity_not_specified
;
80 static dissector_handle_t nbap_handle
;
83 * Structure to hold Setup Request/Response message conversation
84 * we add all src add/port declared in SetupRequest msg
85 * to match it with dst add/port declared in SetupResponse msg
86 * so we gonna have conversation with exact match (src and dst addr and port)
88 typedef struct nbap_setup_conv
90 uint32_t transaction_id
;
93 uint32_t request_frame_number
;
96 umts_fp_conversation_info_t
*umts_fp_conversation_info
;
101 * Hash table to manage Setup Request/Response message conversation
102 * we can look in table for proper conversation
104 static wmem_map_t
*nbap_setup_conv_table
;
111 int ul_chan_tf_size
[MAX_FP_CHANS
];
112 int ul_chan_num_tbs
[MAX_FP_CHANS
];
114 int dl_chan_tf_size
[MAX_FP_CHANS
];
115 int dl_chan_num_tbs
[MAX_FP_CHANS
];
116 }nbap_dch_channel_info_t
;
118 /* Struct to collect E-DCH data in a packet
119 * As the address data comes before the ddi entries
120 * we save the address to be able to find the conversation and update the
125 address crnc_address
;
128 uint8_t edch_ddi
[MAX_EDCH_DDIS
];
129 unsigned edch_macd_pdu_size
[MAX_EDCH_DDIS
];
130 uint8_t edch_type
; /* 1 means T2 */
131 uint8_t lchId
[MAX_EDCH_DDIS
]; /*Logical channel ids.*/
132 } nbap_edch_channel_info_t
;
137 uint32_t crnc_address
;
138 uint16_t crnc_port
[maxNrOfEDCHMACdFlows
];
139 } nbap_edch_port_info_t
;
143 address crnc_address
;
145 enum fp_rlc_mode rlc_mode
;
146 uint32_t hsdsch_physical_layer_category
;
147 uint8_t entity
; /* "ns" means type 1 and "ehs" means type 2, type 3 == ?*/
148 } nbap_hsdsch_channel_info_t
;
152 address crnc_address
;
154 enum fp_rlc_mode rlc_mode
;
155 } nbap_common_channel_info_t
;
157 /*Stuff for mapping NodeB-Communication Context ID to CRNC Communication Context ID*/
158 typedef struct com_ctxt_
{
159 /*unsigned nodeb_context;*/
160 unsigned crnc_context
;
162 }nbap_com_context_id_t
;
164 enum TransportFormatSet_type_enum
173 #define NBAP_MAX_IB_SEGMENT_LENGTH 222
175 typedef struct nbap_ib_segment_t
{
180 static nbap_ib_segment_t
* nbap_parse_ib_sg_data_var1(packet_info
*pinfo
, tvbuff_t
*tvb
,bool is_short
)
184 nbap_ib_segment_t
* output
;
185 if ( tvb_captured_length(tvb
) < 2 ) {
189 bit_length
= tvb_get_uint8(tvb
,0) + 1;
190 data
= (uint8_t*)tvb_memdup(pinfo
->pool
,tvb
,1,(bit_length
+7)/8);
193 bit_length
= NBAP_MAX_IB_SEGMENT_LENGTH
;
194 data
= (uint8_t*)tvb_memdup(pinfo
->pool
,tvb
,0,(bit_length
+7)/8);
196 output
= wmem_new(pinfo
->pool
, nbap_ib_segment_t
);
197 output
->bit_length
= bit_length
;
202 /*****************************************************************************/
203 /* Packet private data */
204 /* For this dissector, all information passed between different ASN.1 nodes */
205 /* should be done only through this API! */
206 /*****************************************************************************/
209 typedef struct nbap_private_data_t
211 uint32_t transportLayerAddress_ipv4
;
212 uint16_t binding_id_port
;
213 enum TransportFormatSet_type_enum transport_format_set_type
;
214 uint32_t procedure_code
;
216 uint32_t ul_scrambling_code
;
217 uint32_t com_context_id
;
220 uint32_t protocol_ie_id
;
222 uint32_t transaction_id
;
225 uint32_t prev_dch_id
;
226 uint32_t common_physical_channel_id
;
227 uint32_t e_dch_macdflow_id
;
228 uint32_t hsdsch_macdflow_id
;
229 bool max_mac_d_pdu_size_ext_ie_present
;
230 uint32_t e_dch_ddi_value
;
231 uint32_t logical_channel_id
;
232 uint32_t common_macdflow_id
;
233 uint32_t mac_d_pdu_size
;
234 uint32_t common_transport_channel_id
;
235 int paging_indications
;
237 uint32_t segment_type
;
238 bool crnc_context_present
; /* Whether 'com_context_id' is set */
239 uint8_t dch_crc_present
;
241 nbap_dch_channel_info_t nbap_dch_chnl_info
[256];
242 nbap_edch_channel_info_t nbap_edch_channel_info
[maxNrOfEDCHMACdFlows
];
243 int hsdsch_macdflow_ids
[maxNrOfMACdFlows
];
244 nbap_hsdsch_channel_info_t nbap_hsdsch_channel_info
[maxNrOfMACdFlows
];
245 nbap_common_channel_info_t nbap_common_channel_info
[maxNrOfMACdFlows
]; /*TODO: Fix this!*/
246 wmem_list_t
* ib_segments
; /* Information block segments */
247 } nbap_private_data_t
;
250 /* Helper function to get or create a private_data struct */
251 static nbap_private_data_t
* nbap_get_private_data(packet_info
*pinfo
)
254 /* NOTE: Unlike other ASN.1 dissectors which store information in
255 * actx->private_data the NBAP dissector can't do so because some fields
256 * are defined as their own 'PDU' (Like BindingID and TransportLayerAddress)
257 * in those cases, the generic ASN.1 dissector creates a NEW 'ASN.1 context'
258 * (asn1_ctx_t) and hence a new 'private data' field for them so information
259 * can't be passes to/from them.
261 nbap_private_data_t
*private_data
= (nbap_private_data_t
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_nbap
, 0);
262 if(private_data
== NULL
) {
263 private_data
= wmem_new0(pinfo
->pool
, nbap_private_data_t
);
264 p_add_proto_data(pinfo
->pool
, pinfo
, proto_nbap
, 0, private_data
);
265 /* Setting default values */
266 private_data
->hsdsch_macdflow_id
= 3;
267 private_data
->crnc_context_present
= false;
268 private_data
->procedure_code
= 0xFFFF;
269 private_data
->dd_mode
= 0xFFFF;
270 private_data
->dch_crc_present
= 2; /* Unknown */
271 for (i
= 0; i
< maxNrOfMACdFlows
; i
++) {
272 private_data
->nbap_hsdsch_channel_info
[i
].entity
= hs
;
278 /* Helper function to reset the private data struct*/
279 static void nbap_reset_private_data(packet_info
*pinfo
)
281 p_remove_proto_data(pinfo
->pool
, pinfo
, proto_nbap
, 0);
284 /*****************************************************************************/
287 /* Global Variables */
289 /* Variables for sub elements dissection */
290 static const char *ProcedureID
;
292 static wmem_tree_t
* edch_flow_port_map
;
293 wmem_tree_t
*nbap_scrambling_code_crncc_map
;
294 wmem_tree_t
*nbap_crncc_urnti_map
;
295 static wmem_tree_t
* com_context_map
;
297 /* This table is used externally from FP, MAC and such, TODO: merge this with
299 uint8_t lchId_type_table
[]= {
300 MAC_CONTENT_UNKNOWN
, /* Shouldn't happen*/
301 MAC_CONTENT_DCCH
, /* 1 to 4 SRB => DCCH*/
305 MAC_CONTENT_CS_DTCH
, /* 5 to 7 Conv CS speech => ?*/
308 MAC_CONTENT_DCCH
, /* 8 SRB => DCCH*/
309 MAC_CONTENT_PS_DTCH
, /* 9 maps to DTCH*/
310 MAC_CONTENT_UNKNOWN
, /* 10 Conv CS unknown*/
311 MAC_CONTENT_PS_DTCH
, /* 11 Interactive PS => DTCH*/
312 MAC_CONTENT_PS_DTCH
, /* 12 Streaming PS => DTCH*/
313 MAC_CONTENT_CS_DTCH
, /* 13 Streaming CS*/
314 MAC_CONTENT_PS_DTCH
, /* 14 Interactive PS => DTCH*/
315 MAC_CONTENT_CCCH
/* This is CCCH? */
318 /* Mapping logicalchannel id to RLC_MODE */
319 uint8_t lchId_rlc_map
[] = {
321 RLC_UM
, /* Logical channel id = 1 is SRB1 which uses RLC_UM*/
325 RLC_TM
, /*5 to 7 Conv CS Speech*/
335 RLC_AM
, /* This is CCCH which is UM?, probably not */
338 /* Preference variables */
339 /* Array with preference variables for easy looping, TODO: merge this with
340 * lchId_type_table[] */
341 static int lch_contents
[16] = {
360 static const enum_val_t content_types
[] = {
361 {"MAC_CONTENT_UNKNOWN", "MAC_CONTENT_UNKNOWN", MAC_CONTENT_UNKNOWN
},
362 {"MAC_CONTENT_DCCH", "MAC_CONTENT_DCCH", MAC_CONTENT_DCCH
},
363 {"MAC_CONTENT_PS_DTCH", "MAC_CONTENT_PS_DTCH", MAC_CONTENT_PS_DTCH
},
364 {"MAC_CONTENT_CS_DTCH", "MAC_CONTENT_CS_DTCH", MAC_CONTENT_CS_DTCH
},
365 {"MAC_CONTENT_CCCH", "MAC_CONTENT_CCCH", MAC_CONTENT_CCCH
},
371 const char *description
;
372 } preference_strings
;
374 /* This is used when registering preferences, name, title, description */
375 static const preference_strings ch_strings
[] = {
376 {"lch1_content", "Logical Channel 1 Content", "foo"},
377 {"lch2_content", "Logical Channel 2 Content", "foo"},
378 {"lch3_content", "Logical Channel 3 Content", "foo"},
379 {"lch4_content", "Logical Channel 4 Content", "foo"},
380 {"lch5_content", "Logical Channel 5 Content", "foo"},
381 {"lch6_content", "Logical Channel 6 Content", "foo"},
382 {"lch7_content", "Logical Channel 7 Content", "foo"},
383 {"lch8_content", "Logical Channel 8 Content", "foo"},
384 {"lch9_content", "Logical Channel 9 Content", "foo"},
385 {"lch10_content", "Logical Channel 10 Content", "foo"},
386 {"lch11_content", "Logical Channel 11 Content", "foo"},
387 {"lch12_content", "Logical Channel 12 Content", "foo"},
388 {"lch13_content", "Logical Channel 13 Content", "foo"},
389 {"lch14_content", "Logical Channel 14 Content", "foo"},
390 {"lch15_content", "Logical Channel 15 Content", "foo"},
391 {"lch16_content", "Logical Channel 16 Content", "foo"}};
393 enum ib_sg_enc_type
{
394 IB_SG_DATA_ENC_VAR_1
,
398 static const enum_val_t ib_sg_enc_vals
[] = {
400 "Encoding Variant 1 (TS 25.433 Annex D.2)", IB_SG_DATA_ENC_VAR_1
},
402 "Encoding Variant 2 (TS 25.433 Annex D.3)", IB_SG_DATA_ENC_VAR_2
},
406 static int preferences_ib_sg_data_encoding
= IB_SG_DATA_ENC_VAR_1
;
408 /* Dissector tables */
409 static dissector_table_t nbap_ies_dissector_table
;
410 static dissector_table_t nbap_extension_dissector_table
;
411 static dissector_table_t nbap_proc_imsg_dissector_table
;
412 static dissector_table_t nbap_proc_sout_dissector_table
;
413 static dissector_table_t nbap_proc_uout_dissector_table
;
415 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
416 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
417 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
418 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
419 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
421 static uint32_t calculate_setup_conv_key(const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
);
422 static void add_setup_conv(const packet_info
*pinfo _U_
, const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
, const uint32_t req_frame_number
,
423 const address
*addr
, const uint32_t port
, umts_fp_conversation_info_t
* umts_fp_conversation_info
, conversation_t
*conv
);
424 static nbap_setup_conv_t
* find_setup_conv(const packet_info
*pinfo _U_
, const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
);
425 static void delete_setup_conv(nbap_setup_conv_t
*conv
);
427 /*Easy way to add hsdhsch binds for corner cases*/
428 static void add_hsdsch_bind(packet_info
* pinfo
);
430 #include "packet-nbap-fn.c"
432 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
434 uint32_t protocol_ie_id
;
435 protocol_ie_id
= nbap_get_private_data(pinfo
)->protocol_ie_id
;
436 return (dissector_try_uint_with_data(nbap_ies_dissector_table
, protocol_ie_id
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
439 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
441 uint32_t protocol_ie_id
;
442 protocol_ie_id
= nbap_get_private_data(pinfo
)->protocol_ie_id
;
443 return (dissector_try_uint_with_data(nbap_extension_dissector_table
, protocol_ie_id
, tvb
, pinfo
, tree
, false, NULL
)) ? tvb_captured_length(tvb
) : 0;
446 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
448 if (!ProcedureID
) return 0;
449 return (dissector_try_string_with_data(nbap_proc_imsg_dissector_table
, ProcedureID
, tvb
, pinfo
, tree
, true, NULL
)) ? tvb_captured_length(tvb
) : 0;
452 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
454 if (!ProcedureID
) return 0;
455 return (dissector_try_string_with_data(nbap_proc_sout_dissector_table
, ProcedureID
, tvb
, pinfo
, tree
, true, NULL
)) ? tvb_captured_length(tvb
) : 0;
458 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
460 if (!ProcedureID
) return 0;
461 return (dissector_try_string_with_data(nbap_proc_uout_dissector_table
, ProcedureID
, tvb
, pinfo
, tree
, true, NULL
)) ? tvb_captured_length(tvb
) : 0;
463 static void add_hsdsch_bind(packet_info
*pinfo
){
465 conversation_t
*conversation
= NULL
;
466 umts_fp_conversation_info_t
*umts_fp_conversation_info
;
467 fp_hsdsch_channel_info_t
* fp_hsdsch_channel_info
= NULL
;
469 nbap_private_data_t
* nbap_private_data
;
470 nbap_hsdsch_channel_info_t
* nbap_hsdsch_channel_info
;
472 if (PINFO_FD_VISITED(pinfo
)){
476 nbap_private_data
= nbap_get_private_data(pinfo
);
477 nbap_hsdsch_channel_info
= nbap_private_data
->nbap_hsdsch_channel_info
;
478 /* Set port to zero use that as an indication of whether we have data or not */
479 clear_address(&null_addr
);
480 for (i
= 0; i
< maxNrOfMACdFlows
; i
++) {
481 if (nbap_hsdsch_channel_info
[i
].crnc_port
!= 0){
482 conversation
= find_conversation(pinfo
->num
, &(nbap_hsdsch_channel_info
[i
].crnc_address
), &null_addr
, CONVERSATION_UDP
,
483 nbap_hsdsch_channel_info
[i
].crnc_port
, 0, NO_ADDR_B
);
485 if (conversation
== NULL
) {
486 /* It's not part of any conversation - create a new one. */
487 conversation
= conversation_new(pinfo
->num
, &(nbap_hsdsch_channel_info
[i
].crnc_address
), &null_addr
, CONVERSATION_UDP
,
488 nbap_hsdsch_channel_info
[i
].crnc_port
, 0, NO_ADDR2
|NO_PORT2
);
491 conversation_set_dissector(conversation
, fp_handle
);
493 if(pinfo
->link_dir
==P2P_DIR_DL
){
494 umts_fp_conversation_info
= wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t
);
495 /* Fill in the HSDSCH relevant data */
496 umts_fp_conversation_info
->iface_type
= IuB_Interface
;
497 umts_fp_conversation_info
->division
= Division_FDD
;
498 umts_fp_conversation_info
->channel
= CHANNEL_HSDSCH
;
499 umts_fp_conversation_info
->dl_frame_number
= 0;
500 umts_fp_conversation_info
->ul_frame_number
= pinfo
->num
;
501 copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info
->crnc_address
), &nbap_hsdsch_channel_info
[i
].crnc_address
);
502 umts_fp_conversation_info
->crnc_port
= nbap_hsdsch_channel_info
[i
].crnc_port
;
504 fp_hsdsch_channel_info
= wmem_new0(wmem_file_scope(), fp_hsdsch_channel_info_t
);
505 umts_fp_conversation_info
->channel_specific_info
= (void*)fp_hsdsch_channel_info
;
506 /*Added june 3, normally just the iterator variable*/
507 fp_hsdsch_channel_info
->hsdsch_macdflow_id
= i
; /*hsdsch_macdflow_ids[i];*/ /* hsdsch_macdflow_id;*/
509 if (nbap_private_data
->crnc_context_present
) {
510 umts_fp_conversation_info
->com_context_id
= nbap_private_data
->com_context_id
;
512 /* XXX: This expert info doesn't get added in subsequent passes,
513 * but probably should.
515 expert_add_info(pinfo
, NULL
, &ei_nbap_no_set_comm_context_id
);
518 /* Cheat and use the DCH entries */
519 umts_fp_conversation_info
->num_dch_in_flow
++;
520 umts_fp_conversation_info
->dch_ids_in_flow_list
[umts_fp_conversation_info
->num_dch_in_flow
-1] = i
;
522 if(nbap_hsdsch_channel_info
[i
].entity
== entity_not_specified
){
524 expert_add_info(pinfo
, NULL
, &ei_nbap_hsdsch_entity_not_specified
);
526 fp_hsdsch_channel_info
->hsdsch_entity
= (enum fp_hsdsch_entity
)nbap_hsdsch_channel_info
[i
].entity
;
528 umts_fp_conversation_info
->rlc_mode
= nbap_hsdsch_channel_info
[i
].rlc_mode
;
529 set_umts_fp_conv_data(conversation
, umts_fp_conversation_info
);
537 * Function used to manage conversation declared in Setup Request/Response message
539 static uint32_t calculate_setup_conv_key(const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
)
541 /* We need to pack 3 values on 32 bits:
542 * 31-16 transaction_id
547 key
= transaction_id
<< 16;
548 key
|= (dd_mode
& 0x03) << 14;
549 key
|= (channel_id
& 0x3fff);
550 ws_debug("\tCalculating key 0x%04x", key
);
554 static void add_setup_conv(const packet_info
*pinfo _U_
, const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
, const uint32_t req_frame_number
,
555 const address
*addr
, const uint32_t port
, umts_fp_conversation_info_t
* umts_fp_conversation_info
, conversation_t
*conv
)
557 nbap_setup_conv_t
*new_conv
= NULL
;
560 ws_debug("Creating new setup conv\t TransactionID: %u\tddMode: %u\tChannelID: %u\t %s:%u",
561 transaction_id
, dd_mode
, channel_id
, address_to_str(pinfo
->pool
, addr
), port
);
563 new_conv
= wmem_new0(wmem_file_scope(), nbap_setup_conv_t
);
566 new_conv
->transaction_id
= transaction_id
;
567 new_conv
->dd_mode
= dd_mode
;
568 new_conv
->channel_id
= channel_id
;
569 new_conv
->request_frame_number
= req_frame_number
;
570 copy_address_wmem(wmem_file_scope(), &new_conv
->addr
, addr
);
571 new_conv
->port
= port
;
572 new_conv
->umts_fp_conversation_info
= umts_fp_conversation_info
;
573 new_conv
->conv
= conv
;
575 key
= calculate_setup_conv_key(new_conv
->transaction_id
, new_conv
->dd_mode
, new_conv
->channel_id
);
577 wmem_map_insert(nbap_setup_conv_table
, GUINT_TO_POINTER(key
), new_conv
);
580 static nbap_setup_conv_t
* find_setup_conv(const packet_info
*pinfo _U_
, const uint32_t transaction_id
, const uint32_t dd_mode
, const uint32_t channel_id
)
582 nbap_setup_conv_t
*conv
;
584 ws_debug("Looking for Setup Conversation match\t TransactionID: %u\t ddMode: %u\t ChannelID: %u", transaction_id
, dd_mode
, channel_id
);
586 key
= calculate_setup_conv_key(transaction_id
, dd_mode
, channel_id
);
588 conv
= (nbap_setup_conv_t
*) wmem_map_lookup(nbap_setup_conv_table
, GUINT_TO_POINTER(key
));
591 ws_debug("\tDidn't find Setup Conversation match");
593 ws_debug("\tFOUND Setup Conversation match\t TransactionID: %u\t ddMode: %u\t ChannelID: %u\t %s:%u",
594 conv
->transaction_id
, conv
->dd_mode
, conv
->channel_id
, address_to_str(pinfo
->pool
, &(conv
->addr
)), conv
->port
);
600 static void delete_setup_conv(nbap_setup_conv_t
*conv
)
604 /* check if conversation exist */
606 ws_debug("Trying delete Setup Conversation that does not exist (ptr == NULL)\t");
609 key
= calculate_setup_conv_key(conv
->transaction_id
, conv
->dd_mode
, conv
->channel_id
);
610 wmem_map_remove(nbap_setup_conv_table
, GUINT_TO_POINTER(key
));
613 static void nbap_init(void){
616 /*Initialize Setup Conversation hash table*/
617 nbap_setup_conv_table
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
619 for (i
= 0; i
< 15; i
++) {
620 lchId_type_table
[i
+1] = lch_contents
[i
];
625 dissect_nbap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
627 proto_item
*nbap_item
= NULL
;
628 proto_tree
*nbap_tree
= NULL
;
629 /* make entry in the Protocol column on summary display */
630 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NBAP");
632 /* create the nbap protocol tree */
633 nbap_item
= proto_tree_add_item(tree
, proto_nbap
, tvb
, 0, -1, ENC_NA
);
634 nbap_tree
= proto_item_add_subtree(nbap_item
, ett_nbap
);
636 /* Clearing any old 'private data' stored */
637 nbap_reset_private_data(pinfo
);
639 return dissect_NBAP_PDU_PDU(tvb
, pinfo
, nbap_tree
, data
);
642 /* Highest ProcedureCode value, used in heuristics */
643 #define NBAP_MAX_PC 56 /* id-secondaryULFrequencyUpdate = 56*/
644 #define NBAP_MSG_MIN_LENGTH 7
646 dissect_nbap_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
649 uint8_t procedure_id
;
652 uint8_t transaction_id_type
;
654 int length_field_offset
;
656 #define PDU_TYPE_OFFSET 0
657 #define PROC_CODE_OFFSET 1
658 #define DD_CRIT_OFFSET 2
659 if (tvb_captured_length(tvb
) < NBAP_MSG_MIN_LENGTH
) {
663 pdu_type
= tvb_get_uint8(tvb
, PDU_TYPE_OFFSET
);
664 if (pdu_type
& 0x1f) {
665 /* pdu_type is not 0x00 (initiatingMessage), 0x20 (succesfulOutcome),
666 0x40 (unsuccesfulOutcome) or 0x60 (outcome), ignore extension bit (0x80) */
670 procedure_id
= tvb_get_uint8(tvb
, PROC_CODE_OFFSET
);
671 if (procedure_id
> NBAP_MAX_PC
) {
675 dd_mode
= tvb_get_uint8(tvb
, DD_CRIT_OFFSET
) >> 5;
676 if (dd_mode
>= 0x03) {
677 /* dd_mode is not 0x00 (tdd), 0x01 (fdd) or 0x02 (common) */
681 criticality
= (tvb_get_uint8(tvb
, DD_CRIT_OFFSET
) & 0x18) >> 3;
682 if (criticality
== 0x03) {
683 /* criticality is not 0x00 (reject), 0x01 (ignore) or 0x02 (notify) */
687 /* Finding the offset for the length field - depends on wether the transaction id is long or short */
688 transaction_id_type
= (tvb_get_uint8(tvb
, DD_CRIT_OFFSET
) & 0x02) >> 1;
689 if(transaction_id_type
== 0x00) { /* Short transaction id - 1 byte*/
690 length_field_offset
= 4;
692 else { /* Long transaction id - 2 bytes*/
693 length_field_offset
= 5;
696 /* compute aligned PER length determinant without calling dissect_per_length_determinant()
697 to avoid exceptions and info added to tree, info column and expert info */
698 length
= tvb_get_uint8(tvb
, length_field_offset
);
699 length_field_offset
+= 1;
701 if ((length
& 0xc0) == 0x80) {
704 length
+= tvb_get_uint8(tvb
, length_field_offset
);
705 length_field_offset
+= 1;
710 if (length
!= (tvb_reported_length(tvb
) - length_field_offset
)){
714 dissect_nbap(tvb
, pinfo
, tree
, data
);
719 /*--- proto_register_nbap -------------------------------------------*/
720 void proto_register_nbap(void)
722 module_t
*nbap_module
;
726 static hf_register_info hf
[] = {
727 { &hf_nbap_transportLayerAddress_ipv4
,
728 { "transportLayerAddress IPv4", "nbap.transportLayerAddress_ipv4",
729 FT_IPv4
, BASE_NONE
, NULL
, 0,
731 { &hf_nbap_transportLayerAddress_ipv6
,
732 { "transportLayerAddress IPv6", "nbap.transportLayerAddress_ipv6",
733 FT_IPv6
, BASE_NONE
, NULL
, 0,
735 { &hf_nbap_transportLayerAddress_nsap
,
736 { "transportLayerAddress NSAP", "nbap.transportLayerAddress_NSAP",
737 FT_BYTES
, BASE_NONE
, NULL
, 0,
739 { &hf_nbap_reassembled_information_block
,
740 { "Reassembled Information Block", "nbap.reassembled_information_block",
741 FT_BYTES
, BASE_NONE
, NULL
, 0,
743 #include "packet-nbap-hfarr.c"
746 /* List of subtrees */
747 static int *ett
[] = {
749 &ett_nbap_TransportLayerAddress
,
750 &ett_nbap_TransportLayerAddress_nsap
,
751 &ett_nbap_ib_sg_data
,
752 #include "packet-nbap-ettarr.c"
755 static ei_register_info ei
[] = {
756 { &ei_nbap_no_set_comm_context_id
, { "nbap.no_set_comm_context_id", PI_MALFORMED
, PI_WARN
, "Couldn't not set Communication Context-ID, fragments over reconfigured channels might fail", EXPFILL
}},
757 { &ei_nbap_no_find_port_info
, { "nbap.no_find_port_info", PI_MALFORMED
, PI_WARN
, "Couldn't not find port information for reconfigured E-DCH flow, unable to reconfigure", EXPFILL
}},
758 { &ei_nbap_hsdsch_entity_not_specified
, { "nbap.hsdsch_entity_not_specified", PI_MALFORMED
,PI_ERROR
, "HSDSCH Entity not specified!", EXPFILL
}},
761 expert_module_t
* expert_nbap
;
763 /* Register protocol */
764 proto_nbap
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
765 /* Register fields and subtrees */
766 proto_register_field_array(proto_nbap
, hf
, array_length(hf
));
767 proto_register_subtree_array(ett
, array_length(ett
));
768 expert_nbap
= expert_register_protocol(proto_nbap
);
769 expert_register_field_array(expert_nbap
, ei
, array_length(ei
));
771 /* Register dissector */
772 nbap_handle
= register_dissector("nbap", dissect_nbap
, proto_nbap
);
774 nbap_module
= prefs_register_protocol(proto_nbap
, NULL
);
776 /* Register preferences for mapping logical channel IDs to MAC content types. */
777 for (i
= 0; i
< 16; i
++) {
778 prefs_register_enum_preference(nbap_module
, ch_strings
[i
].name
, ch_strings
[i
].title
, ch_strings
[i
].description
, &lch_contents
[i
], content_types
, false);
780 prefs_register_enum_preference(nbap_module
, "ib_sg_data_encoding",
781 "IB_SG_DATA encoding",
782 "Encoding used for the IB-SG-DATA element carrying segments of information blocks",
783 &preferences_ib_sg_data_encoding
, ib_sg_enc_vals
, false);
785 /* Register dissector tables */
786 nbap_ies_dissector_table
= register_dissector_table("nbap.ies", "NBAP-PROTOCOL-IES", proto_nbap
, FT_UINT32
, BASE_DEC
);
787 nbap_extension_dissector_table
= register_dissector_table("nbap.extension", "NBAP-PROTOCOL-EXTENSION", proto_nbap
, FT_UINT32
, BASE_DEC
);
788 nbap_proc_imsg_dissector_table
= register_dissector_table("nbap.proc.imsg", "NBAP-ELEMENTARY-PROCEDURE InitiatingMessage", proto_nbap
, FT_STRING
, STRING_CASE_SENSITIVE
);
789 nbap_proc_sout_dissector_table
= register_dissector_table("nbap.proc.sout", "NBAP-ELEMENTARY-PROCEDURE SuccessfulOutcome", proto_nbap
, FT_STRING
, STRING_CASE_SENSITIVE
);
790 nbap_proc_uout_dissector_table
= register_dissector_table("nbap.proc.uout", "NBAP-ELEMENTARY-PROCEDURE UnsuccessfulOutcome", proto_nbap
, FT_STRING
, STRING_CASE_SENSITIVE
);
792 register_init_routine(nbap_init
);
794 com_context_map
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
796 /*Initialize structure for muxed flow indication*/
797 edch_flow_port_map
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
799 /*Initializing Scrambling Code to C-RNC Context & C-RNC Context to U-RNTI maps*/
800 nbap_scrambling_code_crncc_map
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
801 nbap_crncc_urnti_map
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
805 * #define EXTRA_PPI 1
807 /*--- proto_reg_handoff_nbap ---------------------------------------*/
809 proto_reg_handoff_nbap(void)
811 fp_handle
= find_dissector("fp");
812 dissector_add_uint("sctp.ppi", NBAP_PAYLOAD_PROTOCOL_ID
, nbap_handle
);
814 dissector_add_uint("sctp.ppi", 17, nbap_handle
);
816 dissector_add_for_decode_as("sctp.port", nbap_handle
);
817 heur_dissector_add("sctp", dissect_nbap_heur
, "NBAP over SCTP", "nbap_sctp", proto_nbap
, HEURISTIC_ENABLE
);
819 #include "packet-nbap-dis-tab.c"