diff options
Diffstat (limited to 'epan/dissectors/packet-gsm_map.c')
-rw-r--r-- | epan/dissectors/packet-gsm_map.c | 3150 |
1 files changed, 3150 insertions, 0 deletions
diff --git a/epan/dissectors/packet-gsm_map.c b/epan/dissectors/packet-gsm_map.c new file mode 100644 index 0000000000..2f2bbeb8e9 --- /dev/null +++ b/epan/dissectors/packet-gsm_map.c @@ -0,0 +1,3150 @@ +/* packet-gsm_map.c + * Routines for GSM Mobile Application Part dissection + * + * Copyright 2000, Felix Fei <felix.fei [AT] utstar.com> + * + * Michael Lum <mlum [AT] telostech.com>, + * Changed to run on new version of TCAP, many changes for + * EOC matching, and parameter separation. (2003) + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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); +} |