/* packet-gsm_map.c * Routines for GSM Mobile Application Part dissection * * Copyright 2000, Felix Fei * * Michael Lum , * Changed to run on new version of TCAP, many changes for * EOC matching, and parameter separation. (2003) * * $Id: packet-gsm_map.c,v 1.11 2004/04/21 05:53:56 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * Copied from packet-tcap.c (where "WHATEVER_FILE_YOU_USED" * is a dissector file; if you just copied this from README.developer, * don't bother with the "Copied from" - you don't even need to put * in a "Copied from" if you copied an existing dissector, especially * if the bulk of the code in the new dissector is your code) * * 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 #include #include #include "epan/packet.h" #include "tap.h" #include "asn1.h" #include "packet-tcap.h" #include "packet-gsm_ss.h" #include "packet-gsm_map.h" /* OPERATION CODE DEFINITION */ /* LOCATION MANAGEMENT */ #define MAP_UPD_LOC 2 /* Update Location */ #define MAP_CANCEL_LOC 3 /* Cancel Location */ #define MAP_PURGE 67 /* Purge MS */ #define MAP_SEND_ID 5 /* Send Identification */ #define MAP_GPRS_UPD_LOC 23 /* GPRS Update Location */ #define MAP_DET_IMSI 5 /* Detach IMSI */ #define MAP_NOTE_MM_EVT 89 /* Note MM Event */ /* HANDOVER MANAGEMENT */ #define MAP_PREP_HO 68 /* Prepare Handover */ #define MAP_PREP_SUBS_HO 69 /* Prepare Subsequent Handover */ #define MAP_PERF_HO 28 /* Perform Handover */ #define MAP_PERF_SUBS_HO 30 /* Perform Subsequent Handover */ #define MAP_SEND_END_SIG 29 /* Send End Signal */ #define MAP_PROC_ACC_SIG 33 /* Process Access Signalling */ #define MAP_FWD_ACC_SIG 34 /* Forward Access Signalling */ /* AUTHENTICATION MANAGEMENT */ #define MAP_AUTH_INFO 56 /* Send Authintication Info */ #define MAP_AUTH_FAIL_RPT 15 /* Authentication Failure Report */ /* IDENTIFICATION MANAGEMENT */ #define MAP_CHK_IMEI 43 /* Check IMEI */ /* FAULT & RECOVERY MANAGEMENT */ #define MAP_RESET 37 /* Reset */ #define MAP_RESTORE_DATA 57 /* Restore Data */ #define MAP_FWD_CHK_SS_IND 38 /* Forward Check SS Indication */ /* OAM MANAGEMENT */ #define MAP_ACT_TRACE 50 /* Activate Trace */ #define MAP_DEACT_TRACE 51 /* Deactivate Trace Mode */ #define MAP_SEND_IMSI 58 /* Send IMSI */ #define MAP_TRACE_SUBS_ACTV 52 /* Trace Subscriber Activity */ #define MAP_NOTE_INTER_HO 35 /* Not Internal Handover */ /* CALL MANAGEMENT */ #define MAP_ROUTE_INFO 22 /* Send Routing Info */ #define MAP_PROV_ROAM_NUM 4 /* Provide Roaming Number */ #define MAP_PROV_SIWFS_NUM 31 /* Provide SIWFS Number */ #define MAP_SIWFS_SIG_MOD 32 /* SIWFS Signalling Modify */ #define MAP_RES_CALL_HAND 6 /* Resume Call Handling */ #define MAP_SET_RPT_STATE 73 /* Set Reporting State */ #define MAP_STAT_RPT 74 /* Status Report */ #define MAP_REM_USR_FREE 75 /* Remote user free */ #define MAP_PREP_GRP_CALL 39 /* Prepare Group Call */ #define MAP_SND_GRP_CALL_END_SIG 40 /* Send Group Call End Signalling */ #define MAP_PRO_GRP_CALL_SIG 41 /* Process Group Call Signalling */ #define MAP_FWD_GRP_CALL_SIG 42 /* Forward Group Call Signalling */ #define MAP_IST_ALERT 87 /* IST Alert */ #define MAP_IST_COMMAND 88 /* IST Command */ /* SS MANAGEMENT */ #define MAP_REG_SS 10 /* Register SS */ #define MAP_ERASE_SS 11 /* Erase SS */ #define MAP_ACT_SS 12 /* Activate SS */ #define MAP_DEACT_SS 13 /* Deactivate SS */ #define MAP_INTER_SS 14 /* Interrogate SS */ #define MAP_PROC_U_SS_REQ 59 /* Process Unstructured SS Req */ #define MAP_U_SS_REQ 60 /* Unstructured SS Request */ #define MAP_U_SS_NOTIFY 61 /* Unstructured SS Notify */ #define MAP_REG_PASSWD 17 /* Register Password */ #define MAP_GET_PASSWD 18 /* Get Password */ #define MAP_REG_CC_ENT 76 /* Register CC Entry */ #define MAP_ERASE_CC_ENT 77 /* Erase CC Entry */ #define MAP_BEGIN_SUBS_ACTV 54 /* Begin Subscriber Activity */ #define MAP_PROC_U_SS_DATA 19 /* Process Unstructured SS Data */ #define MAP_SS_INV_NOTIFY 72 /* SS Invocation Notify */ /* SMS MANAGEMENT */ #define MAP_MO_FWD_SM 46 /* Mobile Originated Forward Short Message */ #define MAP_MT_FWD_SM 44 /* Mobile Terminated Forward Short Message */ #define MAP_ROUTE_INFO_SM 45 /* Routing Info for SM */ #define MAP_SM_DEL_STAT 47 /* Report SM Delivery Status */ #define MAP_INFORM_SC 63 /* Inform Service Center */ #define MAP_ALERT_SC 64 /* Alert Service Center */ #define MAP_SM_READY 66 /* Ready for Short Message */ #define MAP_NOTE_SUB_PRES 48 /* Note Subscriber Present */ #define MAP_ALERT_SC_W_RES 49 /* Alert SC Without Result */ /* SUBSCRIBER MANAGEMENT */ #define MAP_INS_SUB_DATA 7 /* Insert Subscriber Data */ #define MAP_DEL_SUB_DATA 8 /* Delete Subscriber Data */ #define MAP_PROV_SUB_INFO 70 /* Provide Subscriber Info */ #define MAP_ANY_TIME_INTER 71 /* Any Time Interrogation */ #define MAP_SEND_PARAM 9 /* Send Parameters */ #define MAP_ANY_TIME_SUB_DATA_INTER 62 /* Any Time Subscriber Info Interrogation */ #define MAP_ANY_TIME_MOD 65 /* Any Time Modification */ #define MAP_NOTE_SUB_DATA_MOD 5 /* Note Subscriber Data Modified */ /* PDP ACTIVE MANAGEMENT */ #define MAP_GPRS_ROUTE_INFO 24 /* Rout Info for GPRS */ #define MAP_FAIL_REP 25 /* Failure Report */ #define MAP_GPRS_NOTE_MS_PRES 26 /* GPRS NoteMs Present */ /* LOCATION SERVICE */ #define MAP_PROV_SUB_LOC 83 /* Provide Subscriber Location */ #define MAP_SEND_ROUTE_INFO_FOR_LCS 85 /* Send Routing Info For LCS */ #define MAP_SUB_LOC_REP 86 /* Subscriber Location Report */ #define MAP_OPR_CODE_TAG 0x02 #define MAP_GE_PROBLEM_TAG 0x80 #define MAP_IN_PROBLEM_TAG 0x81 #define MAP_RR_PROBLEM_TAG 0x82 #define MAP_RE_PROBLEM_TAG 0x83 #define MAP_INVALID_TAG 0x00 #define MAP_OK 0x0 #define MAP_FAIL 0x1 const value_string gsm_map_opr_code_strings[] = { /* LOCATION MANAGEMENT */ { MAP_UPD_LOC, "Update Location"}, { MAP_CANCEL_LOC, "Cancel Location"}, { MAP_PURGE, "Purge MS"}, { MAP_SEND_ID, "Send Identification"}, { MAP_GPRS_UPD_LOC, "Update GPRS Location"}, { MAP_DET_IMSI, "Detach IMSI"}, { MAP_NOTE_MM_EVT, "Note MM Event"}, /* HANDOVER MANAGEMENT */ { MAP_PREP_HO, "Prepare Handover"}, { MAP_PREP_SUBS_HO, "Prepare Subsequent Handover"}, { MAP_PERF_HO, "Perform Handover"}, { MAP_PERF_SUBS_HO, "Perform Subsequent Handover"}, { MAP_SEND_END_SIG, "Send End Signal"}, { MAP_PROC_ACC_SIG, "Process Access Signalling"}, { MAP_FWD_ACC_SIG, "Forward Access Signalling"}, /* AUTHENTICATION MANAGEMENT */ { MAP_AUTH_INFO, "Send Authentication Info"}, { MAP_AUTH_FAIL_RPT, "Authentication Failure Report"}, /* IDENTIFICATION MANAGEMENT */ { MAP_CHK_IMEI, "Check IMEI"}, /* FAULT & RECOVERY MANAGEMENT */ { MAP_RESET, "Reset"}, { MAP_RESTORE_DATA, "Restore Data"}, { MAP_FWD_CHK_SS_IND, "Forward Check SS Indication"}, /* OAM MANAGEMENT */ { MAP_ACT_TRACE, "Activate Trace Mode"}, { MAP_DEACT_TRACE, "Deactivate Trace Mode"}, { MAP_SEND_IMSI, "Send IMSI"}, { MAP_TRACE_SUBS_ACTV, "Trace Subscriber Activity"}, { MAP_NOTE_INTER_HO, "Note Internal Handover"}, /* CALL MANAGEMENT */ { MAP_ROUTE_INFO, "Send Routing Info"}, { MAP_PROV_ROAM_NUM, "Provide Roaming Number"}, { MAP_PROV_SIWFS_NUM, "Provide SIWFS Number"}, { MAP_SIWFS_SIG_MOD, "SIWFS Signalling Modify"}, { MAP_RES_CALL_HAND, "Resume Call Handling"}, { MAP_SET_RPT_STATE, "Set Reporting State"}, { MAP_STAT_RPT, "Status Report"}, { MAP_REM_USR_FREE, "Remote User Free"}, { MAP_PREP_GRP_CALL, "Prepare Group Call"}, { MAP_SND_GRP_CALL_END_SIG, "Send Group Call End Signalling"}, { MAP_PRO_GRP_CALL_SIG, "Process Group Call Signalling"}, { MAP_FWD_GRP_CALL_SIG, "Forward Group Call Signalling"}, { MAP_IST_ALERT, "IST Alert"}, { MAP_IST_COMMAND, "IST Command"}, /* SS MANAGEMENT */ { MAP_REG_SS, "Register SS"}, { MAP_ERASE_SS, "Erase SS"}, { MAP_ACT_SS, "Activate SS"}, { MAP_DEACT_SS, "Deactivate SS"}, { MAP_INTER_SS, "Interrogate SS"}, { MAP_PROC_U_SS_REQ, "Process Unstructured SS Request"}, { MAP_U_SS_REQ, "Unstructured SS Request"}, { MAP_U_SS_NOTIFY, "Unstructured SS Notify"}, { MAP_REG_PASSWD, "Register Password"}, { MAP_GET_PASSWD, "Get Password"}, { MAP_REG_CC_ENT, "Register CC Entry"}, { MAP_ERASE_CC_ENT, "Erase CC Entry"}, { MAP_BEGIN_SUBS_ACTV, "Begin Subscriber Activity"}, { MAP_PROC_U_SS_DATA, "Process Unstructured SS Data"}, { MAP_SS_INV_NOTIFY, "SS Invocation Notification"}, /* SMS MANAGEMENT */ { MAP_MO_FWD_SM, "MO Forward SM"}, { MAP_MT_FWD_SM, "MT Forward SM"}, { MAP_ROUTE_INFO_SM, "Send Routing Info For SM"}, { MAP_SM_DEL_STAT, "Report SM Delivery Status"}, { MAP_INFORM_SC, "Inform Service Center"}, { MAP_ALERT_SC, "Alert Service Center"}, { MAP_SM_READY, "Ready For SM"}, { MAP_NOTE_SUB_PRES, "Note Subscriber Present"}, { MAP_ALERT_SC_W_RES, "Alert SC Without Result"}, /* SUBSCRIBER MANAGEMENT */ { MAP_INS_SUB_DATA, "Insert Subscriber Data"}, { MAP_DEL_SUB_DATA, "Delete Subscriber Data"}, { MAP_PROV_SUB_INFO, "Provide Subscriber Info"}, { MAP_ANY_TIME_INTER, "Any Time Interrogation"}, { MAP_SEND_PARAM, "Send Parameters"}, { MAP_ANY_TIME_SUB_DATA_INTER, "Any Time Subscription Interrogation"}, { MAP_ANY_TIME_MOD, "Any Time Modification"}, { MAP_NOTE_SUB_DATA_MOD, "Note Subscriber Data Modified"}, /* PDP ACTIVE MANAGEMENT */ { MAP_GPRS_ROUTE_INFO, "Send Routing Info For GPRS"}, { MAP_FAIL_REP, "Failure Report"}, { MAP_GPRS_NOTE_MS_PRES, "Note MS Present For GPRS"}, /* LOCATION SERVICE */ { MAP_PROV_SUB_LOC, "Provide Subscriber Location"}, { MAP_SEND_ROUTE_INFO_FOR_LCS, "Send Routing Info For LCS"}, { MAP_SUB_LOC_REP, "Subscriber Location Report"}, { 0, NULL} }; /* * Initialize the protocol and registered fields */ static int proto_map = -1; static int gsm_map_tap = -1; static dissector_table_t sms_dissector_table; /* SMS TPDU */ static int gsm_map_app_context = 1; /* XXX should be set from Dialogue */ static packet_info *g_pinfo; static proto_tree *g_tree; static guint g_opr_code; static guint g_comp_type_tag; static int hf_map_length = -1; static int hf_map_opr_code = -1; static int hf_map_int = -1; static int hf_map_imsi = -1; static int hf_map_addrstring = -1; static int hf_map_rand = -1; static int hf_map_sres = -1; static int hf_map_kc = -1; static int hf_map_xres = -1; static int hf_map_ck = -1; static int hf_map_ik = -1; static int hf_map_autn = -1; /* never initialize in field array */ static int hf_null = -1; #define HF_NULL &hf_null /* Initialize the subtree pointers */ static gint ett_map = -1; static gint ett_component = -1; static gint ett_components = -1; static gint ett_sequence = -1; static gint ett_param = -1; static gint ett_params = -1; static gint ett_problem = -1; static gint ett_opr_code = -1; static gint ett_err_code = -1; typedef struct dgt_set_t { unsigned char out[15]; } dgt_set_t; #ifdef MLUM 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','*','#' } }; #endif 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','?','?','?','?','?' } }; /* FORWARD DECLARATIONS */ static int dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree); /* 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); } #define GSM_MAP_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_uint(_Gsubtree_p, hf_map_length, asn1->tvb, \ _len_offset, asn1->offset - _len_offset, *_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)); \ } static int dissect_map_params(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint orig_offset, saved_offset, len_offset; guint tag, len; gboolean def_len = FALSE; proto_item *item; proto_tree *subtree; orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) { break; } saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag)) { GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); dissect_map_params(asn1, subtree, len); if (!def_len) { dissect_map_eoc(asn1, subtree); } continue; } len_offset = asn1->offset; asn1_length_decode(asn1, &def_len, &len); if (!def_len) { proto_tree_add_text(tree, asn1->tvb, saved_offset, len_offset - saved_offset, "Tag: 0x%02x", tag); proto_tree_add_text(tree, asn1->tvb, len_offset, asn1->offset - len_offset, "Length: Indefinite"); len = tcap_find_eoc(asn1); dissect_map_params(asn1, tree, len); dissect_map_eoc(asn1, tree); continue; } item = proto_tree_add_text(tree, asn1->tvb, saved_offset, (asn1->offset - saved_offset) + len, "Parameter"); subtree = proto_item_add_subtree(item, ett_param); proto_tree_add_text(subtree, asn1->tvb, saved_offset, len_offset - saved_offset, "Tag: 0x%02x", tag); proto_tree_add_uint(subtree, hf_map_length, asn1->tvb, len_offset, asn1->offset - len_offset, len); if (len > 0) { proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Parameter Data"); asn1->offset += len; } } return(MAP_OK); } /* PARAMETERS */ static void param_bytes(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { guint saved_offset; saved_offset = asn1->offset; proto_tree_add_bytes(tree, hf_field, asn1->tvb, saved_offset, len, tvb_get_ptr(asn1->tvb, saved_offset, len)); asn1->offset += len; } static void param_imsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { guint saved_offset; guchar *poctets; char bigbuf[1024]; saved_offset = asn1->offset; asn1_string_value_decode(asn1, len, &poctets); my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid); g_free(poctets); if (hf_field == -1) { proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "IMSI %s", bigbuf); } else { proto_tree_add_string_format(tree, hf_field, asn1->tvb, saved_offset, len, bigbuf, "IMSI %s", bigbuf); } } static void param_lmsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { guint saved_offset; gint32 value; hf_field = hf_field; saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &value); proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "LMSI 0x%04x", value); } static void param_boolean(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { guint saved_offset; gint32 value; hf_field = hf_field; saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &value); proto_tree_add_text(tree, asn1->tvb, saved_offset, len, value ? "TRUE" : "FALSE"); } static void param_alertReason(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { guint saved_offset; gint32 value; gchar *str = NULL; hf_field = hf_field; saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &value); switch (value) { case 0x00: str = "ms-Present"; break; case 0x01: str = "memoryAvailable"; break; default: str = "Unrecognized value"; break; } proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str); } typedef enum { GSM_MAP_P_IMSI, /* IMSI */ GSM_MAP_P_LMSI, /* LMSI */ GSM_MAP_P_MSISDN, /* MSISDN */ GSM_MAP_P_SC_ADDR_DA, /* Service Centre Address DA */ GSM_MAP_P_SC_ADDR_OA, /* Service Centre Address OA */ GSM_MAP_P_SC_ADDR, /* Service Centre Address */ GSM_MAP_P_MSC_NUMBER, /* MSC Number */ GSM_MAP_P_VLR_NUMBER, /* VLR Number */ GSM_MAP_P_HLR_NUMBER, /* HLR Number */ GSM_MAP_P_SIG_INFO, /* Signal Info */ GSM_MAP_P_BOOL, /* Boolean */ GSM_MAP_P_LIWLMSI, /* Location Information with LMSI */ GSM_MAP_P_NETNODE_NUM, /* Network Node Number */ GSM_MAP_P_ROAMING_NUM, /* Roaming Number */ GSM_MAP_P_ALERT_REASON, /* Alert Reason */ GSM_MAP_P_GMSC_ADDR, /* GMSC Address */ GSM_MAP_P_RAND, /* Rand */ GSM_MAP_P_SRES, /* Signed Result */ GSM_MAP_P_KC, /* Key Cipher */ GSM_MAP_P_XRES, /* Extended Signed Result */ GSM_MAP_P_CK, /* Ciphering Key */ GSM_MAP_P_IK, /* Integrity Key */ GSM_MAP_P_AUTN, /* Authentication Token */ GSM_MAP_P_NONE /* NONE */ } param_idx_t; #define NUM_PARAM_1 (GSM_MAP_P_NONE+1) static gint ett_param_1[NUM_PARAM_1]; static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = { param_imsi, /* IMSI */ param_lmsi, /* LMSI */ param_AddressString, /* MSISDN */ param_AddressString, /* Service Centre Address DA */ param_AddressString, /* Service Centre Address OA */ param_AddressString, /* Service Centre Address */ param_AddressString, /* MSC Number */ param_AddressString, /* VLR Number */ param_AddressString, /* HLR Number */ NULL, /* Signal Info */ param_boolean, /* Boolean */ NULL, /* Location Information with LMSI */ param_AddressString, /* Network Node Number */ param_AddressString, /* Roaming Number */ param_alertReason, /* Alert Reason */ param_AddressString, /* GMSC Address */ param_bytes, /* Rand */ param_bytes, /* Signed Result */ param_bytes, /* GSM Key Cipher */ param_bytes, /* Extended Signed Result */ param_bytes, /* UMTS Ciphering Key */ param_bytes, /* Integrity Key */ param_bytes, /* Authentication Token */ NULL /* NONE */ }; static int *param_1_hf[] = { &hf_map_imsi, /* IMSI */ HF_NULL, /* LMSI */ &hf_map_addrstring, /* MSISDN */ &hf_map_addrstring, /* Service Centre Address DA */ &hf_map_addrstring, /* Service Centre Address OA */ &hf_map_addrstring, /* Service Centre Address */ &hf_map_addrstring, /* MSC Number */ &hf_map_addrstring, /* VLR Number */ &hf_map_addrstring, /* HLR Number */ HF_NULL, /* Signal Info */ HF_NULL, /* Boolean */ HF_NULL, /* Location Information with LMSI */ &hf_map_addrstring, /* Network Node Number */ &hf_map_addrstring, /* Roaming Number */ HF_NULL, /* Alert Reason */ &hf_map_addrstring, /* GMSC Address */ &hf_map_rand, /* Rand */ &hf_map_sres, /* Signed Result */ &hf_map_kc, /* GSM Key Cipher */ &hf_map_xres, /* Extended Signed Result */ &hf_map_ck, /* UMTS Ciphering Key */ &hf_map_ik, /* Integrity Key */ &hf_map_autn, /* Authentication Token */ NULL /* NONE */ }; #define GSM_MAP_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \ { \ gint _ett_param_idx; \ guint _len; \ void (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \ int *_param_hf = NULL; \ proto_tree *_subtree; \ gboolean _def_len; \ \ if (Ga1 == GSM_MAP_P_NONE) \ { \ _ett_param_idx = ett_param; \ _param_fcn = NULL; \ _param_hf = HF_NULL; \ } \ else \ { \ _ett_param_idx = ett_param_1[Ga1]; \ _param_fcn = param_1_fcn[Ga1]; \ _param_hf = param_1_hf[Ga1]; \ } \ \ GSM_MAP_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \ \ if (_len > 0) \ { \ if (Ga1 == GSM_MAP_P_NONE || _param_fcn == NULL) \ { \ proto_tree_add_text(_subtree, asn1->tvb, \ asn1->offset, _len, "Parameter Data"); \ \ asn1->offset += _len; \ } \ else \ { \ (*_param_fcn)(asn1, _subtree, _len, *_param_hf); \ } \ } \ \ if (!_def_len) \ { \ dissect_map_eoc(asn1, Gtree); \ } \ } static void param_Identity(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); switch (tag) { case 0x04: /* IMSI */ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "Identity"); break; case 0x30: /* IMSI-WithLMSI */ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } break; default: GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_NONE, "Identity"); break; } } static void param_TripletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, orig_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) { break; } saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SRES, "SRES"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_KC, "Kc"); if (!def_len) { dissect_map_eoc(asn1, subtree); } } } static void param_QuintupletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, orig_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) { break; } saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_XRES, "XRES"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_CK, "CK"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IK, "IK"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_AUTN, "AUTN"); if (!def_len) { dissect_map_eoc(asn1, subtree); } } } static void param_SM_RP_DA(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset; guint tag; gint idx; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); switch (tag) { case 0x80: /* IMSI */ idx = GSM_MAP_P_IMSI; break; case 0x81: /* LMSI */ idx = GSM_MAP_P_LMSI; break; case 0x84: /* AddressString */ idx = GSM_MAP_P_SC_ADDR_DA; break; default: /* * this occurs in the mobile terminated case for * subsequent messages */ idx = GSM_MAP_P_NONE; break; } GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-DA"); } static void param_SM_RP_OA(ASN1_SCK *asn1, proto_tree *tree, int *direction_p) { guint saved_offset; guint tag; gint idx; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); switch (tag) { case 0x82: /* MSISDN */ idx = GSM_MAP_P_MSISDN; *direction_p = P2P_DIR_RECV; break; case 0x84: /* AddressString */ idx = GSM_MAP_P_SC_ADDR_OA; *direction_p = P2P_DIR_SENT; break; default: idx = GSM_MAP_P_NONE; /* * this occurs in the mobile terminated case for * subsequent messages */ *direction_p = P2P_DIR_SENT; break; } GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-OA"); } static void param_SM_RP_UI(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; tvbuff_t *tpdu_tvb; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "SM-RP-UI", ett_param_1[GSM_MAP_P_SIG_INFO], &def_len, &len, subtree); proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "TPDU"); /* * dissect the embedded TPDU message */ tpdu_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len); dissector_try_port(sms_dissector_table, 0, tpdu_tvb, g_pinfo, g_tree); asn1->offset += len; if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void param_LWI_LMSI(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "LOCATION INFO WITH LMSI", ett_param_1[GSM_MAP_P_LIWLMSI], &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NETNODE_NUM, "NETWORK NODE NUMBER"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } /* MESSAGES */ static void op_update_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_VLR_NUMBER, "VLR Number"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_update_loc_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_cancel_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (tag != 0xa3) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Constructor Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; param_Identity(asn1, subtree); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_auth_info(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Number Of Requested Vectors"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_auth_info_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if ((tag != 0x30) && (tag != 0x31)) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, (tag == 0x30) ? "TripletList" : "QuintupletList", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; if (tag == 0x30) { param_TripletList(asn1, subtree, len); } else { param_QuintupletList(asn1, subtree, len); } dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_restore_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_restore_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_rti(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_rti_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; /* * spec says [9] but 'real data' show '04' not '89' ! */ if (tcap_check_tag(asn1, 0x04)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); } if (tcap_check_tag(asn1, 0x04)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number"); } dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number"); if (tcap_check_tag(asn1, 0x82)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); } if (tcap_check_tag(asn1, 0x84)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI"); } if (tcap_check_tag(asn1, 0x85)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "GSM Bearer Capability"); } if (tcap_check_tag(asn1, 0xa6)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Network Signal Info"); } if (tcap_check_tag(asn1, 0x87)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Suppression Of Announcement"); } if (tcap_check_tag(asn1, 0x88)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_GMSC_ADDR, "GMSC Address"); } if (tcap_check_tag(asn1, 0x89)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Call Reference Number"); } if (tcap_check_tag(asn1, 0x8a)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Interrogation"); } if (tcap_check_tag(asn1, 0x8b)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Extension Container"); } if (tcap_check_tag(asn1, 0x8c)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Alerting Pattern"); } if (tcap_check_tag(asn1, 0x8d)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "CCBS Call"); } if (tcap_check_tag(asn1, 0x8f)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Supported Camel Phases In GMSC"); } if (tcap_check_tag(asn1, 0x8e)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Additional Signal Info"); } if (tcap_check_tag(asn1, 0x90)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Not Supported In GMSC"); } if (tcap_check_tag(asn1, 0x91)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Pre-paging Supported"); } if (tcap_check_tag(asn1, 0x92)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Long FTN Supported"); } dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_provide_rn_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number"); return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } /* * Description: * Generic dissector for Supplementary Services */ static void op_ss_generic(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; gsm_ss_dissect(asn1, tree, exp_len, g_opr_code, g_comp_type_tag); } static void op_mo_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; param_SM_RP_DA(asn1, subtree); param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir); param_SM_RP_UI(asn1, subtree); /* * older versions of GSM MAP had only one ForwardSM message */ if ((tvb_length_remaining(asn1->tvb, asn1->offset) > (def_len ? 0 : TCAP_EOC_LEN)) && (gsm_map_app_context < 3) && (g_pinfo->p2p_dir == P2P_DIR_SENT)) { /* * 'more messages' for V1 context */ saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send"); } dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_mt_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; param_SM_RP_DA(asn1, subtree); param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir); param_SM_RP_UI(asn1, subtree); if (tvb_length_remaining(asn1->tvb, asn1->offset) > 0) { /* * 'more messages' */ saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send"); } dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_forward_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; param_SM_RP_UI(asn1, subtree); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_rti_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_BOOL, "SM-RP-PRI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_send_rti_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); param_LWI_LMSI(asn1, subtree); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_alert_sc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_ready_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ALERT_REASON, "Alert Reason"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } static void op_alert_sc_wr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; guint tag, len; gboolean def_len = FALSE; proto_tree *subtree; exp_len = exp_len; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); if (TCAP_CONSTRUCTOR(tag) == FALSE) { /* * Hmmm, unexpected */ return; } GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, subtree); start_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address"); dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } } #define GSM_MAP_NUM_OP (sizeof(gsm_map_opr_code_strings)/sizeof(value_string)) static gint ett_op[GSM_MAP_NUM_OP]; static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = { op_update_loc, /* Update Location */ op_cancel_loc, /* Cancel Location */ NULL, /* Purge MS */ NULL, /* Send Identification */ NULL, /* Update GPRS Location */ NULL, /* Detach IMSI */ NULL, /* Note MM Event */ NULL, /* Prepare Handover */ NULL, /* Prepare Subsequent Handover */ NULL, /* Perform Handover */ NULL, /* Perform Subsequent Handover */ NULL, /* Send End Signal */ NULL, /* Process Access Signalling */ NULL, /* Forward Access Signalling */ op_send_auth_info, /* Send Authentication Info */ NULL, /* Authentication Failure Report */ NULL, /* Check IMEI */ NULL, /* Reset */ op_restore_data, /* Restore Data */ NULL, /* Forward Check SS Indication */ NULL, /* Activate Trace Mode */ NULL, /* Deactivate Trace Mode */ NULL, /* Send IMSI */ NULL, /* Trace Subscriber Activity */ NULL, /* Note Internal Handover */ op_send_rti, /* Send Routing Info */ op_provide_rn, /* Provide Roaming Number */ NULL, /* Provide SIWFS Number */ NULL, /* SIWFS Signalling Modify */ NULL, /* Resume Call Handling */ NULL, /* Set Reporting State */ NULL, /* Status Report */ NULL, /* Remote User Free */ NULL, /* Prepare Group Call */ NULL, /* Send Group Call End Signalling */ NULL, /* Process Group Call Signalling */ NULL, /* Forward Group Call Signalling */ NULL, /* IST Alert */ NULL, /* IST Command */ op_ss_generic, /* Register SS */ op_ss_generic, /* Erase SS */ op_ss_generic, /* Activate SS */ op_ss_generic, /* Deactivate SS */ op_ss_generic, /* Interrogate SS */ op_ss_generic, /* Process Unstructured SS Request */ op_ss_generic, /* Unstructured SS Request */ op_ss_generic, /* Unstructured SS Notify */ op_ss_generic, /* Register Password */ op_ss_generic, /* Get Password */ op_ss_generic, /* Register CC Entry */ op_ss_generic, /* Erase CC Entry */ NULL, /* Begin Subscriber Activity */ op_ss_generic, /* Process Unstructured SS Data */ op_ss_generic, /* SS Invocation Notification */ op_mo_forward_sm, /* MO Forward SM */ op_mt_forward_sm, /* MT Forward SM */ op_send_rti_sm, /* Send Routing Info For SM */ NULL, /* Report SM Delivery Status */ NULL, /* Inform Service Center */ op_alert_sc, /* Alert Service Center */ op_ready_sm, /* Ready For SM */ NULL, /* Note Subscriber Present */ op_alert_sc_wr, /* Alert SC Without Result */ NULL, /* Insert Subscriber Data */ NULL, /* Delete Subscriber Data */ NULL, /* Provide Subscriber Info */ NULL, /* Any Time Interrogation */ NULL, /* Send Parameters */ NULL, /* Any Time Subscription Interrogation */ NULL, /* Any Time Modification */ NULL, /* Note Subscriber Data Modified */ NULL, /* Send Routing Info For GPRS */ NULL, /* Failure Report */ NULL, /* Note MS Present For GPRS */ NULL, /* Provide Subscriber Location */ NULL, /* Send Routing Info For LCS */ NULL, /* Subscriber Location Report */ NULL /* NONE */ }; static gint ett_op_rr[GSM_MAP_NUM_OP]; static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = { op_update_loc_rr, /* Update Location */ NULL, /* Cancel Location */ NULL, /* Purge MS */ NULL, /* Send Identification */ NULL, /* Update GPRS Location */ NULL, /* Detach IMSI */ NULL, /* Note MM Event */ NULL, /* Prepare Handover */ NULL, /* Prepare Subsequent Handover */ NULL, /* Perform Handover */ NULL, /* Perform Subsequent Handover */ NULL, /* Send End Signal */ NULL, /* Process Access Signalling */ NULL, /* Forward Access Signalling */ op_send_auth_info_rr, /* Send Authentication Info */ NULL, /* Authentication Failure Report */ NULL, /* Check IMEI */ NULL, /* Reset */ op_restore_data_rr, /* Restore Data */ NULL, /* Forward Check SS Indication */ NULL, /* Activate Trace Mode */ NULL, /* Deactivate Trace Mode */ NULL, /* Send IMSI */ NULL, /* Trace Subscriber Activity */ NULL, /* Note Internal Handover */ op_send_rti_rr, /* Send Routing Info */ op_provide_rn_rr, /* Provide Roaming Number */ NULL, /* Provide SIWFS Number */ NULL, /* SIWFS Signalling Modify */ NULL, /* Resume Call Handling */ NULL, /* Set Reporting State */ NULL, /* Status Report */ NULL, /* Remote User Free */ NULL, /* Prepare Group Call */ NULL, /* Send Group Call End Signalling */ NULL, /* Process Group Call Signalling */ NULL, /* Forward Group Call Signalling */ NULL, /* IST Alert */ NULL, /* IST Command */ op_ss_generic, /* Register SS */ op_ss_generic, /* Erase SS */ op_ss_generic, /* Activate SS */ op_ss_generic, /* Deactivate SS */ op_ss_generic, /* Interrogate SS */ op_ss_generic, /* Process Unstructured SS Request */ op_ss_generic, /* Unstructured SS Request */ op_ss_generic, /* Unstructured SS Notify */ op_ss_generic, /* Register Password */ op_ss_generic, /* Get Password */ op_ss_generic, /* Register CC Entry */ op_ss_generic, /* Erase CC Entry */ NULL, /* Begin Subscriber Activity */ op_ss_generic, /* Process Unstructured SS Data */ op_ss_generic, /* SS Invocation Notification */ op_forward_sm_rr, /* MO Forward SM */ op_forward_sm_rr, /* MT Forward SM */ op_send_rti_sm_rr, /* Send Routing Info For SM */ NULL, /* Report SM Delivery Status */ NULL, /* Inform Service Center */ NULL, /* Alert Service Center */ NULL, /* Ready For SM */ NULL, /* Note Subscriber Present */ NULL, /* Alert SC Without Result */ NULL, /* Insert Subscriber Data */ NULL, /* Delete Subscriber Data */ NULL, /* Provide Subscriber Info */ NULL, /* Any Time Interrogation */ NULL, /* Send Parameters */ NULL, /* Any Time Subscription Interrogation */ NULL, /* Any Time Modification */ NULL, /* Note Subscriber Data Modified */ NULL, /* Send Routing Info For GPRS */ NULL, /* Failure Report */ NULL, /* Note MS Present For GPRS */ NULL, /* Provide Subscriber Location */ NULL, /* Send Routing Info For LCS */ NULL, /* Subscriber Location Report */ NULL /* NONE */ }; /* GENERIC MAP DISSECTOR FUNCTIONS */ static int dissect_map_tag(ASN1_SCK *asn1, proto_tree *tree, guint *tag, guchar * str, proto_item **item_p) { guint saved_offset, real_tag; saved_offset = asn1->offset; asn1_id_decode1(asn1, &real_tag); if ((*tag != (guint) -1) && (real_tag != *tag)) { asn1->offset = saved_offset; return(MAP_FAIL); } *item_p = proto_tree_add_text(tree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "%s: 0x%02x", str, real_tag); return(MAP_OK); } static int dissect_map_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len) { guint saved_offset; saved_offset = asn1->offset; *len = 0; *def_len = FALSE; asn1_length_decode(asn1, def_len, len); if (*def_len) { proto_tree_add_uint(tree, hf_map_length, asn1->tvb, saved_offset, asn1->offset - saved_offset, *len); } else { proto_tree_add_text(tree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Length: Indefinite"); } return(MAP_OK); } static int dissect_map_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, guchar * str) { guint saved_offset; gint32 invokeId; saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &invokeId); proto_tree_add_int_format(tree, hf_map_int, asn1->tvb, saved_offset, asn1->offset - saved_offset, invokeId, "%s %d", str, invokeId); return(MAP_OK); } static int dissect_map_invokeId(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset = 0; guint len; guint tag; proto_item *item, *null_item; proto_tree *subtree; gboolean def_len; if (tcap_check_tag(asn1, TCAP_INVOKE_ID_TAG)) { saved_offset = asn1->offset; item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Invoke Id"); subtree = proto_item_add_subtree(item, ett_component); tag = -1; dissect_map_tag(asn1, subtree, &tag, "Invoke Id Tag", &null_item); dissect_map_len(asn1, subtree, &def_len, &len); dissect_map_integer(asn1, subtree, len, "Invoke Id:"); proto_item_set_len(item, asn1->offset - saved_offset); } return(MAP_OK); } static void dissect_map_problem(ASN1_SCK *asn1, proto_tree *tree) { guint orig_offset, saved_offset, len_offset; guint len; guint tag; proto_tree *subtree; proto_item *item = NULL; gchar *str = NULL; gchar *type_str = NULL; gint32 spec; gboolean def_len; orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); len_offset = asn1->offset; asn1_length_decode(asn1, &def_len, &len); item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code"); subtree = proto_item_add_subtree(item, ett_problem); if (!def_len) { len = tcap_find_eoc(asn1); } proto_item_set_len(item, (asn1->offset - saved_offset) + len + (def_len ? 0 : TCAP_EOC_LEN)); if (len != 1) { proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Unknown encoding of Problem Code"); asn1->offset += len; if (!def_len) { asn1_eoc_decode(asn1, -1); } return; } saved_offset = asn1->offset; asn1_int32_value_decode(asn1, 1, &spec); switch (tag) { case MAP_GE_PROBLEM_TAG: type_str = "General Problem"; switch (spec) { case 0: str = "Unrecognized Component"; break; case 1: str = "Mistyped Component"; break; case 2: str = "Badly Structured Component"; break; default: str = "Undefined"; break; } break; case MAP_IN_PROBLEM_TAG: type_str = "Invoke"; switch (spec) { case 0: str = "Duplicate Invoke ID"; break; case 1: str = "Unrecognized Operation"; break; case 2: str = "Mistyped Parameter"; break; case 3: str = "Resource Limitation"; break; case 4: str = "Initiating Release"; break; case 5: str = "Unrecognized Linked ID"; break; case 6: str = "Linked Response Unexpected"; break; case 7: str = "Unexpected Linked Operation"; break; default: str = "Undefined"; break; } break; case MAP_RR_PROBLEM_TAG: type_str = "Return Result"; switch (spec) { case 0: str = "Unrecognized Invoke ID"; break; case 1: str = "Return Result Unexpected"; break; case 2: str = "Mistyped Parameter"; break; default: str = "Undefined"; break; } break; case MAP_RE_PROBLEM_TAG: type_str = "Return Error"; switch (spec) { case 0: str = "Unrecognized Invoke ID"; break; case 1: str = "Return Error Unexpected"; break; case 2: str = "Unrecognized Error"; break; case 3: str = "Unexpected Error"; break; case 4: str = "Mistyped Parameter"; break; default: str = "Undefined"; break; } break; default: type_str = "Undefined"; break; } proto_tree_add_text(subtree, asn1->tvb, orig_offset, len_offset - orig_offset, "%s: %02x", type_str, tag); if (def_len) { proto_tree_add_uint(subtree, hf_map_length, asn1->tvb, len_offset, saved_offset - len_offset, len); } else { proto_tree_add_text(subtree, asn1->tvb, len_offset, saved_offset - len_offset, "Length: Indefinite"); } proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1, "Problem Specifier %s", str); } static int dissect_map_lnkId(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset = 0; guint len; guint tag; proto_item *item, *null_item; proto_tree *subtree; gboolean def_len; if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG)) { saved_offset = asn1->offset; item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Linked Id"); subtree = proto_item_add_subtree(item, ett_component); tag = -1; dissect_map_tag(asn1, tree, &tag, "Linked Id Tag", &null_item); dissect_map_len(asn1, tree, &def_len, &len); dissect_map_integer(asn1, tree, len, "Linked Id:"); proto_item_set_len(item, asn1->offset - saved_offset); } return(MAP_OK); } static int dissect_map_opr_code(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint *op_idx_p, guint *opr_code_p) { guint opr_offset = 0, saved_offset = 0; guint len; guint tag; gint32 val; gchar *str = NULL; proto_item *item; proto_tree *subtree; gboolean def_len; if (tcap_check_tag(asn1, MAP_OPR_CODE_TAG)) { opr_offset = asn1->offset; item = proto_tree_add_text(tree, asn1->tvb, opr_offset, -1, "Operation Code"); subtree = proto_item_add_subtree(item, ett_opr_code); tag = -1; asn1_id_decode1(asn1, &tag); proto_tree_add_text(subtree, asn1->tvb, opr_offset, asn1->offset - opr_offset, "Operation Code Tag: 0x%02x", tag); dissect_map_len(asn1, subtree, &def_len, &len); saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &val); proto_tree_add_int(subtree, hf_map_opr_code, asn1->tvb, saved_offset, asn1->offset - saved_offset, val); proto_item_set_len(item, asn1->offset - opr_offset); str = my_match_strval(val, gsm_map_opr_code_strings, op_idx_p); if (NULL == str) return(MAP_FAIL); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str); } *opr_code_p = val; } return(MAP_OK); } static int dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree) { guint saved_offset; saved_offset = asn1->offset; if (tvb_length_remaining(asn1->tvb, saved_offset) <= 0) { return(MAP_FAIL); } if (!asn1_eoc(asn1, -1)) { return(MAP_FAIL); } asn1_eoc_decode(asn1, -1); proto_tree_add_text(tree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "End of Contents"); return(MAP_OK); } static void dissect_map_invoke(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree) { proto_tree *subtree; guint orig_offset, saved_offset; guint len; guint tag; proto_item *item; gint op_idx; gboolean def_len; int ret; int opr_code_sts; static gsm_map_tap_rec_t tap_rec; orig_offset = asn1->offset; saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); subtree = proto_item_add_subtree(item, ett_components); proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Invoke Type Tag: 0x%02x", tag); dissect_map_len(asn1, subtree, &def_len, &len); saved_offset = asn1->offset; dissect_map_invokeId(asn1, subtree); dissect_map_lnkId(asn1, subtree); opr_code_sts = dissect_map_opr_code(asn1, pinfo, subtree, &op_idx, &g_opr_code); if (opr_code_sts == MAP_OK) { if (def_len) { len -= asn1->offset - saved_offset; } else { len = tcap_find_eoc(asn1); } /* * decode elements */ if (op_fcn[op_idx] == NULL) { dissect_map_params(asn1, subtree, len); } else { (*op_fcn[op_idx])(asn1, subtree, len); } } if (!def_len) { dissect_map_eoc(asn1, subtree); } proto_item_set_len(item, asn1->offset - orig_offset); if (opr_code_sts == MAP_OK) { tap_rec.invoke = TRUE; tap_rec.opr_code_idx = op_idx; tap_rec.size = asn1->offset - orig_offset; tap_queue_packet(gsm_map_tap, pinfo, &tap_rec); } } static void dissect_map_rr(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gchar *str) { guint tag, len, comp_len; gint op_idx; guint orig_offset, saved_offset; proto_item *item; proto_tree *seq_subtree, *subtree; gboolean def_len; gboolean comp_def_len; int opr_code_sts; static gsm_map_tap_rec_t tap_rec; tag = -1; orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); subtree = proto_item_add_subtree(item, ett_components); proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "%s: %02x", str, tag); dissect_map_len(asn1, subtree, &comp_def_len, &comp_len); saved_offset = asn1->offset; dissect_map_invokeId(asn1, subtree); if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) { proto_item_set_len(item, asn1->offset - orig_offset); return; } saved_offset = asn1->offset; tag = -1; asn1_id_decode1(asn1, &tag); opr_code_sts = MAP_FAIL; if (TCAP_CONSTRUCTOR(tag)) { GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Sequence", ett_sequence, &def_len, &len, seq_subtree); saved_offset = asn1->offset; opr_code_sts = dissect_map_opr_code(asn1, pinfo, seq_subtree, &op_idx, &g_opr_code); if (opr_code_sts == MAP_OK) { len -= asn1->offset - saved_offset; /* * decode elements */ if (op_fcn_rr[op_idx] == NULL) { dissect_map_params(asn1, seq_subtree, len); } else { (*op_fcn_rr[op_idx])(asn1, seq_subtree, len); } } if (!def_len) { dissect_map_eoc(asn1, seq_subtree); } } if (!comp_def_len) { dissect_map_eoc(asn1, subtree); } proto_item_set_len(item, asn1->offset - orig_offset); if (opr_code_sts == MAP_OK) { tap_rec.invoke = FALSE; tap_rec.opr_code_idx = op_idx; tap_rec.size = asn1->offset - orig_offset; tap_queue_packet(gsm_map_tap, pinfo, &tap_rec); } } static int dissect_map_re(ASN1_SCK *asn1, proto_tree *tree) { guint tag, len, comp_len; guint orig_offset, saved_offset; proto_item *item; proto_tree *subtree, *temp_subtree; gboolean comp_def_len, def_len; gchar *str; gint32 int_val; tag = -1; orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); subtree = proto_item_add_subtree(item, ett_components); proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Return Error Type Tag: 0x%02x", tag); dissect_map_len(asn1, subtree, &comp_def_len, &comp_len); if (!comp_def_len) { comp_len = tcap_find_eoc(asn1); } saved_offset = asn1->offset; dissect_map_invokeId(asn1, subtree); saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); #define MAP_LOCAL_ERR_CODE_TAG 0x2 #define MAP_GBL_ERR_CODE_TAG 0x6 switch (tag) { case MAP_LOCAL_ERR_CODE_TAG: GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Local Error Code", ett_err_code, &def_len, &len, temp_subtree); if (len > 0) { saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &int_val); str = match_strval(int_val, gsm_ss_err_code_strings); proto_tree_add_text(temp_subtree, asn1->tvb, saved_offset, len, "Error Code: %s (%d)", (str == NULL) ? "Unknown Error Code" : str, int_val); } break; case MAP_GBL_ERR_CODE_TAG: GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Global Error Code", ett_err_code, &def_len, &len, temp_subtree); if (len > 0) { saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &int_val); proto_tree_add_text(temp_subtree, asn1->tvb, saved_offset, len, "Error Code: %d", int_val); } break; default: GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Unknown Error Code", ett_err_code, &def_len, &len, temp_subtree); if (len > 0) { saved_offset = asn1->offset; asn1_int32_value_decode(asn1, len, &int_val); proto_tree_add_text(temp_subtree, asn1->tvb, saved_offset, len, "Error Code: %d", int_val); } break; } dissect_map_params(asn1, subtree, comp_len - (asn1->offset - saved_offset)); if (!def_len) { dissect_map_eoc(asn1, subtree); } proto_item_set_len(item, asn1->offset - orig_offset); return(MAP_OK); } static void dissect_map_reject(ASN1_SCK *asn1, proto_tree *tree) { guint tag, len; guint saved_offset; proto_item *item; proto_tree *subtree; gboolean def_len; tag = -1; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); subtree = proto_item_add_subtree(item, ett_components); proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Reject Type Tag: 0x%02x", tag); dissect_map_len(asn1, subtree, &def_len, &len); dissect_map_invokeId(asn1, subtree); dissect_map_problem(asn1, subtree); if (!def_len) { dissect_map_eoc(asn1, subtree); } proto_item_set_len(item, asn1->offset - saved_offset); } static void dissect_map_message(packet_info *pinfo, proto_tree *map_tree, ASN1_SCK *asn1) { guint saved_offset; gchar *str = NULL; static int i = 0; saved_offset = asn1->offset; asn1_id_decode1(asn1, &g_comp_type_tag); asn1->offset = saved_offset; str = match_strval(g_comp_type_tag, tcap_component_type_str); if (NULL == str) return; if (check_col(pinfo->cinfo, COL_INFO)) { if (0 == i) { col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "& %s ", str); } } switch(g_comp_type_tag) { case TCAP_COMP_INVOKE : dissect_map_invoke(asn1, pinfo, map_tree); break; case TCAP_COMP_RRL : dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Last) Type Tag"); break; case TCAP_COMP_RE : dissect_map_re(asn1, map_tree); break; case TCAP_COMP_REJECT : dissect_map_reject(asn1, map_tree); break; case TCAP_COMP_RRN : dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Not Last) Type Tag"); break; default: proto_tree_add_text(map_tree, asn1->tvb, saved_offset, -1, "Message type not handled, ignoring"); break; } } static void dissect_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *map_tree; ASN1_SCK asn1; int offset = 0; /* * Make entries in Protocol column on summary display */ if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM MAP"); } /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ if (tree) { g_pinfo = pinfo; g_tree = tree; /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_map, tvb, 0, -1, FALSE); map_tree = proto_item_add_subtree(ti, ett_map); asn1_open(&asn1, tvb, offset); dissect_map_message(pinfo, map_tree, &asn1); asn1_close(&asn1, &offset); } } /* Register the protocol with Ethereal */ void proto_register_map(void) { guint i; gint last_offset; /* Setup list of header fields See Section 1.6.1 for details*/ static hf_register_info hf[] = { { &hf_map_length, { "Length", "map.len", FT_UINT8, BASE_HEX, NULL, 0, "", HFILL } }, { &hf_map_opr_code, { "Operation Code", "map.oprcode", FT_INT32, BASE_DEC, VALS(gsm_map_opr_code_strings), 0, "", HFILL } }, { &hf_map_int, { "Integer Data", "map.data", FT_INT32, BASE_DEC, 0, 0, "", HFILL } }, { &hf_map_imsi, { "IMSI", "map.imsi", FT_STRING, BASE_DEC, 0, 0, "", HFILL } }, { &hf_map_addrstring, { "AddressString", "map.addrstring", FT_STRING, BASE_DEC, 0, 0, "", HFILL } }, { &hf_map_rand, { "RAND", "map.rand", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_sres, { "SRES", "map.sres", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_kc, { "Kc", "map.kc", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_xres, { "XRES", "map.xres", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_ck, { "CK", "map.ck", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_ik, { "IK", "map.ik", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } }, { &hf_map_autn, { "AUTN", "map.autn", FT_BYTES, BASE_HEX, 0, 0, "", HFILL } } }; /* Setup protocol subtree array */ #define NUM_INDIVIDUAL_PARAMS 9 static gint *ett[NUM_INDIVIDUAL_PARAMS+(GSM_MAP_NUM_OP*2)+NUM_PARAM_1]; memset((void *) ett, 0, sizeof(ett)); ett[0] = &ett_map; ett[1] = &ett_opr_code; ett[2] = &ett_component; ett[3] = &ett_components; ett[4] = &ett_sequence; ett[5] = &ett_param; ett[6] = &ett_params; ett[7] = &ett_problem; ett[8] = &ett_err_code; last_offset = NUM_INDIVIDUAL_PARAMS; for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++) { ett_op[i] = -1; ett[last_offset] = &ett_op[i]; } for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++) { ett_op_rr[i] = -1; ett[last_offset] = &ett_op_rr[i]; } for (i=0; i < NUM_PARAM_1; i++, last_offset++) { ett_param_1[i] = -1; ett[last_offset] = &ett_param_1[i]; } /* Register the protocol name and description */ proto_map = proto_register_protocol("GSM Mobile Application Part", "GSM MAP", "gsm_map"); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_map, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); sms_dissector_table = register_dissector_table("gsm_map.sms_tpdu", "GSM SMS TPDU", FT_UINT8, BASE_DEC); gsm_map_tap = register_tap("gsm_map"); } void proto_reg_handoff_map(void) { dissector_handle_t map_handle; map_handle = create_dissector_handle(dissect_map, proto_map); dissector_add("tcap.itu_ssn", 6, map_handle); dissector_add("tcap.itu_ssn", 7, map_handle); dissector_add("tcap.itu_ssn", 8, map_handle); dissector_add("tcap.itu_ssn", 9, map_handle); }