diff options
Diffstat (limited to 'epan/dissectors/packet-gsm_a_common.c')
-rw-r--r-- | epan/dissectors/packet-gsm_a_common.c | 5034 |
1 files changed, 5034 insertions, 0 deletions
diff --git a/epan/dissectors/packet-gsm_a_common.c b/epan/dissectors/packet-gsm_a_common.c new file mode 100644 index 00000000..1cf85fc1 --- /dev/null +++ b/epan/dissectors/packet-gsm_a_common.c @@ -0,0 +1,5034 @@ +/* packet-gsm_a_common.c + * Common routines for GSM A Interface dissection + * + * Copyright 2003, Michael Lum <mlum [AT] telostech.com> + * In association with Telos Technology Inc. + * + * Split from packet-gsm_a.c by Neil Piercy <Neil [AT] littlebriars.co.uk> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <math.h> + +#include <epan/packet.h> +#include <epan/to_str.h> +#include <epan/expert.h> +#include <epan/tap.h> +#include <epan/stat_tap_ui.h> +#include <wsutil/str_util.h> +#include "packet-gsm_a_common.h" +#include "packet-bssap.h" +#include "packet-gmr1_common.h" +#include "packet-e212.h" + +void proto_register_gsm_a_common(void); + +static const value_string gsm_common_elem_strings[] = { + /* Common Information Elements 10.5.1 */ + { DE_CELL_ID, "Cell Identity" }, + { DE_CIPH_KEY_SEQ_NUM, "Ciphering Key Sequence Number" }, + { DE_LAI, "Location Area Identification (LAI)" }, + { DE_MID, "Mobile Identity" }, + { DE_MS_CM_1, "Mobile Station Classmark 1" }, + { DE_MS_CM_2, "Mobile Station Classmark 2" }, + { DE_MS_CM_3, "Mobile Station Classmark 3" }, + { DE_SPARE_NIBBLE, "Spare Half Octet" }, + { DE_D_GB_CALL_REF, "Descriptive group or broadcast call reference" }, + { DE_G_CIPH_KEY_NUM, "Group Cipher Key Number" }, + { DE_PD_SAPI, "PD and SAPI $(CCBS)$" }, + { DE_PRIO, "Priority Level" }, + { DE_CN_COMMON_GSM_MAP_NAS_SYS_INFO, "CN Common GSM-MAP NAS system information" }, + { DE_CS_DOMAIN_SPEC_SYS_INFO, "CS domain specific system information" }, + { DE_PS_DOMAIN_SPEC_SYS_INFO, "PS domain specific system information" }, + { DE_PLMN_LIST, "PLMN List" }, + { DE_NAS_CONT_FOR_PS_HO, "NAS container for PS HO" }, + { DE_MS_NET_FEAT_SUP, "MS network feature support" }, + { 0, NULL } +}; +value_string_ext gsm_common_elem_strings_ext = VALUE_STRING_EXT_INIT(gsm_common_elem_strings); + +static const value_string gsm_a_skip_ind_vals[] = { + { 0, "No indication of selected PLMN"}, + { 1, "PLMN identity of the Common PLMN in the broadcast system information"}, + { 2, "PLMN identity of the first Additional PLMN in the broadcast system information"}, + { 3, "PLMN identity of the second Additional PLMN in the broadcast system information"}, + { 4, "PLMN identity of the third Additional PLMN in the broadcast system information"}, + { 5, "PLMN identity of the fourth Additional PLMN in the broadcast system information"}, + { 6, "Reserved"}, + { 7, "Reserved"}, + { 0, NULL } +}; + +static const true_false_string gsm_a_extension_value = { + "No Extension", + "Extended" +}; + + +/* Mobile Station Classmark Value strings + */ + +/* Mobile Station Classmark + * Revision level + */ +static const value_string gsm_a_msc_rev_vals[] = { + { 0, "Reserved for GSM phase 1"}, + { 1, "Used by GSM phase 2 mobile stations"}, + { 2, "Used by mobile stations supporting R99 or later versions of the protocol"}, + { 3, "Reserved for future use"}, + { 0, NULL } +}; + +/* ES IND (octet 3, bit 5) "Controlled Early Classmark Sending" option implementation */ +static const true_false_string ES_IND_vals = { + "Controlled Early Classmark Sending option is implemented in the MS", + "Controlled Early Classmark Sending option is not implemented in the MS" +}; +/* A5/1 algorithm supported (octet 3, bit 4) */ +static const true_false_string A5_1_algorithm_sup_vals = { + "encryption algorithm A5/1 not available", + "encryption algorithm A5/1 available" +}; +/* RF Power Capability (Octet 3) */ +static const value_string RF_power_capability_vals[] = { + { 0, "class 1"}, + { 1, "class 2"}, + { 2, "class 3"}, + { 3, "class 4"}, + { 4, "class 5"}, + { 7, "RF Power capability is irrelevant in this information element"}, + { 0, NULL } +}; +/* PS capability (pseudo-synchronization capability) (octet 4) */ +static const true_false_string ps_sup_cap_vals = { + "PS capability present", + "PS capability not present" +}; +/* SS Screening Indicator (octet 4)defined in 3GPP TS 24.080 */ +static const value_string SS_screening_indicator_vals[] = { + { 0, "Default value of phase 1"}, + { 1, "Capability of handling of ellipsis notation and phase 2 error handling "}, + { 2, "For future use"}, + { 3, "For future use"}, + { 0, NULL } +}; +/* SM capability (MT SMS pt to pt capability) (octet 4)*/ +static const true_false_string SM_capability_vals = { + "Mobile station supports mobile terminated point to point SMS", + "Mobile station does not support mobile terminated point to point SMS" +}; +/* VBS notification reception (octet 4) */ +static const true_false_string VBS_notification_rec_vals = { + "VBS capability and notifications wanted", + "no VBS capability or no notifications wanted" +}; +/* VGCS notification reception (octet 4) */ +static const true_false_string VGCS_notification_rec_vals = { + "VGCS capability and notifications wanted", + "no VGCS capability or no notifications wanted" +}; +/* FC Frequency Capability (octet 4 ) */ +static const true_false_string FC_frequency_cap_vals = { + "The MS does support the E-GSM or R-GSM", + "The MS does not support the E-GSM or R-GSM band" +}; +/* CM3 (octet 5, bit 8) */ +static const true_false_string CM3_vals = { + "The MS supports options that are indicated in classmark 3 IE", + "The MS does not support any options that are indicated in CM3" +}; +/* LCS VA capability (LCS value added location request notification capability) (octet 5,bit 6) */ +static const true_false_string LCS_VA_cap_vals = { + "LCS value added location request notification capability supported", + "LCS value added location request notification capability not supported" +}; +/* UCS2 treatment (octet 5, bit 5) */ +static const true_false_string UCS2_treatment_vals = { + "the ME has no preference between the use of the default alphabet and the use of UCS2", + "the ME has a preference for the default alphabet" +}; +/* SoLSA (octet 5, bit 4) */ +static const true_false_string SoLSA_vals = { + "The ME supports SoLSA", + "The ME does not support SoLSA" +}; +/* CMSP: CM Service Prompt (octet 5, bit 3) */ +static const true_false_string CMSP_vals = { + "Network initiated MO CM connection request supported for at least one CM protocol", + "Network initiated MO CM connection request not supported" +}; +/* A5/7 algorithm supported */ +static const true_false_string A5_7_algorithm_sup_vals = { + "encryption algorithm A5/7 available", + "encryption algorithm A5/7 not available" +}; +/* A5/6 algorithm supported */ +static const true_false_string A5_6_algorithm_sup_vals = { + "encryption algorithm A5/6 available", + "encryption algorithm A5/6 not available" +}; +/* A5/5 algorithm supported */ +static const true_false_string A5_5_algorithm_sup_vals = { + "encryption algorithm A5/5 available", + "encryption algorithm A5/5 not available" +}; +/* A5/4 algorithm supported */ +static const true_false_string A5_4_algorithm_sup_vals = { + "encryption algorithm A5/4 available", + "encryption algorithm A5/4 not available" +}; +/* A5/3 algorithm supported (octet 5, bit 2) */ +static const true_false_string A5_3_algorithm_sup_vals = { + "encryption algorithm A5/3 available", + "encryption algorithm A5/3 not available" +}; +/* A5/2 algorithm supported (octet 5, bit 1) */ +static const true_false_string A5_2_algorithm_sup_vals = { + "encryption algorithm A5/2 available", + "encryption algorithm A5/2 not available" +}; + +static const value_string mobile_identity_type_vals[] = { + { 0, "No Identity"}, + { 1, "IMSI"}, + { 2, "IMEI"}, + { 3, "IMEISV"}, + { 4, "TMSI/P-TMSI/M-TMSI"}, + { 5, "TMGI and optional MBMS Session Identity"}, /* ETSI TS 124 008 V6.8.0 (2005-03) p326 */ + { 0, NULL } +}; + +static const true_false_string oddevenind_vals = { + "Odd number of identity digits", + "Even number of identity digits" +}; + + +const value_string gsm_a_sms_vals[] = { + { 0, "1/4 timeslot (~144 microseconds)" }, + { 1, "2/4 timeslot (~288 microseconds)" }, + { 2, "3/4 timeslot (~433 microseconds)" }, + { 3, "4/4 timeslot (~577 microseconds)" }, + { 4, "5/4 timeslot (~721 microseconds)" }, + { 5, "6/4 timeslot (~865 microseconds)" }, + { 6, "7/4 timeslot (~1009 microseconds)" }, + { 7, "8/4 timeslot (~1154 microseconds)" }, + { 8, "9/4 timeslot (~1298 microseconds)" }, + { 9, "10/4 timeslot (~1442 microseconds)" }, + { 10, "11/4 timeslot (~1586 microseconds)" }, + { 11, "12/4 timeslot (~1730 microseconds)" }, + { 12, "13/4 timeslot (~1874 microseconds)" }, + { 13, "14/4 timeslot (~2019 microseconds)" }, + { 14, "15/4 timeslot (~2163 microseconds)" }, + { 15, "16/4 timeslot (~2307 microseconds)" }, + { 0, NULL} +}; + +static const true_false_string ms_assisted_e_otd_vals = { + "MS assisted E-OTD supported", + "MS assisted E-OTD not supported" +}; + +static const true_false_string ms_based_e_otd_vals = { + "MS based E-OTD supported", + "MS based E-OTD not supported" +}; + +static const true_false_string ms_assisted_gps_vals = { + "MS assisted GPS supported", + "MS assisted GPS not supported" +}; + +static const true_false_string ms_based_gps_vals = { + "MS based GPS supported", + "MS based GPS not supported" +}; + +static const true_false_string ms_conventional_gps_vals = { + "Conventional GPS supported", + "Conventional GPS not supported" +}; + +static const true_false_string modulation_capability_vals = { + "8-PSK supported for uplink transmission and downlink reception", + "8-PSK supported for downlink reception only" +}; + +static const value_string eight_psk_rf_power_capability_vals[] = { + { 0, "Reserved" }, + { 1, "Power class E1" }, + { 2, "Power class E2" }, + { 3, "Power class E3" }, + { 0, NULL} +}; + +static const value_string gsm_400_bands_supported_vals[] = { + { 1, "GSM 480 supported, GSM 450 not supported" }, + { 2, "GSM 450 supported, GSM 480 not supported" }, + { 3, "GSM 450 supported, GSM 480 supported" }, + { 0, NULL} +}; + +static const true_false_string umts_fdd_rat_cap_vals = { + "UMTS FDD supported", + "UMTS FDD not supported" +}; + +static const true_false_string umts_384_mcps_tdd_rat_cap_vals = { + "UMTS 3.84 Mcps TDD supported", + "UMTS 3.84 Mcps TDD not supported" +}; + +static const true_false_string cdma_2000_rat_cap_vals = { + "CDMA 2000 supported", + "CDMA 2000 not supported" +}; + +static const value_string dtm_gprs_multi_slot_class_vals[] = { + { 0, "Unused. If received, the network shall interpret this as 1" }, + { 1, "Multislot class 5 supported" }, + { 2, "Multislot class 9 supported" }, + { 3, "Multislot class 11 supported" }, + { 0, NULL} +}; + +static const true_false_string single_slot_dtm_vals = { + "Single Slot DTM supported", + "Single Slot DTM not supported" +}; + +static const value_string gsm_band_vals[] = { + { 0, "E-GSM is supported" }, + { 1, "P-GSM is supported" }, + { 2, "GSM 1800 is supported" }, + { 3, "GSM 450 is supported" }, + { 4, "GSM 480 is supported" }, + { 5, "GSM 850 is supported" }, + { 6, "GSM 1900 is supported" }, + { 7, "GSM 750 is supported" }, + { 8, "GSM 710 is supported" }, + { 9, "T-GSM 810 is supported" }, + { 0, NULL} +}; + +static const true_false_string umts_128_mcps_tdd_rat_cap_vals = { + "UMTS 1.28 Mcps TDD supported", + "UMTS 1.28 Mcps TDD not supported" +}; + +static const true_false_string geran_feature_package_1_vals = { + "GERAN feature package 1 supported", + "GERAN feature package 1 not supported" +}; + +static const true_false_string flo_iu_cap_vals = { + "FLO in GERAN Iu Mode supported", + "FLO in GERAN Iu Mode not supported" +}; + +static const true_false_string geran_feature_package_2_vals = { + "GERAN feature package 2 supported", + "GERAN feature package 2 not supported" +}; + +static const value_string gmsk_multislot_power_prof_vals[] = { + { 0, "GMSK_MULTISLOT_POWER_PROFILE 0" }, + { 1, "GMSK_MULTISLOT_POWER_PROFILE 1" }, + { 2, "GMSK_MULTISLOT_POWER_PROFILE 2" }, + { 3, "GMSK_MULTISLOT_POWER_PROFILE 3" }, + { 0, NULL} +}; + +static const value_string eight_psk_multislot_power_prof_vals[] = { + { 0, "8-PSK_MULTISLOT_POWER_PROFILE 0" }, + { 1, "8-PSK_MULTISLOT_POWER_PROFILE 1" }, + { 2, "8-PSK_MULTISLOT_POWER_PROFILE 2" }, + { 3, "8-PSK_MULTISLOT_POWER_PROFILE 3" }, + { 0, NULL} +}; + +static const value_string t_gsm_400_bands_supported_vals[] = { + { 1, "T-GSM 380 supported, T-GSM 410 not supported" }, + { 2, "T-GSM 410 supported, T-GSM 380 not supported" }, + { 3, "T-GSM 410 supported, T-GSM 380 supported" }, + { 0, NULL} +}; + +static const value_string downlink_adv_receiver_perf_vals[] = { + { 0, "Downlink Advanced Receiver Performance not supported" }, + { 1, "Downlink Advanced Receiver Performance - phase I supported" }, + { 2, "Downlink Advanced Receiver Performance - phase II supported" }, + { 0, NULL} +}; + +static const true_false_string dtm_enhancements_cap_vals = { + "The mobile station supports enhanced DTM CS establishment and release procedures", + "The mobile station does not support enhanced DTM CS establishment and release procedures" +}; + +static const true_false_string offset_required_vals = { + "The mobile station requires the offset", + "The mobile station does not require the offset" +}; + +static const value_string dtm_gprs_high_multi_slot_class_vals[] = { + { 0, "Unused. If received, the network shall interpret this as \"0 0 1\"" }, + { 1, "Multislot class 31 or 36 supported" }, + { 2, "Multislot class 32 or 37 supported" }, + { 3, "Multislot class 33 or 38 supported" }, + { 4, "Multislot class 41 supported" }, + { 5, "Multislot class 42 supported" }, + { 6, "Multislot class 43 supported" }, + { 7, "Multislot class 44 supported" }, + { 0, NULL} +}; + +static const true_false_string repeated_acch_cap_vals = { + "The mobile station supports Repeated SACCH and Repeated Downlink FACCH", + "The mobile station does not support Repeated SACCH" +}; + +static const true_false_string ciphering_mode_setting_cap_vals = { + "The mobile station supports the Ciphering Mode Setting IE in the DTM ASSIGNMENT COMMAND message", + "The mobile station does not support the Ciphering Mode Setting IE in the DTM ASSIGNMENT COMMAND message" +}; + +static const true_false_string additional_positioning_caps_vals = { + "The mobile station supports additional positioning capabilities which can be retrieved using RRLP", + "The mobile station does not support additional positioning capabilities which can be retrieved using RRLP" +}; + +static const true_false_string e_utra_fdd_support_vals = { + "E-UTRA FDD supported", + "E-UTRA FDD not supported" +}; + +static const true_false_string e_utra_tdd_support_vals = { + "E-UTRA TDD supported", + "E-UTRA TDD not supported" +}; + +static const true_false_string e_utra_meas_and_report_support_vals = { + "E-UTRAN Neighbour Cell measurements and measurement reporting while having an RR connection supported", + "E-UTRAN Neighbour Cell measurements and measurement reporting while having an RR connection not supported" +}; + +static const true_false_string prio_based_resel_support_vals = { + "Priority-based cell reselection supported", + "Priority-based cell reselection not supported" +}; + +static const true_false_string utra_csg_cells_reporting_vals = { + "Reporting of UTRAN CSG cells supported", + "Reporting of UTRAN CSG cells not supported" +}; + +static const value_string vamos_level_vals[] = { + { 0, "VAMOS not supported" }, + { 1, "VAMOS I supported" }, + { 2, "VAMOS II supported" }, + { 3, "VAMOS III supported" }, + { 0, NULL} +}; + +const value_string tighter_cap_level_vals[] = { + { 0, "TIGHTER not supported" }, + { 1, "TIGHTER supported for speech and signalling channels only" }, + { 2, "TIGHTER supported for speech and signalling channels and for GPRS and EGPRS, but not for EGPRS2" }, + { 3, "TIGHTER supported for speech and signalling channels and for GPRS, EGPRS and EGPRS2" }, + { 0, NULL} +}; + +static const value_string cs_to_ps_srvcc_geran_to_utra_vals[] = { + { 0, "CS to PS SRVCC from GERAN to UMTS FDD and 1.28 Mcps TDD not supported" }, + { 1, "CS to PS SRVCC from GERAN to UMTS FDD supported" }, + { 2, "CS to PS SRVCC from GERAN to UMTS 1.28 Mcps TDD supported" }, + { 3, "CS to PS SRVCC from GERAN to UMTS FDD and 1.28 Mcps TDD supported" }, + { 0, NULL} +}; + +static const value_string cs_to_ps_srvcc_geran_to_eutra_vals[] = { + { 0, "CS to PS SRVCC from GERAN to E-UTRA FDD and TDD not supported" }, + { 1, "CS to PS SRVCC from GERAN to E-UTRA FDD supported" }, + { 2, "CS to PS SRVCC from GERAN to E-UTRA TDD supported" }, + { 3, "CS to PS SRVCC from GERAN to E-UTRA FDD and TDD supported" }, + { 0, NULL} +}; + +static const value_string gsm_a_rr_rxlev_vals [] = { + { 0, "< -110 dBm"}, + { 1, "-110 <= x < -109 dBm"}, + { 2, "-109 <= x < -108 dBm"}, + { 3, "-108 <= x < -107 dBm"}, + { 4, "-107 <= x < -106 dBm"}, + { 5, "-106 <= x < -105 dBm"}, + { 6, "-105 <= x < -104 dBm"}, + { 7, "-104 <= x < -103 dBm"}, + { 8, "-103 <= x < -102 dBm"}, + { 9, "-102 <= x < -101 dBm"}, + { 10, "-101 <= x < -100 dBm"}, + { 11, "-100 <= x < -99 dBm"}, + { 12, "-99 <= x < -98 dBm"}, + { 13, "-98 <= x < -97 dBm"}, + { 14, "-97 <= x < -96 dBm"}, + { 15, "-96 <= x < -95 dBm"}, + { 16, "-95 <= x < -94 dBm"}, + { 17, "-94 <= x < -93 dBm"}, + { 18, "-93 <= x < -92 dBm"}, + { 19, "-92 <= x < -91 dBm"}, + { 20, "-91 <= x < -90 dBm"}, + { 21, "-90 <= x < -89 dBm"}, + { 22, "-89 <= x < -88 dBm"}, + { 23, "-88 <= x < -87 dBm"}, + { 24, "-87 <= x < -86 dBm"}, + { 25, "-86 <= x < -85 dBm"}, + { 26, "-85 <= x < -84 dBm"}, + { 27, "-84 <= x < -83 dBm"}, + { 28, "-83 <= x < -82 dBm"}, + { 29, "-82 <= x < -81 dBm"}, + { 30, "-81 <= x < -80 dBm"}, + { 31, "-80 <= x < -79 dBm"}, + { 32, "-79 <= x < -78 dBm"}, + { 33, "-78 <= x < -77 dBm"}, + { 34, "-77 <= x < -76 dBm"}, + { 35, "-76 <= x < -75 dBm"}, + { 36, "-75 <= x < -74 dBm"}, + { 37, "-74 <= x < -73 dBm"}, + { 38, "-73 <= x < -72 dBm"}, + { 39, "-72 <= x < -71 dBm"}, + { 40, "-71 <= x < -70 dBm"}, + { 41, "-70 <= x < -69 dBm"}, + { 42, "-69 <= x < -68 dBm"}, + { 43, "-68 <= x < -67 dBm"}, + { 44, "-67 <= x < -66 dBm"}, + { 45, "-66 <= x < -65 dBm"}, + { 46, "-65 <= x < -64 dBm"}, + { 47, "-64 <= x < -63 dBm"}, + { 48, "-63 <= x < -62 dBm"}, + { 49, "-62 <= x < -61 dBm"}, + { 50, "-61 <= x < -60 dBm"}, + { 51, "-60 <= x < -59 dBm"}, + { 52, "-59 <= x < -58 dBm"}, + { 53, "-58 <= x < -57 dBm"}, + { 54, "-57 <= x < -56 dBm"}, + { 55, "-56 <= x < -55 dBm"}, + { 56, "-55 <= x < -54 dBm"}, + { 57, "-54 <= x < -53 dBm"}, + { 58, "-53 <= x < -52 dBm"}, + { 59, "-52 <= x < -51 dBm"}, + { 60, "-51 <= x < -50 dBm"}, + { 61, "-50 <= x < -49 dBm"}, + { 62, "-49 <= x < -48 dBm"}, + { 63, ">= -48 dBm"}, + { 0, NULL} +}; +value_string_ext gsm_a_rr_rxlev_vals_ext = VALUE_STRING_EXT_INIT(gsm_a_rr_rxlev_vals); + +const value_string gsm_a_rr_rxqual_vals[] = { + {0, "BER < 0.2%, Mean value 0.14%"}, + {1, "0.2% <= BER < 0.4%, Mean value 0.28%"}, + {2, "0.4% <= BER < 0.8%, Mean value 0.57%"}, + {3, "0.8% <= BER < 1.6%, Mean value 1.13%"}, + {4, "1.6% <= BER < 3.2%, Mean value 2.26%"}, + {5, "3.2% <= BER < 6.4%, Mean value 4.53%"}, + {6, "6.4% <= BER < 12.8%, Mean value 9.05%"}, + {7, "BER > 12.8%, Mean value 18.10%"}, + {0, NULL} +}; + +/* Initialize the protocol and registered fields */ +static int proto_a_common = -1; +static int proto_3gpp = -1; + +int gsm_a_tap = -1; + +int hf_gsm_a_common_elem_id = -1; +static int hf_gsm_a_common_elem_id_f0 = -1; +static int hf_gsm_a_l_ext = -1; +int hf_gsm_a_tmsi = -1; +static int hf_gsm_a_imei = -1; +static int hf_gsm_a_imeisv = -1; + +static int hf_gsm_a_MSC_rev = -1; +static int hf_gsm_a_ES_IND = -1; +static int hf_gsm_a_A5_1_algorithm_sup = -1; +static int hf_gsm_a_RF_power_capability = -1; +static int hf_gsm_a_ps_sup_cap = -1; +static int hf_gsm_a_SS_screening_indicator = -1; +static int hf_gsm_a_SM_capability = -1; +static int hf_gsm_a_VBS_notification_rec = -1; +static int hf_gsm_a_VGCS_notification_rec = -1; +static int hf_gsm_a_FC_frequency_cap = -1; +static int hf_gsm_a_CM3 = -1; +static int hf_gsm_a_LCS_VA_cap = -1; +static int hf_gsm_a_UCS2_treatment = -1; +static int hf_gsm_a_SoLSA = -1; +static int hf_gsm_a_CMSP = -1; +static int hf_gsm_a_A5_7_algorithm_sup = -1; +static int hf_gsm_a_A5_6_algorithm_sup = -1; +static int hf_gsm_a_A5_5_algorithm_sup = -1; +static int hf_gsm_a_A5_4_algorithm_sup = -1; +static int hf_gsm_a_A5_3_algorithm_sup = -1; +static int hf_gsm_a_A5_2_algorithm_sup = -1; + +static int hf_gsm_a_odd_even_ind = -1; +static int hf_gsm_a_id_dig_1 = -1; +static int hf_gsm_a_unused = -1; +static int hf_gsm_a_mobile_identity_type = -1; +static int hf_gsm_a_tmgi_mcc_mnc_ind = -1; +static int hf_gsm_a_mbs_ses_id_ind = -1; +static int hf_gsm_a_mbs_service_id = -1; +static int hf_gsm_a_mbs_session_id = -1; +static int hf_gsm_a_length = -1; +static int hf_gsm_a_element_value = -1; +int hf_gsm_a_extension = -1; +int hf_gsm_a_L3_protocol_discriminator = -1; +int hf_gsm_a_call_prio = -1; +int hf_gsm_a_skip_ind = -1; +int hf_gsm_a_spare_bits = -1; +int hf_gsm_a_lac = -1; + +static int hf_gsm_a_spare_nibble = -1; +static int hf_gsm_a_type_of_ciph_alg = -1; +static int hf_gsm_a_att = -1; +static int hf_gsm_a_nmo_1 = -1; +static int hf_gsm_a_nmo = -1; +static int hf_gsm_a_old_xid = -1; +static int hf_gsm_a_iov_ui = -1; +static int hf_gsm_a_ext_periodic_timers = -1; +static int hf_gsm_a_b7spare = -1; +int hf_gsm_a_b8spare = -1; +static int hf_gsm_a_multi_bnd_sup_fields = -1; +static int hf_gsm_a_pgsm_supported = -1; +static int hf_gsm_a_egsm_supported = -1; +static int hf_gsm_a_gsm1800_supported = -1; +static int hf_gsm_a_ass_radio_cap1 = -1; +static int hf_gsm_a_ass_radio_cap2 = -1; +static int hf_gsm_a_rsupport = -1; +static int hf_gsm_a_r_capabilities = -1; +static int hf_gsm_a_multislot_capabilities = -1; +static int hf_gsm_a_multislot_class = -1; +static int hf_gsm_a_ucs2_treatment = -1; +static int hf_gsm_a_extended_measurement_cap = -1; +static int hf_gsm_a_ms_measurement_capability = -1; +static int hf_gsm_a_sms_value =-1; +static int hf_gsm_a_sm_value =-1; +static int hf_gsm_a_key_seq = -1; +static int hf_gsm_a_ms_pos_method_cap_present = -1; +static int hf_gsm_a_ms_pos_method = -1; +static int hf_gsm_a_ms_assisted_e_otd = -1; +static int hf_gsm_a_ms_based_e_otd = -1; +static int hf_gsm_a_ms_assisted_gps = -1; +static int hf_gsm_a_ms_based_gps = -1; +static int hf_gsm_a_ms_conventional_gps = -1; +static int hf_gsm_a_ecsd_multi_slot_capability = -1; +static int hf_gsm_a_ecsd_multi_slot_class = -1; +static int hf_gsm_a_8_psk_struct_present = -1; +static int hf_gsm_a_8_psk_struct = -1; +static int hf_gsm_a_modulation_capability = -1; +static int hf_gsm_a_8_psk_rf_power_capability_1_present = -1; +static int hf_gsm_a_8_psk_rf_power_capability_1 = -1; +static int hf_gsm_a_8_psk_rf_power_capability_2_present = -1; +static int hf_gsm_a_8_psk_rf_power_capability_2 = -1; +static int hf_gsm_a_gsm_400_band_info_present = -1; +static int hf_gsm_a_gsm_400_bands_supported = -1; +static int hf_gsm_a_gsm_400_assoc_radio_cap = -1; +static int hf_gsm_a_gsm_850_assoc_radio_cap_present = -1; +static int hf_gsm_a_gsm_850_assoc_radio_cap = -1; +static int hf_gsm_a_gsm_1900_assoc_radio_cap_present = -1; +static int hf_gsm_a_gsm_1900_assoc_radio_cap = -1; +static int hf_gsm_a_cm3_A5_bits = -1; +static int hf_gsm_a_umts_fdd_rat_cap = -1; +static int hf_gsm_a_umts_384_mcps_tdd_rat_cap = -1; +static int hf_gsm_a_cdma_2000_rat_cap = -1; +static int hf_gsm_a_dtm_e_gprs_multi_slot_info_present = -1; +static int hf_gsm_a_dtm_gprs_multi_slot_class = -1; +static int hf_gsm_a_single_slot_dtm = -1; +static int hf_gsm_a_dtm_egprs_multi_slot_class_present = -1; +static int hf_gsm_a_dtm_egprs_multi_slot_class = -1; +static int hf_gsm_a_single_band_support = -1; +static int hf_gsm_a_gsm_band = -1; +static int hf_gsm_a_gsm_750_assoc_radio_cap_present = -1; +static int hf_gsm_a_gsm_750_assoc_radio_cap = -1; +static int hf_gsm_a_umts_128_mcps_tdd_rat_cap = -1; +static int hf_gsm_a_geran_feature_package_1 = -1; +static int hf_gsm_a_ext_dtm_e_gprs_multi_slot_info_present = -1; +static int hf_gsm_a_ext_dtm_gprs_multi_slot_class = -1; +static int hf_gsm_a_ext_dtm_egprs_multi_slot_class = -1; +static int hf_gsm_a_high_multislot_cap_present = -1; +static int hf_gsm_a_high_multislot_cap = -1; +static int hf_gsm_a_geran_iu_mode_support = -1; +static int hf_gsm_a_geran_iu_mode_cap = -1; +static int hf_gsm_a_geran_iu_mode_cap_length = -1; +static int hf_gsm_a_flo_iu_cap = -1; +static int hf_gsm_a_geran_feature_package_2 = -1; +static int hf_gsm_a_gmsk_multislot_power_prof = -1; +static int hf_gsm_a_8_psk_multislot_power_prof = -1; +static int hf_gsm_a_t_gsm_400_band_info_present = -1; +static int hf_gsm_a_t_gsm_400_bands_supported = -1; +static int hf_gsm_a_t_gsm_400_assoc_radio_cap = -1; +static int hf_gsm_a_t_gsm_900_assoc_radio_cap_present = -1; +static int hf_gsm_a_t_gsm_900_assoc_radio_cap = -1; +static int hf_gsm_a_downlink_adv_receiver_perf = -1; +static int hf_gsm_a_dtm_enhancements_cap = -1; +static int hf_gsm_a_dtm_e_gprs_high_multi_slot_info_present = -1; +static int hf_gsm_a_dtm_gprs_high_multi_slot_class = -1; +static int hf_gsm_a_offset_required = -1; +static int hf_gsm_a_dtm_egprs_high_multi_slot_class_present = -1; +static int hf_gsm_a_dtm_egprs_high_multi_slot_class = -1; +static int hf_gsm_a_repeated_acch_cap = -1; +static int hf_gsm_a_gsm_710_assoc_radio_cap_present = -1; +static int hf_gsm_a_gsm_710_assoc_radio_cap = -1; +static int hf_gsm_a_t_gsm_810_assoc_radio_cap_present = -1; +static int hf_gsm_a_t_gsm_810_assoc_radio_cap = -1; +static int hf_gsm_a_ciphering_mode_setting_cap = -1; +static int hf_gsm_a_additional_positioning_caps = -1; +static int hf_gsm_a_e_utra_fdd_support = -1; +static int hf_gsm_a_e_utra_tdd_support = -1; +static int hf_gsm_a_e_utra_meas_and_report_support = -1; +static int hf_gsm_a_prio_based_resel_support = -1; +static int hf_gsm_a_utra_csg_cells_reporting = -1; +static int hf_gsm_a_vamos_level = -1; +static int hf_gsm_a_tighter_cap = -1; +static int hf_gsm_a_selective_ciph_down_sacch = -1; +static int hf_gsm_a_cs_to_ps_srvcc_geran_to_utra = -1; +static int hf_gsm_a_cs_to_ps_srvcc_geran_to_eutra = -1; +static int hf_gsm_a_geran_network_sharing_support = -1; +static int hf_gsm_a_eutra_wb_rsrq_support = -1; +static int hf_gsm_a_er_band_support = -1; +static int hf_gsm_a_utra_mfbi_support = -1; +static int hf_gsm_a_eutra_mfbi_support = -1; +static int hf_gsm_a_ext_tsc_set_cap_support = -1; +static int hf_gsm_a_ext_earfcn_value_range = -1; + +static int hf_gsm_a_geo_loc_type_of_shape = -1; +static int hf_gsm_a_geo_loc_sign_of_lat = -1; +static int hf_gsm_a_geo_loc_deg_of_lat =-1; +static int hf_gsm_a_geo_loc_deg_of_long =-1; +static int hf_gsm_a_geo_loc_osm_uri =-1; +static int hf_gsm_a_geo_loc_uncertainty_code = -1; +static int hf_gsm_a_geo_loc_uncertainty_semi_major = -1; +static int hf_gsm_a_geo_loc_uncertainty_semi_minor = -1; +static int hf_gsm_a_geo_loc_orientation_of_major_axis = -1; +static int hf_gsm_a_geo_loc_uncertainty_altitude = -1; +static int hf_gsm_a_geo_loc_confidence = -1; +static int hf_gsm_a_geo_loc_uncertainty_range = -1; +static int hf_gsm_a_geo_loc_horizontal_confidence = -1; +static int hf_gsm_a_geo_loc_horizontal_uncertainty_range = -1; +static int hf_gsm_a_geo_loc_vertical_confidence = -1; +static int hf_gsm_a_geo_loc_vertical_uncertainty_range = -1; +static int hf_gsm_a_geo_loc_high_acc_uncertainty_alt = -1; +static int hf_gsm_a_geo_loc_no_of_points = -1; +static int hf_gsm_a_geo_loc_high_acc_deg_of_lat = -1; +static int hf_gsm_a_geo_loc_high_acc_deg_of_long = -1; +static int hf_gsm_a_geo_loc_high_acc_uncertainty_semi_major = -1; +static int hf_gsm_a_geo_loc_high_acc_uncertainty_semi_minor = -1; +static int hf_gsm_a_geo_loc_high_acc_alt = -1; +static int hf_gsm_a_velocity_type = -1; +static int hf_gsm_a_bearing = -1; +static int hf_gsm_a_horizontal_speed = -1; +static int hf_gsm_a_uncertainty_speed = -1; +static int hf_gsm_a_h_uncertainty_speed = -1; +static int hf_gsm_a_v_uncertainty_speed = -1; +static int hf_gsm_a_vertical_speed = -1; +static int hf_gsm_a_d = -1; +static int hf_gsm_a_geo_loc_D = -1; +static int hf_gsm_a_geo_loc_altitude = -1; +static int hf_gsm_a_geo_loc_inner_radius = -1; +static int hf_gsm_a_geo_loc_uncertainty_radius = -1; +static int hf_gsm_a_geo_loc_offset_angle = -1; +static int hf_gsm_a_geo_loc_included_angle = -1; + +/* Generated from convert_proto_tree_add_text.pl */ +static int hf_gsm_a_filler = -1; +static int hf_gsm_a_identity_digit1 = -1; +static int hf_gsm_a_group_call_reference = -1; +static int hf_gsm_a_service_flag = -1; +static int hf_gsm_a_af_acknowledgement = -1; +static int hf_gsm_a_call_priority = -1; +static int hf_gsm_a_ciphering_info = -1; +static int hf_gsm_a_sapi = -1; + +/* Inter protocol hf */ +int hf_3gpp_tmsi = -1; + +static int ett_gsm_a_plmn = -1; +static int ett_gsm_a_poly_pnt = -1; + +static expert_field ei_gsm_a_extraneous_data = EI_INIT; +static expert_field ei_gsm_a_unknown_element = EI_INIT; +static expert_field ei_gsm_a_unknown_pdu_type = EI_INIT; +static expert_field ei_gsm_a_no_element_dissector = EI_INIT; +static expert_field ei_gsm_a_format_not_supported = EI_INIT; +static expert_field ei_gsm_a_mobile_identity_type = EI_INIT; +static expert_field ei_gsm_a_ie_length_too_short = EI_INIT; + +sccp_assoc_info_t* sccp_assoc = NULL; + +#define NUM_GSM_COMMON_ELEM (sizeof(gsm_common_elem_strings)/sizeof(value_string)) +gint ett_gsm_common_elem[NUM_GSM_COMMON_ELEM]; + + +#define ELLIPSOID_POINT 0 +#define ELLIPSOID_POINT_WITH_UNCERT_CIRC 1 +#define ELLIPSOID_POINT_WITH_UNCERT_ELLIPSE 3 +#define POLYGON 5 +#define ELLIPSOID_POINT_WITH_ALT 8 +#define ELLIPSOID_POINT_WITH_ALT_AND_UNCERT_ELLIPSOID 9 +#define ELLIPSOID_ARC 10 +#define HIGH_ACC_ELLIPSOID_PNT_WITH_UNCERT_ELLIPSE 11 +#define HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_UNCERT_ELLIPSOID 12 +#define HIGH_ACC_ELLIPSOID_PNT_WITH_SCALABLE_UNCERT_ELLIPSE 13 +#define HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_SCALABLE_UNCERT_ELLIPSOID 14 +/* +4 3 2 1 +0 0 0 0 Ellipsoid Point +0 0 0 1 Ellipsoid point with uncertainty Circle +0 0 1 1 Ellipsoid point with uncertainty Ellipse +0 1 0 1 Polygon +1 0 0 0 Ellipsoid point with altitude +1 0 0 1 Ellipsoid point with altitude and uncertainty Ellipsoid +1 0 1 0 Ellipsoid Arc +1 0 1 1 High Accuracy Ellipsoid point with uncertainty ellipse +1 1 0 0 High Accuracy Ellipsoid point with altitude and uncertainty ellipsoid +1 1 0 1 High Accuracy Ellipsoid point with scalable uncertainty ellipse +1 1 1 0 High Accuracy Ellipsoid point with altitude and scalable uncertainty ellipsoid +other values reserved for future use +*/ + +/* TS 23 032 Table 2a: Coding of Type of Shape */ +static const value_string type_of_shape_vals[] = { + { ELLIPSOID_POINT, "Ellipsoid Point"}, + { ELLIPSOID_POINT_WITH_UNCERT_CIRC, "Ellipsoid point with uncertainty Circle"}, + { ELLIPSOID_POINT_WITH_UNCERT_ELLIPSE, "Ellipsoid point with uncertainty Ellipse"}, + { POLYGON, "Polygon"}, + { ELLIPSOID_POINT_WITH_ALT, "Ellipsoid point with altitude"}, + { ELLIPSOID_POINT_WITH_ALT_AND_UNCERT_ELLIPSOID, "Ellipsoid point with altitude and uncertainty Ellipsoid"}, + { ELLIPSOID_ARC, "Ellipsoid Arc"}, + { HIGH_ACC_ELLIPSOID_PNT_WITH_UNCERT_ELLIPSE, "High Accuracy Ellipsoid point with uncertainty ellipse"}, + { HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_UNCERT_ELLIPSOID, "High Accuracy Ellipsoid point with altitude and uncertainty ellipsoid"}, + { HIGH_ACC_ELLIPSOID_PNT_WITH_SCALABLE_UNCERT_ELLIPSE, "High Accuracy Ellipsoid point with scalable uncertainty ellipse"}, + { HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_SCALABLE_UNCERT_ELLIPSOID, "High Accuracy Ellipsoid point with altitude and scalable uncertainty ellipsoid"}, + { 0, NULL } +}; + +/* 3GPP TS 23.032 7.3.1 */ +static const value_string sign_of_latitude_vals[] = { + { 0, "North"}, + { 1, "South"}, + { 0, NULL } +}; + +static const value_string dir_of_alt_vals[] = { + { 0, "Altitude expresses height"}, + { 1, "Altitude expresses depth"}, + { 0, NULL } +}; + +static const value_string uncertainty_range[] = { + { 0, "High Accuracy default uncertainty range used"}, + { 1, "High Accuracy Extended Uncertainty Range used"}, + { 0, NULL } +}; + +typedef guint16 (**elem_func_hander)(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string, int string_len); + +int +dissect_geographical_description(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) { + + proto_item *lat_item, *long_item, *major_item, *minor_item, *alt_item, *uncer_item, *loc_uri_item; + /*proto_tree *subtree; */ + guint32 type_of_shape; + int offset = 0; + int length; + guint8 value; + guint32 uvalue32; + gint32 svalue32; + gchar *deg_lat_str; + gchar *deg_lon_str; + gchar *osm_uri; + int loc_offset; + + /*subtree = proto_item_add_subtree(item, ett_gsm_a_geo_desc);*/ + + length = tvb_reported_length_remaining(tvb, 0); + /* Geographical Location + * The Location Estimate field is composed of 1 or more octets with an internal structure + * according to section 7 in [23.032]. + */ + proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_type_of_shape, tvb, 0, 1, ENC_BIG_ENDIAN, &type_of_shape); + offset++; + if (length < 2) { + return length; + } + switch (type_of_shape) { + case ELLIPSOID_POINT: + /* Ellipsoid Point */ + case ELLIPSOID_POINT_WITH_UNCERT_CIRC: + /* Ellipsoid Point with uncertainty Circle */ + case ELLIPSOID_POINT_WITH_UNCERT_ELLIPSE: + /* Ellipsoid Point with uncertainty Ellipse */ + case ELLIPSOID_POINT_WITH_ALT: + /* Ellipsoid Point with Altitude */ + case ELLIPSOID_POINT_WITH_ALT_AND_UNCERT_ELLIPSOID: + /* Ellipsoid Point with altitude and uncertainty ellipsoid */ + case ELLIPSOID_ARC: + /* Ellipsoid Arc */ + if (length < 4) + return length; + proto_tree_add_item(tree, hf_gsm_a_geo_loc_sign_of_lat, tvb, offset, 1, ENC_BIG_ENDIAN); + + uvalue32 = tvb_get_ntoh24(tvb,offset); + /* convert degrees (X/0x7fffff) * 90 = degrees */ + lat_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_deg_of_lat, tvb, offset, 3, ENC_BIG_ENDIAN); + deg_lat_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (uvalue32 & 0x00800000) ? "-" : "", + ((double)(uvalue32 & 0x7fffff)/8388607.0) * 90); + proto_item_append_text(lat_item, " (%s degrees)", deg_lat_str); + loc_offset = offset; + offset = offset + 3; + if (length < 7) + return offset; + svalue32 = tvb_get_ntoh24(tvb,offset); + svalue32 |= (svalue32 & 0x800000) ? 0xff000000 : 0x00000000; + long_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_deg_of_long, tvb, offset, 3, ENC_BIG_ENDIAN); + /* (X/0xffffff) *360 = degrees */ + deg_lon_str = wmem_strdup_printf(pinfo->pool, "%.5f", + ((double)svalue32/16777215.0) * 360); + proto_item_append_text(long_item, " (%s degrees)", deg_lon_str); + offset = offset + 3; + if (type_of_shape == ELLIPSOID_POINT_WITH_UNCERT_CIRC) { + /* Ellipsoid Point with uncertainty Circle */ + if (length < 8) + return offset; + /* Uncertainty code */ + value = tvb_get_guint8(tvb,offset)&0x7f; + uncer_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_code, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(uncer_item, " (%.1f m)", 10 * (pow(1.1, (double)value) - 1)); + }else if (type_of_shape == ELLIPSOID_POINT_WITH_UNCERT_ELLIPSE) { + /* Ellipsoid Point with uncertainty Ellipse */ + /* Uncertainty semi-major octet 10 + * To convert to metres 10*(((1.1)^X)-1) + */ + value = tvb_get_guint8(tvb,offset) & 0x7f; + major_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_semi_major, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(major_item, " (%.1f m)", 10 * (pow(1.1, (double)value) - 1)); + offset++; + /* Uncertainty semi-minor Octet 11 + * To convert to metres 10*(((1.1)^X)-1) + */ + value = tvb_get_guint8(tvb,offset)&0x7f; + minor_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_semi_minor, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(minor_item, " (%.1f m)", 10 * (pow(1.1, (double)value) - 1)); + offset++; + /* TS 23.032 V15.1.0 (2018-09) + * Orientation of major axis octet 12 + * allowed value from 0-179 + */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_orientation_of_major_axis, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + /* Confidence */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + }else if (type_of_shape == ELLIPSOID_POINT_WITH_ALT) { + /* Ellipsoid Point with Altitude */ + /*D: Direction of Altitude */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_D, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Altitude */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_altitude, tvb, offset, 2, ENC_BIG_ENDIAN); + }else if (type_of_shape == ELLIPSOID_POINT_WITH_ALT_AND_UNCERT_ELLIPSOID) { + /* Ellipsoid Point with altitude and uncertainty ellipsoid */ + /*D: Direction of Altitude octet 8,9 */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_D, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Altitude Octet 8,9*/ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_altitude, tvb, offset, 2, ENC_BIG_ENDIAN); + offset = offset +2; + /* Uncertainty semi-major octet 10 + * To convert to metres 10*(((1.1)^X)-1) + */ + value = tvb_get_guint8(tvb,offset)&0x7f; + major_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_semi_major, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(major_item, " (%.1f m)", 10 * (pow(1.1, (double)value) - 1)); + offset++; + /* Uncertainty semi-minor Octet 11 + * To convert to metres 10*(((1.1)^X)-1) + */ + value = tvb_get_guint8(tvb,offset)&0x7f; + minor_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_semi_minor, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(minor_item, " (%.1f m)", 10 * (pow(1.1, (double)value) - 1)); + offset++; + /* Orientation of major axis octet 12 + * allowed value from 0-179 to convert + * to actual degrees multiply by 2. + */ + value = tvb_get_guint8(tvb,offset)&0x7f; + proto_tree_add_uint(tree, hf_gsm_a_geo_loc_orientation_of_major_axis, tvb, offset, 1, value*2); + offset++; + /* Uncertainty Altitude 13 + * to convert to metres 45*(((1.025)^X)-1) + */ + value = tvb_get_guint8(tvb,offset)&0x7f; + alt_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_altitude, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(alt_item, " (%.1f m)", 45 * (pow(1.025, (double)value) - 1)); + offset++; + /* Confidence octet 14 + */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + }else if (type_of_shape == ELLIPSOID_ARC) { + /* Ellipsoid Arc */ + /* Inner radius */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_inner_radius, tvb, offset, 2, ENC_BIG_ENDIAN); + offset = offset + 2; + /* Uncertainty radius */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_radius, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + /* Offset angle */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_offset_angle, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + /* Included angle */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_included_angle, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + /* Confidence */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + } + osm_uri = wmem_strdup_printf(pinfo->pool, "https://www.openstreetmap.org/?mlat=%s&mlon=%s&zoom=12", deg_lat_str, deg_lon_str); + loc_uri_item = proto_tree_add_string(tree, hf_gsm_a_geo_loc_osm_uri, tvb, loc_offset, 6, osm_uri); + proto_item_set_url(loc_uri_item); + proto_item_set_generated(loc_uri_item); + + break; + case POLYGON: /* Polygon */ + { + /* Number of points */ + guint32 no_of_points; + guint point_no = 0; + proto_tree* sub_tree; + proto_item *ti; + + proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_no_of_points, tvb, 0, 1, ENC_BIG_ENDIAN, &no_of_points); + /* offset increased with 1 after reading of shape abowe*/ + while (no_of_points > 0) { + point_no++; + sub_tree = proto_tree_add_subtree_format(tree, tvb, offset, 6, + ett_gsm_a_poly_pnt, &ti, "Polygon point %u", point_no); + proto_tree_add_item(sub_tree, hf_gsm_a_geo_loc_sign_of_lat, tvb, offset, 1, ENC_BIG_ENDIAN); + + uvalue32 = tvb_get_ntoh24(tvb, offset); + /* convert degrees (X/0x7fffff) * 90 = degrees */ + lat_item = proto_tree_add_item(sub_tree, hf_gsm_a_geo_loc_deg_of_lat, tvb, offset, 3, ENC_BIG_ENDIAN); + deg_lat_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (uvalue32 & 0x00800000) ? "-" : "", + ((double)(uvalue32 & 0x7fffff) / 8388607.0) * 90); + proto_item_append_text(lat_item, " (%s degrees)", deg_lat_str); + loc_offset = offset; + offset = offset + 3; + svalue32 = tvb_get_ntoh24(tvb, offset); + svalue32 |= (svalue32 & 0x800000) ? 0xff000000 : 0x00000000; + long_item = proto_tree_add_item(sub_tree, hf_gsm_a_geo_loc_deg_of_long, tvb, offset, 3, ENC_BIG_ENDIAN); + /* (X/0xffffff) *360 = degrees */ + deg_lon_str = wmem_strdup_printf(pinfo->pool, "%.5f", + ((double)svalue32 / 16777215.0) * 360); + proto_item_append_text(long_item, " (%s degrees)", deg_lon_str); + offset = offset + 3; + no_of_points--; + + osm_uri = wmem_strdup_printf(pinfo->pool, "https://www.openstreetmap.org/?mlat=%s&mlon=%s&zoom=12", deg_lat_str, deg_lon_str); + loc_uri_item = proto_tree_add_string(tree, hf_gsm_a_geo_loc_osm_uri, tvb, loc_offset, 6, osm_uri); + proto_item_set_url(loc_uri_item); + proto_item_set_generated(loc_uri_item); + } + } + break; + case HIGH_ACC_ELLIPSOID_PNT_WITH_UNCERT_ELLIPSE: + case HIGH_ACC_ELLIPSOID_PNT_WITH_SCALABLE_UNCERT_ELLIPSE: + loc_offset = offset; + lat_item = proto_tree_add_item_ret_int(tree, hf_gsm_a_geo_loc_high_acc_deg_of_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &svalue32); + deg_lat_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (svalue32 & 0x80000000) ? "-" : "", + ((double)(svalue32 & 0x7fffffff) / 2147483647.0) * 90); + proto_item_append_text(lat_item, " (%s degrees)", deg_lat_str); + offset += 4; + long_item = proto_tree_add_item_ret_int(tree, hf_gsm_a_geo_loc_high_acc_deg_of_long, tvb, offset, 4, ENC_BIG_ENDIAN, &svalue32); + deg_lon_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (svalue32 & 0x80000000) ? "-" : "", + ((double)svalue32 / 2147483647.0) * 180); + proto_item_append_text(long_item, " (%s degrees)", deg_lon_str); + + offset += 4; + /* High accuracy uncertainty semi-major*/ + major_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_high_acc_uncertainty_semi_major, tvb, offset, 1, ENC_BIG_ENDIAN, &uvalue32); + proto_item_append_text(major_item, " (%.5f m)", 0.3 * (pow(1.02, (double)uvalue32) - 1)); + offset++; + /* High accuracy uncertainty semi-minor*/ + minor_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_high_acc_uncertainty_semi_minor, tvb, offset, 1, ENC_BIG_ENDIAN, &uvalue32); + proto_item_append_text(minor_item, " (%.5f m)", 0.3 * (pow(1.02, (double)uvalue32) - 1)); + offset++; + /* Orientation of major axis */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_orientation_of_major_axis, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + /* Confidence */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + if (type_of_shape == HIGH_ACC_ELLIPSOID_PNT_WITH_SCALABLE_UNCERT_ELLIPSE) { + /* Uncertainty Range */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_uncertainty_range, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + + osm_uri = wmem_strdup_printf(pinfo->pool, "https://www.openstreetmap.org/?mlat=%s&mlon=%s&zoom=12", deg_lat_str, deg_lon_str); + loc_uri_item = proto_tree_add_string(tree, hf_gsm_a_geo_loc_osm_uri, tvb, loc_offset, 6, osm_uri); + proto_item_set_url(loc_uri_item); + proto_item_set_generated(loc_uri_item); + + break; + case HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_UNCERT_ELLIPSOID: + case HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_SCALABLE_UNCERT_ELLIPSOID: + lat_item = proto_tree_add_item_ret_int(tree, hf_gsm_a_geo_loc_high_acc_deg_of_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &svalue32); + deg_lat_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (svalue32 & 0x80000000) ? "-" : "", + ((double)(svalue32 & 0x7fffffff) / 2147483647.0) * 90); + proto_item_append_text(lat_item, " (%s degrees)", deg_lat_str); + offset += 4; + long_item = proto_tree_add_item_ret_int(tree, hf_gsm_a_geo_loc_high_acc_deg_of_long, tvb, offset, 4, ENC_BIG_ENDIAN, &svalue32); + deg_lon_str = wmem_strdup_printf(pinfo->pool, "%s%.5f", + (svalue32 & 0x80000000) ? "-" : "", + ((double)svalue32 / 2147483647.0) * 180); + proto_item_append_text(long_item, " (%s degrees)", deg_lon_str); + offset += 4; + + /* High accuracy altitude + * High accuracy altitude is encoded as a number N between -64000 and 1280000 using 2's complement binary on 22 bits. + */ + + alt_item = proto_tree_add_item_ret_int(tree, hf_gsm_a_geo_loc_high_acc_alt, tvb, offset, 3, ENC_BIG_ENDIAN, &svalue32); + /* double z = pow(double x, double y);*/ + proto_item_append_text(alt_item, " (%.1f m)", (double)svalue32 * pow(2,-7)); + offset += 3; + + /* High accuracy uncertainty semi-major*/ + major_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_high_acc_uncertainty_semi_major, tvb, offset, 1, ENC_BIG_ENDIAN, &uvalue32); + proto_item_append_text(major_item, " (%.5f m)", 0.3 * (pow(1.02, (double)uvalue32) - 1)); + offset++; + /* High accuracy uncertainty semi-minor*/ + minor_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_geo_loc_high_acc_uncertainty_semi_minor, tvb, offset, 1, ENC_BIG_ENDIAN, &uvalue32); + proto_item_append_text(minor_item, " (%.5f m)", 0.3 * (pow(1.02, (double)uvalue32) - 1)); + offset++; + /* Orientation of major axis */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_orientation_of_major_axis, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + /* Horizontal confidence */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_horizontal_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + if (type_of_shape == HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_SCALABLE_UNCERT_ELLIPSOID) { + /* Horizontal Uncertainty Range */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_horizontal_uncertainty_range, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + + /* High accuracy uncertenty altitude */ + value = tvb_get_guint8(tvb, offset) & 0x7f; + alt_item = proto_tree_add_item(tree, hf_gsm_a_geo_loc_high_acc_uncertainty_alt, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(alt_item, " (%.1f m)", 45 * (pow(1.025, (double)value) - 1)); + offset++; + + /* Vertical confidence*/ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_vertical_confidence, tvb, offset, 1, ENC_BIG_ENDIAN); + if (type_of_shape == HIGH_ACC_ELLIPSOID_PNT_WITH_ALT_AND_SCALABLE_UNCERT_ELLIPSOID) { + /* Vertical Uncertainty Range */ + proto_tree_add_item(tree, hf_gsm_a_geo_loc_vertical_uncertainty_range, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + break; + + default: + break; + } + return offset; +} + +/* TS 23.032 + * Ch. 8 Description of Velocity + */ +/* 8.6 Coding of Velocity Type */ +static const value_string gsm_a_velocity_type_vals[] = { + { 0, "Horizontal Velocity"}, + { 1, "Horizontal with Vertical Velocity"}, + { 2, "Horizontal Velocity with Uncertainty"}, + { 3, "Horizontal with Vertical Velocity and Uncertainty"}, + { 4, "reserved for future use"}, + { 5, "reserved for future use"}, + { 6, "reserved for future use"}, + { 7, "reserved for future use"}, + { 8, "reserved for future use"}, + { 9, "reserved for future use"}, + { 10, "reserved for future use"}, + { 11, "reserved for future use"}, + { 12, "reserved for future use"}, + { 13, "reserved for future use"}, + { 14, "reserved for future use"}, + { 15, "reserved for future use"}, + { 0, NULL } +}; + +static const true_false_string gsm_a_dir_of_ver_speed_vals = { + "Downward", + "Upward" +}; + +guint16 +dissect_description_of_velocity(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + proto_item *velocity_item; + guint32 curr_offset; + guint32 velocity_type, uncertainty_speed = 0; + + curr_offset = offset; + + /* Bit 8 - 5 Velocity Type */ + proto_tree_add_item_ret_uint(tree, hf_gsm_a_velocity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &velocity_type); + + switch (velocity_type) { + case 0: + /* 8.12 Coding of Horizontal Velocity */ + /* Spare bits */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+4, 3, ENC_BIG_ENDIAN); + /* Bearing is encoded in increments of 1 degree measured clockwise from North using a 9 bit binary coded number N. */ + proto_tree_add_bits_item(tree, hf_gsm_a_bearing, tvb, (curr_offset<<3)+7, 9, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Horizontal speed is encoded in increments of 1 kilometre per hour using a 16 bit binary coded number N. */ + proto_tree_add_item(tree, hf_gsm_a_horizontal_speed, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + curr_offset += 2; + break; + case 1: + /* 8.13 Coding of Horizontal with Vertical Velocity */ + /* Spare bits */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+4, 2, ENC_BIG_ENDIAN); + /* D: Direction of Vertical Speed */ + proto_tree_add_item(tree, hf_gsm_a_d, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* Bearing is encoded in increments of 1 degree measured clockwise from North using a 9 bit binary coded number N. */ + proto_tree_add_bits_item(tree, hf_gsm_a_bearing, tvb, (curr_offset<<3)+7, 9, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Horizontal speed is encoded in increments of 1 kilometre per hour using a 16 bit binary coded number N. */ + proto_tree_add_item(tree, hf_gsm_a_horizontal_speed, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Vertical Speed Octet 5 + * Vertical speed is encoded in increments of 1 kilometre per hour using 8 bits giving a number N between 0 and 28-1. + */ + proto_tree_add_item(tree, hf_gsm_a_vertical_speed, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + break; + case 2: + /* 8.14 Coding of Horizontal Velocity with Uncertainty */ + /* Spare bits */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+4, 3, ENC_BIG_ENDIAN); + /* Bearing is encoded in increments of 1 degree measured clockwise from North using a 9 bit binary coded number N. */ + proto_tree_add_bits_item(tree, hf_gsm_a_bearing, tvb, (curr_offset<<3)+7, 9, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Horizontal speed is encoded in increments of 1 kilometre per hour using a 16 bit binary coded number N. */ + proto_tree_add_item(tree, hf_gsm_a_horizontal_speed, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Uncertainty Speed Octet 5 + * Uncertainty speed is encoded in increments of 1 kilometre per hour using an 8 bit binary coded number N. The value of + * N gives the uncertainty speed except for N=255 which indicates that the uncertainty is not specified. + */ + velocity_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_uncertainty_speed, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &uncertainty_speed); + if (uncertainty_speed == 255) { + proto_item_append_text(velocity_item, " (not specified)"); + } else { + proto_item_append_text(velocity_item, "km/h"); + } + curr_offset++; + break; + case 3: + /* 8.15 Coding of Horizontal with Vertical Velocity and Uncertainty */ + /* Spare bits */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+4, 2, ENC_BIG_ENDIAN); + /* D: Direction of Vertical Speed */ + proto_tree_add_item(tree, hf_gsm_a_d, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* Bearing is encoded in increments of 1 degree measured clockwise from North using a 9 bit binary coded number N. */ + proto_tree_add_bits_item(tree, hf_gsm_a_bearing, tvb, (curr_offset<<3)+7, 9, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Horizontal speed is encoded in increments of 1 kilometre per hour using a 16 bit binary coded number N. */ + proto_tree_add_item(tree, hf_gsm_a_horizontal_speed, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + curr_offset += 2; + /* Vertical Speed Octet 5 + * Vertical speed is encoded in increments of 1 kilometre per hour using 8 bits giving a number N between 0 and 28-1. + */ + proto_tree_add_item(tree, hf_gsm_a_vertical_speed, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + /* Horizontal Uncertainty Speed Octet 6 */ + velocity_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_h_uncertainty_speed, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &uncertainty_speed); + if (uncertainty_speed == 255) { + proto_item_append_text(velocity_item, " (not specified)"); + } else { + proto_item_append_text(velocity_item, "km/h"); + } + curr_offset++; + + /* Vertical Uncertainty Speed Octet 7 */ + velocity_item = proto_tree_add_item_ret_uint(tree, hf_gsm_a_v_uncertainty_speed, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &uncertainty_speed); + if (uncertainty_speed == 255) { + proto_item_append_text(velocity_item, " (not specified)"); + } else { + proto_item_append_text(velocity_item, "km/h"); + } + curr_offset++; + break; + default: + break; + } + + return (curr_offset - offset); +} + +const char* get_gsm_a_msg_string(int pdu_type, int idx) +{ + const char *msg_string = NULL; + + switch (pdu_type) { + case GSM_A_PDU_TYPE_BSSMAP: + msg_string = val_to_str_ext(idx, &gsm_bssmap_elem_strings_ext, "GSM_A_PDU_TYPE_BSSMAP (%u)"); + break; + case GSM_A_PDU_TYPE_DTAP: + msg_string = val_to_str_ext(idx, &gsm_dtap_elem_strings_ext, "GSM_A_PDU_TYPE_DTAP (%u)"); + break; + case GSM_A_PDU_TYPE_RP: + msg_string = val_to_str_ext(idx, &gsm_rp_elem_strings_ext, "GSM_A_PDU_TYPE_RP (%u)"); + break; + case GSM_A_PDU_TYPE_RR: + msg_string = val_to_str_ext(idx, &gsm_rr_elem_strings_ext, "GSM_A_PDU_TYPE_RR (%u)"); + break; + case GSM_A_PDU_TYPE_COMMON: + msg_string = val_to_str_ext(idx, &gsm_common_elem_strings_ext, "GSM_A_PDU_TYPE_COMMON (%u)"); + break; + case GSM_A_PDU_TYPE_GM: + msg_string = val_to_str_ext(idx, &gsm_gm_elem_strings_ext, "GSM_A_PDU_TYPE_GM (%u)"); + break; + case GSM_A_PDU_TYPE_BSSLAP: + msg_string = val_to_str_ext(idx, &gsm_bsslap_elem_strings_ext, "GSM_A_PDU_TYPE_BSSLAP (%u)"); + break; + case GSM_PDU_TYPE_BSSMAP_LE: + msg_string = val_to_str_ext(idx, &gsm_bssmap_le_elem_strings_ext, "GSM_PDU_TYPE_BSSMAP_LE (%u)"); + break; + case NAS_PDU_TYPE_COMMON: + msg_string = val_to_str_ext(idx, &nas_eps_common_elem_strings_ext, "NAS_PDU_TYPE_COMMON (%u)"); + break; + case NAS_PDU_TYPE_EMM: + msg_string = val_to_str_ext(idx, &nas_emm_elem_strings_ext, "NAS_PDU_TYPE_EMM (%u)"); + break; + case NAS_PDU_TYPE_ESM: + msg_string = val_to_str_ext(idx, &nas_esm_elem_strings_ext, "NAS_PDU_TYPE_ESM (%u)"); + break; + case SGSAP_PDU_TYPE: + msg_string = val_to_str_ext(idx, &sgsap_elem_strings_ext, "SGSAP_PDU_TYPE (%u)"); + break; + case BSSGP_PDU_TYPE: + msg_string = val_to_str_ext(idx, &bssgp_elem_strings_ext, "BSSGP_PDU_TYPE (%u)"); + break; + case GMR1_IE_COMMON: + msg_string = val_to_str_ext(idx, &gmr1_ie_common_strings_ext, "GMR1_IE_COMMON (%u)"); + break; + case GMR1_IE_RR: + msg_string = val_to_str_ext(idx, &gmr1_ie_rr_strings_ext, "GMR1_IE_RR (%u)"); + break; + case NAS_5GS_PDU_TYPE_COMMON: + msg_string = val_to_str_ext(idx, &nas_5gs_common_elem_strings_ext, "NAS_5GS_PDU_TYPE_COMMON (%u)"); + break; + case NAS_5GS_PDU_TYPE_MM: + msg_string = val_to_str_ext(idx, &nas_5gs_mm_elem_strings_ext, "NAS_5GS_PDU_TYPE_MM (%u)"); + break; + case NAS_5GS_PDU_TYPE_SM: + msg_string = val_to_str_ext(idx, &nas_5gs_sm_elem_strings_ext, "NAS_5GS_PDU_TYPE_SM (%u)"); + break; + case NAS_5GS_PDU_TYPE_UPDP: + msg_string = val_to_str_ext(idx, &nas_5gs_updp_elem_strings_ext, "NAS_5GS_PDU_TYPE_UPDP (%u)"); + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + + return msg_string; +} + +static int get_hf_elem_id(int pdu_type) +{ + int hf_elem_id = 0; + + switch (pdu_type) { + case GSM_A_PDU_TYPE_BSSMAP: + hf_elem_id = hf_gsm_a_bssmap_elem_id; + break; + case GSM_A_PDU_TYPE_DTAP: + hf_elem_id = hf_gsm_a_dtap_elem_id; + break; + case GSM_A_PDU_TYPE_RP: + hf_elem_id = hf_gsm_a_rp_elem_id; + break; + case GSM_A_PDU_TYPE_RR: + hf_elem_id = hf_gsm_a_rr_elem_id; + break; + case GSM_A_PDU_TYPE_COMMON: + hf_elem_id = hf_gsm_a_common_elem_id; + break; + case GSM_A_PDU_TYPE_GM: + hf_elem_id = hf_gsm_a_gm_elem_id; + break; + case GSM_A_PDU_TYPE_BSSLAP: + hf_elem_id = hf_gsm_a_bsslap_elem_id; + break; + case GSM_PDU_TYPE_BSSMAP_LE: + hf_elem_id = hf_gsm_bssmap_le_elem_id; + break; + case NAS_PDU_TYPE_COMMON: + hf_elem_id = hf_nas_eps_common_elem_id; + break; + case NAS_PDU_TYPE_EMM: + hf_elem_id = hf_nas_eps_emm_elem_id; + break; + case NAS_PDU_TYPE_ESM: + hf_elem_id = hf_nas_eps_esm_elem_id; + break; + case SGSAP_PDU_TYPE: + hf_elem_id = hf_sgsap_elem_id; + break; + case BSSGP_PDU_TYPE: + hf_elem_id = hf_bssgp_elem_id; + break; + case GMR1_IE_COMMON: + case GMR1_IE_RR: + hf_elem_id = hf_gmr1_elem_id; + break; + case NAS_5GS_PDU_TYPE_COMMON: + hf_elem_id = hf_nas_5gs_common_elem_id; + break; + case NAS_5GS_PDU_TYPE_MM: + hf_elem_id = hf_nas_5gs_mm_elem_id; + break; + case NAS_5GS_PDU_TYPE_SM: + hf_elem_id = hf_nas_5gs_sm_elem_id; + break; + case NAS_5GS_PDU_TYPE_UPDP: + hf_elem_id = hf_nas_5gs_updp_elem_id; + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + + return hf_elem_id; +} + +/* + * Type Length Value (TLV) element dissector + */ +guint16 elem_tlv(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, guint len _U_, const gchar *name_add) +{ + guint8 oct; + guint16 parm_len; + guint8 lengt_length = 1; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + oct = tvb_get_guint8(tvb, curr_offset); + + if (oct == iei) { + parm_len = tvb_get_guint8(tvb, curr_offset + 1); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, parm_len + 1 + lengt_length, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, parm_len + 1 + lengt_length, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, + get_hf_elem_id(pdu_type), tvb, + curr_offset, 1, oct); + + proto_tree_add_uint(subtree, hf_gsm_a_length, tvb, + curr_offset + 1, lengt_length, parm_len); + + if (parm_len > 0) + { + if (elem_funcs[idx] == NULL) + { + proto_tree_add_item(subtree, hf_gsm_a_element_value, tvb, curr_offset + 1 + lengt_length, parm_len, ENC_NA); + /* See ASSERT above */ + consumed = (guint8)parm_len; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar *)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = + (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 2, + parm_len, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + } + + consumed += 1 + lengt_length; + } + + return consumed; +} + +/* + * Type Extendable Length Value (TELV) element dissector + * This is a version where the length field can be one or two octets depending + * if the extension bit is set or not (TS 48.016 p 10.1.2). + * 8 7 6 5 4 3 2 1 + * octet 2 0/1 ext length + * octet 2a length + */ +guint16 elem_telv(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, guint len _U_, const gchar *name_add) +{ + guint8 oct; + guint16 parm_len; + guint8 lengt_length = 1; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + oct = tvb_get_guint8(tvb, curr_offset); + + if (oct == iei) { + parm_len = tvb_get_guint8(tvb, curr_offset + 1); + if ((parm_len&0x80) == 0) { + /* length in 2 octets */ + parm_len = tvb_get_ntohs(tvb, curr_offset + 1); + lengt_length = 2; + }else{ + parm_len = parm_len & 0x7f; + } + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, parm_len + 1 + lengt_length, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, parm_len + 1 + lengt_length, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, + get_hf_elem_id(pdu_type), tvb, + curr_offset, 1, oct); + + proto_tree_add_item(subtree, hf_gsm_a_l_ext, tvb, curr_offset+1, 1, ENC_BIG_ENDIAN); + + proto_tree_add_uint(subtree, hf_gsm_a_length, tvb, + curr_offset + 1, lengt_length, parm_len); + + if (parm_len > 0) + { + if (elem_funcs[idx] == NULL) + { + proto_tree_add_item(subtree, hf_gsm_a_element_value, tvb, curr_offset + 1 + lengt_length, parm_len, ENC_NA); + /* See ASSERT above */ + consumed = parm_len; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = + (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 1 + lengt_length, + parm_len, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + } + + consumed += 1 + lengt_length; + } + + return consumed; +} + +/* + * Type Length Value Extended(TLV-E) element dissector + * TS 24.007 + * information elements of format LV-E or TLV-E with value part consisting of zero, + * one or more octets and a maximum of 65535 octets (type 6). This category is used in EPS only. + */ +guint16 elem_tlv_e(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, guint len _U_, const gchar *name_add) +{ + guint8 oct; + guint16 parm_len; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + oct = tvb_get_guint8(tvb, curr_offset); + + if (oct == iei) { + parm_len = tvb_get_ntohs(tvb, curr_offset + 1); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, parm_len + 1 + 2, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, parm_len + 1 + 2, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, + get_hf_elem_id(pdu_type), tvb, + curr_offset, 1, oct); + + proto_tree_add_uint(subtree, hf_gsm_a_length, tvb, + curr_offset + 1, 2, parm_len); + + if (parm_len > 0) + { + if (elem_funcs[idx] == NULL) + { + proto_tree_add_item(subtree, hf_gsm_a_element_value, tvb, curr_offset + 1 + 2, parm_len, ENC_NA); + /* See ASSERT above */ + consumed = parm_len; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = + (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 1 + 2, + parm_len, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + } + + consumed += 1 + 2; + } + + return consumed; +} + +/* + * Type Value (TV) element dissector + * + * Length cannot be used in these functions, big problem if a element dissector + * is not defined for these. + */ +guint16 elem_tv(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, const gchar *name_add) +{ + guint8 oct; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + oct = tvb_get_guint8(tvb, curr_offset); + + if (oct == iei) + { + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, -1, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, -1, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, + get_hf_elem_id(pdu_type), tvb, + curr_offset, 1, oct); + + if (elem_funcs[idx] == NULL) + { + /* BAD THING, CANNOT DETERMINE LENGTH */ + expert_add_info(pinfo, item, &ei_gsm_a_no_element_dissector); + + consumed = 1; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 1, -1, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + + consumed++; + + proto_item_set_len(item, consumed); + } + + return consumed; +} + +/* + * Type Value (TV) element dissector + * Where top half nibble is IEI and bottom half nibble is value. + * + * Length cannot be used in these functions, big problem if a element dissector + * is not defined for these. + */ +guint16 elem_tv_short(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, const gchar *name_add) +{ + guint8 oct; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + oct = tvb_get_guint8(tvb, curr_offset); + + if ((oct & 0xf0) == (iei & 0xf0)) + { + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, -1, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, -1, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint_format_value(subtree, hf_gsm_a_common_elem_id_f0, tvb, curr_offset, 1, oct, "0x%1x-", oct>>4); + + if (elem_funcs[idx] == NULL) + { + /* BAD THING, CANNOT DETERMINE LENGTH */ + + expert_add_info(pinfo, item, &ei_gsm_a_no_element_dissector); + + consumed++; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset, RIGHT_NIBBLE, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + + proto_item_set_len(item, consumed); + } + + return consumed; +} + +/* + * Type (T) element dissector + */ +guint16 elem_t(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint8 iei, gint pdu_type, int idx, guint32 offset, const gchar *name_add) +{ + guint8 oct; + guint32 curr_offset; + guint16 consumed; + value_string_ext elem_names_ext; + gint *elem_ett; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + (void)elem_ett; + (void)elem_funcs; + + oct = tvb_get_guint8(tvb, curr_offset); + + if (oct == iei) + { + proto_tree_add_uint_format(tree, + get_hf_elem_id(pdu_type), tvb, + curr_offset, 1, oct, + "%s%s", + val_to_str_ext(idx, &elem_names_ext, "Unknown (%u)"), + (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + consumed = 1; + } + + return consumed; +} + +/* + * Length Value (LV) element dissector + */ +guint16 +elem_lv(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint pdu_type, int idx, guint32 offset, guint len _U_, const gchar *name_add) +{ + guint8 parm_len; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + parm_len = tvb_get_guint8(tvb, curr_offset); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, parm_len + 1, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, parm_len + 1, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, hf_gsm_a_length, tvb, + curr_offset, 1, parm_len); + + if (parm_len > 0) + { + if (elem_funcs[idx] == NULL) + { + proto_tree_add_item(subtree, hf_gsm_a_element_value, tvb, curr_offset + 1, parm_len, ENC_NA); + + consumed = parm_len; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = + (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 1, + parm_len, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + } + + return (consumed + 1); +} + +/* + * Length Value Extended(LV-E) element dissector + */ +guint16 elem_lv_e(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint pdu_type, int idx, guint32 offset, guint len _U_, const gchar *name_add) +{ + guint16 parm_len; + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + parm_len = tvb_get_ntohs(tvb, curr_offset); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert_format(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, parm_len + 2, + "Unknown - aborting dissection%s", (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + return consumed; + } + + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, parm_len + 2, elem_ett[idx], &item, + "%s%s", elem_name, (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + proto_tree_add_uint(subtree, hf_gsm_a_length, tvb, + curr_offset, 2, parm_len); + + if (parm_len > 0) + { + if (elem_funcs[idx] == NULL) + { + proto_tree_add_item(subtree, hf_gsm_a_element_value, tvb, curr_offset + 2, parm_len, ENC_NA); + + consumed = parm_len; + } + else + { + gchar *a_add_string; + + a_add_string = (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = + (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset + 2, + parm_len, a_add_string, 1024); + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + } + } + + return (consumed + 2); +} +/* + * Value (V) element dissector + * + * Length cannot be used in these functions, big problem if a element dissector + * is not defined for these. + */ +guint16 elem_v(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint pdu_type, int idx, guint32 offset, const gchar *name_add) +{ + guint16 consumed; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + const gchar *elem_name; + elem_func_hander elem_funcs; + + curr_offset = offset; + consumed = 0; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + if (elem_name == NULL || elem_funcs[idx] == NULL) + { + /* BAD THING, CANNOT DETERMINE LENGTH */ + proto_tree_add_expert(tree, pinfo, &ei_gsm_a_no_element_dissector, tvb, curr_offset, 1); + + consumed = 1; + } + else + { + gchar *a_add_string; + + subtree = + proto_tree_add_subtree_format(tree, + tvb, curr_offset, 0, + elem_ett[idx], &item, "%s%s", elem_name, + (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add); + + a_add_string= (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + consumed = (*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset, -1, a_add_string, 1024); + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + proto_item_set_len(item, consumed); + } + + return (consumed); +} + +/* + * Short Value (V_SHORT) element dissector + * + * nibble is used in this function to indicate right or left nibble of the octet + * This is expected to be used right nibble first, as the tables of 24.008. + */ + +guint16 elem_v_short(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint pdu_type, int idx, guint32 offset, guint32 nibble) +{ + guint16 consumed = 1; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + value_string_ext elem_names_ext; + gint *elem_ett; + elem_fcn *elem_funcs; + gchar *a_add_string; + const gchar *elem_name; + + curr_offset = offset; + + SET_ELEM_VARS(pdu_type, elem_names_ext, elem_ett, elem_funcs, &ei_gsm_a_unknown_pdu_type); + + elem_name = try_val_to_str_ext(idx, &elem_names_ext); + + /* idx is out of range */ + if (elem_name == NULL) { + proto_tree_add_expert(tree, pinfo, &ei_gsm_a_unknown_element, + tvb, curr_offset, 0); + return consumed; + } + + subtree = proto_tree_add_subtree(tree, tvb, curr_offset, 0, elem_ett[idx], &item, elem_name); + + a_add_string= (gchar*)wmem_alloc(pinfo->pool, 1024); + a_add_string[0] = '\0'; + + if (elem_funcs[idx] == NULL) + { + /* NOT NECESSARILY A BAD THING - LENGTH IS HALF OCTET */ + (void)de_spare_nibble(tvb, subtree, pinfo, curr_offset, nibble, a_add_string, 1024); + } + else + { + (void)(*elem_funcs[idx])(tvb, subtree, pinfo, curr_offset, nibble, a_add_string, 1024); + } + + if (a_add_string[0] != '\0') + { + proto_item_append_text(item, "%s", a_add_string); + } + proto_item_set_len(item, consumed); + + return consumed; +} + + +static dgt_set_t Dgt1_9_bcd = { + { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?','?' + } +}; + +/* FUNCTIONS */ + +/* 3GPP TS 24.008 + * [3] 10.5.1.1 Cell Identity + */ +guint16 +de_cell_id(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string, int string_len) +{ + guint32 curr_offset; + + curr_offset = offset; + + curr_offset += + /* 0x02 CI */ + be_cell_id_aux(tvb, tree, pinfo, offset, len, add_string, string_len, 0x02); + + /* no length check possible */ + + return (curr_offset - offset); +} +/* + * 10.5.1.2 Ciphering Key Sequence Number + */ + + +/* + * Key sequence (octet 1) + * Bits + * 3 2 1 + * 0 0 0 + * through + * 1 1 0 + * Possible values for the ciphering key sequence number + * 1 1 1 No key is available (MS to network);Reserved (network to MS) + */ + +static const value_string gsm_a_key_seq_vals[] = { + { 0, "Ciphering key sequence number"}, + { 1, "Ciphering key sequence number"}, + { 2, "Ciphering key sequence number"}, + { 3, "Ciphering key sequence number"}, + { 4, "Ciphering key sequence number"}, + { 5, "Ciphering key sequence number"}, + { 6, "Ciphering key sequence number"}, + { 7, "No key is available (MS to network)"}, + { 0, NULL } +}; + +static guint16 +de_ciph_key_seq_num( tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset, bit_offset; + + curr_offset = offset; + + if (RIGHT_NIBBLE == len) + bit_offset = 4; + else + bit_offset = 0; + + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+bit_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_bits_item(tree, hf_gsm_a_key_seq, tvb, (curr_offset<<3)+bit_offset+1, 3, ENC_BIG_ENDIAN); + curr_offset++; + + return (curr_offset - offset); +} + + +/* + * [3] 10.5.1.3 + */ + +guint16 +de_lai(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint16 value; + guint32 curr_offset; + proto_tree *subtree; + proto_item *item; + gchar *mcc_mnc_str; + + curr_offset = offset; + + subtree = proto_tree_add_subtree(tree, + tvb, curr_offset, 5, ett_gsm_common_elem[DE_LAI], &item, + val_to_str_ext_const(DE_LAI, &gsm_common_elem_strings_ext, "")); + + mcc_mnc_str = dissect_e212_mcc_mnc_wmem_packet_str(tvb, pinfo, subtree, curr_offset, E212_LAI, TRUE); + + curr_offset += 3; + + value = tvb_get_ntohs(tvb, curr_offset); + + proto_tree_add_item(subtree, hf_gsm_a_lac, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + + proto_item_append_text(item, " - %s, LAC %u", mcc_mnc_str, value); + + curr_offset += 2; + + /* no length check possible */ + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.4 Mobile Identity + * 3GPP TS 24.008 version 7.8.0 Release 7 + */ + +guint16 +de_mid(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string, int string_len) +{ + guint8 oct; + guint32 curr_offset; + guint32 value; + gboolean odd; + const gchar *digit_str; + proto_item* ti; + + curr_offset = offset; + + oct = tvb_get_guint8(tvb, curr_offset); + + switch (oct & 0x07) + { + case 0: /* No Identity */ + proto_tree_add_item(tree, hf_gsm_a_unused, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + if (add_string) + snprintf(add_string, string_len, " - No Identity Code"); + + curr_offset++; + + if (len != 1 && len != 3) + { + expert_add_info(pinfo, tree, &ei_gsm_a_format_not_supported); + } + + curr_offset += len - 1; + break; + + case 3: /* IMEISV */ + /* FALLTHRU */ + + case 1: /* IMSI */ + odd = oct & 0x08; + proto_tree_add_item(tree, hf_gsm_a_id_dig_1, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + if (curr_offset - offset >= len) /* Sanity check */ + return (curr_offset - offset); + + if((oct & 0x07) == 3){ + /* imeisv */ + digit_str = tvb_bcd_dig_to_str(pinfo->pool, tvb ,curr_offset , len - (curr_offset - offset), NULL, TRUE); + proto_tree_add_string_format(tree, + hf_gsm_a_imeisv, + tvb, curr_offset, len - (curr_offset - offset), + digit_str, + "BCD Digits: %s", + digit_str); + }else{ + digit_str = dissect_e212_imsi(tvb, pinfo, tree, curr_offset, len - (curr_offset - offset), TRUE); + } + + if (sccp_assoc && ! sccp_assoc->calling_party) { + sccp_assoc->calling_party = wmem_strdup_printf(wmem_file_scope(), + ((oct & 0x07) == 3) ? "IMEISV: %s" : "IMSI: %s", + digit_str ); + } + + if (add_string) + snprintf(add_string, string_len, " - %s (%s)", + ((oct & 0x07) == 3) ? "IMEISV" : "IMSI", + digit_str); + + curr_offset += len - (curr_offset - offset); + + if (!odd) + { + proto_tree_add_item(tree, hf_gsm_a_filler, tvb, curr_offset - 1, 1, ENC_NA); + } + break; + + case 2: /* IMEI */ + proto_tree_add_uint_format_value(tree, hf_gsm_a_identity_digit1, tvb, curr_offset, 1, oct, "%c", Dgt1_9_bcd.out[(oct & 0xf0) >> 4]); + + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + if (curr_offset - offset >= len) /* Sanity check */ + return (curr_offset - offset); + + digit_str = tvb_bcd_dig_to_str(pinfo->pool, tvb, curr_offset, len - (curr_offset - offset), NULL, TRUE); + + proto_tree_add_string_format(tree, + hf_gsm_a_imei, + tvb, curr_offset, len - (curr_offset - offset), + digit_str, + "BCD Digits: %s", + digit_str); + + if (add_string) + snprintf(add_string, string_len, " - IMEI (%s)", digit_str); + + curr_offset += len - (curr_offset - offset); + break; + + case 4: /* TMSI/P-TMSI/M-TMSI */ + proto_tree_add_item(tree, hf_gsm_a_unused, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + proto_tree_add_item_ret_uint(tree, hf_3gpp_tmsi, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &value); + + if (add_string) + snprintf(add_string, string_len, " - TMSI/P-TMSI (0x%04x)", value); + + curr_offset += 4; + break; + + case 5: /* TMGI and optional MBMS Session Identity */ + /* Spare bits (octet 3) Bits 8-7 */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, curr_offset<<3, 2, ENC_BIG_ENDIAN); + /* MBMS Session Identity indication (octet 3) Bit 6 */ + proto_tree_add_item(tree, hf_gsm_a_mbs_ses_id_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* MCC/MNC indication (octet 3) Bit 5 */ + proto_tree_add_item(tree, hf_gsm_a_tmgi_mcc_mnc_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* Odd/even indication (octet 3) Bit 4 */ + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* Type of identity (octet 3) Bits 3-1 */ + proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + /* MBMS Service ID (octet 4, 5 and 6) */ + proto_tree_add_item(tree, hf_gsm_a_mbs_service_id, tvb, curr_offset, 3, ENC_BIG_ENDIAN); + curr_offset += 3; + if ((oct&0x10) == 0x10) { + /* MCC/MNC*/ + /* MCC, Mobile country code (octet 6a, octet 6b bits 1 to 4)*/ + /* MNC, Mobile network code (octet 6b bits 5 to 8, octet 6c) */ + curr_offset = dissect_e212_mcc_mnc(tvb, pinfo, tree, curr_offset, E212_NONE, TRUE); + } + if ((oct&0x20) == 0x20) { + /* MBMS Session Identity (octet 7) + * The MBMS Session Identity field is encoded as the value part + * of the MBMS Session Identity IE as specified in 3GPP TS 48.018 [86]. + */ + proto_tree_add_item(tree, hf_gsm_a_mbs_session_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + } + break; + + default: /* Reserved */ + proto_tree_add_item(tree, hf_gsm_a_odd_even_ind, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + ti = proto_tree_add_item(tree, hf_gsm_a_mobile_identity_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + expert_add_info_format(pinfo, ti, &ei_gsm_a_mobile_identity_type, "Unknown format %u", (oct & 0x07)); + + if (add_string) + snprintf(add_string, string_len, " - Format Unknown"); + + curr_offset += len; + break; + } + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.5 + */ +guint16 +de_ms_cm_1(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + proto_tree *subtree; + + curr_offset = offset; + + subtree = + proto_tree_add_subtree(tree, + tvb, curr_offset, 1, ett_gsm_common_elem[DE_MS_CM_1], NULL, + val_to_str_ext_const(DE_MS_CM_1, &gsm_common_elem_strings_ext, "")); + + proto_tree_add_item(subtree, hf_gsm_a_b8spare, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(subtree, hf_gsm_a_MSC_rev, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(subtree, hf_gsm_a_ES_IND, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(subtree, hf_gsm_a_A5_1_algorithm_sup, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(subtree, hf_gsm_a_RF_power_capability, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset++; + + /* no length check possible */ + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.6 Mobile Station Classmark 2 + * 3GPP TS 24.008 version 7.8.0 Release 7 + */ +guint16 +de_ms_cm_2(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_b8spare, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_MSC_rev, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_ES_IND, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_A5_1_algorithm_sup, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_RF_power_capability, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset++; + + NO_MORE_DATA_CHECK(len); + + proto_tree_add_item(tree, hf_gsm_a_b8spare, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_ps_sup_cap, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gsm_a_SS_screening_indicator, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + /* SM capability (MT SMS pt to pt capability) (octet 4)*/ + proto_tree_add_item(tree, hf_gsm_a_SM_capability, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* VBS notification reception (octet 4) */ + proto_tree_add_item(tree, hf_gsm_a_VBS_notification_rec, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /*VGCS notification reception (octet 4)*/ + proto_tree_add_item(tree, hf_gsm_a_VGCS_notification_rec, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* FC Frequency Capability (octet 4 ) */ + proto_tree_add_item(tree, hf_gsm_a_FC_frequency_cap, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset++; + + NO_MORE_DATA_CHECK(len); + + /* CM3 (octet 5, bit 8) */ + proto_tree_add_item(tree, hf_gsm_a_CM3, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* spare bit 7 */ + proto_tree_add_item(tree, hf_gsm_a_b7spare, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* LCS VA capability (LCS value added location request notification capability) (octet 5,bit 6) */ + proto_tree_add_item(tree, hf_gsm_a_LCS_VA_cap, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* UCS2 treatment (octet 5, bit 5) */ + proto_tree_add_item(tree, hf_gsm_a_UCS2_treatment, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* SoLSA (octet 5, bit 4) */ + proto_tree_add_item(tree, hf_gsm_a_SoLSA, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* CMSP: CM Service Prompt (octet 5, bit 3) */ + proto_tree_add_item(tree, hf_gsm_a_CMSP, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* A5/3 algorithm supported (octet 5, bit 2) */ + proto_tree_add_item(tree, hf_gsm_a_A5_3_algorithm_sup, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* A5/2 algorithm supported (octet 5, bit 1) */ + proto_tree_add_item(tree, hf_gsm_a_A5_2_algorithm_sup, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset++; + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.7 Mobile Station Classmark 3 + * 3GPP TS 24.008 version 12.10.0 Release 12 + */ +#define AVAILABLE_BITS_CHECK(n) \ + bits_left = ((len + offset) << 3) - bit_offset; \ + if (bits_left < (n)) { \ + if (bits_left > 0) \ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, bit_offset, bits_left, ENC_BIG_ENDIAN); \ + else if (bits_left < 0) \ + proto_tree_add_expert(tree, pinfo, &ei_gsm_a_ie_length_too_short, tvb, offset, len); \ + return len; \ + } + +guint16 +de_ms_cm_3(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + guint32 bit_offset; /* Offset in bits */ + guint8 length; + proto_tree *subtree; + proto_item *item; + gint32 bits_left; + guint32 target_bit_offset, old_bit_offset; + guint64 multi_bnd_sup_fields, rsupport, multislotCapability; + guint64 msMeasurementCapability, msPosMethodCapPresent; + guint64 ecsdMultiSlotCapability, eightPskStructPresent, eightPskStructRfPowerCapPresent; + guint64 gsm400BandInfoPresent, gsm850AssocRadioCapabilityPresent; + guint64 gsm1900AssocRadioCapabilityPresent, dtmEGprsMultiSlotInfoPresent; + guint64 dtmEgprsMultiSlotClassPresent, singleBandSupport; + guint64 gsm750AssocRadioCapabilityPresent, extDtmEGprsMultiSlotInfoPresent; + guint64 highMultislotCapPresent, geranIuModeSupport; + guint64 tGsm400BandInfoPresent, tGsm900AssocRadioCapabilityPresent, dtmEGprsHighMultiSlotInfoPresent; + guint64 dtmEgprsHighMultiSlotClassPresent, gsm710AssocRadioCapabilityPresent; + guint64 tGsm810AssocRadioCapabilityPresent; + + curr_offset = offset; + + bit_offset = curr_offset << 3; + + /* Spare bit */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + /* Multiband supported field + * { < Multiband supported : { 000 } > + * < A5 bits > + * | < Multiband supported : { 101 | 110 } > + * < A5 bits > + * < Associated Radio Capability 2 : bit(4) > + * < Associated Radio Capability 1 : bit(4) > + * | < Multiband supported : { 001 | 010 | 100 } > + * < A5 bits > + * < spare bit >(4) + * < Associated Radio Capability 1 : bit(4) > } + */ + + item = proto_tree_add_bits_ret_val(tree, hf_gsm_a_multi_bnd_sup_fields, tvb, bit_offset, 3, &multi_bnd_sup_fields, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gsm_common_elem[DE_MS_CM_3]); + + proto_tree_add_bits_item(subtree, hf_gsm_a_gsm1800_supported, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_egsm_supported, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_pgsm_supported, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + item = proto_tree_add_bits_item(tree, hf_gsm_a_cm3_A5_bits, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gsm_common_elem[DE_MS_CM_3]); + + /* < A5 bits > */ + proto_tree_add_bits_item(subtree, hf_gsm_a_A5_7_algorithm_sup, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + proto_tree_add_bits_item(subtree, hf_gsm_a_A5_6_algorithm_sup, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + proto_tree_add_bits_item(subtree, hf_gsm_a_A5_5_algorithm_sup, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + proto_tree_add_bits_item(subtree, hf_gsm_a_A5_4_algorithm_sup, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + switch (multi_bnd_sup_fields) { + case 0: + /* A5 bits dissected is done */ + break; + /* + * | < Multiband supported : { 001 | 010 | 100 } > + */ + case 1: + case 2: + case 4: + /* < spare bit >(4) */ + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset += 4; + /* < Associated Radio Capability 1 : bit(4) > */ + proto_tree_add_bits_item(tree, hf_gsm_a_ass_radio_cap1, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset += 4; + break; + /* < Multiband supported : { 101 | 110 } > */ + case 5: + /* fall trough */ + case 6: + /* < Associated Radio Capability 2 : bit(4) > */ + proto_tree_add_bits_item(tree, hf_gsm_a_ass_radio_cap2, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset += 4; + /* < Associated Radio Capability 1 : bit(4) > */ + proto_tree_add_bits_item(tree, hf_gsm_a_ass_radio_cap1, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset += 4; + break; + default: + break; + } + /* Extract R Support */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_rsupport, tvb, bit_offset, 1, &rsupport, ENC_BIG_ENDIAN); + bit_offset++; + + if (rsupport == 1) + { + /* + * { 0 | 1 < R Support > } + * Extract R Capabilities + */ + proto_tree_add_bits_item(tree, hf_gsm_a_r_capabilities, tvb, bit_offset, 3, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 3; + } + + /* + * { 0 | 1 < HSCSD Multi Slot Capability > } + * Extract Multislot capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_multislot_capabilities, tvb, bit_offset, 1, &multislotCapability, ENC_BIG_ENDIAN); + bit_offset++; + + if (multislotCapability == 1) + { + /* Extract Multislot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_multislot_class, tvb, bit_offset, 5, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 5; + } + + /* < UCS2 treatment: bit > */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_ucs2_treatment, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < Extended Measurement Capability : bit > */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_extended_measurement_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* { 0 | 1 < MS measurement capability > } + * Extract MS Measurement capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_ms_measurement_capability, tvb, bit_offset, 1, &msMeasurementCapability, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (msMeasurementCapability == 1) + { + /* Extract SMS Value n/4 */ + proto_tree_add_bits_item(tree, hf_gsm_a_sms_value, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + + /* Extract SM Value n/4 */ + proto_tree_add_bits_item(tree, hf_gsm_a_sm_value, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 < MS Positioning Method Capability > } + * Extract MS Positioning Method Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_ms_pos_method_cap_present, tvb, bit_offset, 1, &msPosMethodCapPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (msPosMethodCapPresent == 1) + { + /* Extract MS Positioning Method */ + item = proto_tree_add_bits_item(tree, hf_gsm_a_ms_pos_method, tvb, bit_offset, 5, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gsm_common_elem[DE_MS_CM_3]); + + proto_tree_add_bits_item(subtree, hf_gsm_a_ms_assisted_e_otd, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_ms_based_e_otd, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_ms_assisted_gps, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_ms_based_gps, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + proto_tree_add_bits_item(subtree, hf_gsm_a_ms_conventional_gps, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + } + + /* { 0 | 1 < ECSD Multi Slot Capability > } + * Extract ECSD Multi Slot Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_ecsd_multi_slot_capability, tvb, bit_offset, 1, &ecsdMultiSlotCapability, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (ecsdMultiSlotCapability == 1) + { + /* Extract ECSD Multi Slot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_ecsd_multi_slot_class, tvb, bit_offset, 5, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 5; + } + + /* { 0 | 1 < 8-PSK Struct > } + * Extract 8-PSK struct presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_8_psk_struct_present, tvb, bit_offset, 1, &eightPskStructPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (eightPskStructPresent == 1) + { + /* At lest Modulation Capability and cap1,cap2 presens indicators is present */ + guint8 psk_struct_len = 3; + guint32 tmp_bit_offset = bit_offset; + + /* Check if Power Capability 1 is present */ + tmp_bit_offset++; + if (tvb_get_bits8(tvb,tmp_bit_offset,1) == 1){ + psk_struct_len += 2; + tmp_bit_offset += 2; + } + tmp_bit_offset++; + /* Check if Power Capability 2 is present */ + if (tvb_get_bits8(tvb,tmp_bit_offset,1) == 1){ + psk_struct_len += 2; + } + /* Extract 8-PSK struct */ + item = proto_tree_add_bits_item(tree, hf_gsm_a_8_psk_struct, tvb, bit_offset, psk_struct_len, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gsm_common_elem[DE_MS_CM_3]); + old_bit_offset = bit_offset; + + /* Extract Modulation Capability */ + proto_tree_add_bits_item(subtree, hf_gsm_a_modulation_capability, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* Extract 8_PSK RF Power Capability 1 */ + proto_tree_add_bits_ret_val(subtree, hf_gsm_a_8_psk_rf_power_capability_1_present, tvb, bit_offset, + 1, &eightPskStructRfPowerCapPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + if (eightPskStructRfPowerCapPresent == 1) + { + proto_tree_add_bits_item(subtree, hf_gsm_a_8_psk_rf_power_capability_1, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + } + + /* Extract 8_PSK RF Power Capability 2 */ + proto_tree_add_bits_ret_val(subtree, hf_gsm_a_8_psk_rf_power_capability_2_present, tvb, bit_offset, + 1, &eightPskStructRfPowerCapPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + if (eightPskStructRfPowerCapPresent == 1) + { + proto_tree_add_bits_item(subtree, hf_gsm_a_8_psk_rf_power_capability_2, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + } + length = (guint8)((bit_offset - old_bit_offset)>>3); + if ((bit_offset - old_bit_offset) & 0x07) + length++; + proto_item_set_len(item, length); + } + + /* { 0 | 1 < GSM 400 Bands Supported : { 01 | 10 | 11 } > + * < GSM 400 Associated Radio Capability: bit(4) > } + * Extract GSM 400 Band Information presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_gsm_400_band_info_present, tvb, bit_offset, 1, &gsm400BandInfoPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (gsm400BandInfoPresent == 1) + { + /* Extract GSM 400 Bands Supported */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_400_bands_supported, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* Extract GSM 400 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_400_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 <GSM 850 Associated Radio Capability : bit(4) > } + * Extract GSM 850 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_gsm_850_assoc_radio_cap_present, tvb, bit_offset, 1, &gsm850AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (gsm850AssocRadioCapabilityPresent == 1) + { + /* Extract GSM 850 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_850_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 <GSM 1900 Associated Radio Capability : bit(4) > } + * Extract GSM 1900 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_gsm_1900_assoc_radio_cap_present, tvb, bit_offset, 1, &gsm1900AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (gsm1900AssocRadioCapabilityPresent == 1) + { + /* Extract GSM 1900 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_1900_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* < UMTS FDD Radio Access Technology Capability : bit > + * Extract UMTS FDD Radio Access Technology Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_umts_fdd_rat_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < UMTS 3.84 Mcps TDD Radio Access Technology Capability : bit > + * Extract UMTS 3.84 Mcps TDD Radio Access Technology Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_umts_384_mcps_tdd_rat_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < CDMA 2000 Radio Access Technology Capability : bit > + * Extract CDMA 2000 Radio Access Technology Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_cdma_2000_rat_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* { 0 | 1 < DTM GPRS Multi Slot Class : bit(2) > + * < Single Slot DTM : bit > + * {0 | 1< DTM EGPRS Multi Slot Class : bit(2) > } } + * Extract DTM E/GPRS Information presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_dtm_e_gprs_multi_slot_info_present, tvb, bit_offset, 1, &dtmEGprsMultiSlotInfoPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (dtmEGprsMultiSlotInfoPresent == 1) + { + /* Extract DTM GPRS Multi Slot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_dtm_gprs_multi_slot_class, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* Extract Single Slot DTM */ + proto_tree_add_bits_item(tree, hf_gsm_a_single_slot_dtm, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* Extract DTM EGPRS Multi Slot Class Presence */ + proto_tree_add_bits_ret_val(tree, hf_gsm_a_dtm_egprs_multi_slot_class_present, tvb, bit_offset, 1, &dtmEgprsMultiSlotClassPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* Extract DTM EGPRS Multi Slot Class */ + if (dtmEgprsMultiSlotClassPresent == 1) + { + proto_tree_add_bits_item(tree, hf_gsm_a_dtm_egprs_multi_slot_class, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + } + } + + /* + * Release 4 starts here + * + * { 0 | 1 < Single Band Support > } -- Release 4 starts here: + * Extract Single Band Support + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_single_band_support, tvb, bit_offset, 1, &singleBandSupport, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (singleBandSupport == 1) + { + /* Extract Single Band Support */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_band, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 <GSM 750 Associated Radio Capability : bit(4) > } + * Extract GSM 750 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_gsm_750_assoc_radio_cap_present, tvb, bit_offset, 1, &gsm750AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (gsm750AssocRadioCapabilityPresent == 1) + { + /* Extract GSM 750 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_750_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* < UMTS 1.28 Mcps TDD Radio Access Technology Capability : bit > + * Extract UMTS 1.28 Mcps TDD Radio Access Technology Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_umts_128_mcps_tdd_rat_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < GERAN Feature Package 1 : bit > + * Extract GERAN Feature Package 1 + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_geran_feature_package_1, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* { 0 | 1 < Extended DTM GPRS Multi Slot Class : bit(2) > + * < Extended DTM EGPRS Multi Slot Class : bit(2) > } + * Extract Extended DTM E/GPRS Information presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_ext_dtm_e_gprs_multi_slot_info_present, tvb, bit_offset, 1, &extDtmEGprsMultiSlotInfoPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (extDtmEGprsMultiSlotInfoPresent == 1) + { + /* Extract Extended DTM GPRS Multi Slot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_ext_dtm_gprs_multi_slot_class, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* Extract Extended DTM EGPRS Multi Slot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_ext_dtm_egprs_multi_slot_class, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + } + + /* + * Release 5 starts here + * + * { 0 | 1 < High Multislot Capability : bit(2) > } -- Release 5 starts here. + * Extract High Multislot Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_high_multislot_cap_present, tvb, bit_offset, 1, &highMultislotCapPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (highMultislotCapPresent == 1) + { + /* Extract High Multislot Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_high_multislot_cap, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + } + + /* + * { 0 | 1 < GERAN Iu Mode Capabilities > } -- "1" also means support of GERAN Iu mode + * Extract GERAN Iu Mode Capabilities presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_geran_iu_mode_support, tvb, bit_offset, 1, &geranIuModeSupport, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (geranIuModeSupport == 1) + { + /* Extract GERAN Iu Mode Capabilities Length */ + length = tvb_get_bits8(tvb, bit_offset, 4); + + /* Extract GERAN Iu Mode Capabilities */ + item = proto_tree_add_bits_item(tree, hf_gsm_a_geran_iu_mode_cap, tvb, bit_offset, length + 4, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gsm_common_elem[DE_MS_CM_3]); + + /* Add GERAN Iu Mode Capabilities Length in subtree */ + proto_tree_add_bits_item(subtree, hf_gsm_a_geran_iu_mode_cap_length, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset += 4; + target_bit_offset = bit_offset + length; + + /* Extract FLO Iu Capability */ + proto_tree_add_bits_item(subtree, hf_gsm_a_flo_iu_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset += 1; + + /* If needed, add spare bits */ + if (target_bit_offset > bit_offset) + { + proto_tree_add_bits_item(subtree, hf_gsm_a_spare_bits, tvb, bit_offset, target_bit_offset - bit_offset, ENC_BIG_ENDIAN); + bit_offset = target_bit_offset; + } + } + + /* < GERAN Feature Package 2 : bit > + * Extract GERAN Feature Package 2 + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_geran_feature_package_2, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < GMSK Multislot Power Profile : bit (2) > + * Extract GMSK Multislot Power Profile + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_gmsk_multislot_power_prof, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* < 8-PSK Multislot Power Profile : bit (2) > + * Extract GMSK Multislot Power Profile + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_8_psk_multislot_power_prof, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* + * Release 6 starts here + * + * { 0 | 1 < T-GSM 400 Bands Supported : { 01 | 10 | 11 } > -- Release 6 starts here. + * < T-GSM 400 Associated Radio Capability: bit(4) > } + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_t_gsm_400_band_info_present, tvb, bit_offset, 1, &tGsm400BandInfoPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (tGsm400BandInfoPresent == 1) + { + /* Extract T-GSM 400 Bands Supported */ + proto_tree_add_bits_item(tree, hf_gsm_a_t_gsm_400_bands_supported, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* Extract T-GSM 400 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_t_gsm_400_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 < T-GSM 900 Associated Radio Capability: bit(4) > } + * Extract T-GSM 900 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_t_gsm_900_assoc_radio_cap_present, tvb, bit_offset, 1, &tGsm900AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (tGsm900AssocRadioCapabilityPresent == 1) + { + /* Extract T-GSM 900 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_t_gsm_900_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* < Downlink Advanced Receiver Performance : bit (2)> + * Extract Downlink Advanced Receiver Performance + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_downlink_adv_receiver_perf, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* < DTM Enhancements Capability : bit > + * Extract DTM Enhancements Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_dtm_enhancements_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* { 0 | 1 < DTM GPRS High Multi Slot Class : bit(3) > + * < Offset required : bit> + * { 0 | 1 < DTM EGPRS High Multi Slot Class : bit(3) > } } + * Extract DTM E/GPRS High Multi Slot Information presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_dtm_e_gprs_high_multi_slot_info_present, tvb, bit_offset, 1, &dtmEGprsHighMultiSlotInfoPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (dtmEGprsHighMultiSlotInfoPresent == 1) + { + /* Extract DTM GPRS High Multi Slot Class */ + proto_tree_add_bits_item(tree, hf_gsm_a_dtm_gprs_high_multi_slot_class, tvb, bit_offset, 3, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 3; + + /* Extract Offset Required */ + proto_tree_add_bits_item(tree, hf_gsm_a_offset_required, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* Extract DTM EGPRS High Multi Slot Class Presence */ + proto_tree_add_bits_ret_val(tree, hf_gsm_a_dtm_egprs_high_multi_slot_class_present, tvb, bit_offset, 1, &dtmEgprsHighMultiSlotClassPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* Extract DTM EGPRS High Multi Slot Class */ + if (dtmEgprsHighMultiSlotClassPresent == 1) + { + proto_tree_add_bits_item(tree, hf_gsm_a_dtm_egprs_high_multi_slot_class, tvb, bit_offset, 3, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 3; + } + } + + /* < Repeated ACCH Capability : bit > + * Extract Repeated ACCH Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_repeated_acch_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Release 7 starts here + * + * { 0 | 1 <GSM 710 Associated Radio Capability : bit(4) > } -- Release 7 starts here. + * Extract GSM 710 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_gsm_710_assoc_radio_cap_present, tvb, bit_offset, 1, &gsm710AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (gsm710AssocRadioCapabilityPresent == 1) + { + /* Extract GSM 710 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_gsm_710_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* { 0 | 1 < T-GSM 810 Associated Radio Capability: bit(4) > } + * Extract T-GSM 810 Associated Radio Capability presence + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_ret_val(tree, hf_gsm_a_t_gsm_810_assoc_radio_cap_present, tvb, bit_offset, 1, &tGsm810AssocRadioCapabilityPresent, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + if (tGsm810AssocRadioCapabilityPresent == 1) + { + /* Extract T-GSM 810 Associated Radio Capability */ + proto_tree_add_bits_item(tree, hf_gsm_a_t_gsm_810_assoc_radio_cap, tvb, bit_offset, 4, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 4; + } + + /* < Ciphering Mode Setting Capability : bit > + * Extract Ciphering Mode Setting Capability + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_ciphering_mode_setting_cap, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* < Additional Positioning Capabilities : bit > + * Extract Additional Positioning Capabilities + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_additional_positioning_caps, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Release 8 starts here + * + * <E-UTRA FDD support : bit > -- Release 8 starts here. + * Extract E-UTRA FDD support + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_e_utra_fdd_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * <E-UTRA TDD support : bit > + * Extract E-UTRA TDD support + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_e_utra_tdd_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * <E-UTRA Measurement and Reporting support : bit > + * Extract E-UTRA Measurement and Reporting support + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_e_utra_meas_and_report_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * <Priority-based reselection support : bit > + * Extract Priority-based reselection support + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_prio_based_resel_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Release 9 starts here + * + * <UTRA CSG Cells Reporting : bit > -- Release 9 starts here. + * Extract UTRA CSG Cells Reporting + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_utra_csg_cells_reporting, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * <VAMOS Level : bit(2) > + * Extract VAMOS Level + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_vamos_level, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* + * Release 10 starts here + * + * < TIGHTER Capability : bit(2) > -- Release 10 starts here. + * Extract TIGHTER Capability + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_tighter_cap, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* + * < Selective Ciphering of Downlink SACCH : bit > + * Extract Selective Ciphering of Downlink SACCH + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_selective_ciph_down_sacch, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Release 11 starts here + * + * < CS to PS SRVCC from GERAN to UTRA : bit(2) > -- Release 11 starts here + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_cs_to_ps_srvcc_geran_to_utra, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* + * < CS to PS SRVCC from GERAN to E-UTRA : bit(2)> + */ + AVAILABLE_BITS_CHECK(2); + proto_tree_add_bits_item(tree, hf_gsm_a_cs_to_ps_srvcc_geran_to_eutra, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 2; + + /* + * < GERAN Network Sharing support : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_geran_network_sharing_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * < E-UTRA Wideband RSRQ measurements support : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_eutra_wb_rsrq_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Release 12 starts here + * + * < ER Band support : bit(1) > -- Release 12 starts here + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_er_band_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * < UTRA Multiple Frequency Band Indicators support : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_utra_mfbi_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * < E-UTRA Multiple Frequency Band Indicators support : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_eutra_mfbi_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * < Extended TSC Set Capability support : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_ext_tsc_set_cap_support, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * < Extended EARFCN value range : bit(1)> + */ + AVAILABLE_BITS_CHECK(1); + proto_tree_add_bits_item(tree, hf_gsm_a_ext_earfcn_value_range, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset = bit_offset + 1; + + /* + * Add spare bits until we reach an octet boundary + */ + bits_left = (((len + offset) << 3) - bit_offset) & 0x07; + if (bits_left != 0) + { + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, bit_offset, bits_left, ENC_BIG_ENDIAN); + bit_offset += bits_left; + } + + /* translate to byte offset (we already know that we are on an octet boundary) */ + curr_offset = bit_offset >> 3; + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return len; +} +/* + * [3] 10.5.1.8 + */ +guint16 de_spare_nibble(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + gint bit_offset; + + curr_offset = offset; + if (RIGHT_NIBBLE == len) + bit_offset = 4; + else + bit_offset = 0; + + proto_tree_add_bits_item(tree, hf_gsm_a_spare_nibble, tvb, (curr_offset<<3)+bit_offset, 4, ENC_BIG_ENDIAN); + curr_offset = curr_offset + 1; + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.9 Descriptive group or broadcast call reference + */ +static const true_false_string tfs_vgcs_vbs = { "VGCS (Group call reference)", "VBS (Broadcast call reference)" }; + +static const value_string gsm_a_call_priority_vals[] = { + { 0, "no priority applied"}, + { 1, "call priority level 4"}, + { 2, "call priority level 3"}, + { 3, "call priority level 2"}, + { 4, "call priority level 1"}, + { 5, "call priority level 0"}, + { 6, "call priority level B"}, + { 7, "call priority level A"}, + { 0, NULL } +}; + +guint16 +de_d_gb_call_ref(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_group_call_reference, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_service_flag, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_af_acknowledgement, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_call_priority, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + curr_offset += 4; + + proto_tree_add_item(tree, hf_gsm_a_ciphering_info, tvb, curr_offset, 1, ENC_NA); + + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3)+4, 4, ENC_BIG_ENDIAN); + curr_offset++; + + /* no length check possible */ + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.10a PD and SAPI $(CCBS)$ + */ +static const value_string gsm_a_sapi_vals[] = { + { 0, "SAPI 0"}, + { 1, "Reserved"}, + { 2, "Reserved"}, + { 3, "SAPI 3"}, + { 0, NULL } +}; + +static guint16 +de_pd_sapi(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + proto_tree *subtree; + + curr_offset = offset; + + subtree = + proto_tree_add_subtree(tree, + tvb, curr_offset, 1, ett_gsm_dtap_elem[DE_PD_SAPI], NULL, + val_to_str_ext_const(DE_PD_SAPI, &gsm_dtap_elem_strings_ext, "")); + + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, curr_offset<<3, 2, ENC_BIG_ENDIAN); + + proto_tree_add_item(subtree, hf_gsm_a_sapi, tvb, curr_offset, 1, ENC_NA); + + proto_tree_add_item(tree, hf_gsm_a_L3_protocol_discriminator, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset++; + + /* no length check possible */ + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.11 Priority Level + */ +static const value_string gsm_a_call_prio_vals[] = { + { 0x00, "no priority applied" }, + { 0x01, "call priority level 4" }, + { 0x02, "call priority level 3" }, + { 0x03, "call priority level 2" }, + { 0x04, "call priority level 1" }, + { 0x05, "call priority level 0" }, + { 0x06, "call priority level B" }, + { 0x07, "call priority level A" }, + { 0, NULL } +}; + +static guint16 +de_prio(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + + curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_b8spare, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_bits_item(tree, hf_gsm_a_call_prio, tvb, (curr_offset<<3)+5, 3, ENC_BIG_ENDIAN); + curr_offset++; + + /* no length check possible */ + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.12.1 CN Common GSM-MAP NAS system information + */ +guint16 +de_cn_common_gsm_map_nas_sys_info(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + + curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_lac, tvb, curr_offset, 2, ENC_BIG_ENDIAN); + curr_offset += 2; + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.12.2 CS domain specific system information + */ +static const true_false_string gsm_a_att_value = { + "MSs shall apply IMSI attach and detach procedure", + "MSs shall not apply IMSI attach and detach procedure" +}; + +guint16 +de_cs_domain_spec_sys_info(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + + curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_rr_t3212, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3), 7, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_att, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.12.3 PS domain specific system information + */ +static const true_false_string gsm_a_nmo_1_value = { + "Network Mode of Operation I is used for MS configured for NMO_I_Behaviour", + "Network Mode of Operation indicated in Bit 1 (NMO) is used for MS configured for NMO_I_Behaviour" +}; + +static const true_false_string gsm_a_nmo_value = { + "Network Mode of Operation II", + "Network Mode of Operation I" +}; + +guint16 +de_ps_domain_spec_sys_info(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + + curr_offset = offset; + + proto_tree_add_item(tree, hf_gsm_a_gm_rac, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, (curr_offset<<3), 6, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_nmo_1, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_nmo, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * [3] 10.5.1.13 PLMN list + */ +guint16 +de_plmn_list(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string, int string_len) +{ + gchar *mcc_mnc_str; + guint32 curr_offset; + guint8 num_plmn; + proto_tree* subtree; + + curr_offset = offset; + + num_plmn = 0; + while ((len - (curr_offset - offset)) >= 3) + { + subtree = proto_tree_add_subtree_format(tree, tvb, curr_offset, 3, ett_gsm_a_plmn, NULL, "PLMN[%u]", num_plmn + 1); + mcc_mnc_str = dissect_e212_mcc_mnc_wmem_packet_str(tvb, pinfo, subtree, curr_offset, E212_NONE, TRUE); + proto_item_append_text(subtree, ": %s", mcc_mnc_str); + + curr_offset += 3; + + num_plmn++; + } + + if (add_string) + snprintf(add_string, string_len, " - %u PLMN%s", + num_plmn, plurality(num_plmn, "", "s")); + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * 10.5.1.14 NAS container for PS HO + */ + +static const value_string gsm_a_pld_xid_vals[] = { + { 0x00, "The MS shall perform a Reset of LLC and SNDCP without old XID indicator" }, + { 0x01, "The MS shall perform a Reset of LLC and SNDCP with old XID indicator" }, + { 0, NULL } +}; + +static guint16 +de_nas_cont_for_ps_ho(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset; + + curr_offset = offset; + + /* 8 7 6 5 4 3 2 1 + * 0 0 0 old 0 Type of ciphering + * spare spare spare XID spare algorithm + */ + proto_tree_add_item(tree, hf_gsm_a_old_xid, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gsm_a_type_of_ciph_alg, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + /* IOV-UI value (octet 2 to 5) + * The IOV-UI value consists of 32 bits, the format is defined in 3GPP TS 44.064 [78a]. + */ + proto_tree_add_item(tree, hf_gsm_a_iov_ui, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + curr_offset += 4; + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_extraneous_data); + + return (curr_offset - offset); +} + +/* + * 10.5.1.15 MS network feature support + */ +static const true_false_string gsm_a_ext_periodic_timers_value = { + "MS supports the extended periodic timer in this domain", + "MS does not support the extended periodic timer in this domain" +}; + +static guint16 +de_ms_net_feat_sup(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_) +{ + guint32 curr_offset, bit_offset; + + curr_offset = offset; + bit_offset = (curr_offset<<3)+4; + + proto_tree_add_bits_item(tree, hf_gsm_a_spare_bits, tvb, bit_offset, 3, ENC_BIG_ENDIAN); + bit_offset += 3; + proto_tree_add_bits_item(tree, hf_gsm_a_ext_periodic_timers, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + + return (curr_offset - offset); +} + + +guint16 (*common_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 offset, guint len, gchar *add_string, int string_len) = { + /* Common Information Elements 10.5.1 */ + de_cell_id, /* Cell Identity */ + de_ciph_key_seq_num, /* Ciphering Key Sequence Number */ + de_lai, /* Location Area Identification */ + de_mid, /* Mobile Identity */ + de_ms_cm_1, /* Mobile Station Classmark 1 */ + de_ms_cm_2, /* Mobile Station Classmark 2 */ + de_ms_cm_3, /* Mobile Station Classmark 3 */ + de_spare_nibble, /* Spare Half Octet */ + de_d_gb_call_ref, /* Descriptive group or broadcast call reference */ + NULL /* handled inline */, /* Group Cipher Key Number */ + de_pd_sapi, /* PD and SAPI $(CCBS)$ */ + /* Pos 10 */ + de_prio /* handled inline */, /* Priority Level */ + de_cn_common_gsm_map_nas_sys_info, /* 10.5.1.12.1 CN Common GSM-MAP NAS system information */ + de_cs_domain_spec_sys_info, /* 10.5.1.12.2 CS domain specific system information */ + de_ps_domain_spec_sys_info, /* 10.5.1.12.2 PS domain specific system information */ + de_plmn_list, /* 10.5.1.13 PLMN list */ + de_nas_cont_for_ps_ho, /* 10.5.1.14 NAS container for PS HO */ + de_ms_net_feat_sup, /* 10.5.1.15 MS network feature support */ + NULL, /* NONE */ +}; + +/* TAP STAT INFO */ +typedef enum +{ + IEI_COLUMN, + MSG_NAME_COLUMN, + COUNT_COLUMN +} gsm_a_stat_columns; + +static stat_tap_table_item gsm_a_stat_fields[] = { + {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "IEI", "%d"}, + {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "Message Name", "%-25s"}, + {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Count", "%d"} + }; + +static void gsm_a_stat_init(stat_tap_table_ui* new_stat, const char *table_title, const value_string *msg_strings) +{ + int num_fields = sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item); + stat_tap_table* table; + guint i; + stat_tap_table_item_type items[sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item)]; + + items[IEI_COLUMN].type = TABLE_ITEM_UINT; + items[MSG_NAME_COLUMN].type = TABLE_ITEM_STRING; + items[COUNT_COLUMN].type = TABLE_ITEM_UINT; + items[COUNT_COLUMN].value.uint_value = 0; + + table = stat_tap_find_table(new_stat, table_title); + if (table) { + if (new_stat->stat_tap_reset_table_cb) { + new_stat->stat_tap_reset_table_cb(table); + } + return; + } + + table = stat_tap_init_table(table_title, num_fields, 0, NULL); + stat_tap_add_table(new_stat, table); + + /* Add a row for each value type */ + for (i = 0; i < 256; i++) + { + const char *msg_str = try_val_to_str(i, msg_strings); + char *col_str; + if (msg_str) { + col_str = g_strdup(msg_str); + } else { + col_str = ws_strdup_printf("Unknown message %d", i); + } + + items[IEI_COLUMN].value.uint_value = i; + items[MSG_NAME_COLUMN].value.string_value = col_str; + stat_tap_init_table_row(table, i, num_fields, items); + } +} + +static void gsm_a_bssmap_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F BSSMAP Statistics", gsm_a_bssmap_msg_strings); +} + +static void gsm_a_dtap_mm_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Mobility Management Statistics", gsm_a_dtap_msg_mm_strings); +} + +static void gsm_a_dtap_rr_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Radio Resource Management Statistics", gsm_a_dtap_msg_rr_strings); +} + +static void gsm_a_dtap_cc_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Call Control Statistics", gsm_a_dtap_msg_cc_strings); +} + +static void gsm_a_dtap_gmm_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP GPRS Mobility Management Statistics", gsm_a_dtap_msg_gmm_strings); +} + +static void gsm_a_dtap_sm_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP GPRS Session Management Statistics", gsm_a_dtap_msg_sm_strings); +} + +static void gsm_a_dtap_sms_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Short Message Service Statistics", gsm_a_dtap_msg_sms_strings); +} + +static void gsm_a_dtap_tp_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Special Conformance Testing Functions", gsm_a_dtap_msg_tp_strings); +} + +static void gsm_a_dtap_ss_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F DTAP Supplementary Services Statistics", gsm_a_dtap_msg_ss_strings); +} + +static void gsm_a_sacch_rr_stat_init(stat_tap_table_ui* new_stat) +{ + gsm_a_stat_init(new_stat, + "GSM A-I/F SACCH Statistics", gsm_a_rr_short_pd_msg_strings); +} + +static tap_packet_status +gsm_a_stat_packet(void *tapdata, const void *gatr_ptr, guint8 pdu_type, int protocol_disc) +{ + stat_data_t* stat_data = (stat_data_t*)tapdata; + const gsm_a_tap_rec_t *gatr = (const gsm_a_tap_rec_t *) gatr_ptr; + stat_tap_table* table; + stat_tap_table_item_type* msg_data; + + if (gatr->pdu_type != pdu_type) return TAP_PACKET_DONT_REDRAW; + if (pdu_type == BSSAP_PDU_TYPE_DTAP && (int)gatr->protocol_disc != protocol_disc) return TAP_PACKET_DONT_REDRAW; + if (pdu_type == GSM_A_PDU_TYPE_SACCH && gatr->protocol_disc != 0) return TAP_PACKET_DONT_REDRAW; + + table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0); + msg_data = stat_tap_get_field_data(table, gatr->message_type, COUNT_COLUMN); + msg_data->value.uint_value++; + stat_tap_set_field_data(table, gatr->message_type, COUNT_COLUMN, msg_data); + + return TAP_PACKET_REDRAW; +} + +static tap_packet_status +gsm_a_bssmap_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_BSSMAP, 0); +} + +static tap_packet_status +gsm_a_dtap_mm_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_MM); +} + +static tap_packet_status +gsm_a_dtap_rr_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_RR); +} + +static tap_packet_status +gsm_a_dtap_cc_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_CC); +} + +static tap_packet_status +gsm_a_dtap_gmm_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_GMM); +} + +static tap_packet_status +gsm_a_dtap_sms_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_SMS); +} + +static tap_packet_status +gsm_a_dtap_sm_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_SM); +} + +static tap_packet_status +gsm_a_dtap_ss_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_SS); +} + +static tap_packet_status +gsm_a_dtap_tp_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, BSSAP_PDU_TYPE_DTAP, PD_TP); +} + +static tap_packet_status +gsm_a_sacch_rr_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *gatr_ptr, tap_flags_t flags _U_) +{ + return gsm_a_stat_packet(tapdata, gatr_ptr, GSM_A_PDU_TYPE_SACCH, 0); +} + +static void +gsm_a_stat_reset(stat_tap_table* table) +{ + guint element; + stat_tap_table_item_type* item_data; + + for (element = 0; element < table->num_elements; element++) + { + item_data = stat_tap_get_field_data(table, element, COUNT_COLUMN); + item_data->value.uint_value = 0; + stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data); + } +} + +static void +gsm_a_stat_free_table_item(stat_tap_table* table _U_, guint row _U_, guint column, stat_tap_table_item_type* field_data) +{ + if (column != MSG_NAME_COLUMN) return; + g_free((char*)field_data->value.string_value); +} + +/* Register the protocol with Wireshark */ +void +proto_register_gsm_a_common(void) +{ + guint i; + guint last_offset; + + /* Setup list of header fields */ + static hf_register_info hf[] = + { + { &hf_gsm_a_common_elem_id, + { "Element ID", "gsm_a.common.elem_id", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL } + }, + { &hf_gsm_a_common_elem_id_f0, + { "Element ID", "gsm_a.common.elem_id", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } + }, + { &hf_gsm_a_l_ext, + { "ext", "gsm_a.l_ext", + FT_UINT8, BASE_DEC, NULL, 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_tmsi, + { "TMSI/P-TMSI", "gsm_a.tmsi", + FT_UINT32, BASE_DEC_HEX, 0, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_imei, + { "IMEI", "gsm_a.imei", + FT_STRING, BASE_NONE, 0, 0, + NULL, HFILL } + }, + { &hf_gsm_a_imeisv, + { "IMEISV", "gsm_a.imeisv", + FT_STRING, BASE_NONE, 0, 0, + NULL, HFILL } + }, + { &hf_gsm_a_MSC_rev, + { "Revision Level", "gsm_a.MSC_rev", + FT_UINT8, BASE_DEC, VALS(gsm_a_msc_rev_vals), 0x60, + NULL, HFILL } + }, + { &hf_gsm_a_ES_IND, + { "ES IND", "gsm_a.ES_IND", + FT_BOOLEAN, 8, TFS(&ES_IND_vals), 0x10, + NULL, HFILL } + }, + { &hf_gsm_a_A5_1_algorithm_sup, + { "A5/1 algorithm supported", "gsm_a.A5_1_algorithm_sup", + FT_BOOLEAN, 8, TFS(&A5_1_algorithm_sup_vals), 0x08, + NULL, HFILL } + }, + { &hf_gsm_a_RF_power_capability, + { "RF Power Capability", "gsm_a.RF_power_capability", + FT_UINT8, BASE_DEC, VALS(RF_power_capability_vals), 0x07, + NULL, HFILL } + }, + { &hf_gsm_a_ps_sup_cap, + { "PS capability (pseudo-synchronization capability)", "gsm_a.ps_sup_cap", + FT_BOOLEAN, 8, TFS(&ps_sup_cap_vals), 0x40, + NULL, HFILL } + }, + { &hf_gsm_a_SS_screening_indicator, + { "SS Screening Indicator", "gsm_a.SS_screening_indicator", + FT_UINT8, BASE_DEC, VALS(SS_screening_indicator_vals), 0x30, + NULL, HFILL } + }, + { &hf_gsm_a_SM_capability, + { "SM capability (MT SMS pt to pt capability)", "gsm_a.SM_cap", + FT_BOOLEAN, 8, TFS(&SM_capability_vals), 0x08, + NULL, HFILL } + }, + { &hf_gsm_a_VBS_notification_rec, + { "VBS notification reception", "gsm_a.VBS_notification_rec", + FT_BOOLEAN, 8, TFS(&VBS_notification_rec_vals), 0x04, + NULL, HFILL } + }, + { &hf_gsm_a_VGCS_notification_rec, + { "VGCS notification reception", "gsm_a.VGCS_notification_rec", + FT_BOOLEAN, 8, TFS(&VGCS_notification_rec_vals), 0x02, + NULL, HFILL } + }, + { &hf_gsm_a_FC_frequency_cap, + { "FC Frequency Capability", "gsm_a.FC_frequency_cap", + FT_BOOLEAN, 8, TFS(&FC_frequency_cap_vals), 0x01, + NULL, HFILL } + }, + { &hf_gsm_a_CM3, + { "CM3", "gsm_a.CM3", + FT_BOOLEAN, 8, TFS(&CM3_vals), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_LCS_VA_cap, + { "LCS VA capability (LCS value added location request notification capability)", "gsm_a.LCS_VA_cap", + FT_BOOLEAN, 8, TFS(&LCS_VA_cap_vals), 0x20, + NULL, HFILL } + }, + { &hf_gsm_a_UCS2_treatment, + { "UCS2 treatment", "gsm_a.UCS2_treatment", + FT_BOOLEAN, 8, TFS(&UCS2_treatment_vals), 0x10, + NULL, HFILL } + }, + { &hf_gsm_a_SoLSA, + { "SoLSA", "gsm_a.SoLSA", + FT_BOOLEAN, 8, TFS(&SoLSA_vals), 0x08, + NULL, HFILL } + }, + { &hf_gsm_a_CMSP, + { "CMSP: CM Service Prompt", "gsm_a.CMSP", + FT_BOOLEAN, 8, TFS(&CMSP_vals), 0x04, + NULL, HFILL } + }, + { &hf_gsm_a_A5_7_algorithm_sup, + { "A5/7 algorithm supported", "gsm_a.A5_7_algorithm_sup", + FT_BOOLEAN, BASE_NONE, TFS(&A5_7_algorithm_sup_vals), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_A5_6_algorithm_sup, + { "A5/6 algorithm supported", "gsm_a.A5_6_algorithm_sup", + FT_BOOLEAN, BASE_NONE, TFS(&A5_6_algorithm_sup_vals), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_A5_5_algorithm_sup, + { "A5/5 algorithm supported", "gsm_a.A5_5_algorithm_sup", + FT_BOOLEAN, BASE_NONE, TFS(&A5_5_algorithm_sup_vals), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_A5_4_algorithm_sup, + { "A5/4 algorithm supported", "gsm_a.A5_4_algorithm_sup", + FT_BOOLEAN, BASE_NONE, TFS(&A5_4_algorithm_sup_vals), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_A5_3_algorithm_sup, + { "A5/3 algorithm supported", "gsm_a.A5_3_algorithm_sup", + FT_BOOLEAN, 8, TFS(&A5_3_algorithm_sup_vals), 0x02, + NULL, HFILL } + }, + { &hf_gsm_a_A5_2_algorithm_sup, + { "A5/2 algorithm supported", "gsm_a.A5_2_algorithm_sup", + FT_BOOLEAN, 8, TFS(&A5_2_algorithm_sup_vals), 0x01, + NULL, HFILL } + }, + { &hf_gsm_a_mobile_identity_type, + { "Mobile Identity Type", "gsm_a.ie.mobileid.type", + FT_UINT8, BASE_DEC, VALS(mobile_identity_type_vals), 0x07, + NULL, HFILL } + }, + { &hf_gsm_a_id_dig_1, + { "Identity Digit 1", "gsm_a.id_dig_1", + FT_UINT8, BASE_DEC, NULL, 0xf0, + NULL, HFILL } + }, + { &hf_gsm_a_odd_even_ind, + { "Odd/even indication", "gsm_a.oddevenind", + FT_BOOLEAN, 8, TFS(&oddevenind_vals), 0x08, + NULL, HFILL } + }, + { &hf_gsm_a_unused, + { "Unused", "gsm_a.unused", + FT_UINT8, BASE_HEX, NULL, 0xf0, + NULL, HFILL } + }, + { &hf_gsm_a_tmgi_mcc_mnc_ind, + { "MCC/MNC indication", "gsm_a.tmgi_mcc_mnc_ind", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, + NULL, HFILL} + }, + { &hf_gsm_a_mbs_ses_id_ind, + { "MBMS Session Identity indication", "gsm_a.mbs_session_id_ind", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x20, + NULL, HFILL} + }, + { &hf_gsm_a_mbs_service_id, + { "MBMS Service ID", "gsm_a.mbs_service_id", + FT_UINT24, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_mbs_session_id, + { "MBMS Session ID", "gsm_a.mbs_session_id", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_length, + { "Length", "gsm_a.len", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_gsm_a_element_value, + { "Element Value", "gsm_a.element_value", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_gsm_a_extension, + { "Extension", "gsm_a.extension", + FT_BOOLEAN, 8, TFS(&gsm_a_extension_value), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_L3_protocol_discriminator, + { "Protocol discriminator", "gsm_a.L3_protocol_discriminator", + FT_UINT8, BASE_HEX, VALS(protocol_discriminator_vals), 0x0f, + NULL, HFILL } + }, + { &hf_gsm_a_call_prio, + { "Call priority", "gsm_a.call_prio", + FT_UINT8, BASE_DEC, VALS(gsm_a_call_prio_vals), 0x00, + NULL, HFILL } + }, + { &hf_gsm_a_type_of_ciph_alg, + { "Type of ciphering algorithm", "gsm_a.type_of_ciph_alg", + FT_UINT8, BASE_DEC, VALS(gsm_a_gm_type_of_ciph_alg_vals), 0x07, + NULL, HFILL } + }, + { &hf_gsm_a_att, + { "ATT", "gsm_a.att", + FT_BOOLEAN, 8, TFS(&gsm_a_att_value), 0x01, + "Attach-detach allowed", HFILL } + }, + { &hf_gsm_a_nmo_1, + { "NMO I", "gsm_a.nmo_1", + FT_BOOLEAN, 8, TFS(&gsm_a_nmo_1_value), 0x02, + "Network Mode of Operation I", HFILL } + }, + { &hf_gsm_a_nmo, + { "NMO", "gsm_a.nmo", + FT_BOOLEAN, 8, TFS(&gsm_a_nmo_value), 0x01, + "Network Mode of Operation", HFILL } + }, + { &hf_gsm_a_old_xid, + { "Old XID", "gsm_a.old_xid", + FT_UINT8, BASE_DEC, VALS(gsm_a_pld_xid_vals), 0x10, + NULL, HFILL } + }, + { &hf_gsm_a_iov_ui, + { "IOV-UI", "gsm_a.iov_ui", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_ext_periodic_timers, + { "Extended periodic timers", "gsm_a.ext_periodic_timers", + FT_BOOLEAN, BASE_NONE, TFS(&gsm_a_ext_periodic_timers_value), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_skip_ind, + { "Skip Indicator", "gsm_a.skip.ind", + FT_UINT8, BASE_DEC, VALS(gsm_a_skip_ind_vals), 0xf0, + NULL, HFILL } + }, + { &hf_gsm_a_b7spare, + { "Spare", "gsm_a.spareb7", + FT_UINT8, BASE_DEC, NULL, 0x40, + NULL, HFILL } + }, + { &hf_gsm_a_b8spare, + { "Spare", "gsm_a.spareb8", + FT_UINT8, BASE_DEC, NULL, 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_spare_bits, + { "Spare bit(s)", "gsm_a.spare_bits", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_multi_bnd_sup_fields, + { "Multiband supported field", "gsm_a.multi_bnd_sup_fields", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_pgsm_supported, + { "P-GSM Supported", "gsm_a.classmark3.pgsmSupported", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_egsm_supported, + { "E-GSM or R-GSM Supported", "gsm_a.classmark3.egsmSupported", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_gsm1800_supported, + { "GSM 1800 Supported", "gsm_a.classmark3.gsm1800Supported", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ass_radio_cap1, + { "Associated Radio Capability 1", "gsm_a.classmark3.ass_radio_cap1", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ass_radio_cap2, + { "Associated Radio Capability 2", "gsm_a.classmark3.ass_radio_cap2", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_cm3_A5_bits, + { "A5 bits", "gsm_a.classmark3.a5_bits", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_rsupport, + { "R Support", "gsm_a.classmark3.rsupport", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_r_capabilities, + { "R-GSM band Associated Radio Capability", "gsm_a.classmark3.r_capabilities", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_multislot_capabilities, + { "HSCSD Multi Slot Capability", "gsm_a.classmark3.multislot_capabilities", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_multislot_class, + { "HSCSD Multi Slot Class", "gsm_a.classmark3.multislot_cap", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ucs2_treatment, + { "UCS2 treatment", "gsm_a.UCS2_treatment", + FT_BOOLEAN, BASE_NONE, TFS(&UCS2_treatment_vals), 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_extended_measurement_cap, + { "Extended Measurement Capability", "gsm_a.classmark3.ext_meas_cap", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_measurement_capability, + { "MS measurement capability", "gsm_a.classmark3.ms_measurement_capability", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_sms_value, + { "SMS_VALUE (Switch-Measure-Switch)", "gsm_a.classmark3.sms_value", + FT_UINT8, BASE_DEC, VALS(gsm_a_sms_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_sm_value, + { "SM_VALUE (Switch-Measure)", "gsm_a.classmark3.sm_value", + FT_UINT8, BASE_DEC, VALS(gsm_a_sms_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_pos_method_cap_present, + { "MS Positioning Method Capability present", "gsm_a.classmark3.ms_pos_method_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ms_pos_method, + { "MS Positioning Method", "gsm_a.classmark3.ms_pos_method", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ms_assisted_e_otd, + { "MS assisted E-OTD", "gsm_a.classmark3.ms_assisted_e_otd", + FT_BOOLEAN, BASE_NONE, TFS(&ms_assisted_e_otd_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_based_e_otd, + { "MS based E-OTD", "gsm_a.classmark3.ms_based_e_otd", + FT_BOOLEAN, BASE_NONE, TFS(&ms_based_e_otd_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_assisted_gps, + { "MS assisted GPS", "gsm_a.classmark3.ms_assisted_gps", + FT_BOOLEAN, BASE_NONE, TFS(&ms_assisted_gps_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_based_gps, + { "MS based GPS", "gsm_a.classmark3.ms_based_gps", + FT_BOOLEAN, BASE_NONE, TFS(&ms_based_gps_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ms_conventional_gps, + { "MS Conventional GPS", "gsm_a.classmark3.ms_conventional_gps", + FT_BOOLEAN, BASE_NONE, TFS(&ms_conventional_gps_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_ecsd_multi_slot_capability, + { "ECSD Multi Slot Capability present", "gsm_a.classmark3.ecsd_multi_slot_capability", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ecsd_multi_slot_class, + { "ECSD Multi Slot Class", "gsm_a.classmark3.ecsd_multi_slot_class", + FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_struct_present, + { "8-PSK Struct present", "gsm_a.classmark3.8_psk_struct_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_struct, + { "8-PSK Struct", "gsm_a.classmark3.8_psk_struct", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_modulation_capability, + { "Modulation Capability", "gsm_a.classmark3.modulation_capability", + FT_BOOLEAN, BASE_NONE, TFS(&modulation_capability_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_rf_power_capability_1_present, + { "8-PSK RF Power Capability 1 present", "gsm_a.classmark3.8_psk_rf_power_capability_1_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_rf_power_capability_1, + { "8-PSK RF Power Capability 1", "gsm_a.classmark3.8_psk_rf_power_capability_1", + FT_UINT8, BASE_HEX, VALS(eight_psk_rf_power_capability_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_rf_power_capability_2_present, + { "8-PSK RF Power Capability 2 present", "gsm_a.classmark3.8_psk_rf_power_capability_2_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_rf_power_capability_2, + { "8-PSK RF Power Capability 2", "gsm_a.classmark3.8_psk_rf_power_capability_2", + FT_UINT8, BASE_HEX, VALS(eight_psk_rf_power_capability_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_400_band_info_present, + { "GSM 400 Band Information present", "gsm_a.classmark3.gsm_400_band_info_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_400_bands_supported, + { "GSM 400 Bands Supported", "gsm_a.classmark3.gsm_400_bands_supported", + FT_UINT8, BASE_HEX, VALS(gsm_400_bands_supported_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_400_assoc_radio_cap, + { "GSM 400 Associated Radio Capability", "gsm_a.classmark3.gsm_400_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_850_assoc_radio_cap_present, + { "GSM 850 Associated Radio Capability present", "gsm_a.classmark3.gsm_850_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_850_assoc_radio_cap, + { "GSM 850 Associated Radio Capability", "gsm_a.classmark3.gsm_850_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_1900_assoc_radio_cap_present, + { "GSM 1900 Associated Radio Capability present", "gsm_a.classmark3.gsm_1900_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_1900_assoc_radio_cap, + { "GSM 1900 Associated Radio Capability", "gsm_a.classmark3.gsm_1900_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_umts_fdd_rat_cap, + { "UMTS FDD Radio Access Technology Capability", "gsm_a.classmark3.umts_fdd_rat_cap", + FT_BOOLEAN, BASE_NONE, TFS(&umts_fdd_rat_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_umts_384_mcps_tdd_rat_cap, + { "UMTS 3.84 Mcps TDD Radio Access Technology Capability", "gsm_a.classmark3.umts_384_mcps_tdd_rat_cap", + FT_BOOLEAN, BASE_NONE, TFS(&umts_384_mcps_tdd_rat_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_cdma_2000_rat_cap, + { "CDMA 2000 Radio Access Technology Capability", "gsm_a.classmark3.cdma_2000_rat_cap", + FT_BOOLEAN, BASE_NONE, TFS(&cdma_2000_rat_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_e_gprs_multi_slot_info_present, + { "DTM E/GPRS Multi Slot Information present", "gsm_a.classmark3.dtm_e_gprs_multi_slot_info_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_gprs_multi_slot_class, + { "DTM GPRS Multi Slot Class", "gsm_a.classmark3.dtm_gprs_multi_slot_class", + FT_UINT8, BASE_DEC, VALS(dtm_gprs_multi_slot_class_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_single_slot_dtm, + { "Single Slot DTM", "gsm_a.classmark3.single_slot_dtm_supported", + FT_BOOLEAN, BASE_NONE, TFS(&single_slot_dtm_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_egprs_multi_slot_class_present, + { "DTM EGPRS Multi Slot Class present", "gsm_a.classmark3.dtm_egprs_multi_slot_class_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_egprs_multi_slot_class, + { "DTM EGPRS Multi Slot Class", "gsm_a.classmark3.dtm_egprs_multi_slot_class", + FT_UINT8, BASE_DEC, VALS(dtm_gprs_multi_slot_class_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_single_band_support, + { "Single Band Support", "gsm_a.classmark3.single_band_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_band, + { "GSM Band", "gsm_a.classmark3.gsm_band", + FT_UINT8, BASE_DEC, VALS(gsm_band_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_750_assoc_radio_cap_present, + { "GSM 750 Associated Radio Capability present", "gsm_a.classmark3.gsm_750_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_750_assoc_radio_cap, + { "GSM 750 Associated Radio Capability", "gsm_a.classmark3.gsm_750_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_umts_128_mcps_tdd_rat_cap, + { "UMTS 1.28 Mcps TDD Radio Access Technology Capability", "gsm_a.classmark3.umts_128_mcps_tdd_rat_cap", + FT_BOOLEAN, BASE_NONE, TFS(&umts_128_mcps_tdd_rat_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_feature_package_1, + { "GERAN Feature Package 1", "gsm_a.classmark3.geran_feature_package_1", + FT_BOOLEAN, BASE_NONE, TFS(&geran_feature_package_1_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ext_dtm_e_gprs_multi_slot_info_present, + { "Extended DTM E/GPRS Multi Slot Information present", "gsm_a.classmark3.ext_dtm_e_gprs_info_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ext_dtm_gprs_multi_slot_class, + { "Extended DTM GPRS Multi Slot Class", "gsm_a.classmark3.ext_dtm_gprs_multi_slot_class", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ext_dtm_egprs_multi_slot_class, + { "Extended DTM EGPRS Multi Slot Class", "gsm_a.classmark3.ext_dtm_egprs_multi_slot_class", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_high_multislot_cap_present, + { "High Multislot Capability present", "gsm_a.classmark3.high_multislot_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_high_multislot_cap, + { "High Multislot Capability", "gsm_a.classmark3.high_multislot_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_iu_mode_support, + { "GERAN Iu Mode Support", "gsm_a.classmark3.geran_iu_mode_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_iu_mode_cap, + { "GERAN Iu Mode Capabilities", "gsm_a.classmark3.geran_iu_mode_cap", + FT_UINT24, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_iu_mode_cap_length, + { "Length", "gsm_a.classmark3.geran_iu_mode_cap.length", + FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_flo_iu_cap, + { "FLO Iu Capability", "gsm_a.classmark3.geran_iu_mode_cap.flo_iu_cap", + FT_BOOLEAN, BASE_NONE, TFS(&flo_iu_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_feature_package_2, + { "GERAN Feature Package 2", "gsm_a.classmark3.geran_feature_package_2", + FT_BOOLEAN, BASE_NONE, TFS(&geran_feature_package_2_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gmsk_multislot_power_prof, + { "GMSK Multislot Power Profile", "gsm_a.classmark3.gmsk_multislot_power_prof", + FT_UINT8, BASE_DEC, VALS(gmsk_multislot_power_prof_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_8_psk_multislot_power_prof, + { "8-PSK Multislot Power Profile", "gsm_a.classmark3.8_psk_multislot_power_prof", + FT_UINT8, BASE_DEC, VALS(eight_psk_multislot_power_prof_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_400_band_info_present, + { "T-GSM 400 Band Information present", "gsm_a.classmark3.gsm_400_band_info_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_400_bands_supported, + { "T-GSM 400 Bands Supported", "gsm_a.classmark3.t_gsm_400_bands_supported", + FT_UINT8, BASE_HEX, VALS(t_gsm_400_bands_supported_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_400_assoc_radio_cap, + { "T-GSM 400 Associated Radio Capability", "gsm_a.classmark3.t_gsm_400_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_900_assoc_radio_cap_present, + { "T-GSM 900 Associated Radio Capability present", "gsm_a.classmark3.t_gsm_900_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_900_assoc_radio_cap, + { "T-GSM 900 Associated Radio Capability", "gsm_a.classmark3.t_gsm_900_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_downlink_adv_receiver_perf, + { "Downlink Advanced Receiver Performance", "gsm_a.classmark3.downlink_adv_receiver_perf", + FT_UINT8, BASE_DEC, VALS(downlink_adv_receiver_perf_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_enhancements_cap, + { "DTM Enhancements Capability", "gsm_a.classmark3.dtm_enhancements_capability", + FT_BOOLEAN, BASE_NONE, TFS(&dtm_enhancements_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_e_gprs_high_multi_slot_info_present, + { "DTM E/GPRS High Multi Slot Information present", "gsm_a.classmark3.dtm_e_gprs_high_mutli_slot_info_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_gprs_high_multi_slot_class, + { "DTM GPRS Multi Slot Class", "gsm_a.classmark3.dtm_gprs_multi_slot_class", + FT_UINT8, BASE_DEC, VALS(dtm_gprs_high_multi_slot_class_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_offset_required, + { "Offset required", "gsm_a.classmark3.offset_required", + FT_BOOLEAN, BASE_NONE, TFS(&offset_required_vals), 0x0, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_egprs_high_multi_slot_class_present, + { "DTM EGPRS High Multi Slot Class present", "gsm_a.classmark3.dtm_egprs_high_multi_slot_class_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_dtm_egprs_high_multi_slot_class, + { "DTM EGPRS High Multi Slot Class", "gsm_a.classmark3.dtm_egprs_high_multi_slot_class", + FT_UINT8, BASE_DEC, VALS(dtm_gprs_high_multi_slot_class_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_repeated_acch_cap, + { "Repeated ACCH Capability", "gsm_a.classmark3.repeated_acch_cap", + FT_BOOLEAN, BASE_NONE, TFS(&repeated_acch_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_710_assoc_radio_cap_present, + { "GSM 710 Associated Radio Capability present", "gsm_a.classmark3.gsm_710_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_gsm_710_assoc_radio_cap, + { "GSM 710 Associated Radio Capability", "gsm_a.classmark3.gsm_710_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_810_assoc_radio_cap_present, + { "T-GSM 810 Associated Radio Capability present", "gsm_a.classmark3.t_gsm_810_assoc_radio_cap_present", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_t_gsm_810_assoc_radio_cap, + { "T-GSM 810 Associated Radio Capability", "gsm_a.classmark3.t_gsm_810_assoc_radio_cap", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ciphering_mode_setting_cap, + { "Ciphering Mode Setting Capability", "gsm_a.classmark3.ciphering_mode_setting_cap", + FT_BOOLEAN, BASE_NONE, TFS(&ciphering_mode_setting_cap_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_additional_positioning_caps, + { "Additional Positioning Capabilities", "gsm_a.classmark3.additional_positioning_caps", + FT_BOOLEAN, BASE_NONE, TFS(&additional_positioning_caps_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_e_utra_fdd_support, + { "E-UTRA FDD support", "gsm_a.classmark3.e_utra_fdd_support", + FT_BOOLEAN, BASE_NONE, TFS(&e_utra_fdd_support_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_e_utra_tdd_support, + { "E-UTRA TDD support", "gsm_a.classmark3.e_utra_tdd_support", + FT_BOOLEAN, BASE_NONE, TFS(&e_utra_tdd_support_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_e_utra_meas_and_report_support, + { "E-UTRA Measurement and Reporting support", "gsm_a.classmark3.e_utra_meas_and_report_support", + FT_BOOLEAN, BASE_NONE, TFS(&e_utra_meas_and_report_support_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_prio_based_resel_support, + { "Priority-based reselection support", "gsm_a.classmark3.prio_based_resel_support", + FT_BOOLEAN, BASE_NONE, TFS(&prio_based_resel_support_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_utra_csg_cells_reporting, + { "UTRA CSG Cells Reporting", "gsm_a.classmark3.utra_csg_cells_reporting", + FT_BOOLEAN, BASE_NONE, TFS(&utra_csg_cells_reporting_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_vamos_level, + { "VAMOS Level", "gsm_a.classmark3.vamos_level", + FT_UINT8, BASE_DEC, VALS(vamos_level_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_tighter_cap, + { "TIGHTER Capability", "gsm_a.classmark3.tighter_cap", + FT_UINT8, BASE_DEC, VALS(tighter_cap_level_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_selective_ciph_down_sacch, + { "Selective Ciphering of Downlink SACCH", "gsm_a.classmark3.selective_ciph_down_sacch", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_supported_not_supported), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_cs_to_ps_srvcc_geran_to_utra, + { "CS to PS SRVCC from GERAN to UTRA", "gsm_a.classmark3.cs_to_ps_srvcc_geran_to_utra", + FT_UINT8, BASE_DEC, VALS(cs_to_ps_srvcc_geran_to_utra_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_cs_to_ps_srvcc_geran_to_eutra, + { "CS to PS SRVCC from GERAN to E-UTRA", "gsm_a.classmark3.cs_to_ps_srvcc_geran_to_eutra", + FT_UINT8, BASE_DEC, VALS(cs_to_ps_srvcc_geran_to_eutra_vals), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geran_network_sharing_support, + { "GERAN Network Sharing support", "gsm_a.classmark3.geran_network_sharing_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_eutra_wb_rsrq_support, + { "E-UTRA Wideband RSRQ measurements support", "gsm_a.classmark3.eutra_wb_rsrq_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_er_band_support, + { "ER Band support", "gsm_a.classmark3.er_band_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_utra_mfbi_support, + { "UTRA Multiple Frequency Band Indicators support", "gsm_a.classmark3.utra_mfbi_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_eutra_mfbi_support, + { "E-UTRA Multiple Frequency Band Indicators support", "gsm_a.classmark3.eutra_mfbi_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ext_tsc_set_cap_support, + { "Extended TSC Set Capability support", "gsm_a.classmark3.ext_tsc_set_cap_support", + FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_ext_earfcn_value_range, + { "Extended EARFCN value range", "gsm_a.classmark3.ext_earfcn_value_range", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_supported_not_supported), 0x00, + NULL, HFILL} + }, + { &hf_gsm_a_geo_loc_type_of_shape, + { "Location estimate", "gsm_a.gad.location_estimate", + FT_UINT8, BASE_DEC, VALS(type_of_shape_vals), 0xf0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_sign_of_lat, + { "Sign of latitude", "gsm_a.gad.sign_of_latitude", + FT_UINT8, BASE_DEC, VALS(sign_of_latitude_vals), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_deg_of_lat, + { "Degrees of latitude", "gsm_a.gad.deg_of_latitude", + FT_UINT24, BASE_DEC, NULL, 0x7fffff, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_deg_of_long, + { "Degrees of longitude", "gsm_a.gad.deg_of_longitude", + FT_INT24, BASE_DEC, NULL, 0xffffff, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_osm_uri, + { "Location OSM URI", "gsm_a.gad.location_uri", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_code, + { "Uncertainty code", "gsm_a.gad.uncertainty_code", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_semi_major, + { "Uncertainty semi-major", "gsm_a.gad.uncertainty_semi_major", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_semi_minor, + { "Uncertainty semi-minor", "gsm_a.gad.uncertainty_semi_minor", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_orientation_of_major_axis, + { "Orientation of major axis", "gsm_a.gad.orientation_of_major_axis", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_altitude, + { "Uncertainty Altitude", "gsm_a.gad.uncertainty_altitude", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_confidence, + { "Confidence(%)", "gsm_a.gad.confidence", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_range, + { "Uncertainty Range", "gsm_a.gad.uncertainty_range", + FT_UINT8, BASE_DEC, VALS(uncertainty_range), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_horizontal_confidence, + { "Horizontal confidence(%)", "gsm_a.gad.horizontal_confidence", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_horizontal_uncertainty_range, + { "Horizontal Uncertainty Range", "gsm_a.gad.horizontal_uncertainty_range", + FT_UINT8, BASE_DEC, VALS(uncertainty_range), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_vertical_confidence, + { "Vertical Confidence(%)", "gsm_a.gad.vertical_confidence", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_vertical_uncertainty_range, + { "Vertical Uncertainty Range", "gsm_a.gad.vertical_uncertainty_range", + FT_UINT8, BASE_DEC, VALS(uncertainty_range), 0x80, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_uncertainty_alt, + { "High accuracy uncertainty altitude", "gsm_a.gad.high_acc_uncertainty_alt", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_no_of_points, + { "Number of points", "gsm_a.gad.no_of_points", + FT_UINT8, BASE_DEC, NULL, 0x0f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_deg_of_lat, + { "High accuracy degrees of latitude", "gsm_a.gad.hig_acc_deg_of_lat", + FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_deg_of_long, + { "High accuracy degrees of longitude", "gsm_a.gad.high_acc_deg_of_long", + FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_uncertainty_semi_major, + { "High accuracy uncertainty semi-major", "gsm_a.gad.high_acc_uncertainty_semi_major", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_uncertainty_semi_minor, + { "High accuracy uncertainty semi-minor", "gsm_a.gad.high_acc_uncertainty_semi_minor", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_high_acc_alt, + { "High accuracy altitude", "gsm_a.gad.high_acc_alt", + FT_INT24, BASE_DEC, NULL, 0x3fffff, + NULL, HFILL } + }, + { &hf_gsm_a_velocity_type, + { "Velocity type", "gsm_a.gad.velocity_type", + FT_UINT8, BASE_DEC, VALS(gsm_a_velocity_type_vals), 0xf0, + NULL, HFILL } + }, + { &hf_gsm_a_bearing, + { "Bearing", "gsm_a.gad.bearing", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_horizontal_speed, + { "Horizontal Speed", "gsm_a.gad.horizontal_velocity", + FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_kmh, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_vertical_speed, + { "Vertical Speed", "gsm_a.gad.vertical_speed", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_kmh, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_uncertainty_speed, + { "Uncertainty Speed", "gsm_a.gad.uncertainty_speed", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_h_uncertainty_speed, + { "Horizontal Uncertainty Speed", "gsm_a.gad.v_uncertainty_speed", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_v_uncertainty_speed, + { "Vertical Uncertainty Speed", "gsm_a.gad.h_uncertainty_speed", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_d, + { "Direction of Vertical Speed", "gsm_a.gad.d", + FT_BOOLEAN, 8, TFS(&gsm_a_dir_of_ver_speed_vals), 0x02, + NULL, HFILL} + }, + { &hf_gsm_a_geo_loc_D, + { "D: Direction of Altitude", "gsm_a.gad.D", + FT_UINT16, BASE_DEC, VALS(dir_of_alt_vals), 0x8000, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_altitude, + { "Altitude in meters", "gsm_a.gad.altitude", + FT_UINT16, BASE_DEC, NULL, 0x7fff, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_inner_radius, + { "Inner radius", "gsm_a.gad.inner_radius", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_uncertainty_radius, + { "Uncertainty radius", "gsm_a.gad.no_of_points", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_offset_angle, + { "Offset angle", "gsm_a.gad.offset_angle", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_geo_loc_included_angle, + { "Included angle", "gsm_a.gad.included_angle", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_gsm_a_key_seq, + { "key sequence", "gsm_a.key_seq", + FT_UINT8, BASE_DEC, VALS(gsm_a_key_seq_vals), 0x00, + NULL, HFILL } + }, + { &hf_gsm_a_lac, + { "Location Area Code (LAC)", "gsm_a.lac", + FT_UINT16, BASE_HEX_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_gsm_a_spare_nibble, + { "Spare Nibble", "gsm_a.spare", + FT_UINT8, BASE_DEC_HEX, NULL, 0x00, + NULL, HFILL } + }, + /* Generated from convert_proto_tree_add_text.pl */ + { &hf_gsm_a_filler, { "Filler", "gsm_a.filler", FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL }}, + { &hf_gsm_a_identity_digit1, { "Identity Digit 1", "gsm_a.identity_digit1", FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL }}, + { &hf_gsm_a_group_call_reference, { "Group or Broadcast call reference", "gsm_a.group_call_reference", FT_UINT32, BASE_DEC_HEX, NULL, 0xffffffe0, NULL, HFILL }}, + { &hf_gsm_a_service_flag, { "SF Service Flag", "gsm_a.service_flag", FT_BOOLEAN, 32, TFS(&tfs_vgcs_vbs), 0x00000010, NULL, HFILL }}, + { &hf_gsm_a_af_acknowledgement, { "AF Acknowledgement", "gsm_a.af_acknowledgement", FT_BOOLEAN, 32, TFS(&tfs_required_not_required), 0x00000008, NULL, HFILL }}, + { &hf_gsm_a_call_priority, { "Call Priority", "gsm_a.call_priority", FT_UINT32, BASE_DEC, VALS(gsm_a_call_priority_vals), 0x00000007, NULL, HFILL }}, + { &hf_gsm_a_ciphering_info, { "Ciphering Information", "gsm_a.ciphering_info", FT_UINT8, BASE_HEX, NULL, 0xf0, NULL, HFILL }}, + { &hf_gsm_a_sapi, { "SAPI (Service Access Point Identifier)", "gsm_a.sapi", FT_UINT8, BASE_DEC, VALS(gsm_a_sapi_vals), 0x30, NULL, HFILL }}, + }; + + /* Setup protocol subtree array */ +#define NUM_INDIVIDUAL_ELEMS 2 + static gint *ett[NUM_INDIVIDUAL_ELEMS + + NUM_GSM_COMMON_ELEM]; + + static ei_register_info ei[] = { + { &ei_gsm_a_extraneous_data, { "gsm_a.extraneous_data", PI_PROTOCOL, PI_NOTE, "Extraneous Data, dissector bug or later version spec(report to wireshark.org)", EXPFILL }}, + { &ei_gsm_a_unknown_element, { "gsm_a.unknown_element", PI_PROTOCOL, PI_ERROR, "Unknown - aborting dissection", EXPFILL }}, + { &ei_gsm_a_unknown_pdu_type, { "gsm_a.unknown_pdu_type", PI_PROTOCOL, PI_WARN, "Unknown PDU type", EXPFILL }}, + { &ei_gsm_a_no_element_dissector, { "gsm_a.no_element_dissector", PI_PROTOCOL, PI_WARN, "No element dissector, rest of dissection may be incorrect", EXPFILL }}, + { &ei_gsm_a_format_not_supported, { "gsm_a.format_not_supported", PI_PROTOCOL, PI_WARN, "Format not supported", EXPFILL }}, + { &ei_gsm_a_mobile_identity_type, { "gsm_a.ie.mobileid.type.unknown", PI_PROTOCOL, PI_WARN, "Format unknown", EXPFILL }}, + { &ei_gsm_a_ie_length_too_short, { "gsm_a.ie.length_too_short", PI_PROTOCOL, PI_ERROR, "IE length too short", EXPFILL }} + }; + + expert_module_t* expert_a_common; + + static tap_param gsm_a_stat_params[] = { + { PARAM_FILTER, "filter", "Filter", NULL, TRUE } + }; + + static stat_tap_table_ui gsm_a_bssmap_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface BSSMAP", + "gsm_a", + "gsm_a,bssmap", + gsm_a_bssmap_stat_init, + gsm_a_bssmap_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_mm_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Mobility Management", + "gsm_a", + "gsm_a,dtap_mm", + gsm_a_dtap_mm_stat_init, + gsm_a_dtap_mm_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_rr_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Radio Resource Management", + "gsm_a", + "gsm_a,dtap_rr", + gsm_a_dtap_rr_stat_init, + gsm_a_dtap_rr_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_cc_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Call Control", + "gsm_a", + "gsm_a,dtap_cc", + gsm_a_dtap_cc_stat_init, + gsm_a_dtap_cc_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_gmm_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP GPRS Mobility Management", + "gsm_a", + "gsm_a,dtap_gmm", + gsm_a_dtap_gmm_stat_init, + gsm_a_dtap_gmm_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_sm_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP GPRS Session Management", + "gsm_a", + "gsm_a,dtap_sm", + gsm_a_dtap_sm_stat_init, + gsm_a_dtap_sm_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_sms_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Short Message Service", + "gsm_a", + "gsm_a,dtap_sms", + gsm_a_dtap_sms_stat_init, + gsm_a_dtap_sms_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_tp_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Special Conformance Testing Functions", + "gsm_a", + "gsm_a,dtap_tp", + gsm_a_dtap_tp_stat_init, + gsm_a_dtap_tp_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_dtap_ss_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface DTAP Supplementary Services", + "gsm_a", + "gsm_a,dtap_ss", + gsm_a_dtap_ss_stat_init, + gsm_a_dtap_ss_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + static stat_tap_table_ui gsm_a_sacch_rr_stat_table = { + REGISTER_STAT_GROUP_TELEPHONY_GSM, + "A-Interface SACCH", + "gsm_a", + "gsm_a,dtap_sacch", + gsm_a_sacch_rr_stat_init, + gsm_a_sacch_rr_stat_packet, + gsm_a_stat_reset, + gsm_a_stat_free_table_item, + NULL, + sizeof(gsm_a_stat_fields)/sizeof(stat_tap_table_item), gsm_a_stat_fields, + sizeof(gsm_a_stat_params)/sizeof(tap_param), gsm_a_stat_params, + NULL, + 0 + }; + + last_offset = NUM_INDIVIDUAL_ELEMS; + + ett[0] = &ett_gsm_a_plmn; + ett[1] = &ett_gsm_a_poly_pnt; + for (i=0; i < NUM_GSM_COMMON_ELEM; i++, last_offset++) + { + ett_gsm_common_elem[i] = -1; + ett[last_offset] = &ett_gsm_common_elem[i]; + } + + /* Register the protocol name and description */ + + proto_a_common = + proto_register_protocol("GSM A-I/F COMMON", "GSM COMMON", "gsm_a"); + + proto_register_field_array(proto_a_common, hf, array_length(hf)); + + proto_register_subtree_array(ett, array_length(ett)); + expert_a_common = expert_register_protocol(proto_a_common); + expert_register_field_array(expert_a_common, ei, array_length(ei)); + + + gsm_a_tap = register_tap("gsm_a"); + + register_stat_tap_table_ui(&gsm_a_bssmap_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_mm_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_rr_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_cc_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_gmm_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_sms_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_sm_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_ss_stat_table); + register_stat_tap_table_ui(&gsm_a_dtap_tp_stat_table); + register_stat_tap_table_ui(&gsm_a_sacch_rr_stat_table); + + /* Register a 3GPP protocol to be used for "global hf" that can be used to track inter protocol relations*/ + static hf_register_info hf_3gpp[] = + { + { &hf_3gpp_tmsi, + { "TMSI/P-TMSI/M-TMSI/5G-TMSI", "3gpp.tmsi", + FT_UINT32, BASE_DEC_HEX, 0, 0x0, + "Filter TMSI, P-TMSI, M-TMSI, 5G-TMSI across protocols", HFILL } + }, + }; + + proto_3gpp = proto_register_protocol("3GPP COMMON", "3GPP COMMON", "3gpp"); + + proto_register_field_array(proto_3gpp, hf_3gpp, array_length(hf_3gpp)); + +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |