forked from osmocom/wireshark
![Guy Harris](/assets/img/avatar_default.png)
ANSI and GSM MAP stats enhancements and cleanups; enhanced parameter dissection related to SS for GSM A-interface and MAP; minor GSM SMS fix; GSM SS enhancements for parameter dissection; MTP3 statistics tap. svn path=/trunk/; revision=10655
11378 lines
291 KiB
C
11378 lines
291 KiB
C
/* packet-gsm_a.c
|
|
* Routines for GSM A Interface (BSSMAP/DTAP) dissection
|
|
*
|
|
* Copyright 2003, Michael Lum <mlum [AT] telostech.com>
|
|
* In association with Telos Technology Inc.
|
|
*
|
|
* Title 3GPP Other
|
|
*
|
|
* Reference [1]
|
|
* Mobile radio interface signalling layer 3;
|
|
* General Aspects
|
|
* (3GPP TS 24.007 version 3.9.0 Release 1999)
|
|
*
|
|
* Reference [2]
|
|
* Mobile-services Switching Centre - Base Station System
|
|
* (MSC - BSS) interface;
|
|
* Layer 3 specification
|
|
* (GSM 08.08 version 7.7.0 Release 1998) TS 100 590 v7.7.0
|
|
*
|
|
* Reference [3]
|
|
* Mobile radio interface Layer 3 specification;
|
|
* Core network protocols;
|
|
* Stage 3
|
|
* (3GPP TS 24.008 version 4.7.0 Release 4)
|
|
*
|
|
* Reference [4]
|
|
* Mobile radio interface layer 3 specification;
|
|
* Radio Resource Control Protocol
|
|
* (GSM 04.18 version 8.4.1 Release 1999)
|
|
*
|
|
* Reference [5]
|
|
* Point-to-Point (PP) Short Message Service (SMS)
|
|
* support on mobile radio interface
|
|
* (3GPP TS 24.011 version 4.1.1 Release 4)
|
|
*
|
|
* Reference [6]
|
|
* Mobile radio Layer 3 supplementary service specification;
|
|
* Formats and coding
|
|
* (3GPP TS 24.080 version 4.3.0 Release 4)
|
|
*
|
|
* $Id: packet-gsm_a.c,v 1.13 2004/04/21 05:53:55 guy Exp $
|
|
*
|
|
* Ethereal - Network traffic analyzer
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "epan/packet.h"
|
|
#include "prefs.h"
|
|
#include "tap.h"
|
|
#include "asn1.h"
|
|
|
|
#include "packet-tcap.h"
|
|
#include "packet-bssap.h"
|
|
#include "packet-gsm_ss.h"
|
|
#include "packet-gsm_a.h"
|
|
|
|
/* PROTOTYPES/FORWARDS */
|
|
|
|
const value_string gsm_a_bssmap_msg_strings[] = {
|
|
{ 0x01, "Assignment Request" },
|
|
{ 0x02, "Assignment Complete" },
|
|
{ 0x03, "Assignment Failure" },
|
|
{ 0x10, "Handover Request" },
|
|
{ 0x11, "Handover Required" },
|
|
{ 0x12, "Handover Request Acknowledge" },
|
|
{ 0x13, "Handover Command" },
|
|
{ 0x14, "Handover Complete" },
|
|
{ 0x15, "Handover Succeeded" },
|
|
{ 0x16, "Handover Failure" },
|
|
{ 0x17, "Handover Performed" },
|
|
{ 0x18, "Handover Candidate Enquire" },
|
|
{ 0x19, "Handover Candidate Response" },
|
|
{ 0x1a, "Handover Required Reject" },
|
|
{ 0x1b, "Handover Detect" },
|
|
{ 0x20, "Clear Command" },
|
|
{ 0x21, "Clear Complete" },
|
|
{ 0x22, "Clear Request" },
|
|
{ 0x23, "Reserved" },
|
|
{ 0x24, "Reserved" },
|
|
{ 0x25, "SAPI 'n' Reject" },
|
|
{ 0x26, "Confusion" },
|
|
{ 0x28, "Suspend" },
|
|
{ 0x29, "Resume" },
|
|
{ 0x2a, "Connection Oriented Information" },
|
|
{ 0x2b, "Perform Location Request" },
|
|
{ 0x2c, "LSA Information" },
|
|
{ 0x2d, "Perform Location Response" },
|
|
{ 0x2e, "Perform Location Abort" },
|
|
{ 0x30, "Reset" },
|
|
{ 0x31, "Reset Acknowledge" },
|
|
{ 0x32, "Overload" },
|
|
{ 0x33, "Reserved" },
|
|
{ 0x34, "Reset Circuit" },
|
|
{ 0x35, "Reset Circuit Acknowledge" },
|
|
{ 0x36, "MSC Invoke Trace" },
|
|
{ 0x37, "BSS Invoke Trace" },
|
|
{ 0x3a, "Connectionless Information" },
|
|
{ 0x40, "Block" },
|
|
{ 0x41, "Blocking Acknowledge" },
|
|
{ 0x42, "Unblock" },
|
|
{ 0x43, "Unblocking Acknowledge" },
|
|
{ 0x44, "Circuit Group Block" },
|
|
{ 0x45, "Circuit Group Blocking Acknowledge" },
|
|
{ 0x46, "Circuit Group Unblock" },
|
|
{ 0x47, "Circuit Group Unblocking Acknowledge" },
|
|
{ 0x48, "Unequipped Circuit" },
|
|
{ 0x4e, "Change Circuit" },
|
|
{ 0x4f, "Change Circuit Acknowledge" },
|
|
{ 0x50, "Resource Request" },
|
|
{ 0x51, "Resource Indication" },
|
|
{ 0x52, "Paging" },
|
|
{ 0x53, "Cipher Mode Command" },
|
|
{ 0x54, "Classmark Update" },
|
|
{ 0x55, "Cipher Mode Complete" },
|
|
{ 0x56, "Queuing Indication" },
|
|
{ 0x57, "Complete Layer 3 Information" },
|
|
{ 0x58, "Classmark Request" },
|
|
{ 0x59, "Cipher Mode Reject" },
|
|
{ 0x5a, "Load Indication" },
|
|
{ 0x04, "VGCS/VBS Setup" },
|
|
{ 0x05, "VGCS/VBS Setup Ack" },
|
|
{ 0x06, "VGCS/VBS Setup Refuse" },
|
|
{ 0x07, "VGCS/VBS Assignment Request" },
|
|
{ 0x1c, "VGCS/VBS Assignment Result" },
|
|
{ 0x1d, "VGCS/VBS Assignment Failure" },
|
|
{ 0x1e, "VGCS/VBS Queuing Indication" },
|
|
{ 0x1f, "Uplink Request" },
|
|
{ 0x27, "Uplink Request Acknowledge" },
|
|
{ 0x49, "Uplink Request Confirmation" },
|
|
{ 0x4a, "Uplink Release Indication" },
|
|
{ 0x4b, "Uplink Reject Command" },
|
|
{ 0x4c, "Uplink Release Command" },
|
|
{ 0x4d, "Uplink Seized Command" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_mm_strings[] = {
|
|
{ 0x01, "IMSI Detach Indication" },
|
|
{ 0x02, "Location Updating Accept" },
|
|
{ 0x04, "Location Updating Reject" },
|
|
{ 0x08, "Location Updating Request" },
|
|
{ 0x11, "Authentication Reject" },
|
|
{ 0x12, "Authentication Request" },
|
|
{ 0x14, "Authentication Response" },
|
|
{ 0x1c, "Authentication Failure" },
|
|
{ 0x18, "Identity Request" },
|
|
{ 0x19, "Identity Response" },
|
|
{ 0x1a, "TMSI Reallocation Command" },
|
|
{ 0x1b, "TMSI Reallocation Complete" },
|
|
{ 0x21, "CM Service Accept" },
|
|
{ 0x22, "CM Service Reject" },
|
|
{ 0x23, "CM Service Abort" },
|
|
{ 0x24, "CM Service Request" },
|
|
{ 0x25, "CM Service Prompt" },
|
|
{ 0x26, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x28, "CM Re-establishment Request" },
|
|
{ 0x29, "Abort" },
|
|
{ 0x30, "MM Null" },
|
|
{ 0x31, "MM Status" },
|
|
{ 0x32, "MM Information" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_rr_strings[] = {
|
|
{ 0x3c, "RR Initialisation Request" },
|
|
{ 0x3b, "Additional Assignment" },
|
|
{ 0x3f, "Immediate Assignment" },
|
|
{ 0x39, "Immediate Assignment Extended" },
|
|
{ 0x3a, "Immediate Assignment Reject" },
|
|
|
|
{ 0x48, "DTM Assignment Failure" },
|
|
{ 0x49, "DTM Reject" },
|
|
{ 0x4a, "DTM Request" },
|
|
{ 0x4b, "Main DCCH Assignment Command" },
|
|
{ 0x4c, "Packet Assignment Command" },
|
|
|
|
{ 0x35, "Ciphering Mode Command" },
|
|
{ 0x32, "Ciphering Mode Complete" },
|
|
|
|
{ 0x30, "Configuration Change Command" },
|
|
{ 0x31, "Configuration Change Ack." },
|
|
{ 0x33, "Configuration Change Reject" },
|
|
|
|
{ 0x2e, "Assignment Command" },
|
|
{ 0x29, "Assignment Complete" },
|
|
{ 0x2f, "Assignment Failure" },
|
|
{ 0x2b, "Handover Command" },
|
|
{ 0x2c, "Handover Complete" },
|
|
{ 0x28, "Handover Failure" },
|
|
{ 0x2d, "Physical Information" },
|
|
{ 0x4d, "DTM Assignment Command" },
|
|
|
|
{ 0x08, "RR-cell Change Order" },
|
|
{ 0x23, "PDCH Assignment Command" },
|
|
|
|
{ 0x0d, "Channel Release" },
|
|
{ 0x0a, "Partial Release" },
|
|
{ 0x0f, "Partial Release Complete" },
|
|
|
|
{ 0x21, "Paging Request Type 1" },
|
|
{ 0x22, "Paging Request Type 2" },
|
|
{ 0x24, "Paging Request Type 3" },
|
|
{ 0x27, "Paging Response" },
|
|
{ 0x20, "Notification/NCH" },
|
|
{ 0x25, "Reserved" },
|
|
{ 0x26, "Notification/Response" },
|
|
|
|
{ 0x0b, "Reserved" },
|
|
|
|
/* { 0xc0, "Utran Classmark Change" }, CONFLICTS WITH Handover To UTRAN Command */
|
|
{ 0xc1, "UE RAB Preconfiguration" },
|
|
{ 0xc2, "cdma2000 Classmark Change" },
|
|
|
|
{ 0x18, "System Information Type 8" },
|
|
{ 0x19, "System Information Type 1" },
|
|
{ 0x1a, "System Information Type 2" },
|
|
{ 0x1b, "System Information Type 3" },
|
|
{ 0x1c, "System Information Type 4" },
|
|
{ 0x1d, "System Information Type 5" },
|
|
{ 0x1e, "System Information Type 6" },
|
|
{ 0x1f, "System Information Type 7" },
|
|
|
|
{ 0x02, "System Information Type 2bis" },
|
|
{ 0x03, "System Information Type 2ter" },
|
|
{ 0x07, "System Information Type 2quater" },
|
|
{ 0x05, "System Information Type 5bis" },
|
|
{ 0x06, "System Information Type 5ter" },
|
|
{ 0x04, "System Information Type 9" },
|
|
{ 0x00, "System Information Type 13" },
|
|
|
|
{ 0x3d, "System Information Type 16" },
|
|
{ 0x3e, "System Information Type 17" },
|
|
|
|
{ 0x40, "System Information Type 18" },
|
|
{ 0x41, "System Information Type 19" },
|
|
{ 0x42, "System Information Type 20" },
|
|
|
|
{ 0x10, "Channel Mode Modify" },
|
|
{ 0x12, "RR Status" },
|
|
{ 0x17, "Channel Mode Modify Acknowledge" },
|
|
{ 0x14, "Frequency Redefinition" },
|
|
{ 0x15, "Measurement Report" },
|
|
{ 0x16, "Classmark Change" },
|
|
{ 0x13, "Classmark Enquiry" },
|
|
{ 0x36, "Extended Measurement Report" },
|
|
{ 0x37, "Extended Measurement Order" },
|
|
{ 0x34, "GPRS Suspension Request" },
|
|
|
|
{ 0x09, "VGCS Uplink Grant" },
|
|
{ 0x0e, "Uplink Release" },
|
|
{ 0x0c, "Reserved" },
|
|
{ 0x2a, "Uplink Busy" },
|
|
{ 0x11, "Talker Indication" },
|
|
|
|
{ 0xc0, "UTRAN Classmark Change/Handover To UTRAN Command" }, /* spec conflict */
|
|
|
|
{ 0x38, "Application Information" },
|
|
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_cc_strings[] = {
|
|
{ 0x01, "Alerting" },
|
|
{ 0x08, "Call Confirmed" },
|
|
{ 0x02, "Call Proceeding" },
|
|
{ 0x07, "Connect" },
|
|
{ 0x0f, "Connect Acknowledge" },
|
|
{ 0x0e, "Emergency Setup" },
|
|
{ 0x03, "Progress" },
|
|
{ 0x04, "CC-Establishment" },
|
|
{ 0x06, "CC-Establishment Confirmed" },
|
|
{ 0x0b, "Recall" },
|
|
{ 0x09, "Start CC" },
|
|
{ 0x05, "Setup" },
|
|
{ 0x17, "Modify" },
|
|
{ 0x1f, "Modify Complete" },
|
|
{ 0x13, "Modify Reject" },
|
|
{ 0x10, "User Information" },
|
|
{ 0x18, "Hold" },
|
|
{ 0x19, "Hold Acknowledge" },
|
|
{ 0x1a, "Hold Reject" },
|
|
{ 0x1c, "Retrieve" },
|
|
{ 0x1d, "Retrieve Acknowledge" },
|
|
{ 0x1e, "Retrieve Reject" },
|
|
{ 0x25, "Disconnect" },
|
|
{ 0x2d, "Release" },
|
|
{ 0x2a, "Release Complete" },
|
|
{ 0x39, "Congestion Control" },
|
|
{ 0x3e, "Notify" },
|
|
{ 0x3d, "Status" },
|
|
{ 0x34, "Status Enquiry" },
|
|
{ 0x35, "Start DTMF" },
|
|
{ 0x31, "Stop DTMF" },
|
|
{ 0x32, "Stop DTMF Acknowledge" },
|
|
{ 0x36, "Start DTMF Acknowledge" },
|
|
{ 0x37, "Start DTMF Reject" },
|
|
{ 0x3a, "Facility" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_gmm_strings[] = {
|
|
{ 0x01, "Attach Request" },
|
|
{ 0x02, "Attach Accept" },
|
|
{ 0x03, "Attach Complete" },
|
|
{ 0x04, "Attach Reject" },
|
|
{ 0x05, "Detach Request" },
|
|
{ 0x06, "Detach Accept" },
|
|
{ 0x08, "Routing Area Update Request" },
|
|
{ 0x09, "Routing Area Update Accept" },
|
|
{ 0x0a, "Routing Area Update Complete" },
|
|
{ 0x0b, "Routing Area Update Reject" },
|
|
{ 0x0c, "Service Request" },
|
|
{ 0x0d, "Service Accept" },
|
|
{ 0x0e, "Service Reject" },
|
|
{ 0x10, "P-TMSI Reallocation Command" },
|
|
{ 0x11, "P-TMSI Reallocation Complete" },
|
|
{ 0x12, "Authentication and Ciphering Req" },
|
|
{ 0x13, "Authentication and Ciphering Resp" },
|
|
{ 0x14, "Authentication and Ciphering Rej" },
|
|
{ 0x1c, "Authentication and Ciphering Failure" },
|
|
{ 0x15, "Identity Request" },
|
|
{ 0x16, "Identity Response" },
|
|
{ 0x20, "GMM Status" },
|
|
{ 0x21, "GMM Information" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_sms_strings[] = {
|
|
{ 0x01, "CP-DATA" },
|
|
{ 0x04, "CP-ACK" },
|
|
{ 0x10, "CP-ERROR" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_sm_strings[] = {
|
|
{ 0x41, "Activate PDP Context Request" },
|
|
{ 0x42, "Activate PDP Context Accept" },
|
|
{ 0x43, "Activate PDP Context Reject" },
|
|
{ 0x44, "Request PDP Context Activation" },
|
|
{ 0x45, "Request PDP Context Activation rej." },
|
|
{ 0x46, "Deactivate PDP Context Request" },
|
|
{ 0x47, "Deactivate PDP Context Accept" },
|
|
{ 0x48, "Modify PDP Context Request(Network to MS direction)" },
|
|
{ 0x49, "Modify PDP Context Accept (MS to network direction)" },
|
|
{ 0x4a, "Modify PDP Context Request(MS to network direction)" },
|
|
{ 0x4b, "Modify PDP Context Accept (Network to MS direction)" },
|
|
{ 0x4c, "Modify PDP Context Reject" },
|
|
{ 0x4d, "Activate Secondary PDP Context Request" },
|
|
{ 0x4e, "Activate Secondary PDP Context Accept" },
|
|
{ 0x4f, "Activate Secondary PDP Context Reject" },
|
|
{ 0x50, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x51, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x52, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x53, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x54, "Reserved: was allocated in earlier phases of the protocol" },
|
|
{ 0x55, "SM Status" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const value_string gsm_a_dtap_msg_ss_strings[] = {
|
|
{ 0x2a, "Release Complete" },
|
|
{ 0x3a, "Facility" },
|
|
{ 0x3b, "Register" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
static const value_string gsm_rp_msg_strings[] = {
|
|
{ 0x00, "RP-DATA (MS to Network)" },
|
|
{ 0x01, "RP-DATA (Network to MS)" },
|
|
{ 0x02, "RP-ACK (MS to Network)" },
|
|
{ 0x03, "RP-ACK (Network to MS)" },
|
|
{ 0x04, "RP-ERROR (MS to Network)" },
|
|
{ 0x05, "RP-ERROR (Network to MS)" },
|
|
{ 0x06, "RP-SMMA (MS to Network)" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
static const value_string gsm_bssmap_elem_strings[] = {
|
|
{ 0x01, "Circuit Identity Code" },
|
|
{ 0x02, "Reserved" },
|
|
{ 0x03, "Resource Available" },
|
|
{ 0x04, "Cause" },
|
|
{ 0x05, "Cell Identifier" },
|
|
{ 0x06, "Priority" },
|
|
{ 0x07, "Layer 3 Header Information" },
|
|
{ 0x08, "IMSI" },
|
|
{ 0x09, "TMSI" },
|
|
{ 0x0a, "Encryption Information" },
|
|
{ 0x0b, "Channel Type" },
|
|
{ 0x0c, "Periodicity" },
|
|
{ 0x0d, "Extended Resource Indicator" },
|
|
{ 0x0e, "Number Of MSs" },
|
|
{ 0x0f, "Reserved" },
|
|
{ 0x10, "Reserved" },
|
|
{ 0x11, "Reserved" },
|
|
{ 0x12, "Classmark Information Type 2" },
|
|
{ 0x13, "Classmark Information Type 3" },
|
|
{ 0x14, "Interference Band To Be Used" },
|
|
{ 0x15, "RR Cause" },
|
|
{ 0x16, "Reserved" },
|
|
{ 0x17, "Layer 3 Information" },
|
|
{ 0x18, "DLCI" },
|
|
{ 0x19, "Downlink DTX Flag" },
|
|
{ 0x1a, "Cell Identifier List" },
|
|
{ 0x1b, "Response Request" },
|
|
{ 0x1c, "Resource Indication Method" },
|
|
{ 0x1d, "Classmark Information Type 1" },
|
|
{ 0x1e, "Circuit Identity Code List" },
|
|
{ 0x1f, "Diagnostic" },
|
|
{ 0x20, "Layer 3 Message Contents" },
|
|
{ 0x21, "Chosen Channel" },
|
|
{ 0x22, "Total Resource Accessible" },
|
|
{ 0x23, "Cipher Response Mode" },
|
|
{ 0x24, "Channel Needed" },
|
|
{ 0x25, "Trace Type" },
|
|
{ 0x26, "TriggerID" },
|
|
{ 0x27, "Trace Reference" },
|
|
{ 0x28, "TransactionID" },
|
|
{ 0x29, "Mobile Identity" },
|
|
{ 0x2a, "OMCID" },
|
|
{ 0x2b, "Forward Indicator" },
|
|
{ 0x2c, "Chosen Encryption Algorithm" },
|
|
{ 0x2d, "Circuit Pool" },
|
|
{ 0x2e, "Circuit Pool List" },
|
|
{ 0x2f, "Time Indication" },
|
|
{ 0x30, "Resource Situation" },
|
|
{ 0x31, "Current Channel Type 1" },
|
|
{ 0x32, "Queueing Indicator" },
|
|
{ 0x40, "Speech Version" },
|
|
{ 0x33, "Assignment Requirement" },
|
|
{ 0x35, "Talker Flag" },
|
|
{ 0x36, "Connection Release Requested" },
|
|
{ 0x37, "Group Call Reference" },
|
|
{ 0x38, "eMLPP Priority" },
|
|
{ 0x39, "Configuration Evolution Indication" },
|
|
{ 0x3a, "Old BSS to New BSS Information" },
|
|
{ 0x3b, "LSA Identifier" },
|
|
{ 0x3c, "LSA Identifier List" },
|
|
{ 0x3d, "LSA Information" },
|
|
{ 0x3e, "LCS QoS" },
|
|
{ 0x3f, "LSA access control suppression" },
|
|
{ 0x43, "LCS Priority" },
|
|
{ 0x44, "Location Type" },
|
|
{ 0x45, "Location Estimate" },
|
|
{ 0x46, "Positioning Data" },
|
|
{ 0x47, "LCS Cause" },
|
|
{ 0x48, "LCS Client Type" },
|
|
{ 0x49, "APDU" },
|
|
{ 0x4a, "Network Element Identity" },
|
|
{ 0x4b, "GPS Assistance Data" },
|
|
{ 0x4c, "Deciphering Keys" },
|
|
{ 0x4d, "Return Error Request" },
|
|
{ 0x4e, "Return Error Cause" },
|
|
{ 0x4f, "Segmentation" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
static const value_string gsm_dtap_elem_strings[] = {
|
|
/* Common Information Elements 10.5.1 */
|
|
{ 0x00, "Cell Identity" },
|
|
{ 0x00, "Ciphering Key Sequence Number" },
|
|
{ 0x00, "Location Area Identification" },
|
|
{ 0x00, "Mobile Identity" },
|
|
{ 0x00, "Mobile Station Classmark 1" },
|
|
{ 0x00, "Mobile Station Classmark 2" },
|
|
{ 0x00, "Mobile Station Classmark 3" },
|
|
{ 0x00, "Descriptive group or broadcast call reference" },
|
|
{ 0x00, "Group Cipher Key Number" },
|
|
{ 0x00, "PD and SAPI $(CCBS)$" },
|
|
{ 0x00, "Priority Level" },
|
|
{ 0x00, "PLMN List" },
|
|
/* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
|
|
{ 0x00, "RR Cause" },
|
|
/* Mobility Management Information Elements 10.5.3 */
|
|
{ 0x00, "Authentication Parameter RAND" },
|
|
{ 0x00, "Authentication Parameter AUTN (UMTS authentication challenge only)" },
|
|
{ 0x00, "Authentication Response Parameter" },
|
|
{ 0x00, "Authentication Response Parameter (extension) (UMTS authentication challenge only)" },
|
|
{ 0x00, "Authentication Failure Parameter (UMTS authentication challenge only)" },
|
|
{ 0x00, "CM Service Type" },
|
|
{ 0x00, "Identity Type" },
|
|
{ 0x00, "Location Updating Type" },
|
|
{ 0x00, "Network Name" },
|
|
{ 0x00, "Reject Cause" },
|
|
{ 0x00, "Follow-on Proceed" },
|
|
{ 0x00, "Time Zone" },
|
|
{ 0x00, "Time Zone and Time" },
|
|
{ 0x00, "CTS Permission" },
|
|
{ 0x00, "LSA Identifier" },
|
|
{ 0x00, "Daylight Saving Time" },
|
|
/* Call Control Information Elements 10.5.4 */
|
|
{ 0x00, "Auxiliary States" },
|
|
{ 0x00, "Bearer Capability" },
|
|
{ 0x00, "Call Control Capabilities" },
|
|
{ 0x00, "Call State" },
|
|
{ 0x00, "Called Party BCD Number" },
|
|
{ 0x00, "Called Party Subaddress" },
|
|
{ 0x00, "Calling Party BCD Number" },
|
|
{ 0x00, "Calling Party Subaddress" },
|
|
{ 0x00, "Cause" },
|
|
{ 0x00, "CLIR Suppression" },
|
|
{ 0x00, "CLIR Invocation" },
|
|
{ 0x00, "Congestion Level" },
|
|
{ 0x00, "Connected Number" },
|
|
{ 0x00, "Connected Subaddress" },
|
|
{ 0x00, "Facility" },
|
|
{ 0x00, "High Layer Compatibility" },
|
|
{ 0x00, "Keypad Facility" },
|
|
{ 0x00, "Low Layer Compatibility" },
|
|
{ 0x00, "More Data" },
|
|
{ 0x00, "Notification Indicator" },
|
|
{ 0x00, "Progress Indicator" },
|
|
{ 0x00, "Recall type $(CCBS)$" },
|
|
{ 0x00, "Redirecting Party BCD Number" },
|
|
{ 0x00, "Redirecting Party Subaddress" },
|
|
{ 0x00, "Repeat Indicator" },
|
|
{ 0x00, "Reverse Call Setup Direction" },
|
|
{ 0x00, "SETUP Container $(CCBS)$" },
|
|
{ 0x00, "Signal" },
|
|
{ 0x00, "SS Version Indicator" },
|
|
{ 0x00, "User-user" },
|
|
{ 0x00, "Alerting Pattern $(NIA)$" },
|
|
{ 0x00, "Allowed Actions $(CCBS)$" },
|
|
{ 0x00, "Stream Identifier" },
|
|
{ 0x00, "Network Call Control Capabilities" },
|
|
{ 0x00, "Cause of No CLI" },
|
|
{ 0x00, "Immediate Modification Indicator" },
|
|
{ 0x00, "Supported Codec List" },
|
|
{ 0x00, "Service Category" },
|
|
/* GPRS Mobility Management Information Elements 10.5.5 */
|
|
{ 0x00, "Attach Result" },
|
|
{ 0x00, "Attach Type" },
|
|
{ 0x00, "TMSI Status" },
|
|
{ 0x00, "Detach Type" },
|
|
{ 0x00, "DRX Parameter" },
|
|
{ 0x00, "Force to Standby" },
|
|
{ 0x00, "P-TMSI Signature" },
|
|
{ 0x00, "P-TMSI Signature 2" },
|
|
{ 0x00, "Identity Type 2" },
|
|
{ 0x00, "IMEISV Request" },
|
|
{ 0x00, "Receive N-PDU Numbers List" },
|
|
{ 0x00, "MS Network Capability" },
|
|
{ 0x00, "MS Radio Access Capability" },
|
|
{ 0x00, "GMM Cause" },
|
|
{ 0x00, "Routing Area Identification" },
|
|
{ 0x00, "Update Result" },
|
|
{ 0x00, "A&C Reference Number" },
|
|
{ 0x00, "Service Type" },
|
|
{ 0x00, "Cell Notification" },
|
|
{ 0x00, "Network Feature Support" },
|
|
/* Short Message Service Information Elements [5] 8.1.4 */
|
|
{ 0x00, "CP-User Data" },
|
|
{ 0x00, "CP-Cause" },
|
|
/* Short Message Service Information Elements [5] 8.2 */
|
|
{ 0x00, "RP-Message Reference" },
|
|
{ 0x00, "RP-Origination Address" },
|
|
{ 0x00, "RP-Destination Address" },
|
|
{ 0x00, "RP-User Data" },
|
|
{ 0x00, "RP-Cause" },
|
|
/* Session Management Information Elements 10.5.6 */
|
|
{ 0x00, "Access Point Name" },
|
|
{ 0x00, "Network Service Access Point Identifier" },
|
|
{ 0x00, "Protocol Configuration Options" },
|
|
{ 0x00, "Packet Data Protocol Address" },
|
|
{ 0x00, "Quality Of Service" },
|
|
{ 0x00, "SM Cause" },
|
|
{ 0x00, "Linked TI" },
|
|
{ 0x00, "LLC Service Access Point Identifier" },
|
|
{ 0x00, "Tear Down Indicator" },
|
|
{ 0x00, "Packet Flow Identifier" },
|
|
{ 0x00, "Traffic Flow Template" },
|
|
/* GPRS Common Information Elements 10.5.7 */
|
|
{ 0x00, "PDP Context Status" },
|
|
{ 0x00, "Radio Priority" },
|
|
{ 0x00, "GPRS Timer" },
|
|
{ 0x00, "GPRS Timer 2" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
const gchar *gsm_a_pd_str[] = {
|
|
"Group Call Control",
|
|
"Broadcast Call Control",
|
|
"Reserved: was allocated in earlier phases of the protocol",
|
|
"Call Control; call related SS messages",
|
|
"GPRS Transparent Transport Protocol (GTTP)",
|
|
"Mobility Management messages",
|
|
"Radio Resources Management messages",
|
|
"Unknown",
|
|
"GPRS Mobility Management messages",
|
|
"SMS messages",
|
|
"GPRS Session Management messages",
|
|
"Non call related SS messages",
|
|
"Location Services",
|
|
"Unknown",
|
|
"Reserved for extension of the PD to one octet length",
|
|
"Reserved for tests procedures"
|
|
};
|
|
|
|
static const value_string bssap_cc_values[] = {
|
|
{ 0x00, "not further specified" },
|
|
{ 0x80, "FACCH or SDCCH" },
|
|
{ 0xc0, "SACCH" },
|
|
{ 0, NULL } };
|
|
|
|
static const value_string bssap_sapi_values[] = {
|
|
{ 0x00, "RR/MM/CC" },
|
|
{ 0x03, "SMS" },
|
|
{ 0, NULL } };
|
|
|
|
static const gchar *cell_disc_str[] = {
|
|
"The whole Cell Global Identification, CGI, is used to identify the cells",
|
|
"Location Area Code, LAC, and Cell Identify, CI, is used to identify the cells",
|
|
"Cell Identity, CI, is used to identify the cells",
|
|
"No cell is associated with the transaction",
|
|
"Location Area Identification, LAI, is used to identify all cells within a Location Area",
|
|
"Location Area Code, LAC, is used to identify all cells within a location area",
|
|
"All cells on the BSS are identified"
|
|
};
|
|
#define NUM_CELL_DISC_STR (sizeof(cell_disc_str)/sizeof(gchar *))
|
|
|
|
#define DTAP_PD_MASK 0x0f
|
|
#define DTAP_SKIP_MASK 0xf0
|
|
#define DTAP_TI_MASK DTAP_SKIP_MASK
|
|
#define DTAP_TIE_PRES_MASK 0x07 /* after TI shifted to right */
|
|
#define DTAP_TIE_MASK 0x7f
|
|
|
|
#define DTAP_MM_IEI_MASK 0x3f
|
|
#define DTAP_RR_IEI_MASK 0xff
|
|
#define DTAP_CC_IEI_MASK 0x3f
|
|
#define DTAP_GMM_IEI_MASK 0xff
|
|
#define DTAP_SMS_IEI_MASK 0xff
|
|
#define DTAP_SM_IEI_MASK 0xff
|
|
#define DTAP_SS_IEI_MASK 0x3f
|
|
|
|
/* Initialize the protocol and registered fields */
|
|
static int proto_a_bssmap = -1;
|
|
static int proto_a_dtap = -1;
|
|
static int proto_a_rp = -1;
|
|
|
|
static int gsm_a_tap = -1;
|
|
|
|
static int hf_gsm_a_none = -1;
|
|
static int hf_gsm_a_bssmap_msg_type = -1;
|
|
static int hf_gsm_a_dtap_msg_mm_type = -1;
|
|
static int hf_gsm_a_dtap_msg_rr_type = -1;
|
|
static int hf_gsm_a_dtap_msg_cc_type = -1;
|
|
static int hf_gsm_a_dtap_msg_gmm_type = -1;
|
|
static int hf_gsm_a_dtap_msg_sms_type = -1;
|
|
static int hf_gsm_a_dtap_msg_sm_type = -1;
|
|
static int hf_gsm_a_dtap_msg_ss_type = -1;
|
|
static int hf_gsm_a_rp_msg_type = -1;
|
|
static int hf_gsm_a_length = -1;
|
|
static int hf_gsm_a_bssmap_elem_id = -1;
|
|
static int hf_gsm_a_dtap_elem_id = -1;
|
|
static int hf_gsm_a_imsi = -1;
|
|
static 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_cld_party_bcd_num = -1;
|
|
static int hf_gsm_a_clg_party_bcd_num = -1;
|
|
static int hf_gsm_a_cell_ci = -1;
|
|
static int hf_gsm_a_cell_lac = -1;
|
|
static int hf_gsm_a_dlci_cc = -1;
|
|
static int hf_gsm_a_dlci_spare = -1;
|
|
static int hf_gsm_a_dlci_sapi = -1;
|
|
static int hf_gsm_a_bssmap_cause = -1;
|
|
static int hf_gsm_a_dtap_cause = -1;
|
|
|
|
/* Initialize the subtree pointers */
|
|
static gint ett_bssmap_msg = -1;
|
|
static gint ett_dtap_msg = -1;
|
|
static gint ett_rp_msg = -1;
|
|
static gint ett_elems = -1;
|
|
static gint ett_elem = -1;
|
|
static gint ett_dtap_oct_1 = -1;
|
|
static gint ett_cm_srvc_type = -1;
|
|
static gint ett_gsm_enc_info = -1;
|
|
static gint ett_cell_list = -1;
|
|
static gint ett_dlci = -1;
|
|
static gint ett_bc_oct_3a = -1;
|
|
static gint ett_bc_oct_4 = -1;
|
|
static gint ett_bc_oct_5 = -1;
|
|
static gint ett_bc_oct_5a = -1;
|
|
static gint ett_bc_oct_5b = -1;
|
|
static gint ett_bc_oct_6 = -1;
|
|
static gint ett_bc_oct_6a = -1;
|
|
static gint ett_bc_oct_6b = -1;
|
|
static gint ett_bc_oct_6c = -1;
|
|
static gint ett_bc_oct_6d = -1;
|
|
static gint ett_bc_oct_6e = -1;
|
|
static gint ett_bc_oct_6f = -1;
|
|
static gint ett_bc_oct_6g = -1;
|
|
static gint ett_bc_oct_7 = -1;
|
|
|
|
static gint ett_tc_component = -1;
|
|
static gint ett_tc_invoke_id = -1;
|
|
static gint ett_tc_linked_id = -1;
|
|
static gint ett_tc_opr_code = -1;
|
|
static gint ett_tc_err_code = -1;
|
|
static gint ett_tc_prob_code = -1;
|
|
static gint ett_tc_sequence = -1;
|
|
|
|
static char a_bigbuf[1024];
|
|
static gchar a_add_string[1024];
|
|
|
|
static dissector_handle_t data_handle;
|
|
static dissector_handle_t bssmap_handle;
|
|
static dissector_handle_t dtap_handle;
|
|
static dissector_handle_t rp_handle;
|
|
static dissector_table_t sms_dissector_table; /* SMS TPDU */
|
|
|
|
static packet_info *g_pinfo;
|
|
static proto_tree *g_tree;
|
|
|
|
/*
|
|
* this should be set on a per message basis, if possible
|
|
*/
|
|
#define IS_UPLINK_FALSE 0
|
|
#define IS_UPLINK_TRUE 1
|
|
#define IS_UPLINK_UNKNOWN 2
|
|
static gint is_uplink;
|
|
|
|
|
|
typedef struct dgt_set_t
|
|
{
|
|
unsigned char out[15];
|
|
}
|
|
dgt_set_t;
|
|
|
|
static dgt_set_t Dgt_mbcd = {
|
|
{
|
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e */
|
|
'0','1','2','3','4','5','6','7','8','9','*','#','a','b','c'
|
|
}
|
|
};
|
|
|
|
static dgt_set_t Dgt_tbcd = {
|
|
{
|
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e */
|
|
'0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
|
|
}
|
|
};
|
|
|
|
static dgt_set_t Dgt_msid = {
|
|
{
|
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e */
|
|
'0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
|
|
}
|
|
};
|
|
|
|
/* FUNCTIONS */
|
|
|
|
/*
|
|
* Unpack BCD input pattern into output ASCII pattern
|
|
*
|
|
* Input Pattern is supplied using the same format as the digits
|
|
*
|
|
* Returns: length of unpacked pattern
|
|
*/
|
|
static int
|
|
my_dgt_tbcd_unpack(
|
|
char *out, /* ASCII pattern out */
|
|
guchar *in, /* packed pattern in */
|
|
int num_octs, /* Number of octets to unpack */
|
|
dgt_set_t *dgt /* Digit definitions */
|
|
)
|
|
{
|
|
int cnt = 0;
|
|
unsigned char i;
|
|
|
|
while (num_octs)
|
|
{
|
|
/*
|
|
* unpack first value in byte
|
|
*/
|
|
i = *in++;
|
|
*out++ = dgt->out[i & 0x0f];
|
|
cnt++;
|
|
|
|
/*
|
|
* unpack second value in byte
|
|
*/
|
|
i >>= 4;
|
|
|
|
if (i == 0x0f) /* odd number bytes - hit filler */
|
|
break;
|
|
|
|
*out++ = dgt->out[i];
|
|
cnt++;
|
|
num_octs--;
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
return(cnt);
|
|
}
|
|
|
|
static gchar *
|
|
my_match_strval(guint32 val, const value_string *vs, gint *idx)
|
|
{
|
|
gint i = 0;
|
|
|
|
while (vs[i].strptr)
|
|
{
|
|
if (vs[i].value == val)
|
|
{
|
|
*idx = i;
|
|
return(vs[i].strptr);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
*idx = -1;
|
|
return(NULL);
|
|
}
|
|
|
|
/* ELEMENT FUNCTIONS */
|
|
|
|
#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
|
|
if ((edc_len) > (edc_max_len)) \
|
|
{ \
|
|
proto_tree_add_text(tree, tvb, \
|
|
curr_offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
|
|
curr_offset += ((edc_len) - (edc_max_len)); \
|
|
}
|
|
|
|
#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
|
|
if ((sdc_len) < (sdc_min_len)) \
|
|
{ \
|
|
proto_tree_add_text(tree, tvb, \
|
|
curr_offset, (sdc_len), "Short Data (?)"); \
|
|
curr_offset += (sdc_len); \
|
|
return(curr_offset - offset); \
|
|
}
|
|
|
|
#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
|
|
if ((edc_len) != (edc_eq_len)) \
|
|
{ \
|
|
proto_tree_add_text(tree, tvb, \
|
|
curr_offset, (edc_len), "Unexpected Data Length"); \
|
|
curr_offset += (edc_len); \
|
|
return(curr_offset - offset); \
|
|
}
|
|
|
|
#define NO_MORE_DATA_CHECK(nmdc_len) \
|
|
if ((nmdc_len) == (curr_offset - offset)) return(nmdc_len);
|
|
|
|
/*
|
|
* Decode the MCC/MNC from 3 octets in 'octs'
|
|
*/
|
|
static void
|
|
mcc_mnc_aux(guint8 *octs, gchar *mcc, gchar *mnc)
|
|
{
|
|
if ((octs[0] & 0x0f) <= 9)
|
|
{
|
|
mcc[0] = Dgt_tbcd.out[octs[0] & 0x0f];
|
|
}
|
|
else
|
|
{
|
|
mcc[0] = (octs[0] & 0x0f) + 55;
|
|
}
|
|
|
|
if (((octs[0] & 0xf0) >> 4) <= 9)
|
|
{
|
|
mcc[1] = Dgt_tbcd.out[(octs[0] & 0xf0) >> 4];
|
|
}
|
|
else
|
|
{
|
|
mcc[1] = ((octs[0] & 0xf0) >> 4) + 55;
|
|
}
|
|
|
|
if ((octs[1] & 0x0f) <= 9)
|
|
{
|
|
mcc[2] = Dgt_tbcd.out[octs[1] & 0x0f];
|
|
}
|
|
else
|
|
{
|
|
mcc[2] = (octs[1] & 0x0f) + 55;
|
|
}
|
|
|
|
mcc[3] = '\0';
|
|
|
|
if (((octs[1] & 0xf0) >> 4) <= 9)
|
|
{
|
|
mnc[2] = Dgt_tbcd.out[(octs[1] & 0xf0) >> 4];
|
|
}
|
|
else
|
|
{
|
|
mnc[2] = ((octs[1] & 0xf0) >> 4) + 55;
|
|
}
|
|
|
|
if ((octs[2] & 0x0f) <= 9)
|
|
{
|
|
mnc[0] = Dgt_tbcd.out[octs[2] & 0x0f];
|
|
}
|
|
else
|
|
{
|
|
mnc[0] = (octs[2] & 0x0f) + 55;
|
|
}
|
|
|
|
if (((octs[2] & 0xf0) >> 4) <= 9)
|
|
{
|
|
mnc[1] = Dgt_tbcd.out[(octs[2] & 0xf0) >> 4];
|
|
}
|
|
else
|
|
{
|
|
mnc[1] = ((octs[2] & 0xf0) >> 4) + 55;
|
|
}
|
|
|
|
if (mnc[1] == 'F')
|
|
{
|
|
/*
|
|
* only a 1 digit MNC (very old)
|
|
*/
|
|
mnc[1] = '\0';
|
|
}
|
|
else if (mnc[2] == 'F')
|
|
{
|
|
/*
|
|
* only a 2 digit MNC
|
|
*/
|
|
mnc[2] = '\0';
|
|
}
|
|
else
|
|
{
|
|
mnc[3] = '\0';
|
|
}
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
BE_CIC, /* Circuit Identity Code */
|
|
BE_RSVD_1, /* Reserved */
|
|
BE_RES_AVAIL, /* Resource Available */
|
|
BE_CAUSE, /* Cause */
|
|
BE_CELL_ID, /* Cell Identifier */
|
|
BE_PRIO, /* Priority */
|
|
BE_L3_HEADER_INFO, /* Layer 3 Header Information */
|
|
BE_IMSI, /* IMSI */
|
|
BE_TMSI, /* TMSI */
|
|
BE_ENC_INFO, /* Encryption Information */
|
|
BE_CHAN_TYPE, /* Channel Type */
|
|
BE_PERIODICITY, /* Periodicity */
|
|
BE_EXT_RES_IND, /* Extended Resource Indicator */
|
|
BE_NUM_MS, /* Number Of MSs */
|
|
BE_RSVD_2, /* Reserved */
|
|
BE_RSVD_3, /* Reserved */
|
|
BE_RSVD_4, /* Reserved */
|
|
BE_CM_INFO_2, /* Classmark Information Type 2 */
|
|
BE_CM_INFO_3, /* Classmark Information Type 3 */
|
|
BE_INT_BAND, /* Interference Band To Be Used */
|
|
BE_RR_CAUSE, /* RR Cause */
|
|
BE_RSVD_5, /* Reserved */
|
|
BE_L3_INFO, /* Layer 3 Information */
|
|
BE_DLCI, /* DLCI */
|
|
BE_DOWN_DTX_FLAG, /* Downlink DTX Flag */
|
|
BE_CELL_ID_LIST, /* Cell Identifier List */
|
|
BE_RESP_REQ, /* Response Request */
|
|
BE_RES_IND_METHOD, /* Resource Indication Method */
|
|
BE_CM_INFO_1, /* Classmark Information Type 1 */
|
|
BE_CIC_LIST, /* Circuit Identity Code List */
|
|
BE_DIAG, /* Diagnostic */
|
|
BE_L3_MSG, /* Layer 3 Message Contents */
|
|
BE_CHOSEN_CHAN, /* Chosen Channel */
|
|
BE_TOT_RES_ACC, /* Total Resource Accessible */
|
|
BE_CIPH_RESP_MODE, /* Cipher Response Mode */
|
|
BE_CHAN_NEEDED, /* Channel Needed */
|
|
BE_TRACE_TYPE, /* Trace Type */
|
|
BE_TRIGGERID, /* TriggerID */
|
|
BE_TRACE_REF, /* Trace Reference */
|
|
BE_TRANSID, /* TransactionID */
|
|
BE_MID, /* Mobile Identity */
|
|
BE_OMCID, /* OMCID */
|
|
BE_FOR_IND, /* Forward Indicator */
|
|
BE_CHOSEN_ENC_ALG, /* Chosen Encryption Algorithm */
|
|
BE_CCT_POOL, /* Circuit Pool */
|
|
BE_CCT_POOL_LIST, /* Circuit Pool List */
|
|
BE_TIME_IND, /* Time Indication */
|
|
BE_RES_SIT, /* Resource Situation */
|
|
BE_CURR_CHAN_1, /* Current Channel Type 1 */
|
|
BE_QUE_IND, /* Queueing Indicator */
|
|
BE_SPEECH_VER, /* Speech Version */
|
|
BE_ASS_REQ, /* Assignment Requirement */
|
|
BE_TALKER_FLAG, /* Talker Flag */
|
|
BE_CONN_REL_REQ, /* Connection Release Requested */
|
|
BE_GROUP_CALL_REF, /* Group Call Reference */
|
|
BE_EMLPP_PRIO, /* eMLPP Priority */
|
|
BE_CONF_EVO_IND, /* Configuration Evolution Indication */
|
|
BE_OLD2NEW_INFO, /* Old BSS to New BSS Information */
|
|
BE_LSA_ID, /* LSA Identifier */
|
|
BE_LSA_ID_LIST, /* LSA Identifier List */
|
|
BE_LSA_INFO, /* LSA Information */
|
|
BE_LCS_QOS, /* LCS QoS */
|
|
BE_LSA_ACC_CTRL, /* LSA access control suppression */
|
|
BE_LCS_PRIO, /* LCS Priority */
|
|
BE_LOC_TYPE, /* Location Type */
|
|
BE_LOC_EST, /* Location Estimate */
|
|
BE_POS_DATA, /* Positioning Data */
|
|
BE_LCS_CAUSE, /* LCS Cause */
|
|
BE_LCS_CLIENT, /* LCS Client Type */
|
|
BE_APDU, /* APDU */
|
|
BE_NE_ID, /* Network Element Identity */
|
|
BE_GSP_ASSIST_DATA, /* GPS Assistance Data */
|
|
BE_DECIPH_KEYS, /* Deciphering Keys */
|
|
BE_RET_ERR_REQ, /* Return Error Request */
|
|
BE_RET_ERR_CAUSE, /* Return Error Cause */
|
|
BE_SEG, /* Segmentation */
|
|
BE_NONE /* NONE */
|
|
}
|
|
bssmap_elem_idx_t;
|
|
|
|
#define NUM_GSM_BSSMAP_ELEM (sizeof(gsm_bssmap_elem_strings)/sizeof(value_string))
|
|
static gint ett_gsm_bssmap_elem[NUM_GSM_BSSMAP_ELEM];
|
|
|
|
/*
|
|
* [2] 3.2.2.2
|
|
*/
|
|
static guint8
|
|
be_cic(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 value;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
value = tvb_get_ntohs(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 2,
|
|
"%s : PCM Multiplexer: %u",
|
|
a_bigbuf,
|
|
(value & 0xffe0) >> 5);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 2,
|
|
"%s : Timeslot: %u",
|
|
a_bigbuf,
|
|
value & 0x001f);
|
|
|
|
curr_offset += 2;
|
|
|
|
sprintf(add_string, " - (%u) (0x%04x)", value, value);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.5
|
|
*/
|
|
static guint8
|
|
be_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 value;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
if (oct & 0x80)
|
|
{
|
|
/* 2 octet cause */
|
|
|
|
if ((oct & 0x0f) == 0x00)
|
|
{
|
|
/* national cause */
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0: str = "Normal Event"; break;
|
|
case 1: str = "Normal Event"; break;
|
|
case 2: str = "Resource Unavailable"; break;
|
|
case 3: str = "Service or option not available"; break;
|
|
case 4: str = "Service or option not implemented"; break;
|
|
case 5: str = "Invalid message (e.g., parameter out of range)"; break;
|
|
case 6: str = "Protocol error"; break;
|
|
default:
|
|
str = "Interworking";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Cause Class: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : National Cause",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, 1,
|
|
"Cause Value");
|
|
|
|
curr_offset++;
|
|
|
|
strcpy(add_string, " - (National Cause)");
|
|
}
|
|
else
|
|
{
|
|
value = tvb_get_guint8(tvb, curr_offset + 1);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Cause (MSB): %u",
|
|
a_bigbuf,
|
|
((oct & 0x7f) << 8) | value);
|
|
|
|
curr_offset++;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 1,
|
|
"%s : Cause (LSB)",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (oct)
|
|
{
|
|
case 0x00: str = "Radio interface message failure"; break;
|
|
case 0x01: str = "Radio interface failure"; break;
|
|
case 0x02: str = "Uplink quality"; break;
|
|
case 0x03: str = "Uplink strength"; break;
|
|
case 0x04: str = "Downlink quality"; break;
|
|
case 0x05: str = "Downlink strength"; break;
|
|
case 0x06: str = "Distance"; break;
|
|
case 0x07: str = "O and M intervention"; break;
|
|
case 0x08: str = "Response to MSC invocation"; break;
|
|
case 0x09: str = "Call control"; break;
|
|
case 0x0a: str = "Radio interface failure, reversion to old channel"; break;
|
|
case 0x0b: str = "Handover successful"; break;
|
|
case 0x0c: str = "Better Cell"; break;
|
|
case 0x0d: str = "Directed Retry"; break;
|
|
case 0x0e: str = "Joined group call channel"; break;
|
|
case 0x0f: str = "Traffic"; break;
|
|
|
|
case 0x20: str = "Equipment failure"; break;
|
|
case 0x21: str = "No radio resource available"; break;
|
|
case 0x22: str = "Requested terrestrial resource unavailable"; break;
|
|
case 0x23: str = "CCCH overload"; break;
|
|
case 0x24: str = "Processor overload"; break;
|
|
case 0x25: str = "BSS not equipped"; break;
|
|
case 0x26: str = "MS not equipped"; break;
|
|
case 0x27: str = "Invalid cell"; break;
|
|
case 0x28: str = "Traffic Load"; break;
|
|
case 0x29: str = "Preemption"; break;
|
|
|
|
case 0x30: str = "Requested transcoding/rate adaption unavailable"; break;
|
|
case 0x31: str = "Circuit pool mismatch"; break;
|
|
case 0x32: str = "Switch circuit pool"; break;
|
|
case 0x33: str = "Requested speech version unavailable"; break;
|
|
case 0x34: str = "LSA not allowed"; break;
|
|
|
|
case 0x40: str = "Ciphering algorithm not supported"; break;
|
|
|
|
case 0x50: str = "Terrestrial circuit already allocated"; break;
|
|
case 0x51: str = "Invalid message contents"; break;
|
|
case 0x52: str = "Information element or field missing"; break;
|
|
case 0x53: str = "Incorrect value"; break;
|
|
case 0x54: str = "Unknown Message type"; break;
|
|
case 0x55: str = "Unknown Information Element"; break;
|
|
|
|
case 0x60: str = "Protocol Error between BSS and MSC"; break;
|
|
case 0x61: str = "VGCS/VBS call non existent"; break;
|
|
|
|
default:
|
|
if ((oct >= 0x10) && (oct <= 0x17)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x18) && (oct <= 0x1f)) { str = "Reserved for national use"; }
|
|
else if ((oct >= 0x2a) && (oct <= 0x2f)) { str = "Reserved for national use"; }
|
|
else if ((oct >= 0x35) && (oct <= 0x3f)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x41) && (oct <= 0x47)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x48) && (oct <= 0x4f)) { str = "Reserved for national use"; }
|
|
else if ((oct >= 0x56) && (oct <= 0x57)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x58) && (oct <= 0x5f)) { str = "Reserved for national use"; }
|
|
else if ((oct >= 0x62) && (oct <= 0x67)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x68) && (oct <= 0x6f)) { str = "Reserved for national use"; }
|
|
else if ((oct >= 0x70) && (oct <= 0x77)) { str = "Reserved for international use"; }
|
|
else if ((oct >= 0x78) && (oct <= 0x7f)) { str = "Reserved for national use"; }
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_uint_format(tree, hf_gsm_a_bssmap_cause,
|
|
tvb, curr_offset, 1, oct & 0x7f,
|
|
"%s : Cause: (%u) %s",
|
|
a_bigbuf,
|
|
oct & 0x7f,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
|
|
}
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.7
|
|
*/
|
|
static guint8
|
|
be_tmsi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 value;
|
|
|
|
curr_offset = offset;
|
|
|
|
value = tvb_get_ntohl(tvb, curr_offset);
|
|
|
|
proto_tree_add_uint(tree, hf_gsm_a_tmsi,
|
|
tvb, curr_offset, 4,
|
|
value);
|
|
|
|
sprintf(add_string, " - (0x%04x)", value);
|
|
|
|
curr_offset += 4;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.9
|
|
*/
|
|
static guint8
|
|
be_l3_header_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, DTAP_PD_MASK, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Protocol Discriminator: %s",
|
|
a_bigbuf,
|
|
gsm_a_pd_str[oct & DTAP_PD_MASK]);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : TI flag: %s",
|
|
a_bigbuf,
|
|
((oct & 0x08) ? "allocated by receiver" : "allocated by sender"));
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : TIO: %u",
|
|
a_bigbuf,
|
|
oct & 0x07);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.10
|
|
*/
|
|
static guint8
|
|
be_enc_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 mask;
|
|
guint8 alg_id;
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
mask = 0x80;
|
|
alg_id = 7;
|
|
|
|
do
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, mask, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : GSM A5/%u: %spermitted",
|
|
a_bigbuf,
|
|
alg_id,
|
|
(mask & oct) ? "" : "not ");
|
|
|
|
mask >>= 1;
|
|
alg_id--;
|
|
}
|
|
while (mask != 0x01);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, mask, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : No encryption: %spermitted",
|
|
a_bigbuf,
|
|
(mask & oct) ? "" : "not ");
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Key");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.11
|
|
*/
|
|
static guint8
|
|
be_chan_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 sdi;
|
|
guint8 num_chan;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
sdi = oct & 0x0f;
|
|
switch (sdi)
|
|
{
|
|
case 1: str = "Speech"; break;
|
|
case 2: str = "Data"; break;
|
|
case 3: str = "Signalling"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Speech/Data Indicator: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
sprintf(add_string, " - (%s)", str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (sdi == 0x01)
|
|
{
|
|
/* speech */
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x08: str = "Full rate TCH channel Bm. Prefer full rate TCH"; break;
|
|
case 0x09: str = "Half rate TCH channel Lm. Prefer half rate TCH"; break;
|
|
case 0x0a: str = "Full or Half rate channel, Full rate preferred changes allowed after first allocation"; break;
|
|
case 0x0b: str = "Full or Half rate channel, Half rate preferred changes allowed after first allocation"; break;
|
|
case 0x1a: str = "Full or Half rate channel, Full rate preferred changes between full and half rate not allowed after first allocation"; break;
|
|
case 0x1b: str = "Full or Half rate channel, Half rate preferred changes between full and half rate not allowed after first allocation"; break;
|
|
case 0x0f: str = "Full or Half rate channel, changes allowed after first allocation"; break;
|
|
case 0x1f: str = "Full or Half rate channel, changes between full and half rate not allowed after first allocation"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Channel Rate and Type: %s",
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
do
|
|
{
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
switch (oct & 0x7f)
|
|
{
|
|
case 0x01: str = "GSM speech full rate version 1"; break;
|
|
case 0x11: str = "GSM speech full rate version 2"; break;
|
|
case 0x21: str = "GSM speech full rate version 3 (AMR)"; break;
|
|
|
|
case 0x05: str = "GSM speech half rate version 1"; break;
|
|
case 0x15: str = "GSM speech half rate version 2"; break;
|
|
case 0x25: str = "GSM speech half rate version 3 (AMR)"; break;
|
|
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Speech version identifier: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
}
|
|
while ((len - (curr_offset - offset)) > 0);
|
|
}
|
|
else if (sdi == 0x02)
|
|
{
|
|
/* data */
|
|
|
|
num_chan = 0;
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x08: str = "Full rate TCH channel Bm"; break;
|
|
case 0x09: str = "Half rate TCH channel Lm"; break;
|
|
case 0x0a: str = "Full or Half rate TCH channel, Full rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
|
|
case 0x0b: str = "Full or Half rate TCH channel, Half rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
|
|
case 0x1a: str = "Full or Half rate TCH channel, Full rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
|
|
case 0x1b: str = "Full or Half rate TCH channel. Half rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
|
|
default:
|
|
if ((oct >= 0x20) && (oct <= 0x27))
|
|
{
|
|
str = "Full rate TCH channels in a multislot configuration, changes by the BSS of the the number of TCHs and if applicable the used radio interface rate per channel allowed after first channel allocation as a result of the request";
|
|
|
|
num_chan = (oct - 0x20) + 1;
|
|
}
|
|
else if ((oct >= 0x30) && (oct <= 0x37))
|
|
{
|
|
str = "Full rate TCH channels in a multislot configuration, changes by the BSS of the number of TCHs or the used radio interface rate per channel not allowed after first channel allocation as a result of the request";
|
|
|
|
num_chan = (oct - 0x30) + 1;
|
|
}
|
|
else
|
|
{
|
|
str = "Reserved";
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (num_chan > 0)
|
|
{
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Channel Rate and Type: Max channels %u, %s",
|
|
num_chan,
|
|
str);
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Channel Rate and Type: %s",
|
|
str);
|
|
}
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : %sTransparent service",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "Non-" : "");
|
|
|
|
if (num_chan == 0)
|
|
{
|
|
if (oct & 0x40)
|
|
{
|
|
/* non-transparent */
|
|
|
|
switch (oct & 0x3f)
|
|
{
|
|
case 0x00: str = "12 kbit/s if the channel is a full rate TCH, or 6 kbit/s if the channel is a half rate TCH"; break;
|
|
case 0x18: str = "14.5 kbit/s"; break;
|
|
case 0x10: str = "12 kbits/s"; break;
|
|
case 0x11: str = "6 kbits/s"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (oct & 0x3f)
|
|
{
|
|
case 0x18: str = "14.4 kbit/s"; break;
|
|
case 0x10: str = "9.6kbit/s"; break;
|
|
case 0x11: str = "4.8kbit/s"; break;
|
|
case 0x12: str = "2.4kbit/s"; break;
|
|
case 0x13: str = "1.2Kbit/s"; break;
|
|
case 0x14: str = "600 bit/s"; break;
|
|
case 0x15: str = "1200/75 bit/s (1200 network-to-MS / 75 MS-to-network)"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (oct & 0x40)
|
|
{
|
|
/* non-transparent */
|
|
|
|
switch (oct & 0x3f)
|
|
{
|
|
case 0x16: str = "58 kbit/s (4x14.5 kbit/s)"; break;
|
|
case 0x14: str = "48.0 / 43.5 kbit/s (4x12 kbit/s or 3x14.5 kbit/s)"; break;
|
|
case 0x13: str = "36.0 / 29.0 kbit/s (3x12 kbit/s or 2x14.5 kbit/s)"; break;
|
|
case 0x12: str = "24.0 / 24.0 (4x6 kbit/s or 2x12 kbit/s)"; break;
|
|
case 0x11: str = "18.0 / 14.5 kbit/s (3x6 kbit/s or 1x14.5 kbit/s)"; break;
|
|
case 0x10: str = "12.0 / 12.0 kbit/s (2x6 kbit/s or 1x12 kbit/s)"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (oct & 0x3f)
|
|
{
|
|
case 0x1f: str = "64 kbit/s, bit transparent"; break;
|
|
case 0x1e: str = "56 kbit/s, bit transparent"; break;
|
|
case 0x1d: str = "56 kbit/s"; break;
|
|
case 0x1c: str = "48 kbit/s"; break;
|
|
case 0x1b: str = "38.4 kbit/s"; break;
|
|
case 0x1a: str = "28.8 kbit/s"; break;
|
|
case 0x19: str = "19.2 kbit/s"; break;
|
|
case 0x18: str = "14.4 kbit/s"; break;
|
|
case 0x10: str = "9.6 kbit/s"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Rate: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
if (num_chan == 0)
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 14.5 kbit/s (TCH/F14.4) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 12.0 kbit/s (TCH F/9.6) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 6.0 kbit/s (TCH F/4.8) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "" : "not ");
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 14.5/14.4 kbit/s (TCH/F14.4) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 12.0/9.6 kbit/s (TCH F/9.6) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : 6.0/4.8 kbit/s (TCH F/4.8) %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "" : "not ");
|
|
}
|
|
|
|
curr_offset++;
|
|
}
|
|
else if (sdi == 0x03)
|
|
{
|
|
/* signalling */
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x00: str = "SDCCH or Full rate TCH channel Bm or Half rate TCH channel Lm"; break;
|
|
case 0x01: str = "SDCCH"; break;
|
|
case 0x02: str = "SDCCH or Full rate TCH channel Bm"; break;
|
|
case 0x03: str = "SDCCH or Half rate TCH channel Lm"; break;
|
|
case 0x08: str = "Full rate TCH channel Bm"; break;
|
|
case 0x09: str = "Half rate TCH channel Lm"; break;
|
|
case 0x0a: str = "Full or Half rate TCH channel, Full rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
|
|
case 0x0b: str = "Full or Half rate TCH channel, Half rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
|
|
case 0x1a: str = "Full or Half rate TCH channel, Full rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
|
|
case 0x1b: str = "Full or Half rate TCH channel. Half rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Channel Rate and Type: %s",
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Spare");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
}
|
|
else
|
|
{
|
|
/* unknown format */
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Unknown format");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
}
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.17
|
|
* Formats everything after the discriminator, shared function
|
|
*/
|
|
static guint8
|
|
be_cell_id_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, guint8 disc)
|
|
{
|
|
guint8 octs[3];
|
|
guint32 value;
|
|
guint32 curr_offset;
|
|
gchar mcc[4];
|
|
gchar mnc[4];
|
|
|
|
add_string[0] = '\0';
|
|
curr_offset = offset;
|
|
|
|
switch (disc)
|
|
{
|
|
case 0x00:
|
|
/* FALLTHRU */
|
|
|
|
case 0x04:
|
|
octs[0] = tvb_get_guint8(tvb, curr_offset);
|
|
octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
|
|
octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
|
|
|
|
mcc_mnc_aux(octs, mcc, mnc);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 3,
|
|
"Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
|
|
mcc,
|
|
mnc);
|
|
|
|
curr_offset += 3;
|
|
|
|
/* FALLTHRU */
|
|
|
|
case 0x01:
|
|
case 0x05:
|
|
|
|
/* LAC */
|
|
|
|
value = tvb_get_ntohs(tvb, curr_offset);
|
|
|
|
proto_tree_add_uint(tree, hf_gsm_a_cell_lac, tvb,
|
|
curr_offset, 2, value);
|
|
|
|
curr_offset += 2;
|
|
|
|
sprintf(add_string, " - LAC (0x%04x)", value);
|
|
|
|
if ((disc == 0x04) || (disc == 0x05)) break;
|
|
|
|
/* FALLTHRU */
|
|
|
|
case 0x02:
|
|
|
|
/* CI */
|
|
|
|
value = tvb_get_ntohs(tvb, curr_offset);
|
|
|
|
proto_tree_add_uint(tree, hf_gsm_a_cell_ci, tvb,
|
|
curr_offset, 2, value);
|
|
|
|
curr_offset += 2;
|
|
|
|
if (add_string[0] == '\0')
|
|
{
|
|
sprintf(add_string, " - CI (%u)", value);
|
|
}
|
|
else
|
|
{
|
|
sprintf(add_string, "%s/CI (%u)", add_string, value);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(tree, tvb, curr_offset, len - 1,
|
|
"Cell ID - Unknown format");
|
|
|
|
curr_offset += (len - 1);
|
|
break;
|
|
}
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
static guint8
|
|
be_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 disc;
|
|
guint32 curr_offset;
|
|
const gchar *str = NULL;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
disc = oct & 0x0f;
|
|
|
|
if (disc >= (gint) NUM_CELL_DISC_STR)
|
|
{
|
|
str = "Unknown";
|
|
}
|
|
else
|
|
{
|
|
str = cell_disc_str[disc];
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Cell Identification Discriminator: (%u) %s",
|
|
a_bigbuf,
|
|
disc,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
curr_offset +=
|
|
be_cell_id_aux(tvb, tree, curr_offset, len - (curr_offset - offset), add_string, disc);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.18
|
|
*/
|
|
static guint8
|
|
be_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Preemption Capability Indicator (PCI): this allocation request %s preempt an existing connection",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "may" : "shall not");
|
|
|
|
switch ((oct & 0x3c) >> 2)
|
|
{
|
|
case 0x00: str = "Spare"; break;
|
|
case 0x0f: str = "priority not used"; break;
|
|
default:
|
|
str = "1 is highest";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x3c, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Priority Level: (%u) %s",
|
|
a_bigbuf,
|
|
(oct & 0x3c) >> 2,
|
|
str);
|
|
|
|
sprintf(add_string, " - (%u)", (oct & 0x3c) >> 2);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Queuing Allowed Indicator (QA): queuing %sallowed",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Preemption Vulnerability Indicator (PVI): this connection %s be preempted by another allocation request",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "might" : "shall not");
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.24
|
|
*/
|
|
static guint8
|
|
be_l3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
tvbuff_t *l3_tvb;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"Layer 3 Information value");
|
|
|
|
/*
|
|
* dissect the embedded DTAP message
|
|
*/
|
|
l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
|
|
|
|
call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.25
|
|
*/
|
|
static guint8
|
|
be_dlci(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
proto_item *item = NULL;
|
|
proto_tree *subtree = NULL;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
item =
|
|
proto_tree_add_text(tree, tvb, curr_offset, 1,
|
|
"Data Link Connection Identifier");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_dlci);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
proto_tree_add_uint(subtree, hf_gsm_a_dlci_cc, tvb, curr_offset, 1, oct);
|
|
proto_tree_add_uint(subtree, hf_gsm_a_dlci_spare, tvb, curr_offset, 1, oct);
|
|
proto_tree_add_uint(subtree, hf_gsm_a_dlci_sapi, tvb, curr_offset, 1, oct);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.26
|
|
*/
|
|
static guint8
|
|
be_down_dtx_flag(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : BSS is %s to activate DTX in the downlink direction",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "forbidden" : "allowed");
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.27
|
|
*/
|
|
static guint8
|
|
be_cell_id_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 consumed;
|
|
guint8 disc;
|
|
guint8 num_cells;
|
|
guint32 curr_offset;
|
|
proto_item *item = NULL;
|
|
proto_tree *subtree = NULL;
|
|
const gchar *str = NULL;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
disc = oct & 0x0f;
|
|
|
|
if (disc >= (gint) NUM_CELL_DISC_STR)
|
|
{
|
|
str = "Unknown";
|
|
}
|
|
else
|
|
{
|
|
str = cell_disc_str[disc];
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Cell Identification Discriminator: (%u) %s",
|
|
a_bigbuf,
|
|
disc,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
num_cells = 0;
|
|
do
|
|
{
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, -1,
|
|
"Cell %u",
|
|
num_cells + 1);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_cell_list);
|
|
|
|
add_string[0] = '\0';
|
|
consumed =
|
|
be_cell_id_aux(tvb, subtree, curr_offset, len - (curr_offset - offset), add_string, disc);
|
|
|
|
if (add_string[0] != '\0')
|
|
{
|
|
proto_item_append_text(item, add_string);
|
|
}
|
|
|
|
proto_item_set_len(item, consumed);
|
|
|
|
curr_offset += consumed;
|
|
|
|
num_cells++;
|
|
}
|
|
while ((len - (curr_offset - offset)) > 0);
|
|
|
|
sprintf(add_string, " - %u cell%s",
|
|
num_cells, plurality(num_cells, "", "s"));
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.33
|
|
*/
|
|
static guint8
|
|
be_chosen_chan(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch ((oct & 0xf0) >> 4)
|
|
{
|
|
case 0: str = "No channel mode indication"; break;
|
|
case 9: str = "Speech (full rate or half rate)"; break;
|
|
case 14: str = "Data, 14.5 kbit/s radio interface rate"; break;
|
|
case 11: str = "Data, 12.0 kbit/s radio interface rate"; break;
|
|
case 12: str = "Data, 6.0 kbit/s radio interface rate"; break;
|
|
case 13: str = "Data, 3.6 kbit/s radio interface rate"; break;
|
|
case 8: str = "Signalling only"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Channel mode: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "None"; break;
|
|
case 1: str = "SDCCH"; break;
|
|
case 8: str = "1 Full rate TCH"; break;
|
|
case 9: str = "1 Half rate TCH"; break;
|
|
case 10: str = "2 Full Rate TCHs"; break;
|
|
case 11: str = "3 Full Rate TCHs"; break;
|
|
case 12: str = "4 Full Rate TCHs"; break;
|
|
case 13: str = "5 Full Rate TCHs"; break;
|
|
case 14: str = "6 Full Rate TCHs"; break;
|
|
case 15: str = "7 Full Rate TCHs"; break;
|
|
case 4: str = "8 Full Rate TCHs"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Channel: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.34
|
|
*/
|
|
static guint8
|
|
be_ciph_resp_mode(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : IMEISV must %sbe included by the mobile station",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "" : "not ");
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.35
|
|
*/
|
|
static guint8
|
|
be_l3_msg(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
tvbuff_t *l3_tvb;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"Layer 3 Message Contents");
|
|
|
|
/*
|
|
* dissect the embedded DTAP message
|
|
*/
|
|
l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
|
|
|
|
call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.43
|
|
*/
|
|
static guint8
|
|
be_for_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 1: str = "forward to subsequent BSS, no trace at MSC"; break;
|
|
case 2: str = "forward to subsequent BSS, and trace at MSC"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.44
|
|
*/
|
|
static guint8
|
|
be_chosen_enc_alg(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x01: str = "No encryption used"; break;
|
|
case 0x02: str = "GSM A5/1"; break;
|
|
case 0x03: str = "GSM A5/2"; break;
|
|
case 0x04: str = "GSM A5/3"; break;
|
|
case 0x05: str = "GSM A5/4"; break;
|
|
case 0x06: str = "GSM A5/5"; break;
|
|
case 0x07: str = "GSM A5/6"; break;
|
|
case 0x08: str = "GSM A5/7"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Algorithm Identifier: %s",
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - %s", str);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.45
|
|
*/
|
|
static guint8
|
|
be_cct_pool(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (oct <= 32)
|
|
{
|
|
str = "";
|
|
}
|
|
else if ((oct >= 0x80) && (oct <= 0x8f))
|
|
{
|
|
str = ", for national/local use";
|
|
}
|
|
else
|
|
{
|
|
str = ", reserved for future international use";
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Circuit pool number: %u%s",
|
|
oct,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%u)", oct);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.49
|
|
*/
|
|
static guint8
|
|
be_curr_chan_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch ((oct & 0xf0) >> 4)
|
|
{
|
|
case 0x00: str = "Signalling only"; break;
|
|
case 0x01: str = "Speech (full rate or half rate)"; break;
|
|
case 0x06: str = "Data, 14.5 kbit/s radio interface rate"; break;
|
|
case 0x03: str = "Data, 12.0 kbit/s radio interface rate"; break;
|
|
case 0x04: str = "Data, 6.0 kbit/s radio interface rate"; break;
|
|
case 0x05: str = "Data, 3.6 kbit/s radio interface rate"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Channel Mode: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0x01: str = "SDCCH"; break;
|
|
case 0x08: str = "1 Full rate TCH"; break;
|
|
case 0x09: str = "1 Half rate TCH"; break;
|
|
case 0x0a: str = "2 Full Rate TCHs"; break;
|
|
case 0x0b: str = "3 Full Rate TCHs"; break;
|
|
case 0x0c: str = "4 Full Rate TCHs"; break;
|
|
case 0x0d: str = "5 Full Rate TCHs"; break;
|
|
case 0x0e: str = "6 Full Rate TCHs"; break;
|
|
case 0x0f: str = "7 Full Rate TCHs"; break;
|
|
case 0x04: str = "8 Full Rate TCHs"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Channel: (%u) %s",
|
|
a_bigbuf,
|
|
oct & 0x0f,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.50
|
|
*/
|
|
static guint8
|
|
be_que_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : qri: it is recommended %sto allow queuing",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.51
|
|
*/
|
|
static guint8
|
|
be_speech_ver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str = NULL;
|
|
gchar *short_str = NULL;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x7f)
|
|
{
|
|
case 0x01: str = "GSM speech full rate version 1"; short_str = "FR1"; break;
|
|
case 0x11: str = "GSM speech full rate version 2"; short_str = "FR2"; break;
|
|
case 0x21: str = "GSM speech full rate version 3 (AMR)"; short_str = "FR3 (AMR)"; break;
|
|
|
|
case 0x05: str = "GSM speech half rate version 1"; short_str = "HR1"; break;
|
|
case 0x15: str = "GSM speech half rate version 2"; short_str = "HR2"; break;
|
|
case 0x25: str = "GSM speech half rate version 3 (AMR)"; short_str = "HR3 (AMR)"; break;
|
|
|
|
default:
|
|
str = "Reserved";
|
|
short_str = str;
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Speech version identifier: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%s)", short_str);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.2.68
|
|
*/
|
|
static guint8
|
|
be_apdu(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"APDU");
|
|
|
|
/*
|
|
* dissect the embedded APDU message
|
|
* if someone writes a TS 09.31 dissector
|
|
*/
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
/* 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_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_PLMN_LIST, /* PLMN List */
|
|
/* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
|
|
DE_RR_CAUSE, /* RR Cause */
|
|
/* Mobility Management Information Elements 10.5.3 */
|
|
DE_AUTH_PARAM_RAND, /* Authentication Parameter RAND */
|
|
DE_AUTH_PARAM_AUTN, /* Authentication Parameter AUTN (UMTS authentication challenge only) */
|
|
DE_AUTH_RESP_PARAM, /* Authentication Response Parameter */
|
|
DE_AUTH_RESP_PARAM_EXT, /* Authentication Response Parameter (extension) (UMTS authentication challenge only) */
|
|
DE_AUTH_FAIL_PARAM, /* Authentication Failure Parameter (UMTS authentication challenge only) */
|
|
DE_CM_SRVC_TYPE, /* CM Service Type */
|
|
DE_ID_TYPE, /* Identity Type */
|
|
DE_LOC_UPD_TYPE, /* Location Updating Type */
|
|
DE_NETWORK_NAME, /* Network Name */
|
|
DE_REJ_CAUSE, /* Reject Cause */
|
|
DE_FOP, /* Follow-on Proceed */
|
|
DE_TIME_ZONE, /* Time Zone */
|
|
DE_TIME_ZONE_TIME, /* Time Zone and Time */
|
|
DE_CTS_PERM, /* CTS Permission */
|
|
DE_LSA_ID, /* LSA Identifier */
|
|
DE_DAY_SAVING_TIME, /* Daylight Saving Time */
|
|
/* Call Control Information Elements 10.5.4 */
|
|
DE_AUX_STATES, /* Auxiliary States */
|
|
DE_BEARER_CAP, /* Bearer Capability */
|
|
DE_CC_CAP, /* Call Control Capabilities */
|
|
DE_CALL_STATE, /* Call State */
|
|
DE_CLD_PARTY_BCD_NUM, /* Called Party BCD Number */
|
|
DE_CLD_PARTY_SUB_ADDR, /* Called Party Subaddress */
|
|
DE_CLG_PARTY_BCD_NUM, /* Calling Party BCD Number */
|
|
DE_CLG_PARTY_SUB_ADDR, /* Calling Party Subaddress */
|
|
DE_CAUSE, /* Cause */
|
|
DE_CLIR_SUP, /* CLIR Suppression */
|
|
DE_CLIR_INV, /* CLIR Invocation */
|
|
DE_CONGESTION, /* Congestion Level */
|
|
DE_CONN_NUM, /* Connected Number */
|
|
DE_CONN_SUB_ADDR, /* Connected Subaddress */
|
|
DE_FACILITY, /* Facility */
|
|
DE_HLC, /* High Layer Compatibility */
|
|
DE_KEYPAD_FACILITY, /* Keypad Facility */
|
|
DE_LLC, /* Low Layer Compatibility */
|
|
DE_MORE_DATA, /* More Data */
|
|
DE_NOT_IND, /* Notification Indicator */
|
|
DE_PROG_IND, /* Progress Indicator */
|
|
DE_RECALL_TYPE, /* Recall type $(CCBS)$ */
|
|
DE_RED_PARTY_BCD_NUM, /* Redirecting Party BCD Number */
|
|
DE_RED_PARTY_SUB_ADDR, /* Redirecting Party Subaddress */
|
|
DE_REPEAT_IND, /* Repeat Indicator */
|
|
DE_REV_CALL_SETUP_DIR, /* Reverse Call Setup Direction */
|
|
DE_SETUP_CONTAINER, /* SETUP Container $(CCBS)$ */
|
|
DE_SIGNAL, /* Signal */
|
|
DE_SS_VER_IND, /* SS Version Indicator */
|
|
DE_USER_USER, /* User-user */
|
|
DE_ALERT_PATTERN, /* Alerting Pattern $(NIA)$ */
|
|
DE_ALLOWED_ACTIONS, /* Allowed Actions $(CCBS)$ */
|
|
DE_SI, /* Stream Identifier */
|
|
DE_NET_CC_CAP, /* Network Call Control Capabilities */
|
|
DE_CAUSE_NO_CLI, /* Cause of No CLI */
|
|
DE_IMM_MOD_IND, /* Immediate Modification Indicator */
|
|
DE_SUP_CODEC_LIST, /* Supported Codec List */
|
|
DE_SRVC_CAT, /* Service Category */
|
|
/* GPRS Mobility Management Information Elements 10.5.5 */
|
|
DE_ATTACH_RES, /* Attach Result */
|
|
DE_ATTACH_TYPE, /* Attach Type */
|
|
DE_TMSI_STAT, /* TMSI Status */
|
|
DE_DETACH_TYPE, /* Detach Type */
|
|
DE_DRX_PARAM, /* DRX Parameter */
|
|
DE_FORCE_TO_STAND, /* Force to Standby */
|
|
DE_P_TMSI_SIG, /* P-TMSI Signature */
|
|
DE_P_TMSI_SIG_2, /* P-TMSI Signature 2 */
|
|
DE_ID_TYPE_2, /* Identity Type 2 */
|
|
DE_IMEISV_REQ, /* IMEISV Request */
|
|
DE_REC_N_PDU_NUM_LIST, /* Receive N-PDU Numbers List */
|
|
DE_MS_NET_CAP, /* MS Network Capability */
|
|
DE_MS_RAD_ACC_CAP, /* MS Radio Access Capability */
|
|
DE_GMM_CAUSE, /* GMM Cause */
|
|
DE_RAI, /* Routing Area Identification */
|
|
DE_UPD_RES, /* Update Result */
|
|
DE_AC_REF_NUM, /* A&C Reference Number */
|
|
DE_SRVC_TYPE, /* Service Type */
|
|
DE_CELL_NOT, /* Cell Notification */
|
|
DE_NET_FEAT_SUP, /* Network Feature Support */
|
|
/* Short Message Service Information Elements [5] 8.1.4 */
|
|
DE_CP_USER_DATA, /* CP-User Data */
|
|
DE_CP_CAUSE, /* CP-Cause */
|
|
/* Short Message Service Information Elements [5] 8.2 */
|
|
DE_RP_MESSAGE_REF, /* RP-Message Reference */
|
|
DE_RP_ORIG_ADDR, /* RP-Origination Address */
|
|
DE_RP_DEST_ADDR, /* RP-Destination Address */
|
|
DE_RP_USER_DATA, /* RP-User Data */
|
|
DE_RP_CAUSE, /* RP-Cause */
|
|
/* Session Management Information Elements 10.5.6 */
|
|
DE_ACC_POINT_NAME, /* Access Point Name */
|
|
DE_NET_SAPI, /* Network Service Access Point Identifier */
|
|
DE_PRO_CONF_OPT, /* Protocol Configuration Options */
|
|
DE_PD_PRO_ADDR, /* Packet Data Protocol Address */
|
|
DE_QOS, /* Quality Of Service */
|
|
DE_SM_CAUSE, /* SM Cause */
|
|
DE_LINKED_TI, /* Linked TI */
|
|
DE_LLC_SAPI, /* LLC Service Access Point Identifier */
|
|
DE_TEAR_DOWN_IND, /* Tear Down Indicator */
|
|
DE_PACKET_FLOW_ID, /* Packet Flow Identifier */
|
|
DE_TRAFFIC_FLOW_TEMPLATE, /* Traffic Flow Template */
|
|
/* GPRS Common Information Elements 10.5.7 */
|
|
DE_PDP_CONTEXT_STAT, /* PDP Context Status */
|
|
DE_RAD_PRIO, /* Radio Priority */
|
|
DE_GPRS_TIMER, /* GPRS Timer */
|
|
DE_GPRS_TIMER_2, /* GPRS Timer 2 */
|
|
DE_NONE /* NONE */
|
|
}
|
|
dtap_elem_idx_t;
|
|
|
|
#define NUM_GSM_DTAP_ELEM (sizeof(gsm_dtap_elem_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_elem[NUM_GSM_DTAP_ELEM];
|
|
|
|
/*
|
|
* [3] 10.5.1.1
|
|
*/
|
|
static guint8
|
|
de_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
curr_offset = offset;
|
|
|
|
curr_offset +=
|
|
be_cell_id_aux(tvb, tree, offset, len, add_string, 0x02);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.3
|
|
*/
|
|
static guint8
|
|
de_lai(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 octs[3];
|
|
guint16 value;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar mcc[4];
|
|
gchar mnc[4];
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
octs[0] = tvb_get_guint8(tvb, curr_offset);
|
|
octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
|
|
octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
|
|
|
|
mcc_mnc_aux(octs, mcc, mnc);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 5,
|
|
gsm_dtap_elem_strings[DE_LAI].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_LAI]);
|
|
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 3,
|
|
"Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
|
|
mcc,
|
|
mnc);
|
|
|
|
curr_offset += 3;
|
|
|
|
value = tvb_get_ntohs(tvb, curr_offset);
|
|
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 2,
|
|
"Location Area Code (LAC): 0x%04x (%u)",
|
|
value,
|
|
value);
|
|
|
|
proto_item_append_text(item, " - LAC (0x%04x)", value);
|
|
|
|
curr_offset += 2;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.4
|
|
*/
|
|
static guint8
|
|
de_mid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
guint8 *poctets;
|
|
guint32 value;
|
|
gboolean odd;
|
|
|
|
curr_offset = offset;
|
|
odd = FALSE;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0: /* No Identity */
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Unused",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even Indicator: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "ODD" : "EVEN");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of Identity: No Identity Code",
|
|
a_bigbuf);
|
|
|
|
strcpy(add_string, " - No Identity Code");
|
|
|
|
curr_offset++;
|
|
|
|
if (len > 1)
|
|
{
|
|
proto_tree_add_text(tree, tvb, curr_offset, len - 1,
|
|
"Format not supported");
|
|
}
|
|
|
|
curr_offset += len - 1;
|
|
break;
|
|
|
|
case 3: /* IMEISV */
|
|
|
|
/* FALLTHRU */
|
|
|
|
case 1: /* IMSI */
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Identity Digit 1: %c",
|
|
a_bigbuf,
|
|
Dgt_msid.out[(oct & 0xf0) >> 4]);
|
|
|
|
odd = oct & 0x08;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even Indicator: %s",
|
|
a_bigbuf,
|
|
odd ? "ODD" : "EVEN");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of Identity: %s",
|
|
a_bigbuf,
|
|
((oct & 0x07) == 3) ? "IMEISV" : "IMSI");
|
|
|
|
a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
|
|
curr_offset++;
|
|
|
|
poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
|
|
|
|
my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
|
|
&Dgt_msid);
|
|
g_free(poctets);
|
|
|
|
proto_tree_add_string_format(tree,
|
|
((oct & 0x07) == 3) ? hf_gsm_a_imeisv : hf_gsm_a_imsi,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
a_bigbuf,
|
|
"BCD Digits: %s",
|
|
a_bigbuf);
|
|
|
|
sprintf(add_string, " - %s (%s)",
|
|
((oct & 0x07) == 3) ? "IMEISV" : "IMSI",
|
|
a_bigbuf);
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
if (!odd)
|
|
{
|
|
oct = tvb_get_guint8(tvb, curr_offset - 1);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset - 1, 1,
|
|
"%s : Filler",
|
|
a_bigbuf);
|
|
}
|
|
break;
|
|
|
|
case 2: /* IMEI */
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Identity Digit 1: %c",
|
|
a_bigbuf,
|
|
Dgt_msid.out[(oct & 0xf0) >> 4]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even Indicator: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "ODD" : "EVEN");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of Identity: IMEI",
|
|
a_bigbuf);
|
|
|
|
a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
|
|
curr_offset++;
|
|
|
|
poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
|
|
|
|
my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
|
|
&Dgt_msid);
|
|
g_free(poctets);
|
|
|
|
proto_tree_add_string_format(tree,
|
|
hf_gsm_a_imei,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
a_bigbuf,
|
|
"BCD Digits: %s",
|
|
a_bigbuf);
|
|
|
|
sprintf(add_string, " - IMEI (%s)", a_bigbuf);
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
break;
|
|
|
|
case 4: /* TMSI/P-TMSI */
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Unused",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even Indicator: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "ODD" : "EVEN");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of Identity: TMSI/P-TMSI",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
value = tvb_get_ntohl(tvb, curr_offset);
|
|
|
|
proto_tree_add_uint(tree, hf_gsm_a_tmsi,
|
|
tvb, curr_offset, 4,
|
|
value);
|
|
|
|
sprintf(add_string, " - TMSI/P-TMSI (0x%04x)", value);
|
|
|
|
curr_offset += 4;
|
|
break;
|
|
|
|
default: /* Reserved */
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"Format Unknown");
|
|
|
|
strcpy(add_string, " - Format Unknown");
|
|
|
|
curr_offset += len;
|
|
break;
|
|
}
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.5
|
|
*/
|
|
static guint8
|
|
de_ms_cm_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_MS_CM_1].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_MS_CM_1]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0: str = "Reserved for GSM phase 1"; break;
|
|
case 1: str = "Used by GSM phase 2 mobile stations"; break;
|
|
case 2: str = "Used by mobile stations supporting R99 or later versions of the protocol"; break;
|
|
default:
|
|
str = "Reserved for future use";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Revision Level: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : ES IND: Controlled Early Classmark Sending is %simplemented",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : A5/1: encryption algorithm A5/1 %savailable",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "not " : "");
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0: str = "Class 1"; break;
|
|
case 1: str = "Class 2"; break;
|
|
case 2: str = "Class 3"; break;
|
|
case 3: str = "Class 4"; break;
|
|
case 4: str = "Class 5"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : RF power capability: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.6
|
|
*/
|
|
static guint8
|
|
de_ms_cm_2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0: str = "Reserved for GSM phase 1"; break;
|
|
case 1: str = "Used by GSM phase 2 mobile stations"; break;
|
|
case 2: str = "Used by mobile stations supporting R99 or later versions of the protocol"; break;
|
|
default:
|
|
str = "Reserved for future use";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Revision Level: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : ES IND: Controlled Early Classmark Sending is %simplemented",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : A5/1: encryption algorithm A5/1 %savailable",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "not " : "");
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0: str = "Class 1"; break;
|
|
case 1: str = "Class 2"; break;
|
|
case 2: str = "Class 3"; break;
|
|
case 3: str = "Class 4"; break;
|
|
case 4: str = "Class 5"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : RF power capability: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : PS capability (pseudo-synchronization capability): %spresent",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "" : "not ");
|
|
|
|
switch ((oct & 0x30) >> 4)
|
|
{
|
|
case 0: str = "Default value for phase 1"; break;
|
|
case 1: str = "Capability of handling of ellipsis notation and phase 2 error handling"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : SS Screening Indicator: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : SM capability (MT SMS pt to pt capability): MS %s MT SMS",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "supports" : "does not support");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : VBS notification reception: %s",
|
|
a_bigbuf,
|
|
(oct & 0x04) ? "VBS capability and notifications wanted" :
|
|
"no VBS capability or no notifications wanted");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : VGCS notification reception: %s",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "VGCS capability and notifications wanted" :
|
|
"no VGCS capability or no notifications wanted");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : FC Frequency Capability",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : CM3: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ?
|
|
"The MS supports options that are indicated in classmark 3 IE" :
|
|
"The MS does not support any options that are indicated in CM3");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : LCS VA capability: LCS value added location request notification capability %ssupported",
|
|
a_bigbuf,
|
|
(oct & 0x20) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : UCS2 treatment: %s",
|
|
a_bigbuf,
|
|
(oct & 0x10) ?
|
|
"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 (defined in 3GPP TS 03.38) over UCS2");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : SoLSA: the ME %s SoLSA",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "supports" : "does not support");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : CMSP (CM Service Prompt): %s",
|
|
a_bigbuf,
|
|
(oct & 0x04) ?
|
|
"'Network initiated MO CM connection request' supported for at least one CM protocol" :
|
|
"'Network initiated MO CM connection request' not supported");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : A5/3: encryption algorithm A5/3 %savailable",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : A5/2: encryption algorithm A5/2 %savailable",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "" : "not ");
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.9
|
|
*/
|
|
static guint8
|
|
de_d_gb_call_ref(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 value;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
value = tvb_get_ntohl(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0xffffffe0, 32);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 4,
|
|
"%s : Group or Broadcast call reference: %u (0x%04x)",
|
|
a_bigbuf,
|
|
(value & 0xffffffe0) >> 5,
|
|
(value & 0xffffffe0) >> 5);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0x00000010, 32);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 4,
|
|
"%s : SF Service Flag: %s",
|
|
a_bigbuf,
|
|
(value & 0x00000010) ?
|
|
"VGCS (Group call reference)" : "VBS (Broadcast call reference)");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0x00000008, 32);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 4,
|
|
"%s : AF Acknowledgement Flag: acknowledgment is %srequired",
|
|
a_bigbuf,
|
|
(value & 0x00000008) ? "" : "not ");
|
|
|
|
switch (value & 0x00000007)
|
|
{
|
|
case 1: str = "call priority level 4"; break;
|
|
case 2: str = "call priority level 3"; break;
|
|
case 3: str = "call priority level 2"; break;
|
|
case 4: str = "call priority level 1"; break;
|
|
case 5: str = "call priority level 0"; break;
|
|
case 6: str = "call priority level B"; break;
|
|
case 7: str = "call priority level A"; break;
|
|
default:
|
|
str = "no priority applied";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, value, 0x00000007, 32);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 4,
|
|
"%s : Call Priority: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset += 4;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 1,
|
|
"%s : Ciphering Information",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree, tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.10a
|
|
*/
|
|
static guint8
|
|
de_pd_sapi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_PD_SAPI].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_PD_SAPI]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
|
|
proto_tree_add_text(subtree, tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x30) >> 4)
|
|
{
|
|
case 0: str = "SAPI 0"; break;
|
|
case 3: str = "SAPI 3"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
|
|
proto_tree_add_text(subtree, tvb, curr_offset, 1,
|
|
"%s : SAPI (Sevice Access Point Identifier): %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree, tvb, curr_offset, 1,
|
|
"%s : PD (Protocol Discriminator): %s",
|
|
a_bigbuf,
|
|
gsm_a_pd_str[oct & 0x0f]);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.11
|
|
*/
|
|
static guint8
|
|
de_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 1: str = "Call priority level 4"; break;
|
|
case 2: str = "Call priority level 3"; break;
|
|
case 3: str = "Call priority level 2"; break;
|
|
case 4: str = "Call priority level 1"; break;
|
|
case 5: str = "Call priority level 0"; break;
|
|
case 6: str = "Call priority level B"; break;
|
|
case 7: str = "Call priority level A"; break;
|
|
default:
|
|
str = "No priority applied";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.1.13
|
|
*/
|
|
static guint8
|
|
de_plmn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 octs[3];
|
|
guint32 curr_offset;
|
|
gchar mcc[4];
|
|
gchar mnc[4];
|
|
guint8 num_plmn;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
num_plmn = 0;
|
|
while ((len - (curr_offset - offset)) >= 3)
|
|
{
|
|
octs[0] = tvb_get_guint8(tvb, curr_offset);
|
|
octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
|
|
octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
|
|
|
|
mcc_mnc_aux(octs, mcc, mnc);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 3,
|
|
"PLMN[%u] Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
|
|
num_plmn + 1,
|
|
mcc,
|
|
mnc);
|
|
|
|
curr_offset += 3;
|
|
|
|
num_plmn++;
|
|
}
|
|
|
|
sprintf(add_string, " - %u PLMN%s",
|
|
num_plmn, plurality(num_plmn, "", "s"));
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.2.31
|
|
*/
|
|
static guint8
|
|
de_rr_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x00: str = "Normal event"; break;
|
|
case 0x01: str = "Abnormal release, unspecified"; break;
|
|
case 0x02: str = "Abnormal release, channel unacceptable"; break;
|
|
case 0x03: str = "Abnormal release, timer expired"; break;
|
|
case 0x04: str = "Abnormal release, no activity on the radio path"; break;
|
|
case 0x05: str = "Preemptive release"; break;
|
|
case 0x08: str = "Handover impossible, timing advance out of range"; break;
|
|
case 0x09: str = "Channel mode unacceptable"; break;
|
|
case 0x0a: str = "Frequency not implemented"; break;
|
|
case 0x41: str = "Call already cleared"; break;
|
|
case 0x5f: str = "Semantically incorrect message"; break;
|
|
case 0x60: str = "Invalid mandatory information"; break;
|
|
case 0x61: str = "Message type non-existent or not implemented"; break;
|
|
case 0x62: str = "Message type not compatible with protocol state"; break;
|
|
case 0x64: str = "Conditional IE error"; break;
|
|
case 0x65: str = "No cell allocation available"; break;
|
|
case 0x6f: str = "Protocol error unspecified"; break;
|
|
default:
|
|
str = "Reserved, treat as Normal event";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"RR Cause value: 0x%02x (%u) %s",
|
|
oct,
|
|
oct,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.1
|
|
*/
|
|
static guint8
|
|
de_auth_param_rand(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
/*
|
|
* 12 octets == 128 bits
|
|
*/
|
|
#define AUTH_PARAM_RAND_LEN 12
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, AUTH_PARAM_RAND_LEN,
|
|
"RAND value");
|
|
|
|
curr_offset += AUTH_PARAM_RAND_LEN;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.1.1
|
|
*/
|
|
static guint8
|
|
de_auth_param_autn(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len,
|
|
"AUTN value");
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.2
|
|
*/
|
|
static guint8
|
|
de_auth_resp_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
/*
|
|
* 4 octets == 32 bits
|
|
*/
|
|
#define AUTH_PARAM_RESP_LEN 4
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, AUTH_PARAM_RESP_LEN,
|
|
"SRES value");
|
|
|
|
curr_offset += AUTH_PARAM_RESP_LEN;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.2.1
|
|
*/
|
|
static guint8
|
|
de_auth_resp_param_ext(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len,
|
|
"RES (extension) value");
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.2.2
|
|
*/
|
|
static guint8
|
|
de_auth_fail_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len,
|
|
"AUTS value");
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.5a
|
|
*/
|
|
static guint8
|
|
de_network_name(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0x00: str = "Cell Broadcast data coding scheme, GSM default alphabet, language unspecified, defined in 3GPP TS 03.38"; break;
|
|
case 0x01: str = "UCS2 (16 bit)"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding Scheme: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Add CI: The MS should %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ?
|
|
"add the letters for the Country's Initials and a separator (e.g. a space) to the text string" :
|
|
"The MS should not add the letters for the Country's Initials to the text string");
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 1: str = "bit 8 is spare and set to '0' in octet n"; break;
|
|
case 2: str = "bits 7 and 8 are spare and set to '0' in octet n"; break;
|
|
case 3: str = "bits 6 to 8(inclusive) are spare and set to '0' in octet n"; break;
|
|
case 4: str = "bits 5 to 8(inclusive) are spare and set to '0' in octet n"; break;
|
|
case 5: str = "bits 4 to 8(inclusive) are spare and set to '0' in octet n"; break;
|
|
case 6: str = "bits 3 to 8(inclusive) are spare and set to '0' in octet n"; break;
|
|
case 7: str = "bits 2 to 8(inclusive) are spare and set to '0' in octet n"; break;
|
|
default:
|
|
str = "this field carries no information about the number of spare bits in octet n";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Number of spare bits in last octet: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - 1,
|
|
"Text string encoded according to Coding Scheme");
|
|
|
|
curr_offset += len - 1;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.6
|
|
*/
|
|
static guint8
|
|
de_rej_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct)
|
|
{
|
|
case 0x02: str = "IMSI unknown in HLR"; break;
|
|
case 0x03: str = "Illegal MS"; break;
|
|
case 0x04: str = "IMSI unknown in VLR"; break;
|
|
case 0x05: str = "IMEI not accepted"; break;
|
|
case 0x06: str = "Illegal ME"; break;
|
|
case 0x0b: str = "PLMN not allowed"; break;
|
|
case 0x0c: str = "Location Area not allowed"; break;
|
|
case 0x0d: str = "Roaming not allowed in this location area"; break;
|
|
case 0x0f: str = "No Suitable Cells In Location Area"; break;
|
|
case 0x11: str = "Network failure"; break;
|
|
case 0x14: str = "MAC failure"; break;
|
|
case 0x15: str = "Synch failure"; break;
|
|
case 0x16: str = "Congestion"; break;
|
|
case 0x17: str = "GSM authentication unacceptable"; break;
|
|
case 0x20: str = "Service option not supported"; break;
|
|
case 0x21: str = "Requested service option not subscribed"; break;
|
|
case 0x22: str = "Service option temporarily out of order"; break;
|
|
case 0x26: str = "Call cannot be identified"; break;
|
|
case 0x5f: str = "Semantically incorrect message"; break;
|
|
case 0x60: str = "Invalid mandatory information"; break;
|
|
case 0x61: str = "Message type non-existent or not implemented"; break;
|
|
case 0x62: str = "Message type not compatible with the protocol state"; break;
|
|
case 0x63: str = "Information element non-existent or not implemented"; break;
|
|
case 0x64: str = "Conditional IE error"; break;
|
|
case 0x65: str = "Message not compatible with the protocol state"; break;
|
|
case 0x6f: str = "Protocol error, unspecified"; break;
|
|
default:
|
|
switch (is_uplink)
|
|
{
|
|
case IS_UPLINK_FALSE:
|
|
str = "Service option temporarily out of order";
|
|
break;
|
|
default:
|
|
str = "Protocol error, unspecified";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Reject Cause value: 0x%02x (%u) %s",
|
|
oct,
|
|
oct,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.8
|
|
*/
|
|
static guint8
|
|
de_time_zone(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Time Zone: 0x%02x (%u)",
|
|
oct,
|
|
oct);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.9
|
|
*/
|
|
static guint8
|
|
de_time_zone_time(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct, oct2, oct3;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
oct2 = tvb_get_guint8(tvb, curr_offset+1);
|
|
oct3 = tvb_get_guint8(tvb, curr_offset+2);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 3,
|
|
"Year %u%u, Month %u%u, Day %u%u",
|
|
oct & 0x0f,
|
|
(oct & 0xf0) >> 4,
|
|
oct2 & 0x0f,
|
|
(oct2 & 0xf0) >> 4,
|
|
oct3 & 0x0f,
|
|
(oct3 & 0xf0) >> 4);
|
|
|
|
curr_offset += 3;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
oct2 = tvb_get_guint8(tvb, curr_offset+1);
|
|
oct3 = tvb_get_guint8(tvb, curr_offset+2);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 3,
|
|
"Hour %u%u, Minutes %u%u, Seconds %u%u",
|
|
oct & 0x0f,
|
|
(oct & 0xf0) >> 4,
|
|
oct2 & 0x0f,
|
|
(oct2 & 0xf0) >> 4,
|
|
oct3 & 0x0f,
|
|
(oct3 & 0xf0) >> 4);
|
|
|
|
curr_offset += 3;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Time Zone: 0x%02x (%u)",
|
|
oct,
|
|
oct);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.11
|
|
*/
|
|
static guint8
|
|
de_lsa_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len,
|
|
"LSA ID");
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.3.12
|
|
*/
|
|
static guint8
|
|
de_day_saving_time(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x03)
|
|
{
|
|
case 0: str = "No adjustment for Daylight Saving Time"; break;
|
|
case 1: str = "+1 hour adjustment for Daylight Saving Time"; break;
|
|
case 2: str = "+2 hours adjustment for Daylight Saving Time"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.4
|
|
*/
|
|
static guint8
|
|
de_aux_states(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x0c) >> 2)
|
|
{
|
|
case 0: str = "Idle"; break;
|
|
case 1: str = "Hold request"; break;
|
|
case 2: str = "Call held"; break;
|
|
default:
|
|
str = "Retrieve request";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Hold auxiliary state: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x03)
|
|
{
|
|
case 0: str = "Idle"; break;
|
|
case 1: str = "MPTY request"; break;
|
|
case 2: str = "Call in MPTY"; break;
|
|
default:
|
|
str = "Split request";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Multi party auxiliary state: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.5
|
|
*/
|
|
static guint8
|
|
de_bearer_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 itc;
|
|
gboolean extended;
|
|
guint32 curr_offset;
|
|
guint32 saved_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
#define DE_BC_ITC_SPEECH 0x00
|
|
#define DE_BC_ITC_UDI 0x01
|
|
#define DE_BC_ITC_EX_PLMN 0x02
|
|
#define DE_BC_ITC_FASC_G3 0x03
|
|
#define DE_BC_ITC_OTHER_ITC 0x05
|
|
#define DE_BC_ITC_RSVD_NET 0x07
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
/* octet 3 */
|
|
|
|
/*
|
|
* warning, bearer cap uses extended values that
|
|
* are reversed from other parameters!
|
|
*/
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
itc = oct & 0x07;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
switch (is_uplink)
|
|
{
|
|
case IS_UPLINK_FALSE:
|
|
str = "Spare";
|
|
break;
|
|
|
|
case IS_UPLINK_TRUE:
|
|
/*
|
|
* depends on Information transfer capability
|
|
*/
|
|
switch (itc)
|
|
{
|
|
case DE_BC_ITC_SPEECH:
|
|
if (extended)
|
|
{
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 1: str = "MS supports at least full rate speech version 1 but does not support half rate speech version 1"; break;
|
|
case 2: str = "MS supports at least full rate speech version 1 and half rate speech version 1. MS has a greater preference for half rate speech version 1 than for full rate speech version 1"; break;
|
|
case 3: str = "MS supports at least full rate speech version 1 and half rate speech version 1. MS has a greater preference for full rate speech version 1 than for half rate speech version 1"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 1: str = "Full rate support only MS/fullrate speech version 1 supported"; break;
|
|
case 2: str = "Dual rate support MS/half rate speech version 1 preferred, full rate speech version 1 also supported"; break;
|
|
case 3: str = "Dual rate support MS/full rate speech version 1 preferred, half rate speech version 1 also supported"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 1: str = "Full rate support only MS"; break;
|
|
case 2: str = "Dual rate support MS/half rate preferred"; break;
|
|
case 3: str = "Dual rate support MS/full rate preferred"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
str = "(dissect problem)";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Radio channel requirement: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding standard: %s",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "reserved" : "GSM standardized coding");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Transfer mode: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "packet" : "circuit");
|
|
|
|
switch (itc)
|
|
{
|
|
case DE_BC_ITC_SPEECH: str = "Speech"; break;
|
|
case DE_BC_ITC_UDI: str = "Unrestricted digital information"; break;
|
|
case DE_BC_ITC_EX_PLMN: str = "3.1 kHz audio, ex PLMN"; break;
|
|
case DE_BC_ITC_FASC_G3: str = "Facsimile group 3"; break;
|
|
case DE_BC_ITC_OTHER_ITC: str = "Other ITC (See Octet 5a)"; break;
|
|
case DE_BC_ITC_RSVD_NET: str = "Reserved, to be used in the network"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Information transfer capability: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
sprintf(add_string, " - (%s)", str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
switch (itc)
|
|
{
|
|
case DE_BC_ITC_SPEECH:
|
|
/* octets 3a */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, -1,
|
|
"Octets 3a - Speech Versions");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_3a);
|
|
|
|
saved_offset = curr_offset;
|
|
|
|
do
|
|
{
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding: octet used for %s",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "other extension of octet 3" :
|
|
"extension of information transfer capability");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "GSM full rate speech version 1"; break;
|
|
case 2: str = "GSM full rate speech version 2"; break;
|
|
case 4: str = "GSM full rate speech version 3"; break;
|
|
case 1: str = "GSM half rate speech version 1"; break;
|
|
case 5: str = "GSM half rate speech version 3"; break;
|
|
default:
|
|
str = "Speech version TBD";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Speech version indication: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
}
|
|
while (extended &&
|
|
((len - (curr_offset - offset)) > 0));
|
|
|
|
proto_item_set_len(item, curr_offset - saved_offset);
|
|
break;
|
|
|
|
default:
|
|
/* octet 4 */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 4");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_4);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Compression: data compression %s%s",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "" : "not ",
|
|
is_uplink ? "allowed" : "possible");
|
|
|
|
switch ((oct & 0x30) >> 4)
|
|
{
|
|
case 0x00: str = "Service data unit integrity"; break;
|
|
case 0x03: str = "Unstructured"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Structure: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Duplex mode: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "Full" : "Half");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Configuration: %s",
|
|
a_bigbuf,
|
|
(oct & 0x04) ? "Reserved" : "Point-to-point");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : NIRR: %s",
|
|
a_bigbuf,
|
|
(oct & 0x02) ?
|
|
"Data up to and including 4.8 kb/s, full rate, non-transparent, 6 kb/s radio interface rate is requested" :
|
|
"No meaning is associated with this value");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Establishment: %s",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "Reserved" : "Demand");
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
/* octet 5 */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 5");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_5);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Access Identity: %s",
|
|
a_bigbuf,
|
|
(oct & 0x60) ? "Reserved" : "Octet identifier");
|
|
|
|
switch ((oct & 0x18) >> 3)
|
|
{
|
|
case 0x00: str = "No rate adaption"; break;
|
|
case 0x01: str = "V.110, I.460/X.30 rate adaptation"; break;
|
|
case 0x02: str = "ITU-T X.31 flag stuffing"; break;
|
|
default:
|
|
str = "Other rate adaption (see octet 5a)"; break;
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Rate Adaption: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0x01: str = "I.440/450"; break;
|
|
case 0x02: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x03: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x04: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x05: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x06: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
default:
|
|
str = "Reserved"; break;
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Signalling Access Protocol: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_6;
|
|
|
|
/* octet 5a */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 5a");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_5a);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Other ITC: %s",
|
|
a_bigbuf,
|
|
(oct & 0x60) ? "Reserved" : "Restricted digital information");
|
|
|
|
switch ((oct & 0x18) >> 3)
|
|
{
|
|
case 0x00: str = "V.120"; break;
|
|
case 0x01: str = "H.223 & H.245"; break;
|
|
case 0x02: str = "PIAFS"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Other Rate Adaption: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_6;
|
|
|
|
/* octet 5b */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 5b");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_5b);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Rate Adaption Header: %sincluded",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Multiple frame establishment support in data link: %s",
|
|
a_bigbuf,
|
|
(oct & 0x20) ? "Supported" : "Not supported, only UI frames allowed");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Mode of operation: %s",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "Protocol sensitive" : "Bit transparent");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Logical link identifier negotiation: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "Full protocol negotiation" : "Default, LLI=256 only");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Assignor/Assignee: Message originator is '%s'",
|
|
a_bigbuf,
|
|
(oct & 0x04) ? "assignor only" : "default assignee");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : In band/Out of band negotiation: Negotiation is done %s",
|
|
a_bigbuf,
|
|
(oct & 0x02) ?
|
|
"with USER INFORMATION messages on a temporary signalling connection" :
|
|
"in-band using logical link zero");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
bc_octet_6:
|
|
|
|
/* octet 6 */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Layer 1 Identity: %s",
|
|
a_bigbuf,
|
|
((oct & 0x60) == 0x20) ? "Octet identifier" : "Reserved");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x1e, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : User information layer 1 protocol: %s",
|
|
a_bigbuf,
|
|
(oct & 0x1e) ? "Reserved" : "Default layer 1 protocol");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Synchronous/asynchronous: %s",
|
|
a_bigbuf,
|
|
(oct & 0x01) ? "Asynchronous" : "Synchronous");
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6a */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6a");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6a);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Number of Stop Bits: %s",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "2" : "1");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Negotiation: %s",
|
|
a_bigbuf,
|
|
(oct & 0x20) ? "Reserved" : "In-band negotiation not possible");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Number of data bits excluding parity bit if present: %s",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "8" : "7");
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0x01: str = "0.3 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x02: str = "1.2 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x03: str = "2.4 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x04: str = "4.8 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x05: str = "9.6 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x06: str = "12.0 kbit/s transparent (non compliance with X.1 and V.110)"; break;
|
|
case 0x07: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : User rate: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6b */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6b");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6b);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0x02: str = "8 kbit/s"; break;
|
|
case 0x03: str = "16 kbit/s"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : V.110/X.30 rate adaptation Intermediate rate: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Network independent clock (NIC) on transmission (Tx): %s to send data with network independent clock",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "requires" : "does not require");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Network independent clock (NIC) on reception (Rx): %s accept data with network independent clock",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "can" : "cannot");
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0x00: str = "Odd"; break;
|
|
case 0x02: str = "Even"; break;
|
|
case 0x03: str = "None"; break;
|
|
case 0x04: str = "Forced to 0"; break;
|
|
case 0x05: str = "Forced to 1"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Parity information: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6c */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6c");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6c);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0x01: str = "Non transparent (RLP)"; break;
|
|
case 0x02: str = "Both, transparent preferred"; break;
|
|
case 0x03: str = "Both, non transparent preferred"; break;
|
|
default:
|
|
str = "Transparent";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Connection element: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x1f)
|
|
{
|
|
case 0x00: str = "None"; break;
|
|
case 0x01: str = "V.21"; break;
|
|
case 0x02: str = "V.22"; break;
|
|
case 0x03: str = "V.22 bis"; break;
|
|
case 0x04: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x05: str = "V.26 ter"; break;
|
|
case 0x06: str = "V.32"; break;
|
|
case 0x07: str = "Modem for undefined interface"; break;
|
|
case 0x08: str = "Autobauding type 1"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Modem type: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6d */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6d");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6d);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0x00: str = "No other modem type specified in this field"; break;
|
|
case 0x02: str = "V.34"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Other modem type: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x1f)
|
|
{
|
|
case 0x00: str = "Fixed network user rate not applicable/No meaning is associated with this value"; break;
|
|
case 0x01: str = "9.6 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x02: str = "14.4 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x03: str = "19.2 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x04: str = "28.8 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x05: str = "38.4 kbit/s Recommendation X.1 and V.110"; break;
|
|
case 0x06: str = "48.0 kbit/s Recommendation X.1 and V.110(synch)"; break;
|
|
case 0x07: str = "56.0 kbit/s Recommendation X.1 and V.110(synch) /bit transparent"; break;
|
|
case 0x08: str = "64.0 kbit/s bit transparent"; break;
|
|
case 0x09: str = "33.6 kbit/s bit transparent"; break;
|
|
case 0x0a: str = "32.0 kbit/s Recommendation I.460"; break;
|
|
case 0x0b: str = "31.2 kbit/s Recommendation V.34"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Fixed network user rate: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6e */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6e");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6e);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
if (is_uplink == IS_UPLINK_TRUE)
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings: TCH/F14.4 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings: Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings: TCH/F9.6 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings: TCH/F4.8 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Maximum number of traffic channels: %u TCH",
|
|
a_bigbuf,
|
|
(oct & 0x07) + 1);
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x78, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings: Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Maximum number of traffic channels: Spare",
|
|
a_bigbuf);
|
|
}
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6f */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6f");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6f);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0x00: str = "not allowed/required/applicable"; break;
|
|
case 0x01: str = "up to 1 TCH/F allowed/may be requested"; break;
|
|
case 0x02: str = "up to 2 TCH/F allowed/may be requested"; break;
|
|
case 0x03: str = "up to 3 TCH/F allowed/may be requested"; break;
|
|
case 0x04: str = "up to 4 TCH/F allowed/may be requested"; break;
|
|
default:
|
|
str = "up to 4 TCH/F may be requested";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : UIMI, User initiated modification indication: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
if (is_uplink == IS_UPLINK_TRUE)
|
|
{
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0x00: str = "Air interface user rate not applicable/No meaning associated with this value"; break;
|
|
case 0x01: str = "9.6 kbit/s"; break;
|
|
case 0x02: str = "14.4 kbit/s"; break;
|
|
case 0x03: str = "19.2 kbit/s"; break;
|
|
case 0x05: str = "28.8 kbit/s"; break;
|
|
case 0x06: str = "38.4 kbit/s"; break;
|
|
case 0x07: str = "43.2 kbit/s"; break;
|
|
case 0x08: str = "57.6 kbit/s"; break;
|
|
case 0x09: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
|
|
case 0x0a: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
|
|
case 0x0b: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
|
|
case 0x0c: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Wanted air interface user rate: %s",
|
|
a_bigbuf,
|
|
str);
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Wanted air interface user rate: Spare",
|
|
a_bigbuf);
|
|
}
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
if (!extended) goto bc_octet_7;
|
|
|
|
/* octet 6g */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 6g");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_6g);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
if (is_uplink == IS_UPLINK_TRUE)
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings extended: TCH/F28.8 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x40) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings extended: TCH/F32.0 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x20) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings extended: TCH/F43.2 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "" : "not ");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Acceptable channel codings extended: TCH/F43.2 %sacceptable",
|
|
a_bigbuf,
|
|
(oct & 0x10) ? "" : "not ");
|
|
|
|
switch ((oct & 0x0c) >> 2)
|
|
{
|
|
case 0: str = "Channel coding symmetry preferred"; break;
|
|
case 2: str = "Downlink biased channel coding asymmetry is preferred"; break;
|
|
case 1: str = "Uplink biased channel coding asymmetry is preferred"; break;
|
|
default:
|
|
str = "Unused, treat as Channel coding symmetry preferred";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Channel Coding Asymmetry Indication: %s",
|
|
a_bigbuf,
|
|
str);
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7c, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : EDGE Channel Codings: Spare",
|
|
a_bigbuf);
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
bc_octet_7:
|
|
|
|
/* octet 7 */
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Octet 7");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_bc_oct_7);
|
|
|
|
extended = (oct & 0x80) ? FALSE : TRUE;
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
extended ? "extended" : "not extended");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Layer 2 Identity: %s",
|
|
a_bigbuf,
|
|
((oct & 0x60) == 0x40) ? "Octet identifier" : "Reserved");
|
|
|
|
switch (oct & 0x1f)
|
|
{
|
|
case 0x06: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
case 0x08: str = "ISO 6429, codeset 0 (DC1/DC3)"; break;
|
|
case 0x09: str = "Reserved: was allocated but never used in earlier phases of the protocol"; break;
|
|
case 0x0a: str = "Videotex profile 1"; break;
|
|
case 0x0c: str = "COPnoFlCt (Character oriented Protocol with no Flow Control mechanism)"; break;
|
|
case 0x0d: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : User information layer 2 protocol: %s",
|
|
a_bigbuf,
|
|
str);
|
|
break;
|
|
}
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.5a
|
|
*/
|
|
static guint8
|
|
de_cc_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
|
|
switch ((oct & 0xf0) >> 4)
|
|
{
|
|
case 0:
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Maximum number of supported bearers: 1",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Maximum number of supported bearers: %u",
|
|
a_bigbuf,
|
|
(oct & 0xf0) >> 4);
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : PCP: the mobile station %s the Prolonged Clearing Procedure",
|
|
a_bigbuf,
|
|
(oct & 0x02) ? "supports" : "does not support");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : DTMF: %s",
|
|
a_bigbuf,
|
|
(oct & 0x01) ?
|
|
"the mobile station supports DTMF as specified in subclause 5.5.7 of TS 24.008" :
|
|
"reserved for earlier versions of the protocol");
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Maximum number of speech bearers: %u",
|
|
a_bigbuf,
|
|
oct & 0x0f);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.6
|
|
*/
|
|
static guint8
|
|
de_call_state(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CALL_STATE].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CALL_STATE]);
|
|
|
|
switch ((oct & 0xc0) >> 6)
|
|
{
|
|
case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
|
|
case 1: str = "Reserved for other international standards"; break;
|
|
case 2: str = "National standard"; break;
|
|
default:
|
|
str = "Standard defined for the GSM PLMNS";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding standard: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
switch (oct & 0x3f)
|
|
{
|
|
case 0x00: str = "UO - null NO - null"; break;
|
|
case 0x02: str = "U0.1- MM connection pending N0.1- MM connection pending"; break;
|
|
case 0x22: str = "U0.2- CC prompt present N0.2- CC connection pending"; break;
|
|
case 0x23: str = "U0.3- Wait for network information N0.3- Network answer pending"; break;
|
|
case 0x24: str = "U0.4- CC-Establishment present N0.4- CC-Establishment present"; break;
|
|
case 0x25: str = "U0.5- CC-Establishment confirmed N0.5- CC-Establishment confirmed"; break;
|
|
case 0x26: str = "U0.6- Recall present N0.6- Recall present"; break;
|
|
case 0x01: str = "U1 - call initiated N1 - call initiated"; break;
|
|
case 0x03: str = "U3 - mobile originating call proceeding N3 - mobile originating call proceeding"; break;
|
|
case 0x04: str = "U4 - call delivered N4 - call delivered"; break;
|
|
case 0x06: str = "U6 - call present N6 - call present"; break;
|
|
case 0x07: str = "U7 - call received N7 - call received"; break;
|
|
case 0x08: str = "U8 - connect request N8 - connect request"; break;
|
|
case 0x09: str = "U9 - mobile terminating call confirmed N9 - mobile terminating call confirmed"; break;
|
|
case 0x0a: str = "U10- active N10- active"; break;
|
|
case 0x0b: str = "U11- disconnect request"; break;
|
|
case 0x0c: str = "U12- disconnect indication N12-disconnect indication"; break;
|
|
case 0x13: str = "U19- release request N19- release request"; break;
|
|
case 0x1a: str = "U26- mobile originating modify N26- mobile originating modify"; break;
|
|
case 0x1b: str = "U27- mobile terminating modify N27- mobile terminating modify"; break;
|
|
case 0x1c: str = " N28- connect indication"; break;
|
|
default:
|
|
str = "Unknown";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Call state value: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.7
|
|
*/
|
|
static guint8
|
|
de_cld_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 ton;
|
|
guint8 *poctets;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
ton = (oct & 0x70) >> 4;
|
|
switch (ton)
|
|
{
|
|
case 0: str = "Unknown"; break;
|
|
case 1: str = "International number"; break;
|
|
case 2: str = "National number"; break;
|
|
case 3: str = "Network specific number"; break;
|
|
case 4: str = "Dedicated access, short code"; break;
|
|
case 7: str = "Reserved for extension"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of number: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
if ((ton == 0) ||
|
|
(ton == 1) ||
|
|
(ton == 2) ||
|
|
(ton == 4))
|
|
{
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "Unknown"; break;
|
|
case 1: str = "ISDN/telephony numbering plan (Rec. E.164/E.163)"; break;
|
|
case 3: str = "Data numbering plan (Recommendation X.121)"; break;
|
|
case 4: str = "Telex numbering plan (Recommendation F.69)"; break;
|
|
case 8: str = "National numbering plan"; break;
|
|
case 9: str = "Private numbering plan"; break;
|
|
case 11: str = "Reserved for CTS (see 3GPP TS 44.056)"; break;
|
|
case 15: str = "Reserved for extension"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
str = "not applicable";
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Numbering plan identification: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
|
|
|
|
my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
|
|
&Dgt_mbcd);
|
|
g_free(poctets);
|
|
|
|
proto_tree_add_string_format(tree, hf_gsm_a_cld_party_bcd_num,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
a_bigbuf,
|
|
"BCD Digits: %s",
|
|
a_bigbuf);
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
sprintf(add_string, " - (%s)", a_bigbuf);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.8
|
|
*/
|
|
static guint8
|
|
de_cld_party_sub_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0: str = "NSAP (X.213/ISO 8348 AD2)"; break;
|
|
case 2: str = "User specified"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of subaddress: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even indicator: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ?
|
|
"odd number of address signals" : "even number of address signals");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Subaddress information");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.9
|
|
*/
|
|
static guint8
|
|
de_clg_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 ton;
|
|
guint8 *poctets;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
ton = (oct & 0x70) >> 4;
|
|
switch (ton)
|
|
{
|
|
case 0: str = "Unknown"; break;
|
|
case 1: str = "International number"; break;
|
|
case 2: str = "National number"; break;
|
|
case 3: str = "Network specific number"; break;
|
|
case 4: str = "Dedicated access, short code"; break;
|
|
case 7: str = "Reserved for extension"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of number: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
if ((ton == 0) ||
|
|
(ton == 1) ||
|
|
(ton == 2) ||
|
|
(ton == 4))
|
|
{
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "Unknown"; break;
|
|
case 1: str = "ISDN/telephony numbering plan (Rec. E.164/E.163)"; break;
|
|
case 3: str = "Data numbering plan (Recommendation X.121)"; break;
|
|
case 4: str = "Telex numbering plan (Recommendation F.69)"; break;
|
|
case 8: str = "National numbering plan"; break;
|
|
case 9: str = "Private numbering plan"; break;
|
|
case 11: str = "Reserved for CTS (see 3GPP TS 44.056)"; break;
|
|
case 15: str = "Reserved for extension"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
str = "not applicable";
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Numbering plan identification: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0: str = "Presentation allowed"; break;
|
|
case 1: str = "Presentation restricted"; break;
|
|
case 2: str = "Number not available due to interworking"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Presentation indicator: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x03)
|
|
{
|
|
case 0: str = "User-provided, not screened"; break;
|
|
case 1: str = "User-provided, verified and passed"; break;
|
|
case 2: str = "User-provided, verified and failed"; break;
|
|
default:
|
|
str = "Network provided";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Screening indicator: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
|
|
|
|
my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
|
|
&Dgt_mbcd);
|
|
g_free(poctets);
|
|
|
|
proto_tree_add_string_format(tree, hf_gsm_a_clg_party_bcd_num,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
a_bigbuf,
|
|
"BCD Digits: %s",
|
|
a_bigbuf);
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
sprintf(add_string, " - (%s)", a_bigbuf);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.10
|
|
*/
|
|
static guint8
|
|
de_clg_party_sub_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0: str = "NSAP (X.213/ISO 8348 AD2)"; break;
|
|
case 2: str = "User specified"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of subaddress: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Odd/Even indicator: %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ?
|
|
"odd number of address signals" : "even number of address signals");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Subaddress information");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.11
|
|
*/
|
|
static guint8
|
|
de_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint8 cause;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "not extended" : "extended");
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
|
|
case 1: str = "Reserved for other international standards"; break;
|
|
case 2: str = "National standard"; break;
|
|
default:
|
|
str = "Standard defined for the GSM PLMNS";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding standard: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "User"; break;
|
|
case 1: str = "Private network serving the local user"; break;
|
|
case 2: str = "Public network serving the local user"; break;
|
|
case 3: str = "Transit network"; break;
|
|
case 4: str = "Public network serving the remote user"; break;
|
|
case 5: str = "Private network serving the remote user"; break;
|
|
case 7: str = "International network"; break;
|
|
case 10: str = "Network beyond interworking point"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Location: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (!(oct & 0x80))
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Recommendation",
|
|
a_bigbuf);
|
|
|
|
curr_offset++;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
cause = oct & 0x7f;
|
|
switch (cause)
|
|
{
|
|
case 1: str = "Unassigned (unallocated) number"; break;
|
|
case 3: str = "No route to destination"; break;
|
|
case 6: str = "Channel unacceptable"; break;
|
|
case 8: str = "Operator determined barring"; break;
|
|
case 16: str = "Normal call clearing"; break;
|
|
case 17: str = "User busy"; break;
|
|
case 18: str = "No user responding"; break;
|
|
case 19: str = "User alerting, no answer"; break;
|
|
case 21: str = "Call rejected"; break;
|
|
case 22: str = "Number changed"; break;
|
|
case 25: str = "Pre-emption"; break;
|
|
case 26: str = "Non selected user clearing"; break;
|
|
case 27: str = "Destination out of order"; break;
|
|
case 28: str = "Invalid number format (incomplete number)"; break;
|
|
case 29: str = "Facility rejected"; break;
|
|
case 30: str = "Response to STATUS ENQUIRY"; break;
|
|
case 31: str = "Normal, unspecified"; break;
|
|
case 34: str = "No circuit/channel available"; break;
|
|
case 38: str = "Network out of order"; break;
|
|
case 41: str = "Temporary failure"; break;
|
|
case 42: str = "Switching equipment congestion"; break;
|
|
case 43: str = "Access information discarded"; break;
|
|
case 44: str = "requested circuit/channel not available"; break;
|
|
case 47: str = "Resources unavailable, unspecified"; break;
|
|
case 49: str = "Quality of service unavailable"; break;
|
|
case 50: str = "Requested facility not subscribed"; break;
|
|
case 55: str = "Incoming calls barred within the CUG"; break;
|
|
case 57: str = "Bearer capability not authorized"; break;
|
|
case 58: str = "Bearer capability not presently available"; break;
|
|
case 63: str = "Service or option not available, unspecified"; break;
|
|
case 65: str = "Bearer service not implemented"; break;
|
|
case 68: str = "ACM equal to or greater than ACMmax"; break;
|
|
case 69: str = "Requested facility not implemented"; break;
|
|
case 70: str = "Only restricted digital information bearer capability is available"; break;
|
|
case 79: str = "Service or option not implemented, unspecified"; break;
|
|
case 81: str = "Invalid transaction identifier value"; break;
|
|
case 87: str = "User not member of CUG"; break;
|
|
case 88: str = "Incompatible destination"; break;
|
|
case 91: str = "Invalid transit network selection"; break;
|
|
case 95: str = "Semantically incorrect message"; break;
|
|
case 96: str = "Invalid mandatory information"; break;
|
|
case 97: str = "Message type non-existent or not implemented"; break;
|
|
case 98: str = "Message type not compatible with protocol state"; break;
|
|
case 99: str = "Information element non-existent or not implemented"; break;
|
|
case 100: str = "Conditional IE error"; break;
|
|
case 101: str = "Message not compatible with protocol state"; break;
|
|
case 102: str = "Recovery on timer expiry"; break;
|
|
case 111: str = "Protocol error, unspecified"; break;
|
|
case 127: str = "Interworking, unspecified"; break;
|
|
default:
|
|
if (cause <= 31) { str = "Treat as Normal, unspecified"; }
|
|
else if ((cause >= 32) && (cause <= 47)) { str = "Treat as Resources unavailable, unspecified"; }
|
|
else if ((cause >= 48) && (cause <= 63)) { str = "Treat as Service or option not available, unspecified"; }
|
|
else if ((cause >= 64) && (cause <= 79)) { str = "Treat as Service or option not implemented, unspecified"; }
|
|
else if ((cause >= 80) && (cause <= 95)) { str = "Treat as Semantically incorrect message"; }
|
|
else if ((cause >= 96) && (cause <= 111)) { str = "Treat as Protocol error, unspecified"; }
|
|
else if ((cause >= 112) && (cause <= 127)) { str = "Treat as Interworking, unspecified"; }
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_uint_format(tree, hf_gsm_a_dtap_cause,
|
|
tvb, curr_offset, 1, cause,
|
|
"%s : Cause: (%u) %s",
|
|
a_bigbuf,
|
|
cause,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%u) %s", cause, str);
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Diagnostics");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
|
|
#define GSM_A_TC_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
|
|
{ \
|
|
guint _len_offset; \
|
|
proto_item *_item; \
|
|
\
|
|
_len_offset = asn1->offset; \
|
|
asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
|
|
\
|
|
_item = \
|
|
proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
|
|
\
|
|
_Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
|
|
\
|
|
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
|
|
_Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
|
|
\
|
|
if (*_Gdef_len_p) \
|
|
{ \
|
|
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
|
|
_len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
|
|
} \
|
|
else \
|
|
{ \
|
|
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
|
|
_len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
|
|
\
|
|
*_Glen_p = tcap_find_eoc(asn1); \
|
|
} \
|
|
\
|
|
proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
|
|
(*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
|
|
}
|
|
|
|
/*
|
|
* [6] 3.6
|
|
*/
|
|
static guint8
|
|
de_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
ASN1_SCK asn1_real, *asn1;
|
|
proto_item *item;
|
|
proto_tree *subtree, *temp_subtree, *seq_subtree;
|
|
guint saved_offset, comp_saved_offset, comp_len_offset, comp_data_offset;
|
|
guint comp_len, temp_len;
|
|
gboolean def_len[3];
|
|
guint comp_tag, tag;
|
|
gchar *str;
|
|
gint32 int_val;
|
|
|
|
add_string = add_string;
|
|
|
|
asn1 = &asn1_real;
|
|
asn1_open(asn1, tvb, offset);
|
|
|
|
/* call next dissector for EACH component */
|
|
|
|
while ((len - (asn1->offset - offset)) > 0)
|
|
{
|
|
comp_saved_offset = asn1->offset;
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &comp_tag);
|
|
|
|
comp_len_offset = asn1->offset;
|
|
comp_len = 0;
|
|
def_len[0] = FALSE;
|
|
asn1_length_decode(asn1, &def_len[0], &comp_len);
|
|
comp_data_offset = asn1->offset;
|
|
|
|
if (def_len[0])
|
|
{
|
|
temp_len = comp_len + (asn1->offset - saved_offset);
|
|
}
|
|
else
|
|
{
|
|
comp_len = tcap_find_eoc(asn1);
|
|
temp_len = comp_len + (asn1->offset - saved_offset) + TCAP_EOC_LEN;
|
|
}
|
|
|
|
item =
|
|
proto_tree_add_text(tree, asn1->tvb, comp_saved_offset, temp_len, "Component");
|
|
|
|
subtree = proto_item_add_subtree(item, ett_tc_component);
|
|
|
|
str = match_strval((guint32) comp_tag, tcap_component_type_str);
|
|
|
|
if (str == NULL)
|
|
{
|
|
proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset, temp_len,
|
|
"Unknown component type tag, ignoring component");
|
|
|
|
asn1->offset = comp_saved_offset + temp_len;
|
|
continue;
|
|
}
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset,
|
|
comp_len_offset - comp_saved_offset,
|
|
"%s Type Tag: 0x%02x", str, comp_tag);
|
|
|
|
if (def_len[0])
|
|
{
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
comp_len_offset, asn1->offset - comp_len_offset, "Length: %d", comp_len);
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
comp_len_offset, asn1->offset - comp_len_offset, "Length: Indefinite");
|
|
}
|
|
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Invoke ID",
|
|
ett_tc_invoke_id, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Invoke ID: %d", int_val);
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
|
|
switch (comp_tag)
|
|
{
|
|
case TCAP_COMP_INVOKE:
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
if (tag == TCAP_LINKED_ID_TAG)
|
|
{
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Linked ID",
|
|
ett_tc_linked_id, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Linked ID: %d", int_val);
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
}
|
|
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Operation Code",
|
|
ett_tc_opr_code, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
str = match_strval(int_val, gsm_ss_opr_code_strings);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Operation Code: %s (%d)",
|
|
(str == NULL) ? "Unknown Operation Code" : str,
|
|
int_val);
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
|
|
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
|
|
{
|
|
gsm_ss_dissect(asn1, subtree,
|
|
comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
|
|
}
|
|
break;
|
|
|
|
case TCAP_COMP_RRL:
|
|
if ((len - (asn1->offset - offset)) > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Sequence",
|
|
ett_tc_sequence, &def_len[1], &temp_len, seq_subtree);
|
|
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
GSM_A_TC_START_SUBTREE(seq_subtree, saved_offset, tag, "Operation Code",
|
|
ett_tc_opr_code, &def_len[2], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
str = match_strval(int_val, gsm_ss_opr_code_strings);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Operation Code: %s (%d)",
|
|
(str == NULL) ? "Unknown Operation Code" : str,
|
|
int_val);
|
|
}
|
|
|
|
if (!def_len[2])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
|
|
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
|
|
{
|
|
gsm_ss_dissect(asn1, seq_subtree,
|
|
comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TCAP_COMP_RE:
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
switch (tag)
|
|
{
|
|
case 0x02:
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Local Error Code",
|
|
ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
str = match_strval(int_val, gsm_ss_err_code_strings);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Error Code: %s (%d)",
|
|
(str == NULL) ? "Unknown Error Code" : str,
|
|
int_val);
|
|
}
|
|
break;
|
|
|
|
case 0x06:
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Global Error Code",
|
|
ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Error Code: %d",
|
|
int_val);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Unknown Error Code",
|
|
ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_int32_value_decode(asn1, temp_len, &int_val);
|
|
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
saved_offset, temp_len, "Error Code: %d",
|
|
int_val);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
|
|
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
|
|
{
|
|
/*
|
|
* XXX need conversations to determine 'opr_code'
|
|
*/
|
|
gsm_ss_dissect(asn1, subtree,
|
|
comp_len - (asn1->offset - comp_data_offset), 0, comp_tag);
|
|
}
|
|
break;
|
|
|
|
case TCAP_COMP_REJECT:
|
|
saved_offset = asn1->offset;
|
|
asn1_id_decode1(asn1, &tag);
|
|
|
|
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Problem Code",
|
|
ett_tc_prob_code, &def_len[1], &temp_len, temp_subtree);
|
|
|
|
if (temp_len > 0)
|
|
{
|
|
proto_tree_add_text(temp_subtree, asn1->tvb,
|
|
asn1->offset, temp_len, "Problem Code");
|
|
|
|
asn1->offset += temp_len;
|
|
}
|
|
|
|
if (!def_len[1])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!def_len[0])
|
|
{
|
|
saved_offset = asn1->offset;
|
|
asn1_eoc_decode(asn1, -1);
|
|
|
|
proto_tree_add_text(subtree, asn1->tvb,
|
|
saved_offset, asn1->offset - saved_offset, "End of Contents");
|
|
}
|
|
}
|
|
|
|
return(len);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.17
|
|
*/
|
|
static guint8
|
|
de_keypad_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Keypad information: %c",
|
|
a_bigbuf,
|
|
oct & 0x7f);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - %c", oct & 0x7f);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.21
|
|
*/
|
|
static guint8
|
|
de_prog_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
switch ((oct & 0x60) >> 5)
|
|
{
|
|
case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
|
|
case 1: str = "Reserved for other international standards"; break;
|
|
case 2: str = "National standard"; break;
|
|
default:
|
|
str = "Standard defined for the GSM PLMNS";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Coding standard: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "User"; break;
|
|
case 1: str = "Private network serving the local user"; break;
|
|
case 2: str = "Public network serving the local user"; break;
|
|
case 4: str = "Public network serving the remote user"; break;
|
|
case 5: str = "Private network serving the remote user"; break;
|
|
case 10: str = "Network beyond interworking point"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Location: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
switch (oct & 0x7f)
|
|
{
|
|
case 1: str = "Call is not end-to-end PLMN/ISDN, further call progress information may be available in-band"; break;
|
|
case 2: str = "Destination address in non-PLMN/ISDN"; break;
|
|
case 3: str = "Origination address in non-PLMN/ISDN"; break;
|
|
case 4: str = "Call has returned to the PLMN/ISDN"; break;
|
|
case 8: str = "In-band information or appropriate pattern now available"; break;
|
|
case 32: str = "Call is end-to-end PLMN/ISDN"; break;
|
|
case 64: str = "Queueing"; break;
|
|
default:
|
|
str = "Unspecific";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Progress Description: %s (%d)",
|
|
a_bigbuf,
|
|
str,
|
|
oct & 0x7f);
|
|
|
|
sprintf(add_string, " - %d", oct & 0x7f);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [3] 10.5.4.22
|
|
*/
|
|
static guint8
|
|
de_repeat_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 1: str = "Circular for successive selection 'mode 1 alternate mode 2'"; break;
|
|
case 2: str = "Support of fallback mode 1 preferred, mode 2 selected if setup of mode 1 fails"; break;
|
|
case 3: str = "Reserved: was allocated in earlier phases of the protocol"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [6] 3.7.2
|
|
*/
|
|
static guint8
|
|
de_ss_ver_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct)
|
|
{
|
|
case 0: str = "Phase 2 service, ellipsis notation, and phase 2 error handling is supported"; break;
|
|
case 1: str = "SS-Protocol version 3 is supported, and phase 2 error handling is supported"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s",
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [5] 8.1.4.1
|
|
*/
|
|
static guint8
|
|
de_cp_user_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
tvbuff_t *rp_tvb;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"RPDU");
|
|
|
|
/*
|
|
* dissect the embedded RP message
|
|
*/
|
|
rp_tvb = tvb_new_subset(tvb, curr_offset, len, len);
|
|
|
|
call_dissector(rp_handle, rp_tvb, g_pinfo, g_tree);
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [5] 8.1.4.2
|
|
*/
|
|
static guint8
|
|
de_cp_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
switch (oct)
|
|
{
|
|
case 17: str = "Network failure"; break;
|
|
case 22: str = "Congestion"; break;
|
|
case 81: str = "Invalid Transaction Identifier value"; break;
|
|
case 95: str = "Semantically incorrect message"; break;
|
|
case 96: str = "Invalid mandatory information"; break;
|
|
case 97: str = "Message type non-existent or not implemented"; break;
|
|
case 98: str = "Message not compatible with the short message protocol state"; break;
|
|
case 99: str = "Information element non-existent or not implemented"; break;
|
|
case 111: str = "Protocol error, unspecified"; break;
|
|
default:
|
|
str = "Reserved, treat as Protocol error, unspecified";
|
|
break;
|
|
}
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"Cause: (%u) %s",
|
|
oct,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%u) %s", oct, str);
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [5] 8.2.3
|
|
*/
|
|
static guint8
|
|
de_rp_message_ref(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
|
|
len = len;
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"RP-Message Reference: 0x%02x (%u)",
|
|
oct,
|
|
oct);
|
|
|
|
curr_offset++;
|
|
|
|
/* no length check possible */
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [5] 8.2.5.1
|
|
*/
|
|
static guint8
|
|
de_rp_orig_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
return(de_cld_party_bcd_num(tvb, tree, offset, len, add_string));
|
|
}
|
|
|
|
/*
|
|
* [5] 8.2.5.2
|
|
*/
|
|
static guint8
|
|
de_rp_dest_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
return(de_cld_party_bcd_num(tvb, tree, offset, len, add_string));
|
|
}
|
|
|
|
/*
|
|
* [5] 8.2.5.3
|
|
*/
|
|
static guint8
|
|
de_rp_user_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint32 curr_offset;
|
|
tvbuff_t *tpdu_tvb;
|
|
|
|
add_string = add_string;
|
|
curr_offset = offset;
|
|
|
|
proto_tree_add_text(tree, tvb, curr_offset, len,
|
|
"TPDU");
|
|
|
|
/*
|
|
* dissect the embedded TPDU message
|
|
*/
|
|
tpdu_tvb = tvb_new_subset(tvb, curr_offset, len, len);
|
|
|
|
dissector_try_port(sms_dissector_table, 0, tpdu_tvb, g_pinfo, g_tree);
|
|
|
|
curr_offset += len;
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
/*
|
|
* [5] 8.2.5.4
|
|
*/
|
|
static guint8
|
|
de_rp_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Extension: %s",
|
|
a_bigbuf,
|
|
(oct & 0x80) ? "extended" : "not extended");
|
|
|
|
switch (oct & 0x7f)
|
|
{
|
|
case 1: str = "Unassigned (unallocated) number"; break;
|
|
case 8: str = "Operator determined barring"; break;
|
|
case 10: str = "Call barred"; break;
|
|
case 11: str = "Reserved"; break;
|
|
case 21: str = "Short message transfer rejected"; break;
|
|
case 22: str = "Memory capacity exceeded"; break;
|
|
case 27: str = "Destination out of order"; break;
|
|
case 28: str = "Unidentified subscriber"; break;
|
|
case 29: str = "Facility rejected"; break;
|
|
case 30: str = "Unknown subscriber"; break;
|
|
case 38: str = "Network out of order"; break;
|
|
case 41: str = "Temporary failure"; break;
|
|
case 42: str = "Congestion"; break;
|
|
case 47: str = "Resources unavailable, unspecified"; break;
|
|
case 50: str = "Requested facility not subscribed"; break;
|
|
case 69: str = "Requested facility not implemented"; break;
|
|
case 81: str = "Invalid short message transfer reference value"; break;
|
|
case 95: str = "Semantically incorrect message"; break;
|
|
case 96: str = "Invalid mandatory information"; break;
|
|
case 97: str = "Message type non-existent or not implemented"; break;
|
|
case 98: str = "Message not compatible with short message protocol state"; break;
|
|
case 99: str = "Information element non-existent or not implemented"; break;
|
|
case 111: str = "Protocol error, unspecified"; break;
|
|
case 127: str = "Interworking, unspecified"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Cause: (%u) %s",
|
|
a_bigbuf,
|
|
oct & 0x7f,
|
|
str);
|
|
|
|
curr_offset++;
|
|
|
|
sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
|
|
|
|
NO_MORE_DATA_CHECK(len);
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, len - (curr_offset - offset),
|
|
"Diagnostic field");
|
|
|
|
curr_offset += len - (curr_offset - offset);
|
|
|
|
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
|
|
|
|
return(curr_offset - offset);
|
|
}
|
|
|
|
static guint8 (*bssmap_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
|
|
be_cic, /* Circuit Identity Code */
|
|
NULL, /* Reserved */
|
|
NULL, /* Resource Available */
|
|
be_cause, /* Cause */
|
|
be_cell_id, /* Cell Identifier */
|
|
be_prio, /* Priority */
|
|
be_l3_header_info, /* Layer 3 Header Information */
|
|
de_mid, /* IMSI */
|
|
be_tmsi, /* TMSI */
|
|
be_enc_info, /* Encryption Information */
|
|
be_chan_type, /* Channel Type */
|
|
NULL, /* Periodicity */
|
|
NULL, /* Extended Resource Indicator */
|
|
NULL, /* Number Of MSs */
|
|
NULL, /* Reserved */
|
|
NULL, /* Reserved */
|
|
NULL, /* Reserved */
|
|
de_ms_cm_2, /* Classmark Information Type 2 */
|
|
NULL, /* Classmark Information Type 3 */
|
|
NULL, /* Interference Band To Be Used */
|
|
de_rr_cause, /* RR Cause */
|
|
NULL, /* Reserved */
|
|
be_l3_info, /* Layer 3 Information */
|
|
be_dlci, /* DLCI */
|
|
be_down_dtx_flag, /* Downlink DTX Flag */
|
|
be_cell_id_list, /* Cell Identifier List */
|
|
NULL /* no associated data */, /* Response Request */
|
|
NULL, /* Resource Indication Method */
|
|
de_ms_cm_1, /* Classmark Information Type 1 */
|
|
NULL, /* Circuit Identity Code List */
|
|
NULL, /* Diagnostic */
|
|
be_l3_msg, /* Layer 3 Message Contents */
|
|
be_chosen_chan, /* Chosen Channel */
|
|
NULL, /* Total Resource Accessible */
|
|
be_ciph_resp_mode, /* Cipher Response Mode */
|
|
NULL, /* Channel Needed */
|
|
NULL, /* Trace Type */
|
|
NULL, /* TriggerID */
|
|
NULL, /* Trace Reference */
|
|
NULL, /* TransactionID */
|
|
de_mid, /* Mobile Identity */
|
|
NULL, /* OMCID */
|
|
be_for_ind, /* Forward Indicator */
|
|
be_chosen_enc_alg, /* Chosen Encryption Algorithm */
|
|
be_cct_pool, /* Circuit Pool */
|
|
NULL, /* Circuit Pool List */
|
|
NULL, /* Time Indication */
|
|
NULL, /* Resource Situation */
|
|
be_curr_chan_1, /* Current Channel Type 1 */
|
|
be_que_ind, /* Queueing Indicator */
|
|
be_speech_ver, /* Speech Version */
|
|
NULL, /* Assignment Requirement */
|
|
NULL /* no associated data */, /* Talker Flag */
|
|
NULL /* no associated data */, /* Connection Release Requested */
|
|
NULL, /* Group Call Reference */
|
|
NULL, /* eMLPP Priority */
|
|
NULL, /* Configuration Evolution Indication */
|
|
NULL /* no decode required */, /* Old BSS to New BSS Information */
|
|
NULL, /* LSA Identifier */
|
|
NULL, /* LSA Identifier List */
|
|
NULL, /* LSA Information */
|
|
NULL, /* LCS QoS */
|
|
NULL, /* LSA access control suppression */
|
|
NULL, /* LCS Priority */
|
|
NULL, /* Location Type */
|
|
NULL, /* Location Estimate */
|
|
NULL, /* Positioning Data */
|
|
NULL, /* LCS Cause */
|
|
NULL, /* LCS Client Type */
|
|
be_apdu, /* APDU */
|
|
NULL, /* Network Element Identity */
|
|
NULL, /* GPS Assistance Data */
|
|
NULL, /* Deciphering Keys */
|
|
NULL, /* Return Error Request */
|
|
NULL, /* Return Error Cause */
|
|
NULL, /* Segmentation */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
static guint8 (*dtap_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
|
|
/* Common Information Elements 10.5.1 */
|
|
de_cell_id, /* Cell Identity */
|
|
NULL /* handled inline */, /* 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 */
|
|
NULL, /* Mobile Station Classmark 3 */
|
|
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)$ */
|
|
de_prio /* handled inline */, /* Priority Level */
|
|
de_plmn_list, /* PLMN List */
|
|
/* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
|
|
de_rr_cause, /* RR Cause */
|
|
/* Mobility Management Information Elements 10.5.3 */
|
|
de_auth_param_rand, /* Authentication Parameter RAND */
|
|
de_auth_param_autn, /* Authentication Parameter AUTN (UMTS authentication challenge only) */
|
|
de_auth_resp_param, /* Authentication Response Parameter */
|
|
de_auth_resp_param_ext, /* Authentication Response Parameter (extension) (UMTS authentication challenge only) */
|
|
de_auth_fail_param, /* Authentication Failure Parameter (UMTS authentication challenge only) */
|
|
NULL /* handled inline */, /* CM Service Type */
|
|
NULL /* handled inline */, /* Identity Type */
|
|
NULL /* handled inline */, /* Location Updating Type */
|
|
de_network_name, /* Network Name */
|
|
de_rej_cause, /* Reject Cause */
|
|
NULL /* no associated data */, /* Follow-on Proceed */
|
|
de_time_zone, /* Time Zone */
|
|
de_time_zone_time, /* Time Zone and Time */
|
|
NULL /* no associated data */, /* CTS Permission */
|
|
de_lsa_id, /* LSA Identifier */
|
|
de_day_saving_time, /* Daylight Saving Time */
|
|
/* Call Control Information Elements 10.5.4 */
|
|
de_aux_states, /* Auxiliary States */
|
|
de_bearer_cap, /* Bearer Capability */
|
|
de_cc_cap, /* Call Control Capabilities */
|
|
de_call_state, /* Call State */
|
|
de_cld_party_bcd_num, /* Called Party BCD Number */
|
|
de_cld_party_sub_addr, /* Called Party Subaddress */
|
|
de_clg_party_bcd_num, /* Calling Party BCD Number */
|
|
de_clg_party_sub_addr, /* Calling Party Subaddress */
|
|
de_cause, /* Cause */
|
|
NULL /* no associated data */, /* CLIR Suppression */
|
|
NULL /* no associated data */, /* CLIR Invocation */
|
|
NULL /* handled inline */, /* Congestion Level */
|
|
NULL, /* Connected Number */
|
|
NULL, /* Connected Subaddress */
|
|
de_facility, /* Facility */
|
|
NULL, /* High Layer Compatibility */
|
|
de_keypad_facility, /* Keypad Facility */
|
|
NULL, /* Low Layer Compatibility */
|
|
NULL, /* More Data */
|
|
NULL, /* Notification Indicator */
|
|
de_prog_ind, /* Progress Indicator */
|
|
NULL, /* Recall type $(CCBS)$ */
|
|
NULL, /* Redirecting Party BCD Number */
|
|
NULL, /* Redirecting Party Subaddress */
|
|
de_repeat_ind, /* Repeat Indicator */
|
|
NULL /* no associated data */, /* Reverse Call Setup Direction */
|
|
NULL, /* SETUP Container $(CCBS)$ */
|
|
NULL, /* Signal */
|
|
de_ss_ver_ind, /* SS Version Indicator */
|
|
NULL, /* User-user */
|
|
NULL, /* Alerting Pattern $(NIA)$ */
|
|
NULL, /* Allowed Actions $(CCBS)$ */
|
|
NULL, /* Stream Identifier */
|
|
NULL, /* Network Call Control Capabilities */
|
|
NULL, /* Cause of No CLI */
|
|
NULL, /* Immediate Modification Indicator */
|
|
NULL, /* Supported Codec List */
|
|
NULL, /* Service Category */
|
|
/* GPRS Mobility Management Information Elements 10.5.5 */
|
|
NULL, /* Attach Result */
|
|
NULL, /* Attach Type */
|
|
NULL, /* TMSI Status */
|
|
NULL, /* Detach Type */
|
|
NULL, /* DRX Parameter */
|
|
NULL, /* Force to Standby */
|
|
NULL, /* P-TMSI Signature */
|
|
NULL, /* P-TMSI Signature 2 */
|
|
NULL, /* Identity Type 2 */
|
|
NULL, /* IMEISV Request */
|
|
NULL, /* Receive N-PDU Numbers List */
|
|
NULL, /* MS Network Capability */
|
|
NULL, /* MS Radio Access Capability */
|
|
NULL, /* GMM Cause */
|
|
NULL, /* Routing Area Identification */
|
|
NULL, /* Update Result */
|
|
NULL, /* A&C Reference Number */
|
|
NULL, /* Service Type */
|
|
NULL, /* Cell Notification */
|
|
NULL, /* Network Feature Support */
|
|
/* Short Message Service Information Elements [5] 8.1.4 */
|
|
de_cp_user_data, /* CP-User Data */
|
|
de_cp_cause, /* CP-Cause */
|
|
/* Short Message Service Information Elements [5] 8.2 */
|
|
de_rp_message_ref, /* RP-Message Reference */
|
|
de_rp_orig_addr, /* RP-Origination Address */
|
|
de_rp_dest_addr, /* RP-Destination Address */
|
|
de_rp_user_data, /* RP-User Data */
|
|
de_rp_cause, /* RP-Cause */
|
|
/* Session Management Information Elements 10.5.6 */
|
|
NULL, /* Access Point Name */
|
|
NULL, /* Network Service Access Point Identifier */
|
|
NULL, /* Protocol Configuration Options */
|
|
NULL, /* Packet Data Protocol Address */
|
|
NULL, /* Quality Of Service */
|
|
NULL, /* SM Cause */
|
|
NULL, /* Linked TI */
|
|
NULL, /* LLC Service Access Point Identifier */
|
|
NULL, /* Tear Down Indicator */
|
|
NULL, /* Packet Flow Identifier */
|
|
NULL, /* Traffic Flow Template */
|
|
/* GPRS Common Information Elements 10.5.7 */
|
|
NULL, /* PDP Context Status */
|
|
NULL, /* Radio Priority */
|
|
NULL, /* GPRS Timer */
|
|
NULL, /* GPRS Timer 2 */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define SET_ELEM_VARS(SEV_pdu_type, SEV_elem_names, SEV_elem_ett, SEV_elem_funcs) \
|
|
switch (SEV_pdu_type) \
|
|
{ \
|
|
case BSSAP_PDU_TYPE_BSSMAP: \
|
|
SEV_elem_names = gsm_bssmap_elem_strings; \
|
|
SEV_elem_ett = ett_gsm_bssmap_elem; \
|
|
SEV_elem_funcs = bssmap_elem_fcn; \
|
|
break; \
|
|
case BSSAP_PDU_TYPE_DTAP: \
|
|
SEV_elem_names = gsm_dtap_elem_strings; \
|
|
SEV_elem_ett = ett_gsm_dtap_elem; \
|
|
SEV_elem_funcs = dtap_elem_fcn; \
|
|
break; \
|
|
default: \
|
|
proto_tree_add_text(tree, \
|
|
tvb, curr_offset, -1, \
|
|
"Unknown PDU type (%u)", SEV_pdu_type); \
|
|
return(consumed); \
|
|
}
|
|
|
|
/*
|
|
* Type Length Value (TLV) element dissector
|
|
*/
|
|
static guint8
|
|
elem_tlv(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, guint len, gchar *name_add)
|
|
{
|
|
guint8 oct, parm_len;
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (oct == iei)
|
|
{
|
|
parm_len = tvb_get_guint8(tvb, curr_offset + 1);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, parm_len + 2,
|
|
"%s%s",
|
|
elem_names[idx].strptr,
|
|
(name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
|
|
|
|
subtree = proto_item_add_subtree(item, elem_ett[idx]);
|
|
|
|
proto_tree_add_uint(subtree,
|
|
(BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
|
|
curr_offset, 1, oct);
|
|
|
|
proto_tree_add_uint(subtree, hf_gsm_a_length, tvb,
|
|
curr_offset + 1, 1, parm_len);
|
|
|
|
if (parm_len > 0)
|
|
{
|
|
if (elem_funcs[idx] == NULL)
|
|
{
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset + 2, parm_len,
|
|
"Element Value");
|
|
|
|
consumed = parm_len;
|
|
}
|
|
else
|
|
{
|
|
a_add_string[0] = '\0';
|
|
consumed =
|
|
(*elem_funcs[idx])(tvb, subtree, curr_offset + 2,
|
|
parm_len, a_add_string);
|
|
|
|
if (a_add_string[0] != '\0')
|
|
{
|
|
proto_item_append_text(item, a_add_string);
|
|
a_add_string[0] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
consumed += 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.
|
|
*/
|
|
static guint8
|
|
elem_tv(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
|
|
{
|
|
guint8 oct;
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (oct == iei)
|
|
{
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, -1,
|
|
"%s%s",
|
|
elem_names[idx].strptr,
|
|
(name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
|
|
|
|
subtree = proto_item_add_subtree(item, elem_ett[idx]);
|
|
|
|
proto_tree_add_uint(subtree,
|
|
(BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
|
|
curr_offset, 1, oct);
|
|
|
|
if (elem_funcs[idx] == NULL)
|
|
{
|
|
/* BAD THING, CANNOT DETERMINE LENGTH */
|
|
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset + 1, 1,
|
|
"No element dissector, rest of dissection may be incorrect");
|
|
|
|
consumed = 1;
|
|
}
|
|
else
|
|
{
|
|
a_add_string[0] = '\0';
|
|
consumed = (*elem_funcs[idx])(tvb, subtree, curr_offset + 1, -1, a_add_string);
|
|
|
|
if (a_add_string[0] != '\0')
|
|
{
|
|
proto_item_append_text(item, a_add_string);
|
|
a_add_string[0] = '\0';
|
|
}
|
|
}
|
|
|
|
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.
|
|
*/
|
|
static guint8
|
|
elem_tv_short(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
|
|
{
|
|
guint8 oct;
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if ((oct & 0xf0) == (iei & 0xf0))
|
|
{
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, -1,
|
|
"%s%s",
|
|
elem_names[idx].strptr,
|
|
(name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
|
|
|
|
subtree = proto_item_add_subtree(item, elem_ett[idx]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Element ID",
|
|
a_bigbuf);
|
|
|
|
if (elem_funcs[idx] == NULL)
|
|
{
|
|
/* BAD THING, CANNOT DETERMINE LENGTH */
|
|
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"No element dissector, rest of dissection may be incorrect");
|
|
|
|
consumed++;
|
|
}
|
|
else
|
|
{
|
|
a_add_string[0] = '\0';
|
|
consumed = (*elem_funcs[idx])(tvb, subtree, curr_offset, -1, a_add_string);
|
|
|
|
if (a_add_string[0] != '\0')
|
|
{
|
|
proto_item_append_text(item, a_add_string);
|
|
a_add_string[0] = '\0';
|
|
}
|
|
}
|
|
|
|
proto_item_set_len(item, consumed);
|
|
}
|
|
|
|
return(consumed);
|
|
}
|
|
|
|
/*
|
|
* Type (T) element dissector
|
|
*/
|
|
static guint8
|
|
elem_t(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
guint8 consumed;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
if (oct == iei)
|
|
{
|
|
proto_tree_add_uint_format(tree,
|
|
(BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
|
|
curr_offset, 1, oct,
|
|
"%s%s",
|
|
elem_names[idx].strptr,
|
|
(name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
|
|
|
|
consumed = 1;
|
|
}
|
|
|
|
return(consumed);
|
|
}
|
|
|
|
/*
|
|
* Length Value (LV) element dissector
|
|
*/
|
|
static guint8
|
|
elem_lv(tvbuff_t *tvb, proto_tree *tree, gint pdu_type, int idx, guint32 offset, guint len, gchar *name_add)
|
|
{
|
|
guint8 parm_len;
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
len = len;
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
parm_len = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, parm_len + 1,
|
|
"%s%s",
|
|
elem_names[idx].strptr,
|
|
(name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
|
|
|
|
subtree = proto_item_add_subtree(item, elem_ett[idx]);
|
|
|
|
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_text(subtree,
|
|
tvb, curr_offset + 1, parm_len,
|
|
"Element Value");
|
|
|
|
consumed = parm_len;
|
|
}
|
|
else
|
|
{
|
|
a_add_string[0] = '\0';
|
|
consumed =
|
|
(*elem_funcs[idx])(tvb, subtree, curr_offset + 1,
|
|
parm_len, a_add_string);
|
|
|
|
if (a_add_string[0] != '\0')
|
|
{
|
|
proto_item_append_text(item, a_add_string);
|
|
a_add_string[0] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
return(consumed + 1);
|
|
}
|
|
|
|
/*
|
|
* Value (V) element dissector
|
|
*
|
|
* Length cannot be used in these functions, big problem if a element dissector
|
|
* is not defined for these.
|
|
*/
|
|
static guint8
|
|
elem_v(tvbuff_t *tvb, proto_tree *tree, gint pdu_type, int idx, guint32 offset)
|
|
{
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
const value_string *elem_names;
|
|
gint *elem_ett;
|
|
guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
|
|
|
|
curr_offset = offset;
|
|
consumed = 0;
|
|
|
|
SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
|
|
|
|
if (elem_funcs[idx] == NULL)
|
|
{
|
|
/* BAD THING, CANNOT DETERMINE LENGTH */
|
|
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"No element dissector, rest of dissection may be incorrect");
|
|
|
|
consumed = 1;
|
|
}
|
|
else
|
|
{
|
|
a_add_string[0] = '\0';
|
|
consumed = (*elem_funcs[idx])(tvb, tree, curr_offset, -1, a_add_string);
|
|
a_add_string[0] = '\0';
|
|
}
|
|
|
|
return(consumed);
|
|
}
|
|
|
|
#define ELEM_MAND_TLV(EMT_iei, EMT_pdu_type, EMT_elem_idx, EMT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_tlv(tvb, tree, (guint8) EMT_iei, EMT_pdu_type, EMT_elem_idx, curr_offset, curr_len, EMT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
else \
|
|
{ \
|
|
proto_tree_add_text(tree, \
|
|
tvb, curr_offset, 0, \
|
|
"Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
|
|
EMT_iei, \
|
|
(EMT_pdu_type == BSSAP_PDU_TYPE_BSSMAP) ? \
|
|
gsm_bssmap_elem_strings[EMT_elem_idx].strptr : gsm_dtap_elem_strings[EMT_elem_idx].strptr, \
|
|
(EMT_elem_name_addition == NULL) || (EMT_elem_name_addition[0] == '\0') ? "" : EMT_elem_name_addition \
|
|
); \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_OPT_TLV(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_tlv(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, curr_len, EOT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_MAND_TV(EMT_iei, EMT_pdu_type, EMT_elem_idx, EMT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_tv(tvb, tree, (guint8) EMT_iei, EMT_pdu_type, EMT_elem_idx, curr_offset, EMT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
else \
|
|
{ \
|
|
proto_tree_add_text(tree, \
|
|
tvb, curr_offset, 0, \
|
|
"Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
|
|
EMT_iei, \
|
|
(EMT_pdu_type == BSSAP_PDU_TYPE_BSSMAP) ? \
|
|
gsm_bssmap_elem_strings[EMT_elem_idx].strptr : gsm_dtap_elem_strings[EMT_elem_idx].strptr, \
|
|
(EMT_elem_name_addition == NULL) || (EMT_elem_name_addition[0] == '\0') ? "" : EMT_elem_name_addition \
|
|
); \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_OPT_TV(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_tv(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_OPT_TV_SHORT(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_tv_short(tvb, tree, EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_OPT_T(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_t(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_MAND_LV(EML_pdu_type, EML_elem_idx, EML_elem_name_addition) \
|
|
{\
|
|
if ((consumed = elem_lv(tvb, tree, EML_pdu_type, EML_elem_idx, curr_offset, curr_len, EML_elem_name_addition)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Mandatory, but nothing we can do */ \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
#define ELEM_MAND_V(EMV_pdu_type, EMV_elem_idx) \
|
|
{\
|
|
if ((consumed = elem_v(tvb, tree, EMV_pdu_type, EMV_elem_idx, curr_offset)) > 0) \
|
|
{ \
|
|
curr_offset += consumed; \
|
|
curr_len -= consumed; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Mandatory, but nothing we can do */ \
|
|
} \
|
|
if (curr_len <= 0) return; \
|
|
}
|
|
|
|
|
|
/* MESSAGE FUNCTIONS */
|
|
|
|
/*
|
|
* [2] 3.2.1.1
|
|
*/
|
|
static void
|
|
bssmap_ass_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CHAN_TYPE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_TYPE, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_PRIO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_DOWN_DTX_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DOWN_DTX_FLAG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_INT_BAND].value, BSSAP_PDU_TYPE_BSSMAP, BE_INT_BAND, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_GROUP_CALL_REF].value, BSSAP_PDU_TYPE_BSSMAP, BE_GROUP_CALL_REF, "");
|
|
|
|
ELEM_OPT_T(gsm_bssmap_elem_strings[BE_TALKER_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_TALKER_FLAG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_LSA_ACC_CTRL].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ACC_CTRL, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.2
|
|
*/
|
|
static void
|
|
bssmap_ass_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.3
|
|
*/
|
|
static void
|
|
bssmap_ass_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.4
|
|
*/
|
|
static void
|
|
bssmap_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_T(gsm_bssmap_elem_strings[BE_CONN_REL_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONN_REL_REQ, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.5
|
|
*/
|
|
static void
|
|
bssmap_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.6
|
|
*/
|
|
static void
|
|
bssmap_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_T(gsm_bssmap_elem_strings[BE_CONN_REL_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONN_REL_REQ, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.7
|
|
*/
|
|
static void
|
|
bssmap_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.8
|
|
*/
|
|
static void
|
|
bssmap_ho_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CHAN_TYPE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_TYPE, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_ENC_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_ENC_INFO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CM_INFO_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_1, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, " (Serving)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_PRIO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_DOWN_DTX_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DOWN_DTX_FLAG, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, " (Target)");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_INT_BAND].value, BSSAP_PDU_TYPE_BSSMAP, BE_INT_BAND, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_3].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_3, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CURR_CHAN_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CURR_CHAN_1, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Used)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_GROUP_CALL_REF].value, BSSAP_PDU_TYPE_BSSMAP, BE_GROUP_CALL_REF, "");
|
|
|
|
ELEM_OPT_T(gsm_bssmap_elem_strings[BE_TALKER_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_TALKER_FLAG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CONF_EVO_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONF_EVO_IND, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, " (Serving)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_OLD2NEW_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_OLD2NEW_INFO, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_INFO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_LSA_ACC_CTRL].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ACC_CTRL, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.9
|
|
*/
|
|
static void
|
|
bssmap_ho_reqd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_OPT_T(gsm_bssmap_elem_strings[BE_RESP_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_RESP_REQ, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, " (Preferred)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CURR_CHAN_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CURR_CHAN_1, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Used)");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_QUE_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_QUE_IND, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_OLD2NEW_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_OLD2NEW_INFO, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.10
|
|
*/
|
|
static void
|
|
bssmap_ho_req_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.11
|
|
*/
|
|
static void
|
|
bssmap_ho_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.12
|
|
*/
|
|
static void
|
|
bssmap_ho_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.14
|
|
*/
|
|
static void
|
|
bssmap_ho_cand_enq(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_NUM_MS].value, BSSAP_PDU_TYPE_BSSMAP, BE_NUM_MS, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.15
|
|
*/
|
|
static void
|
|
bssmap_ho_cand_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_NUM_MS].value, BSSAP_PDU_TYPE_BSSMAP, BE_NUM_MS, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.16
|
|
*/
|
|
static void
|
|
bssmap_ho_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.19
|
|
*/
|
|
static void
|
|
bssmap_paging(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_IMSI].value, BSSAP_PDU_TYPE_BSSMAP, BE_IMSI, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_TMSI].value, BSSAP_PDU_TYPE_BSSMAP, BE_TMSI, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CHAN_NEEDED].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_NEEDED, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_EMLPP_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_EMLPP_PRIO, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.20
|
|
*/
|
|
static void
|
|
bssmap_clear_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.21
|
|
*/
|
|
static void
|
|
bssmap_clear_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.23
|
|
*/
|
|
static void
|
|
bssmap_reset(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_UNKNOWN;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.25
|
|
*/
|
|
static void
|
|
bssmap_ho_performed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.26
|
|
*/
|
|
static void
|
|
bssmap_overload(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.29
|
|
*/
|
|
static void
|
|
bssmap_cm_upd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_3].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_3, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.30
|
|
*/
|
|
static void
|
|
bssmap_ciph_mode_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_ENC_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_ENC_INFO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIPH_RESP_MODE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIPH_RESP_MODE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.31
|
|
*/
|
|
static void
|
|
bssmap_ciph_mode_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_MSG].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_MSG, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.32
|
|
*/
|
|
static void
|
|
bssmap_cl3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID_LIST, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_APDU].value, BSSAP_PDU_TYPE_BSSMAP, BE_APDU, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.34
|
|
*/
|
|
static void
|
|
bssmap_sapi_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint8 consumed;
|
|
guint32 curr_offset;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_DLCI].value, BSSAP_PDU_TYPE_BSSMAP, BE_DLCI, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.37
|
|
*/
|
|
static void
|
|
bssmap_ho_reqd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.38
|
|
*/
|
|
static void
|
|
bssmap_reset_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.39
|
|
*/
|
|
static void
|
|
bssmap_reset_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.41
|
|
*/
|
|
static void
|
|
bssmap_cct_group_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.42
|
|
*/
|
|
static void
|
|
bssmap_cct_group_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.43
|
|
*/
|
|
static void
|
|
bssmap_cct_group_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.44
|
|
*/
|
|
static void
|
|
bssmap_cct_group_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.45
|
|
*/
|
|
static void
|
|
bssmap_confusion(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_DIAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DIAG, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.47
|
|
*/
|
|
static void
|
|
bssmap_unequipped_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.48
|
|
*/
|
|
static void
|
|
bssmap_ciph_mode_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.49
|
|
*/
|
|
static void
|
|
bssmap_load_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_TIME_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_TIME_IND, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, " (Target)");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_RES_SIT].value, BSSAP_PDU_TYPE_BSSMAP, BE_RES_SIT, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.66
|
|
*/
|
|
static void
|
|
bssmap_change_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.67
|
|
*/
|
|
static void
|
|
bssmap_change_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.69
|
|
*/
|
|
static void
|
|
bssmap_lsa_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_LSA_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_INFO, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [2] 3.2.1.70
|
|
*/
|
|
static void
|
|
bssmap_conn_oriented(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_APDU].value, BSSAP_PDU_TYPE_BSSMAP, BE_APDU, "");
|
|
|
|
ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_SEG].value, BSSAP_PDU_TYPE_BSSMAP, BE_SEG, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
#define NUM_GSM_BSSMAP_MSG (sizeof(gsm_a_bssmap_msg_strings)/sizeof(value_string))
|
|
static gint ett_gsm_bssmap_msg[NUM_GSM_BSSMAP_MSG];
|
|
static void (*bssmap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
bssmap_ass_req, /* Assignment Request */
|
|
bssmap_ass_complete, /* Assignment Complete */
|
|
bssmap_ass_failure, /* Assignment Failure */
|
|
bssmap_ho_req, /* Handover Request */
|
|
bssmap_ho_reqd, /* Handover Required */
|
|
bssmap_ho_req_ack, /* Handover Request Acknowledge */
|
|
bssmap_ho_cmd, /* Handover Command */
|
|
bssmap_ho_complete, /* Handover Complete */
|
|
NULL /* no associated data */, /* Handover Succeeded */
|
|
bssmap_ho_failure, /* Handover Failure */
|
|
bssmap_ho_performed, /* Handover Performed */
|
|
bssmap_ho_cand_enq, /* Handover Candidate Enquire */
|
|
bssmap_ho_cand_resp, /* Handover Candidate Response */
|
|
bssmap_ho_reqd_rej, /* Handover Required Reject */
|
|
NULL /* no associated data */, /* Handover Detect */
|
|
bssmap_clear_cmd, /* Clear Command */
|
|
NULL /* no associated data */, /* Clear Complete */
|
|
bssmap_clear_req, /* Clear Request */
|
|
NULL, /* Reserved */
|
|
NULL, /* Reserved */
|
|
bssmap_sapi_rej, /* SAPI 'n' Reject */
|
|
bssmap_confusion, /* Confusion */
|
|
NULL, /* Suspend */
|
|
NULL, /* Resume */
|
|
bssmap_conn_oriented, /* Connection Oriented Information */
|
|
NULL, /* Perform Location Request */
|
|
bssmap_lsa_info, /* LSA Information */
|
|
NULL, /* Perform Location Response */
|
|
NULL, /* Perform Location Abort */
|
|
bssmap_reset, /* Reset */
|
|
NULL /* no associated data */, /* Reset Acknowledge */
|
|
bssmap_overload, /* Overload */
|
|
NULL, /* Reserved */
|
|
bssmap_reset_cct, /* Reset Circuit */
|
|
bssmap_reset_cct_ack, /* Reset Circuit Acknowledge */
|
|
NULL, /* MSC Invoke Trace */
|
|
NULL, /* BSS Invoke Trace */
|
|
NULL, /* Connectionless Information */
|
|
bssmap_block, /* Block */
|
|
bssmap_block_ack, /* Blocking Acknowledge */
|
|
bssmap_unblock, /* Unblock */
|
|
bssmap_unblock_ack, /* Unblocking Acknowledge */
|
|
bssmap_cct_group_block, /* Circuit Group Block */
|
|
bssmap_cct_group_block_ack, /* Circuit Group Blocking Acknowledge */
|
|
bssmap_cct_group_unblock, /* Circuit Group Unblock */
|
|
bssmap_cct_group_unblock_ack, /* Circuit Group Unblocking Acknowledge */
|
|
bssmap_unequipped_cct, /* Unequipped Circuit */
|
|
bssmap_change_cct, /* Change Circuit */
|
|
bssmap_change_cct_ack, /* Change Circuit Acknowledge */
|
|
NULL, /* Resource Request */
|
|
NULL, /* Resource Indication */
|
|
bssmap_paging, /* Paging */
|
|
bssmap_ciph_mode_cmd, /* Cipher Mode Command */
|
|
bssmap_cm_upd, /* Classmark Update */
|
|
bssmap_ciph_mode_complete, /* Cipher Mode Complete */
|
|
NULL /* no associated data */, /* Queuing Indication */
|
|
bssmap_cl3_info, /* Complete Layer 3 Information */
|
|
NULL /* no associated data */, /* Classmark Request */
|
|
bssmap_ciph_mode_rej, /* Cipher Mode Reject */
|
|
bssmap_load_ind, /* Load Indication */
|
|
NULL, /* VGCS/VBS Setup */
|
|
NULL, /* VGCS/VBS Setup Ack */
|
|
NULL, /* VGCS/VBS Setup Refuse */
|
|
NULL, /* VGCS/VBS Assignment Request */
|
|
NULL, /* VGCS/VBS Assignment Result */
|
|
NULL, /* VGCS/VBS Assignment Failure */
|
|
NULL, /* VGCS/VBS Queuing Indication */
|
|
NULL, /* Uplink Request */
|
|
NULL, /* Uplink Request Acknowledge */
|
|
NULL, /* Uplink Request Confirmation */
|
|
NULL, /* Uplink Release Indication */
|
|
NULL, /* Uplink Reject Command */
|
|
NULL, /* Uplink Release Command */
|
|
NULL, /* Uplink Seized Command */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
/*
|
|
* [4] 9.2.2
|
|
*/
|
|
static void
|
|
dtap_mm_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
/*
|
|
* special dissection for Cipher Key Sequence Number
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0x07:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: No key is available",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: %u",
|
|
a_bigbuf,
|
|
oct & 0x07);
|
|
break;
|
|
}
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_AUTH_PARAM_RAND);
|
|
|
|
ELEM_OPT_TLV(0x20, BSSAP_PDU_TYPE_DTAP, DE_AUTH_PARAM_AUTN, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.2.3
|
|
*/
|
|
static void
|
|
dtap_mm_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_AUTH_RESP_PARAM);
|
|
|
|
ELEM_OPT_TLV(0x21, BSSAP_PDU_TYPE_DTAP, DE_AUTH_RESP_PARAM_EXT, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.2.3a
|
|
*/
|
|
static void
|
|
dtap_mm_auth_fail(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
|
|
|
|
ELEM_OPT_TLV(0x22, BSSAP_PDU_TYPE_DTAP, DE_AUTH_FAIL_PARAM, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.4
|
|
*/
|
|
static void
|
|
dtap_mm_cm_reestab_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
/*
|
|
* special dissection for Cipher Key Sequence Number
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0x07:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: No key is available",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: %u",
|
|
a_bigbuf,
|
|
oct & 0x07);
|
|
break;
|
|
}
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
ELEM_OPT_TV(0x13, BSSAP_PDU_TYPE_DTAP, DE_LAI, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.5a
|
|
*/
|
|
static void
|
|
dtap_mm_cm_srvc_prompt(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_PD_SAPI);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.2.6
|
|
*/
|
|
static void
|
|
dtap_mm_cm_srvc_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.2.8
|
|
*/
|
|
static void
|
|
dtap_mm_abort(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.9
|
|
*/
|
|
static void
|
|
dtap_mm_cm_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
/*
|
|
* special dissection for CM Service Type
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0x07:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: No key is available",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: %u",
|
|
a_bigbuf,
|
|
(oct & 0x70) >> 4);
|
|
break;
|
|
}
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CM_SRVC_TYPE].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CM_SRVC_TYPE]);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0x01: str = "Mobile originating call establishment or packet mode connection establishment"; break;
|
|
case 0x02: str = "Emergency call establishment"; break;
|
|
case 0x04: str = "Short message service"; break;
|
|
case 0x08: str = "Supplementary service activation"; break;
|
|
case 0x09: str = "Voice group call establishment"; break;
|
|
case 0x0a: str = "Voice broadcast call establishment"; break;
|
|
case 0x0b: str = "Location Services"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Service Type: (%u) %s",
|
|
a_bigbuf,
|
|
oct & 0x0f,
|
|
str);
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.10
|
|
*/
|
|
static void
|
|
dtap_mm_id_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint8 oct;
|
|
guint32 curr_offset;
|
|
guint curr_len;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
/*
|
|
* special dissection for Identity Type
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_ID_TYPE].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_ID_TYPE]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 1: str = "IMSI"; break;
|
|
case 2: str = "IMEI"; break;
|
|
case 3: str = "IMEISV"; break;
|
|
case 4: str = "TMSI"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Type of identity: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.11
|
|
*/
|
|
static void
|
|
dtap_mm_id_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.12
|
|
*/
|
|
static void
|
|
dtap_mm_imsi_det_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_1);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.13
|
|
*/
|
|
static void
|
|
dtap_mm_loc_upd_acc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
|
|
|
|
ELEM_OPT_TLV(0x17, BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
ELEM_OPT_T(0xa1, BSSAP_PDU_TYPE_DTAP, DE_FOP, "");
|
|
|
|
ELEM_OPT_T(0xa2, BSSAP_PDU_TYPE_DTAP, DE_CTS_PERM, "");
|
|
|
|
ELEM_OPT_TLV(0x4a, BSSAP_PDU_TYPE_DTAP, DE_PLMN_LIST, " Equivalent");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.14
|
|
*/
|
|
static void
|
|
dtap_mm_loc_upd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.15
|
|
*/
|
|
static void
|
|
dtap_mm_loc_upd_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
/*
|
|
* special dissection for Location Updating Type
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
|
|
|
|
switch ((oct & 0x70) >> 4)
|
|
{
|
|
case 0x07:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: No key is available",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: %u",
|
|
a_bigbuf,
|
|
(oct & 0x70) >> 4);
|
|
break;
|
|
}
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_LOC_UPD_TYPE].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_LOC_UPD_TYPE]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Follow-On Request (FOR): %s",
|
|
a_bigbuf,
|
|
(oct & 0x08) ? "Follow-on request pending" : "No follow-on request pending");
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
switch (oct & 0x03)
|
|
{
|
|
case 0: str = "Normal"; break;
|
|
case 1: str = "Periodic"; break;
|
|
case 2: str = "IMSI attach"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Updating Type: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
proto_item_append_text(item, " - %s", str);
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_1);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
ELEM_OPT_TLV(0x33, BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.1.15a
|
|
*/
|
|
static void
|
|
dtap_mm_mm_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(0x43, BSSAP_PDU_TYPE_DTAP, DE_NETWORK_NAME, " - Full Name");
|
|
|
|
ELEM_OPT_TLV(0x45, BSSAP_PDU_TYPE_DTAP, DE_NETWORK_NAME, " - Short Name");
|
|
|
|
ELEM_OPT_TV(0x46, BSSAP_PDU_TYPE_DTAP, DE_TIME_ZONE, " - Local");
|
|
|
|
ELEM_OPT_TV(0x47, BSSAP_PDU_TYPE_DTAP, DE_TIME_ZONE_TIME, " - Universal Time and Local Time Zone");
|
|
|
|
ELEM_OPT_TLV(0x48, BSSAP_PDU_TYPE_DTAP, DE_LSA_ID, "");
|
|
|
|
ELEM_OPT_TLV(0x49, BSSAP_PDU_TYPE_DTAP, DE_DAY_SAVING_TIME, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.1.16
|
|
*/
|
|
static void
|
|
dtap_mm_mm_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [3] 9.2.17
|
|
*/
|
|
static void
|
|
dtap_mm_tmsi_realloc_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.1.25
|
|
*/
|
|
static void
|
|
dtap_rr_paging_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
/*
|
|
* special dissection for Cipher Key Sequence Number
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
|
|
|
|
switch (oct & 0x07)
|
|
{
|
|
case 0x07:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: No key is available",
|
|
a_bigbuf);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Ciphering Key Sequence Number: %u",
|
|
a_bigbuf,
|
|
oct & 0x07);
|
|
break;
|
|
}
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.1.29
|
|
*/
|
|
static void
|
|
dtap_rr_rr_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.1
|
|
*/
|
|
static void
|
|
dtap_cc_alerting(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.2
|
|
*/
|
|
static void
|
|
dtap_cc_call_conf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
|
|
|
|
ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.3
|
|
*/
|
|
static void
|
|
dtap_cc_call_proceed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
|
|
|
|
ELEM_OPT_TLV(0x2f, BSSAP_PDU_TYPE_DTAP, DE_NET_CC_CAP, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.4
|
|
*/
|
|
static void
|
|
dtap_cc_congestion_control(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
guint8 oct;
|
|
proto_tree *subtree;
|
|
proto_item *item;
|
|
gchar *str;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
/*
|
|
* special dissection for Congestion Level
|
|
*/
|
|
oct = tvb_get_guint8(tvb, curr_offset);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Spare",
|
|
a_bigbuf);
|
|
|
|
item =
|
|
proto_tree_add_text(tree,
|
|
tvb, curr_offset, 1,
|
|
gsm_dtap_elem_strings[DE_CONGESTION].strptr);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CONGESTION]);
|
|
|
|
switch (oct & 0x0f)
|
|
{
|
|
case 0: str = "Receiver ready"; break;
|
|
case 15: str = "Receiver not ready"; break;
|
|
default:
|
|
str = "Reserved";
|
|
break;
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
|
|
proto_tree_add_text(subtree,
|
|
tvb, curr_offset, 1,
|
|
"%s : Congestion level: %s",
|
|
a_bigbuf,
|
|
str);
|
|
|
|
curr_offset++;
|
|
curr_len--;
|
|
|
|
if (curr_len <= 0) return;
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.5
|
|
*/
|
|
static void
|
|
dtap_cc_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TLV(0x4c, BSSAP_PDU_TYPE_DTAP, DE_CONN_NUM, "");
|
|
|
|
ELEM_OPT_TLV(0x4d, BSSAP_PDU_TYPE_DTAP, DE_CONN_SUB_ADDR, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.7
|
|
*/
|
|
static void
|
|
dtap_cc_disconnect(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
ELEM_OPT_TLV(0x7b, BSSAP_PDU_TYPE_DTAP, DE_ALLOWED_ACTIONS, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.8
|
|
*/
|
|
static void
|
|
dtap_cc_emerg_setup(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
|
|
|
|
ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
|
|
|
|
ELEM_OPT_TLV(0x2e, BSSAP_PDU_TYPE_DTAP, DE_SRVC_CAT, " Emergency");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.9
|
|
*/
|
|
static void
|
|
dtap_cc_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.12
|
|
*/
|
|
static void
|
|
dtap_cc_hold_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.13
|
|
*/
|
|
static void
|
|
dtap_cc_modify(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
|
|
|
|
ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
|
|
|
|
ELEM_OPT_T(0xa3, BSSAP_PDU_TYPE_DTAP, DE_REV_CALL_SETUP_DIR, "");
|
|
|
|
ELEM_OPT_T(0xa4, BSSAP_PDU_TYPE_DTAP, DE_IMM_MOD_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.14
|
|
*/
|
|
static void
|
|
dtap_cc_modify_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
|
|
|
|
ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
|
|
|
|
ELEM_OPT_T(0xa3, BSSAP_PDU_TYPE_DTAP, DE_REV_CALL_SETUP_DIR, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.15
|
|
*/
|
|
static void
|
|
dtap_cc_modify_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
|
|
|
|
ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.16
|
|
*/
|
|
static void
|
|
dtap_cc_notify(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_NOT_IND);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.17
|
|
*/
|
|
static void
|
|
dtap_cc_progress(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.17a
|
|
*/
|
|
static void
|
|
dtap_cc_cc_est(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_SETUP_CONTAINER, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.17b
|
|
*/
|
|
static void
|
|
dtap_cc_cc_est_conf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " Repeat indicator");
|
|
|
|
ELEM_MAND_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.18
|
|
*/
|
|
static void
|
|
dtap_cc_release(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, " 2");
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.18a
|
|
*/
|
|
static void
|
|
dtap_cc_recall(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RECALL_TYPE);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.19
|
|
*/
|
|
static void
|
|
dtap_cc_release_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.22
|
|
*/
|
|
static void
|
|
dtap_cc_retrieve_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.23
|
|
*/
|
|
static void
|
|
dtap_cc_setup(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
|
|
|
|
ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
|
|
|
|
ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
|
|
|
|
ELEM_OPT_TV(0x34, BSSAP_PDU_TYPE_DTAP, DE_SIGNAL, "");
|
|
|
|
ELEM_OPT_TLV(0x5c, BSSAP_PDU_TYPE_DTAP, DE_CLG_PARTY_BCD_NUM, "");
|
|
|
|
ELEM_OPT_TLV(0x5d, BSSAP_PDU_TYPE_DTAP, DE_CLG_PARTY_SUB_ADDR, "");
|
|
|
|
ELEM_OPT_TLV(0x5e, BSSAP_PDU_TYPE_DTAP, DE_CLD_PARTY_BCD_NUM, "");
|
|
|
|
ELEM_OPT_TLV(0x6d, BSSAP_PDU_TYPE_DTAP, DE_CLD_PARTY_SUB_ADDR, "");
|
|
|
|
ELEM_OPT_TLV(0x74, BSSAP_PDU_TYPE_DTAP, DE_RED_PARTY_BCD_NUM, "");
|
|
|
|
ELEM_OPT_TLV(0x75, BSSAP_PDU_TYPE_DTAP, DE_RED_PARTY_SUB_ADDR, "");
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " LLC repeat indicator");
|
|
|
|
ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, " 1");
|
|
|
|
ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, " 2");
|
|
|
|
ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " HLC repeat indicator");
|
|
|
|
ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, " 1");
|
|
|
|
ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, " 2");
|
|
|
|
ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
/* downlink only */
|
|
|
|
ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
|
|
|
|
ELEM_OPT_TLV(0x19, BSSAP_PDU_TYPE_DTAP, DE_ALERT_PATTERN, "");
|
|
|
|
ELEM_OPT_TLV(0x2f, BSSAP_PDU_TYPE_DTAP, DE_NET_CC_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x3a, BSSAP_PDU_TYPE_DTAP, DE_CAUSE_NO_CLI, "");
|
|
|
|
/* uplink only */
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
ELEM_OPT_T(0xa1, BSSAP_PDU_TYPE_DTAP, DE_FOP, "");
|
|
|
|
ELEM_OPT_T(0xa2, BSSAP_PDU_TYPE_DTAP, DE_CTS_PERM, "");
|
|
|
|
ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
|
|
|
|
ELEM_OPT_TLV(0x1d, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, " $(CCBS)$ (advanced recall alignment)");
|
|
|
|
ELEM_OPT_TLV(0x1b, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, " (recall alignment Not essential) $(CCBS)$");
|
|
|
|
ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
|
|
|
|
ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.23a
|
|
*/
|
|
static void
|
|
dtap_cc_start_cc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.24
|
|
*/
|
|
static void
|
|
dtap_cc_start_dtmf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TV(0x2c, BSSAP_PDU_TYPE_DTAP, DE_KEYPAD_FACILITY, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.25
|
|
*/
|
|
static void
|
|
dtap_cc_start_dtmf_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_TV(0x2c, BSSAP_PDU_TYPE_DTAP, DE_KEYPAD_FACILITY, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.26
|
|
*/
|
|
static void
|
|
dtap_cc_start_dtmf_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.27
|
|
*/
|
|
static void
|
|
dtap_cc_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_CALL_STATE);
|
|
|
|
ELEM_OPT_TLV(0x24, BSSAP_PDU_TYPE_DTAP, DE_AUX_STATES, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [4] 9.3.31
|
|
*/
|
|
static void
|
|
dtap_cc_user_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
|
|
|
|
ELEM_OPT_T(0xa0, BSSAP_PDU_TYPE_DTAP, DE_MORE_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [6] 2.4.2
|
|
*/
|
|
static void
|
|
dtap_ss_register(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
|
|
|
|
ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.2.1
|
|
*/
|
|
static void
|
|
dtap_sms_cp_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.2.3
|
|
*/
|
|
static void
|
|
dtap_sms_cp_error(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_CP_CAUSE);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.1.1
|
|
*/
|
|
static void
|
|
rp_data_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
g_pinfo->p2p_dir = P2P_DIR_SENT;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_ORIG_ADDR, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_DEST_ADDR, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.1.2
|
|
*/
|
|
static void
|
|
rp_data_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
g_pinfo->p2p_dir = P2P_DIR_RECV;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_ORIG_ADDR, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_DEST_ADDR, "");
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.2
|
|
*/
|
|
static void
|
|
rp_smma(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.3
|
|
*/
|
|
static void
|
|
rp_ack_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
g_pinfo->p2p_dir = P2P_DIR_SENT;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.3
|
|
*/
|
|
static void
|
|
rp_ack_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
g_pinfo->p2p_dir = P2P_DIR_RECV;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.4
|
|
*/
|
|
static void
|
|
rp_error_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_FALSE;
|
|
g_pinfo->p2p_dir = P2P_DIR_SENT;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
/*
|
|
* [5] 7.3.4
|
|
*/
|
|
static void
|
|
rp_error_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
|
|
{
|
|
guint32 curr_offset;
|
|
guint32 consumed;
|
|
guint curr_len;
|
|
|
|
curr_offset = offset;
|
|
curr_len = len;
|
|
|
|
is_uplink = IS_UPLINK_TRUE;
|
|
g_pinfo->p2p_dir = P2P_DIR_RECV;
|
|
|
|
ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
|
|
|
|
ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_CAUSE, "");
|
|
|
|
ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
|
|
|
|
EXTRANEOUS_DATA_CHECK(curr_len, 0);
|
|
}
|
|
|
|
#define NUM_GSM_DTAP_MSG_MM (sizeof(gsm_a_dtap_msg_mm_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_mm[NUM_GSM_DTAP_MSG_MM];
|
|
static void (*dtap_msg_mm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
dtap_mm_imsi_det_ind, /* IMSI Detach Indication */
|
|
dtap_mm_loc_upd_acc, /* Location Updating Accept */
|
|
dtap_mm_loc_upd_rej, /* Location Updating Reject */
|
|
dtap_mm_loc_upd_req, /* Location Updating Request */
|
|
NULL /* no associated data */, /* Authentication Reject */
|
|
dtap_mm_auth_req, /* Authentication Request */
|
|
dtap_mm_auth_resp, /* Authentication Response */
|
|
dtap_mm_auth_fail, /* Authentication Failure */
|
|
dtap_mm_id_req, /* Identity Request */
|
|
dtap_mm_id_resp, /* Identity Response */
|
|
dtap_mm_tmsi_realloc_cmd, /* TMSI Reallocation Command */
|
|
NULL /* no associated data */, /* TMSI Reallocation Complete */
|
|
NULL /* no associated data */, /* CM Service Accept */
|
|
dtap_mm_cm_srvc_rej, /* CM Service Reject */
|
|
NULL /* no associated data */, /* CM Service Abort */
|
|
dtap_mm_cm_srvc_req, /* CM Service Request */
|
|
dtap_mm_cm_srvc_prompt, /* CM Service Prompt */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
dtap_mm_cm_reestab_req, /* CM Re-establishment Request */
|
|
dtap_mm_abort, /* Abort */
|
|
NULL /* no associated data */, /* MM Null */
|
|
dtap_mm_mm_status, /* MM Status */
|
|
dtap_mm_mm_info, /* MM Information */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_RR (sizeof(gsm_a_dtap_msg_rr_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_rr[NUM_GSM_DTAP_MSG_RR];
|
|
static void (*dtap_msg_rr_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
NULL, /* RR Initialisation Request */
|
|
NULL, /* Additional Assignment */
|
|
NULL, /* Immediate Assignment */
|
|
NULL, /* Immediate Assignment Extended */
|
|
NULL, /* Immediate Assignment Reject */
|
|
|
|
NULL, /* DTM Assignment Failure */
|
|
NULL, /* DTM Reject */
|
|
NULL, /* DTM Request */
|
|
NULL, /* Main DCCH Assignment Command */
|
|
NULL, /* Packet Assignment Command */
|
|
|
|
NULL, /* Ciphering Mode Command */
|
|
NULL, /* Ciphering Mode Complete */
|
|
|
|
NULL, /* Configuration Change Command */
|
|
NULL, /* Configuration Change Ack. */
|
|
NULL, /* Configuration Change Reject */
|
|
|
|
NULL, /* Assignment Command */
|
|
NULL, /* Assignment Complete */
|
|
NULL, /* Assignment Failure */
|
|
NULL, /* Handover Command */
|
|
NULL, /* Handover Complete */
|
|
NULL, /* Handover Failure */
|
|
NULL, /* Physical Information */
|
|
NULL, /* DTM Assignment Command */
|
|
|
|
NULL, /* RR-cell Change Order */
|
|
NULL, /* PDCH Assignment Command */
|
|
|
|
NULL, /* Channel Release */
|
|
NULL, /* Partial Release */
|
|
NULL, /* Partial Release Complete */
|
|
|
|
NULL, /* Paging Request Type 1 */
|
|
NULL, /* Paging Request Type 2 */
|
|
NULL, /* Paging Request Type 3 */
|
|
dtap_rr_paging_resp, /* Paging Response */
|
|
NULL, /* Notification/NCH */
|
|
NULL, /* Reserved */
|
|
NULL, /* Notification/Response */
|
|
|
|
NULL, /* Reserved */
|
|
|
|
/* NULL, * Utran Classmark Change * CONFLICTS WITH Handover To UTRAN Command */
|
|
NULL, /* UE RAB Preconfiguration */
|
|
NULL, /* cdma2000 Classmark Change */
|
|
|
|
NULL, /* System Information Type 8 */
|
|
NULL, /* System Information Type 1 */
|
|
NULL, /* System Information Type 2 */
|
|
NULL, /* System Information Type 3 */
|
|
NULL, /* System Information Type 4 */
|
|
NULL, /* System Information Type 5 */
|
|
NULL, /* System Information Type 6 */
|
|
NULL, /* System Information Type 7 */
|
|
|
|
NULL, /* System Information Type 2bis */
|
|
NULL, /* System Information Type 2ter */
|
|
NULL, /* System Information Type 2quater */
|
|
NULL, /* System Information Type 5bis */
|
|
NULL, /* System Information Type 5ter */
|
|
NULL, /* System Information Type 9 */
|
|
NULL, /* System Information Type 13 */
|
|
|
|
NULL, /* System Information Type 16 */
|
|
NULL, /* System Information Type 17 */
|
|
|
|
NULL, /* System Information Type 18 */
|
|
NULL, /* System Information Type 19 */
|
|
NULL, /* System Information Type 20 */
|
|
|
|
NULL, /* Channel Mode Modify */
|
|
dtap_rr_rr_status, /* RR Status */
|
|
NULL, /* Channel Mode Modify Acknowledge */
|
|
NULL, /* Frequency Redefinition */
|
|
NULL, /* Measurement Report */
|
|
NULL, /* Classmark Change */
|
|
NULL, /* Classmark Enquiry */
|
|
NULL, /* Extended Measurement Report */
|
|
NULL, /* Extended Measurement Order */
|
|
NULL, /* GPRS Suspension Request */
|
|
|
|
NULL, /* VGCS Uplink Grant */
|
|
NULL, /* Uplink Release */
|
|
NULL, /* Reserved */
|
|
NULL, /* Uplink Busy */
|
|
NULL, /* Talker Indication */
|
|
|
|
NULL, /* UTRAN Classmark Change/Handover To UTRAN Command */ /* spec conflict */
|
|
|
|
NULL, /* Application Information */
|
|
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_CC (sizeof(gsm_a_dtap_msg_cc_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_cc[NUM_GSM_DTAP_MSG_CC];
|
|
static void (*dtap_msg_cc_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
dtap_cc_alerting, /* Alerting */
|
|
dtap_cc_call_conf, /* Call Confirmed */
|
|
dtap_cc_call_proceed, /* Call Proceeding */
|
|
dtap_cc_connect, /* Connect */
|
|
NULL /* no associated data */, /* Connect Acknowledge */
|
|
dtap_cc_emerg_setup, /* Emergency Setup */
|
|
dtap_cc_progress, /* Progress */
|
|
dtap_cc_cc_est, /* CC-Establishment */
|
|
dtap_cc_cc_est_conf, /* CC-Establishment Confirmed */
|
|
dtap_cc_recall, /* Recall */
|
|
dtap_cc_start_cc, /* Start CC */
|
|
dtap_cc_setup, /* Setup */
|
|
dtap_cc_modify, /* Modify */
|
|
dtap_cc_modify_complete, /* Modify Complete */
|
|
dtap_cc_modify_rej, /* Modify Reject */
|
|
dtap_cc_user_info, /* User Information */
|
|
NULL /* no associated data */, /* Hold */
|
|
NULL /* no associated data */, /* Hold Acknowledge */
|
|
dtap_cc_hold_rej, /* Hold Reject */
|
|
NULL /* no associated data */, /* Retrieve */
|
|
NULL /* no associated data */, /* Retrieve Acknowledge */
|
|
dtap_cc_retrieve_rej, /* Retrieve Reject */
|
|
dtap_cc_disconnect, /* Disconnect */
|
|
dtap_cc_release, /* Release */
|
|
dtap_cc_release_complete, /* Release Complete */
|
|
dtap_cc_congestion_control, /* Congestion Control */
|
|
dtap_cc_notify, /* Notify */
|
|
dtap_cc_status, /* Status */
|
|
NULL /* no associated data */, /* Status Enquiry */
|
|
dtap_cc_start_dtmf, /* Start DTMF */
|
|
NULL /* no associated data */, /* Stop DTMF */
|
|
NULL /* no associated data */, /* Stop DTMF Acknowledge */
|
|
dtap_cc_start_dtmf_ack, /* Start DTMF Acknowledge */
|
|
dtap_cc_start_dtmf_rej, /* Start DTMF Reject */
|
|
dtap_cc_facility, /* Facility */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_GMM (sizeof(gsm_a_dtap_msg_gmm_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_gmm[NUM_GSM_DTAP_MSG_GMM];
|
|
static void (*dtap_msg_gmm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
NULL, /* Attach Request */
|
|
NULL, /* Attach Accept */
|
|
NULL, /* Attach Complete */
|
|
NULL, /* Attach Reject */
|
|
NULL, /* Detach Request */
|
|
NULL, /* Detach Accept */
|
|
NULL, /* Routing Area Update Request */
|
|
NULL, /* Routing Area Update Accept */
|
|
NULL, /* Routing Area Update Complete */
|
|
NULL, /* Routing Area Update Reject */
|
|
NULL, /* Service Request */
|
|
NULL, /* Service Accept */
|
|
NULL, /* Service Reject */
|
|
NULL, /* P-TMSI Reallocation Command */
|
|
NULL, /* P-TMSI Reallocation Complete */
|
|
NULL, /* Authentication and Ciphering Req */
|
|
NULL, /* Authentication and Ciphering Resp */
|
|
NULL, /* Authentication and Ciphering Rej */
|
|
NULL, /* Authentication and Ciphering Failure */
|
|
NULL, /* Identity Request */
|
|
NULL, /* Identity Response */
|
|
NULL, /* GMM Status */
|
|
NULL, /* GMM Information */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_SMS (sizeof(gsm_a_dtap_msg_sms_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_sms[NUM_GSM_DTAP_MSG_SMS];
|
|
static void (*dtap_msg_sms_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
dtap_sms_cp_data, /* CP-DATA */
|
|
NULL /* no associated data */, /* CP-ACK */
|
|
dtap_sms_cp_error, /* CP-ERROR */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_SM (sizeof(gsm_a_dtap_msg_sm_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_sm[NUM_GSM_DTAP_MSG_SM];
|
|
static void (*dtap_msg_sm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
NULL, /* Activate PDP Context Request */
|
|
NULL, /* Activate PDP Context Accept */
|
|
NULL, /* Activate PDP Context Reject */
|
|
NULL, /* Request PDP Context Activation */
|
|
NULL, /* Request PDP Context Activation rej. */
|
|
NULL, /* Deactivate PDP Context Request */
|
|
NULL, /* Deactivate PDP Context Accept */
|
|
NULL, /* Modify PDP Context Request(Network to MS direction) */
|
|
NULL, /* Modify PDP Context Accept (MS to network direction) */
|
|
NULL, /* Modify PDP Context Request(MS to network direction) */
|
|
NULL, /* Modify PDP Context Accept (Network to MS direction) */
|
|
NULL, /* Modify PDP Context Reject */
|
|
NULL, /* Activate Secondary PDP Context Request */
|
|
NULL, /* Activate Secondary PDP Context Accept */
|
|
NULL, /* Activate Secondary PDP Context Reject */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
NULL, /* Reserved: was allocated in earlier phases of the protocol */
|
|
NULL, /* SM Status */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_DTAP_MSG_SS (sizeof(gsm_a_dtap_msg_ss_strings)/sizeof(value_string))
|
|
static gint ett_gsm_dtap_msg_ss[NUM_GSM_DTAP_MSG_SS];
|
|
static void (*dtap_msg_ss_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
dtap_cc_release_complete, /* Release Complete */
|
|
dtap_cc_facility, /* Facility */
|
|
dtap_ss_register, /* Register */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
#define NUM_GSM_RP_MSG (sizeof(gsm_rp_msg_strings)/sizeof(value_string))
|
|
static gint ett_gsm_rp_msg[NUM_GSM_RP_MSG];
|
|
static void (*rp_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
|
|
rp_data_ms_n, /* RP-DATA (MS to Network) */
|
|
rp_data_n_ms, /* RP-DATA (Network to MS */
|
|
rp_ack_ms_n, /* RP-ACK (MS to Network) */
|
|
rp_ack_n_ms, /* RP-ACK (Network to MS) */
|
|
rp_error_ms_n, /* RP-ERROR (MS to Network) */
|
|
rp_error_n_ms, /* RP-ERROR (Network to MS) */
|
|
rp_smma, /* RP-SMMA (MS to Network) */
|
|
NULL, /* NONE */
|
|
};
|
|
|
|
/* GENERIC DISSECTOR FUNCTIONS */
|
|
|
|
static void
|
|
dissect_rp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
guint8 oct;
|
|
guint32 offset, saved_offset;
|
|
guint32 len;
|
|
gint idx;
|
|
proto_item *rp_item = NULL;
|
|
proto_tree *rp_tree = NULL;
|
|
gchar *str;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_str(pinfo->cinfo, COL_INFO, "(RP) ");
|
|
}
|
|
|
|
/*
|
|
* In the interest of speed, if "tree" is NULL, don't do any work
|
|
* not necessary to generate protocol tree items.
|
|
*/
|
|
if (!tree)
|
|
{
|
|
return;
|
|
}
|
|
|
|
offset = 0;
|
|
saved_offset = offset;
|
|
|
|
g_pinfo = pinfo;
|
|
g_tree = tree;
|
|
|
|
len = tvb_length(tvb);
|
|
|
|
/*
|
|
* add RP message name
|
|
*/
|
|
oct = tvb_get_guint8(tvb, offset++);
|
|
|
|
str = my_match_strval((guint32) oct, gsm_rp_msg_strings, &idx);
|
|
|
|
/*
|
|
* create the protocol tree
|
|
*/
|
|
if (str == NULL)
|
|
{
|
|
rp_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, len,
|
|
"GSM A-I/F RP - Unknown RP Message Type (0x%02x)",
|
|
oct);
|
|
|
|
rp_tree = proto_item_add_subtree(rp_item, ett_rp_msg);
|
|
}
|
|
else
|
|
{
|
|
rp_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, -1,
|
|
"GSM A-I/F RP - %s",
|
|
str);
|
|
|
|
rp_tree = proto_item_add_subtree(rp_item, ett_gsm_rp_msg[idx]);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* add RP message name
|
|
*/
|
|
proto_tree_add_uint_format(rp_tree, hf_gsm_a_rp_msg_type,
|
|
tvb, saved_offset, 1, oct, "Message Type");
|
|
|
|
if (str == NULL) return;
|
|
|
|
if ((len - offset) <= 0) return;
|
|
|
|
/*
|
|
* decode elements
|
|
*/
|
|
if (rp_msg_fcn[idx] == NULL)
|
|
{
|
|
proto_tree_add_text(rp_tree,
|
|
tvb, offset, len - offset,
|
|
"Message Elements");
|
|
}
|
|
else
|
|
{
|
|
(*rp_msg_fcn[idx])(tvb, rp_tree, offset, len - offset);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_bssmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
static gsm_a_tap_rec_t tap_rec[4];
|
|
static gsm_a_tap_rec_t *tap_p;
|
|
static int tap_current=0;
|
|
guint8 oct;
|
|
guint32 offset, saved_offset;
|
|
guint32 len;
|
|
gint idx;
|
|
proto_item *bssmap_item = NULL;
|
|
proto_tree *bssmap_tree = NULL;
|
|
gchar *str;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_str(pinfo->cinfo, COL_INFO, "(BSSMAP) ");
|
|
}
|
|
|
|
/*
|
|
* set tap record pointer
|
|
*/
|
|
tap_current++;
|
|
if (tap_current == 4)
|
|
{
|
|
tap_current = 0;
|
|
}
|
|
tap_p = &tap_rec[tap_current];
|
|
|
|
|
|
offset = 0;
|
|
saved_offset = offset;
|
|
|
|
g_pinfo = pinfo;
|
|
g_tree = tree;
|
|
|
|
len = tvb_length(tvb);
|
|
|
|
/*
|
|
* add BSSMAP message name
|
|
*/
|
|
oct = tvb_get_guint8(tvb, offset++);
|
|
|
|
str = my_match_strval((guint32) oct, gsm_a_bssmap_msg_strings, &idx);
|
|
|
|
/*
|
|
* create the protocol tree
|
|
*/
|
|
if (str == NULL)
|
|
{
|
|
bssmap_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_bssmap, tvb, 0, len,
|
|
"GSM A-I/F BSSMAP - Unknown BSSMAP Message Type (0x%02x)",
|
|
oct);
|
|
|
|
bssmap_tree = proto_item_add_subtree(bssmap_item, ett_bssmap_msg);
|
|
}
|
|
else
|
|
{
|
|
bssmap_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_bssmap, tvb, 0, -1,
|
|
"GSM A-I/F BSSMAP - %s",
|
|
str);
|
|
|
|
bssmap_tree = proto_item_add_subtree(bssmap_item, ett_gsm_bssmap_msg[idx]);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* add BSSMAP message name
|
|
*/
|
|
proto_tree_add_uint_format(bssmap_tree, hf_gsm_a_bssmap_msg_type,
|
|
tvb, saved_offset, 1, oct, "Message Type");
|
|
|
|
tap_p->pdu_type = BSSAP_PDU_TYPE_BSSMAP;
|
|
tap_p->message_type = oct;
|
|
|
|
tap_queue_packet(gsm_a_tap, pinfo, tap_p);
|
|
|
|
if (str == NULL) return;
|
|
|
|
if ((len - offset) <= 0) return;
|
|
|
|
/*
|
|
* decode elements
|
|
*/
|
|
if (bssmap_msg_fcn[idx] == NULL)
|
|
{
|
|
proto_tree_add_text(bssmap_tree,
|
|
tvb, offset, len - offset,
|
|
"Message Elements");
|
|
}
|
|
else
|
|
{
|
|
(*bssmap_msg_fcn[idx])(tvb, bssmap_tree, offset, len - offset);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
static gsm_a_tap_rec_t tap_rec[4];
|
|
static gsm_a_tap_rec_t *tap_p;
|
|
static int tap_current=0;
|
|
void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len);
|
|
guint8 oct;
|
|
guint8 pd;
|
|
guint32 offset;
|
|
guint32 len;
|
|
guint32 oct_1, oct_2;
|
|
gint idx;
|
|
proto_item *dtap_item = NULL;
|
|
proto_tree *dtap_tree = NULL;
|
|
proto_item *oct_1_item = NULL;
|
|
proto_tree *pd_tree = NULL;
|
|
gchar *msg_str;
|
|
const gchar *str;
|
|
gint ett_tree;
|
|
gint ti;
|
|
int hf_idx;
|
|
gboolean nsd;
|
|
|
|
|
|
len = tvb_length(tvb);
|
|
|
|
if (len < 2)
|
|
{
|
|
/*
|
|
* too short to be DTAP
|
|
*/
|
|
call_dissector(data_handle, tvb, pinfo, tree);
|
|
return;
|
|
}
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_str(pinfo->cinfo, COL_INFO, "(DTAP) ");
|
|
}
|
|
|
|
/*
|
|
* set tap record pointer
|
|
*/
|
|
tap_current++;
|
|
if (tap_current == 4)
|
|
{
|
|
tap_current = 0;
|
|
}
|
|
tap_p = &tap_rec[tap_current];
|
|
|
|
|
|
offset = 0;
|
|
oct_2 = 0;
|
|
|
|
g_pinfo = pinfo;
|
|
g_tree = tree;
|
|
|
|
/*
|
|
* get protocol discriminator
|
|
*/
|
|
oct_1 = tvb_get_guint8(tvb, offset++);
|
|
|
|
if ((((oct_1 & DTAP_TI_MASK) >> 4) & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
|
|
{
|
|
/*
|
|
* eventhough we don't know if a TI should be in the message yet
|
|
* we rely on the TI/SKIP indicator to be 0 to avoid taking this
|
|
* octet
|
|
*/
|
|
oct_2 = tvb_get_guint8(tvb, offset++);
|
|
}
|
|
|
|
oct = tvb_get_guint8(tvb, offset);
|
|
|
|
pd = oct_1 & DTAP_PD_MASK;
|
|
ti = -1;
|
|
msg_str = NULL;
|
|
ett_tree = -1;
|
|
hf_idx = -1;
|
|
msg_fcn = NULL;
|
|
nsd = FALSE;
|
|
|
|
/*
|
|
* octet 1
|
|
*/
|
|
switch (pd)
|
|
{
|
|
case 3:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_CC_IEI_MASK), gsm_a_dtap_msg_cc_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_cc[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_cc_type;
|
|
msg_fcn = dtap_msg_cc_fcn[idx];
|
|
ti = (oct_1 & DTAP_TI_MASK) >> 4;
|
|
nsd = TRUE;
|
|
break;
|
|
|
|
case 5:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_MM_IEI_MASK), gsm_a_dtap_msg_mm_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_mm[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_mm_type;
|
|
msg_fcn = dtap_msg_mm_fcn[idx];
|
|
nsd = TRUE;
|
|
break;
|
|
|
|
case 6:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_RR_IEI_MASK), gsm_a_dtap_msg_rr_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_rr[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_rr_type;
|
|
msg_fcn = dtap_msg_rr_fcn[idx];
|
|
break;
|
|
|
|
case 8:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_GMM_IEI_MASK), gsm_a_dtap_msg_gmm_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_gmm[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_gmm_type;
|
|
msg_fcn = dtap_msg_gmm_fcn[idx];
|
|
break;
|
|
|
|
case 9:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_SMS_IEI_MASK), gsm_a_dtap_msg_sms_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_sms[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_sms_type;
|
|
msg_fcn = dtap_msg_sms_fcn[idx];
|
|
ti = (oct_1 & DTAP_TI_MASK) >> 4;
|
|
break;
|
|
|
|
case 10:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_SM_IEI_MASK), gsm_a_dtap_msg_sm_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_sm[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_sm_type;
|
|
msg_fcn = dtap_msg_sm_fcn[idx];
|
|
ti = (oct_1 & DTAP_TI_MASK) >> 4;
|
|
break;
|
|
|
|
case 11:
|
|
str = gsm_a_pd_str[pd];
|
|
msg_str = my_match_strval((guint32) (oct & DTAP_SS_IEI_MASK), gsm_a_dtap_msg_ss_strings, &idx);
|
|
ett_tree = ett_gsm_dtap_msg_ss[idx];
|
|
hf_idx = hf_gsm_a_dtap_msg_ss_type;
|
|
msg_fcn = dtap_msg_ss_fcn[idx];
|
|
ti = (oct_1 & DTAP_TI_MASK) >> 4;
|
|
nsd = TRUE;
|
|
break;
|
|
|
|
default:
|
|
str = gsm_a_pd_str[pd];
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* create the protocol tree
|
|
*/
|
|
if (msg_str == NULL)
|
|
{
|
|
dtap_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, len,
|
|
"GSM A-I/F DTAP - Unknown DTAP Message Type (0x%02x)",
|
|
oct);
|
|
|
|
dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap_msg);
|
|
}
|
|
else
|
|
{
|
|
dtap_item =
|
|
proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, -1,
|
|
"GSM A-I/F DTAP - %s",
|
|
msg_str);
|
|
|
|
dtap_tree = proto_item_add_subtree(dtap_item, ett_tree);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
|
|
}
|
|
}
|
|
|
|
oct_1_item =
|
|
proto_tree_add_text(dtap_tree,
|
|
tvb, 0, 1,
|
|
"Protocol Discriminator: %s",
|
|
str);
|
|
|
|
pd_tree = proto_item_add_subtree(oct_1_item, ett_dtap_oct_1);
|
|
|
|
if (ti == -1)
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct_1, 0xf0, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 0, 1,
|
|
"%s : Skip Indicator",
|
|
a_bigbuf);
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct_1, 0x80, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 0, 1,
|
|
"%s : TI flag: %s",
|
|
a_bigbuf,
|
|
((oct_1 & 0x80) ? "allocated by receiver" : "allocated by sender"));
|
|
|
|
if ((ti & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
|
|
{
|
|
/* ti is extended to next octet */
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct_1, 0x70, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 0, 1,
|
|
"%s : TIO: The TI value is given by the TIE in octet 2",
|
|
a_bigbuf);
|
|
}
|
|
else
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct_1, 0x70, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 0, 1,
|
|
"%s : TIO: %u",
|
|
a_bigbuf,
|
|
ti & DTAP_TIE_PRES_MASK);
|
|
}
|
|
}
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct_1, DTAP_PD_MASK, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 0, 1,
|
|
"%s : Protocol Discriminator: %u",
|
|
a_bigbuf,
|
|
pd);
|
|
|
|
if ((ti != -1) &&
|
|
(ti & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
|
|
{
|
|
other_decode_bitfield_value(a_bigbuf, oct_2, 0x80, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 1, 1,
|
|
"%s : Extension",
|
|
a_bigbuf);
|
|
|
|
other_decode_bitfield_value(a_bigbuf, oct_2, DTAP_TIE_MASK, 8);
|
|
proto_tree_add_text(pd_tree,
|
|
tvb, 1, 1,
|
|
"%s : TIE: %u",
|
|
a_bigbuf,
|
|
oct_2 & DTAP_TIE_MASK);
|
|
}
|
|
|
|
/*
|
|
* N(SD)
|
|
*/
|
|
if ((pinfo->p2p_dir == P2P_DIR_RECV) &&
|
|
nsd)
|
|
{
|
|
/* XXX */
|
|
}
|
|
|
|
/*
|
|
* add DTAP message name
|
|
*/
|
|
proto_tree_add_uint_format(dtap_tree, hf_idx,
|
|
tvb, offset, 1, oct,
|
|
"Message Type");
|
|
|
|
offset++;
|
|
|
|
tap_p->pdu_type = BSSAP_PDU_TYPE_DTAP;
|
|
tap_p->message_type = (nsd ? (oct & 0x3f) : oct);
|
|
tap_p->protocol_disc = pd;
|
|
|
|
tap_queue_packet(gsm_a_tap, pinfo, tap_p);
|
|
|
|
if (msg_str == NULL) return;
|
|
|
|
if ((len - offset) <= 0) return;
|
|
|
|
/*
|
|
* decode elements
|
|
*/
|
|
if (msg_fcn == NULL)
|
|
{
|
|
proto_tree_add_text(dtap_tree,
|
|
tvb, offset, len - offset,
|
|
"Message Elements");
|
|
}
|
|
else
|
|
{
|
|
(*msg_fcn)(tvb, dtap_tree, offset, len - offset);
|
|
}
|
|
}
|
|
|
|
|
|
/* Register the protocol with Ethereal */
|
|
void
|
|
proto_register_gsm_a(void)
|
|
{
|
|
guint i;
|
|
guint last_offset;
|
|
|
|
/* Setup list of header fields */
|
|
|
|
static hf_register_info hf[] =
|
|
{
|
|
{ &hf_gsm_a_bssmap_msg_type,
|
|
{ "BSSMAP Message Type", "gsm_a.bssmap_msgtype",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_bssmap_msg_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_mm_type,
|
|
{ "DTAP Mobility Management Message Type", "gsm_a.dtap_msg_mm_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_mm_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_rr_type,
|
|
{ "DTAP Radio Resources Management Message Type", "gsm_a.dtap_msg_rr_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_rr_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_cc_type,
|
|
{ "DTAP Call Control Message Type", "gsm_a.dtap_msg_cc_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_cc_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_gmm_type,
|
|
{ "DTAP GPRS Mobility Management Message Type", "gsm_a.dtap_msg_gmm_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_gmm_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_sms_type,
|
|
{ "DTAP Short Message Service Message Type", "gsm_a.dtap_msg_sms_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_sms_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_sm_type,
|
|
{ "DTAP GPRS Session Management Message Type", "gsm_a.dtap_msg_sm_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_sm_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_msg_ss_type,
|
|
{ "DTAP Non call Supplementary Service Message Type", "gsm_a.dtap_msg_ss_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_ss_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_rp_msg_type,
|
|
{ "RP Message Type", "gsm_a.rp_msg_type",
|
|
FT_UINT8, BASE_HEX, VALS(gsm_rp_msg_strings), 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_bssmap_elem_id,
|
|
{ "Element ID", "gsm_a_bssmap.elem_id",
|
|
FT_UINT8, BASE_DEC, NULL, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_elem_id,
|
|
{ "Element ID", "gsm_a_dtap.elem_id",
|
|
FT_UINT8, BASE_DEC, NULL, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_length,
|
|
{ "Length", "gsm_a.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_none,
|
|
{ "Sub tree", "gsm_a.none",
|
|
FT_NONE, 0, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_imsi,
|
|
{ "IMSI", "gsm_a.imsi",
|
|
FT_STRING, BASE_DEC, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_tmsi,
|
|
{ "TMSI/P-TMSI", "gsm_a.tmsi",
|
|
FT_UINT32, BASE_HEX, 0, 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_imei,
|
|
{ "IMEI", "gsm_a.imei",
|
|
FT_STRING, BASE_DEC, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_imeisv,
|
|
{ "IMEISV", "gsm_a.imeisv",
|
|
FT_STRING, BASE_DEC, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_cld_party_bcd_num,
|
|
{ "Called Party BCD Number", "gsm_a.cld_party_bcd_num",
|
|
FT_STRING, BASE_DEC, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_clg_party_bcd_num,
|
|
{ "Calling Party BCD Number", "gsm_a.clg_party_bcd_num",
|
|
FT_STRING, BASE_DEC, 0, 0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_cell_ci,
|
|
{ "Cell CI", "gsm_a.cell_ci",
|
|
FT_UINT16, BASE_HEX, 0, 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_cell_lac,
|
|
{ "Cell LAC", "gsm_a.cell_lac",
|
|
FT_UINT16, BASE_HEX, 0, 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dlci_cc,
|
|
{ "Control Channel", "bssap.dlci.cc",
|
|
FT_UINT8, BASE_HEX, VALS(bssap_cc_values), 0xc0,
|
|
"", HFILL}
|
|
},
|
|
{ &hf_gsm_a_dlci_spare,
|
|
{ "Spare", "bssap.dlci.spare",
|
|
FT_UINT8, BASE_HEX, NULL, 0x38,
|
|
"", HFILL}
|
|
},
|
|
{ &hf_gsm_a_dlci_sapi,
|
|
{ "SAPI", "bssap.dlci.sapi",
|
|
FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), 0x07,
|
|
"", HFILL}
|
|
},
|
|
{ &hf_gsm_a_bssmap_cause,
|
|
{ "BSSMAP Cause", "gsm_a_bssmap.cause",
|
|
FT_UINT8, BASE_HEX, 0, 0x0,
|
|
"", HFILL }
|
|
},
|
|
{ &hf_gsm_a_dtap_cause,
|
|
{ "DTAP Cause", "gsm_a_dtap.cause",
|
|
FT_UINT8, BASE_HEX, 0, 0x0,
|
|
"", HFILL }
|
|
},
|
|
};
|
|
|
|
/* Setup protocol subtree array */
|
|
#define NUM_INDIVIDUAL_ELEMS 31
|
|
static gint *ett[NUM_INDIVIDUAL_ELEMS + NUM_GSM_BSSMAP_MSG +
|
|
NUM_GSM_DTAP_MSG_MM + NUM_GSM_DTAP_MSG_RR + NUM_GSM_DTAP_MSG_CC +
|
|
NUM_GSM_DTAP_MSG_GMM + NUM_GSM_DTAP_MSG_SMS +
|
|
NUM_GSM_DTAP_MSG_SM + NUM_GSM_DTAP_MSG_SS + NUM_GSM_RP_MSG +
|
|
NUM_GSM_BSSMAP_ELEM + NUM_GSM_DTAP_ELEM +
|
|
NUM_GSM_SS_ETT];
|
|
|
|
ett[0] = &ett_bssmap_msg;
|
|
ett[1] = &ett_dtap_msg;
|
|
ett[2] = &ett_rp_msg;
|
|
ett[3] = &ett_elems;
|
|
ett[4] = &ett_elem;
|
|
ett[5] = &ett_dtap_oct_1;
|
|
ett[6] = &ett_cm_srvc_type;
|
|
ett[7] = &ett_gsm_enc_info;
|
|
ett[8] = &ett_cell_list;
|
|
ett[9] = &ett_dlci;
|
|
ett[10] = &ett_bc_oct_3a;
|
|
ett[11] = &ett_bc_oct_4;
|
|
ett[12] = &ett_bc_oct_5;
|
|
ett[13] = &ett_bc_oct_5a;
|
|
ett[14] = &ett_bc_oct_5b;
|
|
ett[15] = &ett_bc_oct_6;
|
|
ett[16] = &ett_bc_oct_6a;
|
|
ett[17] = &ett_bc_oct_6b;
|
|
ett[18] = &ett_bc_oct_6c;
|
|
ett[19] = &ett_bc_oct_6d;
|
|
ett[20] = &ett_bc_oct_6e;
|
|
ett[21] = &ett_bc_oct_6f;
|
|
ett[22] = &ett_bc_oct_6g;
|
|
ett[23] = &ett_bc_oct_7;
|
|
|
|
ett[24] = &ett_tc_component;
|
|
ett[25] = &ett_tc_invoke_id;
|
|
ett[26] = &ett_tc_linked_id;
|
|
ett[27] = &ett_tc_opr_code;
|
|
ett[28] = &ett_tc_err_code;
|
|
ett[29] = &ett_tc_prob_code;
|
|
ett[30] = &ett_tc_sequence;
|
|
|
|
last_offset = NUM_INDIVIDUAL_ELEMS;
|
|
|
|
for (i=0; i < NUM_GSM_BSSMAP_MSG; i++, last_offset++)
|
|
{
|
|
ett_gsm_bssmap_msg[i] = -1;
|
|
ett[last_offset] = &ett_gsm_bssmap_msg[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_MM; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_mm[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_mm[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_RR; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_rr[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_rr[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_CC; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_cc[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_cc[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_GMM; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_gmm[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_gmm[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_SMS; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_sms[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_sms[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_SM; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_sm[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_sm[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_MSG_SS; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_msg_ss[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_msg_ss[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_RP_MSG; i++, last_offset++)
|
|
{
|
|
ett_gsm_rp_msg[i] = -1;
|
|
ett[last_offset] = &ett_gsm_rp_msg[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_BSSMAP_ELEM; i++, last_offset++)
|
|
{
|
|
ett_gsm_bssmap_elem[i] = -1;
|
|
ett[last_offset] = &ett_gsm_bssmap_elem[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_DTAP_ELEM; i++, last_offset++)
|
|
{
|
|
ett_gsm_dtap_elem[i] = -1;
|
|
ett[last_offset] = &ett_gsm_dtap_elem[i];
|
|
}
|
|
|
|
for (i=0; i < NUM_GSM_SS_ETT; i++, last_offset++)
|
|
{
|
|
gsm_ss_ett[i] = -1;
|
|
ett[last_offset] = &gsm_ss_ett[i];
|
|
}
|
|
|
|
/* Register the protocol name and description */
|
|
|
|
proto_a_bssmap =
|
|
proto_register_protocol("GSM A-I/F BSSMAP", "GSM BSSMAP", "gsm_a_bssmap");
|
|
|
|
proto_register_field_array(proto_a_bssmap, hf, array_length(hf));
|
|
|
|
proto_a_dtap =
|
|
proto_register_protocol("GSM A-I/F DTAP", "GSM DTAP", "gsm_a_dtap");
|
|
|
|
proto_a_rp =
|
|
proto_register_protocol("GSM A-I/F RP", "GSM RP", "gsm_a_rp");
|
|
|
|
sms_dissector_table =
|
|
register_dissector_table("gsm_a.sms_tpdu", "GSM SMS TPDU",
|
|
FT_UINT8, BASE_DEC);
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
gsm_a_tap = register_tap("gsm_a");
|
|
}
|
|
|
|
|
|
void
|
|
proto_reg_handoff_gsm_a(void)
|
|
{
|
|
|
|
bssmap_handle = create_dissector_handle(dissect_bssmap, proto_a_bssmap);
|
|
dtap_handle = create_dissector_handle(dissect_dtap, proto_a_dtap);
|
|
rp_handle = create_dissector_handle(dissect_rp, proto_a_rp);
|
|
|
|
dissector_add("bssap.pdu_type", BSSAP_PDU_TYPE_BSSMAP, bssmap_handle);
|
|
dissector_add("bssap.pdu_type", BSSAP_PDU_TYPE_DTAP, dtap_handle);
|
|
dissector_add("ranap.nas_pdu", BSSAP_PDU_TYPE_DTAP, dtap_handle);
|
|
|
|
data_handle = find_dissector("data");
|
|
}
|