Move the tap infrastructure to the epan directory.
[obnox/wireshark/wip.git] / epan / dissectors / packet-gsm_map.c
1 /* packet-gsm_map.c
2  * Routines for GSM Mobile Application Part dissection
3  *
4  * Copyright 2000, Felix Fei <felix.fei [AT] utstar.com>
5  *
6  * Michael Lum <mlum [AT] telostech.com>,
7  * Changed to run on new version of TCAP, many changes for
8  * EOC matching, and parameter separation.  (2003)
9  *
10  * $Id$
11  *
12  * Ethereal - Network traffic analyzer
13  * By Gerald Combs <gerald@ethereal.com>
14  * Copyright 1998 Gerald Combs
15  *
16  * Copied from packet-tcap.c (where "WHATEVER_FILE_YOU_USED"
17  * is a dissector file; if you just copied this from README.developer,
18  * don't bother with the "Copied from" - you don't even need to put
19  * in a "Copied from" if you copied an existing dissector, especially
20  * if the bulk of the code in the new dissector is your code)
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public License
24  * as published by the Free Software Foundation; either version 2
25  * of the License, or (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35  */
36
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "epan/packet.h"
46 #include <epan/tap.h>
47 #include "asn1.h"
48
49 #include "packet-tcap.h"
50 #include "packet-gsm_ss.h"
51 #include "packet-gsm_map.h"
52
53
54 /* OPERATION CODE DEFINITION */
55
56 /* LOCATION MANAGEMENT */
57 #define MAP_UPD_LOC                     2       /* Update Location */
58 #define MAP_CANCEL_LOC                  3       /* Cancel Location */
59 #define MAP_PURGE                       67      /* Purge MS */
60 #define MAP_SEND_ID                     5       /* Send Identification */
61 #define MAP_GPRS_UPD_LOC                23      /* GPRS Update Location */
62 #define MAP_DET_IMSI                    5       /* Detach IMSI */
63 #define MAP_NOTE_MM_EVT                 89      /* Note MM Event */
64
65 /* HANDOVER MANAGEMENT */
66 #define MAP_PREP_HO                     68      /* Prepare Handover */
67 #define MAP_PREP_SUBS_HO                69      /* Prepare Subsequent Handover */
68 #define MAP_PERF_HO                     28      /* Perform Handover */
69 #define MAP_PERF_SUBS_HO                30      /* Perform Subsequent Handover */
70 #define MAP_SEND_END_SIG                29      /* Send End Signal */
71 #define MAP_PROC_ACC_SIG                33      /* Process Access Signalling */
72 #define MAP_FWD_ACC_SIG                 34      /* Forward Access Signalling */
73
74 /* AUTHENTICATION MANAGEMENT */
75 #define MAP_AUTH_INFO                   56      /* Send Authintication Info */
76 #define MAP_AUTH_FAIL_RPT               15      /* Authentication Failure Report */
77
78 /*  IDENTIFICATION MANAGEMENT */
79 #define MAP_CHK_IMEI                    43      /* Check IMEI */
80
81 /* FAULT & RECOVERY MANAGEMENT */
82 #define MAP_RESET                       37      /* Reset */
83 #define MAP_RESTORE_DATA                57      /* Restore Data */
84 #define MAP_FWD_CHK_SS_IND              38      /* Forward Check SS Indication */
85
86 /* OAM MANAGEMENT */
87 #define MAP_ACT_TRACE                   50      /* Activate Trace */
88 #define MAP_DEACT_TRACE                 51      /* Deactivate Trace Mode */
89 #define MAP_SEND_IMSI                   58      /* Send IMSI */
90 #define MAP_TRACE_SUBS_ACTV             52      /* Trace Subscriber Activity */
91 #define MAP_NOTE_INTER_HO               35      /* Not Internal Handover */
92
93 /* CALL MANAGEMENT */
94 #define MAP_ROUTE_INFO                  22      /* Send Routing Info */
95 #define MAP_PROV_ROAM_NUM               4       /* Provide Roaming Number */
96 #define MAP_PROV_SIWFS_NUM              31      /* Provide SIWFS Number */
97 #define MAP_SIWFS_SIG_MOD               32      /* SIWFS Signalling Modify */
98 #define MAP_RES_CALL_HAND               6       /* Resume Call Handling */
99 #define MAP_SET_RPT_STATE               73      /* Set Reporting State */
100 #define MAP_STAT_RPT                    74      /* Status Report */
101 #define MAP_REM_USR_FREE                75      /* Remote user free */
102 #define MAP_PREP_GRP_CALL               39      /* Prepare Group Call */
103 #define MAP_SND_GRP_CALL_END_SIG        40      /* Send Group Call End Signalling */
104 #define MAP_PRO_GRP_CALL_SIG            41      /* Process Group Call Signalling  */
105 #define MAP_FWD_GRP_CALL_SIG            42      /* Forward Group Call Signalling  */
106 #define MAP_IST_ALERT                   87      /* IST Alert */
107 #define MAP_IST_COMMAND                 88      /* IST Command */
108
109 /* SS MANAGEMENT */
110 #define MAP_REG_SS                      10      /* Register SS */
111 #define MAP_ERASE_SS                    11      /* Erase SS */
112 #define MAP_ACT_SS                      12      /* Activate SS */
113 #define MAP_DEACT_SS                    13      /* Deactivate SS */
114 #define MAP_INTER_SS                    14      /* Interrogate SS */
115 #define MAP_PROC_U_SS_REQ               59      /* Process Unstructured SS Req */
116 #define MAP_U_SS_REQ                    60      /* Unstructured SS Request */
117 #define MAP_U_SS_NOTIFY                 61      /* Unstructured SS Notify */
118 #define MAP_REG_PASSWD                  17      /* Register Password */
119 #define MAP_GET_PASSWD                  18      /* Get Password */
120 #define MAP_REG_CC_ENT                  76      /* Register CC Entry */
121 #define MAP_ERASE_CC_ENT                77      /* Erase CC Entry */
122 #define MAP_BEGIN_SUBS_ACTV             54      /* Begin Subscriber Activity */
123 #define MAP_PROC_U_SS_DATA              19      /* Process Unstructured SS Data */
124 #define MAP_SS_INV_NOTIFY               72      /* SS Invocation Notify */
125
126 /* SMS MANAGEMENT */
127 #define MAP_MO_FWD_SM                   46      /* Mobile Originated Forward Short Message */
128 #define MAP_MT_FWD_SM                   44      /* Mobile Terminated Forward Short Message */
129 #define MAP_ROUTE_INFO_SM               45      /* Routing Info for SM */
130 #define MAP_SM_DEL_STAT                 47      /* Report SM Delivery Status */
131 #define MAP_INFORM_SC                   63      /* Inform Service Center */
132 #define MAP_ALERT_SC                    64      /* Alert Service Center */
133 #define MAP_SM_READY                    66      /* Ready for Short Message */
134 #define MAP_NOTE_SUB_PRES               48      /* Note Subscriber Present */
135 #define MAP_ALERT_SC_W_RES              49      /* Alert SC Without Result */
136
137 /* SUBSCRIBER MANAGEMENT */
138 #define MAP_INS_SUB_DATA                7       /* Insert Subscriber Data */
139 #define MAP_DEL_SUB_DATA                8       /* Delete Subscriber Data */
140 #define MAP_PROV_SUB_INFO               70      /* Provide Subscriber Info */
141 #define MAP_ANY_TIME_INTER              71      /* Any Time Interrogation */
142 #define MAP_SEND_PARAM                  9       /* Send Parameters */
143 #define MAP_ANY_TIME_SUB_DATA_INTER     62      /* Any Time Subscriber Info Interrogation */
144 #define MAP_ANY_TIME_MOD                65      /* Any Time Modification */
145 #define MAP_NOTE_SUB_DATA_MOD           5       /* Note Subscriber Data Modified */
146
147 /* PDP ACTIVE MANAGEMENT */
148 #define MAP_GPRS_ROUTE_INFO             24      /* Rout Info for GPRS */
149 #define MAP_FAIL_REP                    25      /* Failure Report */
150 #define MAP_GPRS_NOTE_MS_PRES           26      /* GPRS NoteMs Present */
151
152 /* LOCATION SERVICE */
153 #define MAP_PROV_SUB_LOC                83      /* Provide Subscriber Location */
154 #define MAP_SEND_ROUTE_INFO_FOR_LCS     85      /* Send Routing Info For LCS */
155 #define MAP_SUB_LOC_REP                 86      /* Subscriber Location Report */
156
157
158 #define MAP_OPR_CODE_TAG        0x02
159 #define MAP_GE_PROBLEM_TAG      0x80
160 #define MAP_IN_PROBLEM_TAG      0x81
161 #define MAP_RR_PROBLEM_TAG      0x82
162 #define MAP_RE_PROBLEM_TAG      0x83
163 #define MAP_INVALID_TAG         0x00
164
165 #define MAP_OK                  0x0
166 #define MAP_FAIL                0x1
167
168 const value_string gsm_map_opr_code_strings[] = {
169
170 /* LOCATION MANAGEMENT */
171     { MAP_UPD_LOC,                      "Update Location"},
172     { MAP_CANCEL_LOC,                   "Cancel Location"},
173     { MAP_PURGE,                        "Purge MS"},
174     { MAP_SEND_ID,                      "Send Identification"},
175     { MAP_GPRS_UPD_LOC,                 "Update GPRS Location"},
176     { MAP_DET_IMSI,                     "Detach IMSI"},
177     { MAP_NOTE_MM_EVT,                  "Note MM Event"},
178
179 /* HANDOVER MANAGEMENT */
180     { MAP_PREP_HO,                      "Prepare Handover"},
181     { MAP_PREP_SUBS_HO,                 "Prepare Subsequent Handover"},
182     { MAP_PERF_HO,                      "Perform Handover"},
183     { MAP_PERF_SUBS_HO,                 "Perform Subsequent Handover"},
184     { MAP_SEND_END_SIG,                 "Send End Signal"},
185     { MAP_PROC_ACC_SIG,                 "Process Access Signalling"},
186     { MAP_FWD_ACC_SIG,                  "Forward Access Signalling"},
187
188 /* AUTHENTICATION MANAGEMENT */
189     { MAP_AUTH_INFO,                    "Send Authentication Info"},
190     { MAP_AUTH_FAIL_RPT,                "Authentication Failure Report"},
191
192 /* IDENTIFICATION MANAGEMENT */
193     { MAP_CHK_IMEI,                     "Check IMEI"},
194
195 /* FAULT & RECOVERY MANAGEMENT */
196     { MAP_RESET,                        "Reset"},
197     { MAP_RESTORE_DATA,                 "Restore Data"},
198     { MAP_FWD_CHK_SS_IND,               "Forward Check SS Indication"},
199
200 /* OAM MANAGEMENT */
201     { MAP_ACT_TRACE,                    "Activate Trace Mode"},
202     { MAP_DEACT_TRACE,                  "Deactivate Trace Mode"},
203     { MAP_SEND_IMSI,                    "Send IMSI"},
204     { MAP_TRACE_SUBS_ACTV,              "Trace Subscriber Activity"},
205     { MAP_NOTE_INTER_HO,                "Note Internal Handover"},
206
207 /*  CALL MANAGEMENT */
208     { MAP_ROUTE_INFO,                   "Send Routing Info"},
209     { MAP_PROV_ROAM_NUM,                "Provide Roaming Number"},
210     { MAP_PROV_SIWFS_NUM,               "Provide SIWFS Number"},
211     { MAP_SIWFS_SIG_MOD,                "SIWFS Signalling Modify"},
212     { MAP_RES_CALL_HAND,                "Resume Call Handling"},
213     { MAP_SET_RPT_STATE,                "Set Reporting State"},
214     { MAP_STAT_RPT,                     "Status Report"},
215     { MAP_REM_USR_FREE,                 "Remote User Free"},
216     { MAP_PREP_GRP_CALL,                "Prepare Group Call"},
217     { MAP_SND_GRP_CALL_END_SIG,         "Send Group Call End Signalling"},
218     { MAP_PRO_GRP_CALL_SIG,             "Process Group Call Signalling"},
219     { MAP_FWD_GRP_CALL_SIG,             "Forward Group Call Signalling"},
220     { MAP_IST_ALERT,                    "IST Alert"},
221     { MAP_IST_COMMAND,                  "IST Command"},
222
223 /* SS MANAGEMENT */
224     { MAP_REG_SS,                       "Register SS"},
225     { MAP_ERASE_SS,                     "Erase SS"},
226     { MAP_ACT_SS,                       "Activate SS"},
227     { MAP_DEACT_SS,                     "Deactivate SS"},
228     { MAP_INTER_SS,                     "Interrogate SS"},
229     { MAP_PROC_U_SS_REQ,                "Process Unstructured SS Request"},
230     { MAP_U_SS_REQ,                     "Unstructured SS Request"},
231     { MAP_U_SS_NOTIFY,                  "Unstructured SS Notify"},
232     { MAP_REG_PASSWD,                   "Register Password"},
233     { MAP_GET_PASSWD,                   "Get Password"},
234     { MAP_REG_CC_ENT,                   "Register CC Entry"},
235     { MAP_ERASE_CC_ENT,                 "Erase CC Entry"},
236     { MAP_BEGIN_SUBS_ACTV,              "Begin Subscriber Activity"},
237     { MAP_PROC_U_SS_DATA,               "Process Unstructured SS Data"},
238     { MAP_SS_INV_NOTIFY,                "SS Invocation Notification"},
239
240 /* SMS MANAGEMENT */
241     { MAP_MO_FWD_SM,                    "MO Forward SM"},
242     { MAP_MT_FWD_SM,                    "MT Forward SM"},
243     { MAP_ROUTE_INFO_SM,                "Send Routing Info For SM"},
244     { MAP_SM_DEL_STAT,                  "Report SM Delivery Status"},
245     { MAP_INFORM_SC,                    "Inform Service Center"},
246     { MAP_ALERT_SC,                     "Alert Service Center"},
247     { MAP_SM_READY,                     "Ready For SM"},
248     { MAP_NOTE_SUB_PRES,                "Note Subscriber Present"},
249     { MAP_ALERT_SC_W_RES,               "Alert SC Without Result"},
250
251 /* SUBSCRIBER MANAGEMENT */
252     { MAP_INS_SUB_DATA,                 "Insert Subscriber Data"},
253     { MAP_DEL_SUB_DATA,                 "Delete Subscriber Data"},
254     { MAP_PROV_SUB_INFO,                "Provide Subscriber Info"},
255     { MAP_ANY_TIME_INTER,               "Any Time Interrogation"},
256     { MAP_SEND_PARAM,                   "Send Parameters"},
257     { MAP_ANY_TIME_SUB_DATA_INTER,      "Any Time Subscription Interrogation"},
258     { MAP_ANY_TIME_MOD,                 "Any Time Modification"},
259     { MAP_NOTE_SUB_DATA_MOD,            "Note Subscriber Data Modified"},
260
261 /* PDP ACTIVE MANAGEMENT */
262     { MAP_GPRS_ROUTE_INFO,              "Send Routing Info For GPRS"},
263     { MAP_FAIL_REP,                     "Failure Report"},
264     { MAP_GPRS_NOTE_MS_PRES,            "Note MS Present For GPRS"},
265
266 /* LOCATION SERVICE */
267     { MAP_PROV_SUB_LOC,                 "Provide Subscriber Location"},
268     { MAP_SEND_ROUTE_INFO_FOR_LCS,      "Send Routing Info For LCS"},
269     { MAP_SUB_LOC_REP,                  "Subscriber Location Report"},
270
271     { 0,                                NULL}
272 };
273
274 /*
275  * Initialize the protocol and registered fields
276  */
277 static int                      proto_map = -1;
278
279 static int                      gsm_map_tap = -1;
280
281 static dissector_table_t        sms_dissector_table;    /* SMS TPDU */
282
283 static int                      gsm_map_app_context = 1;        /* XXX should be set from Dialogue */
284
285 static packet_info              *g_pinfo;
286 static proto_tree               *g_tree;
287 static guint                    g_opr_code;
288 static guint                    g_comp_type_tag;
289
290 static int hf_map_length = -1;
291 static int hf_map_opr_code = -1;
292 static int hf_map_int = -1;
293 static int hf_map_imsi = -1;
294 static int hf_map_addrstring = -1;
295 static int hf_map_rand = -1;
296 static int hf_map_sres = -1;
297 static int hf_map_kc = -1;
298 static int hf_map_xres = -1;
299 static int hf_map_ck = -1;
300 static int hf_map_ik = -1;
301 static int hf_map_autn = -1;
302
303 /* never initialize in field array */
304 static int hf_null = -1;
305 #define HF_NULL         &hf_null
306
307 /* Initialize the subtree pointers */
308 static gint ett_map = -1;
309 static gint ett_component = -1;
310 static gint ett_components = -1;
311 static gint ett_sequence = -1;
312 static gint ett_param = -1;
313 static gint ett_params = -1;
314 static gint ett_problem = -1;
315 static gint ett_opr_code = -1;
316 static gint ett_err_code = -1;
317
318 typedef struct dgt_set_t
319 {
320     unsigned char out[15];
321 }
322 dgt_set_t;
323
324 #ifdef MLUM
325 static dgt_set_t Dgt_tbcd = {
326     {
327   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
328      '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
329     }
330 };
331 #endif
332
333 static dgt_set_t Dgt_msid = {
334     {
335   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
336      '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
337     }
338 };
339
340
341 /* FORWARD DECLARATIONS */
342
343 static int dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree);
344
345 /* FUNCTIONS */
346
347 /*
348  * Unpack BCD input pattern into output ASCII pattern
349  *
350  * Input Pattern is supplied using the same format as the digits
351  *
352  * Returns: length of unpacked pattern
353  */
354 static int
355 my_dgt_tbcd_unpack(
356     char        *out,           /* ASCII pattern out */
357     guchar      *in,            /* packed pattern in */
358     int         num_octs,       /* Number of octets to unpack */
359     dgt_set_t   *dgt            /* Digit definitions */
360     )
361 {
362     int cnt = 0;
363     unsigned char i;
364
365     while (num_octs)
366     {
367         /*
368          * unpack first value in byte
369          */
370         i = *in++;
371         *out++ = dgt->out[i & 0x0f];
372         cnt++;
373
374         /*
375          * unpack second value in byte
376          */
377         i >>= 4;
378
379         if (i == 0x0f)  /* odd number bytes - hit filler */
380             break;
381
382         *out++ = dgt->out[i];
383         cnt++;
384         num_octs--;
385     }
386
387     *out = '\0';
388
389     return(cnt);
390 }
391
392 static gchar *
393 my_match_strval(guint32 val, const value_string *vs, gint *idx)
394 {
395     gint        i = 0;
396
397     while (vs[i].strptr) {
398         if (vs[i].value == val)
399         {
400             *idx = i;
401             return(vs[i].strptr);
402         }
403
404         i++;
405     }
406
407     *idx = -1;
408     return(NULL);
409 }
410
411 #define GSM_MAP_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
412     { \
413         guint           _len_offset; \
414         proto_item      *_item; \
415  \
416         _len_offset = asn1->offset; \
417         asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
418  \
419         _item = \
420             proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
421  \
422         _Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
423  \
424         proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
425             _Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
426  \
427         if (*_Gdef_len_p) \
428         { \
429             proto_tree_add_uint(_Gsubtree_p, hf_map_length, asn1->tvb, \
430                 _len_offset, asn1->offset - _len_offset, *_Glen_p); \
431         } \
432         else \
433         { \
434             proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
435                 _len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
436  \
437             *_Glen_p = tcap_find_eoc(asn1); \
438         } \
439  \
440         proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
441             (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
442     }
443
444 static int
445 dissect_map_params(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
446 {
447     guint       orig_offset, saved_offset, len_offset;
448     guint       tag, len;
449     gboolean    def_len = FALSE;
450     proto_item  *item;
451     proto_tree  *subtree;
452
453     orig_offset = asn1->offset;
454
455     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
456         (!tcap_check_tag(asn1, 0)))
457     {
458         if ((exp_len != 0) &&
459             ((asn1->offset - orig_offset) >= exp_len))
460         {
461             break;
462         }
463
464         saved_offset = asn1->offset;
465         asn1_id_decode1(asn1, &tag);
466
467         if (TCAP_CONSTRUCTOR(tag))
468         {
469             GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
470                 ett_sequence,
471                 &def_len, &len, subtree);
472
473             dissect_map_params(asn1, subtree, len);
474
475             if (!def_len)
476             {
477                 dissect_map_eoc(asn1, subtree);
478             }
479             continue;
480         }
481
482         len_offset = asn1->offset;
483         asn1_length_decode(asn1, &def_len, &len);
484
485         if (!def_len)
486         {
487             proto_tree_add_text(tree, asn1->tvb,
488                 saved_offset, len_offset - saved_offset,
489                 "Tag: 0x%02x", tag);
490
491             proto_tree_add_text(tree, asn1->tvb,
492                 len_offset, asn1->offset - len_offset, "Length: Indefinite");
493
494             len = tcap_find_eoc(asn1);
495
496             dissect_map_params(asn1, tree, len);
497
498             dissect_map_eoc(asn1, tree);
499             continue;
500         }
501
502         item =
503             proto_tree_add_text(tree, asn1->tvb,
504                 saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
505
506         subtree = proto_item_add_subtree(item, ett_param);
507
508         proto_tree_add_text(subtree, asn1->tvb,
509             saved_offset, len_offset - saved_offset,
510             "Tag: 0x%02x", tag);
511
512         proto_tree_add_uint(subtree, hf_map_length, asn1->tvb,
513             len_offset, asn1->offset - len_offset, len);
514
515         if (len > 0)
516         {
517             proto_tree_add_text(subtree, asn1->tvb,
518                 asn1->offset, len, "Parameter Data");
519
520             asn1->offset += len;
521         }
522     }
523
524     return(MAP_OK);
525 }
526
527
528 /* PARAMETERS */
529
530 static void
531 param_bytes(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
532 {
533     guint       saved_offset;
534
535     saved_offset = asn1->offset;
536
537     proto_tree_add_bytes(tree, hf_field, asn1->tvb,
538         saved_offset, len, tvb_get_ptr(asn1->tvb, saved_offset, len));
539
540     asn1->offset += len;
541 }
542
543 static void
544 param_imsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
545 {
546     guint       saved_offset;
547     guchar      *poctets;
548     char        bigbuf[1024];
549
550     saved_offset = asn1->offset;
551     asn1_string_value_decode(asn1, len, &poctets);
552
553     my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid);
554     g_free(poctets);
555
556     if (hf_field == -1)
557     {
558         proto_tree_add_text(tree, asn1->tvb,
559             saved_offset, len, "IMSI %s", bigbuf);
560     }
561     else
562     {
563         proto_tree_add_string_format(tree, hf_field, asn1->tvb,
564             saved_offset, len, bigbuf, "IMSI %s", bigbuf);
565     }
566 }
567
568 static void
569 param_lmsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
570 {
571     guint       saved_offset;
572     gint32      value;
573
574     hf_field = hf_field;
575
576     saved_offset = asn1->offset;
577     asn1_int32_value_decode(asn1, len, &value);
578
579     proto_tree_add_text(tree, asn1->tvb,
580         saved_offset, len, "LMSI 0x%04x", value);
581 }
582
583 static void
584 param_boolean(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
585 {
586     guint       saved_offset;
587     gint32      value;
588
589     hf_field = hf_field;
590
591     saved_offset = asn1->offset;
592     asn1_int32_value_decode(asn1, len, &value);
593
594     proto_tree_add_text(tree, asn1->tvb,
595         saved_offset, len, value ? "TRUE" : "FALSE");
596 }
597
598 static void
599 param_alertReason(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
600 {
601     guint       saved_offset;
602     gint32      value;
603     gchar       *str = NULL;
604
605     hf_field = hf_field;
606
607     saved_offset = asn1->offset;
608     asn1_int32_value_decode(asn1, len, &value);
609
610     switch (value)
611     {
612     case 0x00:
613         str = "ms-Present";
614         break;
615
616     case 0x01:
617         str = "memoryAvailable";
618         break;
619
620     default:
621         str = "Unrecognized value";
622         break;
623     }
624
625     proto_tree_add_text(tree, asn1->tvb,
626         saved_offset, len, str);
627 }
628
629
630 typedef enum
631 {
632     GSM_MAP_P_IMSI,                     /* IMSI */
633     GSM_MAP_P_LMSI,                     /* LMSI */
634     GSM_MAP_P_MSISDN,                   /* MSISDN */
635     GSM_MAP_P_SC_ADDR_DA,               /* Service Centre Address DA */
636     GSM_MAP_P_SC_ADDR_OA,               /* Service Centre Address OA */
637     GSM_MAP_P_SC_ADDR,                  /* Service Centre Address */
638     GSM_MAP_P_MSC_NUMBER,               /* MSC Number */
639     GSM_MAP_P_VLR_NUMBER,               /* VLR Number */
640     GSM_MAP_P_HLR_NUMBER,               /* HLR Number */
641     GSM_MAP_P_SIG_INFO,                 /* Signal Info */
642     GSM_MAP_P_BOOL,                     /* Boolean */
643     GSM_MAP_P_LIWLMSI,                  /* Location Information with LMSI */
644     GSM_MAP_P_NETNODE_NUM,              /* Network Node Number */
645     GSM_MAP_P_ROAMING_NUM,              /* Roaming Number */
646     GSM_MAP_P_ALERT_REASON,             /* Alert Reason */
647     GSM_MAP_P_GMSC_ADDR,                /* GMSC Address */
648     GSM_MAP_P_RAND,                     /* Rand */
649     GSM_MAP_P_SRES,                     /* Signed Result */
650     GSM_MAP_P_KC,                       /* Key Cipher */
651     GSM_MAP_P_XRES,                     /* Extended Signed Result */
652     GSM_MAP_P_CK,                       /* Ciphering Key */
653     GSM_MAP_P_IK,                       /* Integrity Key */
654     GSM_MAP_P_AUTN,                     /* Authentication Token */
655     GSM_MAP_P_NONE                      /* NONE */
656 }
657 param_idx_t;
658
659 #define NUM_PARAM_1 (GSM_MAP_P_NONE+1)
660 static gint ett_param_1[NUM_PARAM_1];
661 static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = {
662     param_imsi,                         /* IMSI */
663     param_lmsi,                         /* LMSI */
664     param_AddressString,                /* MSISDN */
665     param_AddressString,                /* Service Centre Address DA */
666     param_AddressString,                /* Service Centre Address OA */
667     param_AddressString,                /* Service Centre Address */
668     param_AddressString,                /* MSC Number */
669     param_AddressString,                /* VLR Number */
670     param_AddressString,                /* HLR Number */
671     NULL,                               /* Signal Info */
672     param_boolean,                      /* Boolean */
673     NULL,                               /* Location Information with LMSI */
674     param_AddressString,                /* Network Node Number */
675     param_AddressString,                /* Roaming Number */
676     param_alertReason,                  /* Alert Reason */
677     param_AddressString,                /* GMSC Address */
678     param_bytes,                        /* Rand */
679     param_bytes,                        /* Signed Result */
680     param_bytes,                        /* GSM Key Cipher */
681     param_bytes,                        /* Extended Signed Result */
682     param_bytes,                        /* UMTS Ciphering Key */
683     param_bytes,                        /* Integrity Key */
684     param_bytes,                        /* Authentication Token */
685     NULL                                /* NONE */
686 };
687
688 static int *param_1_hf[] = {
689     &hf_map_imsi,                       /* IMSI */
690     HF_NULL,                            /* LMSI */
691     &hf_map_addrstring,                 /* MSISDN */
692     &hf_map_addrstring,                 /* Service Centre Address DA */
693     &hf_map_addrstring,                 /* Service Centre Address OA */
694     &hf_map_addrstring,                 /* Service Centre Address */
695     &hf_map_addrstring,                 /* MSC Number */
696     &hf_map_addrstring,                 /* VLR Number */
697     &hf_map_addrstring,                 /* HLR Number */
698     HF_NULL,                            /* Signal Info */
699     HF_NULL,                            /* Boolean */
700     HF_NULL,                            /* Location Information with LMSI */
701     &hf_map_addrstring,                 /* Network Node Number */
702     &hf_map_addrstring,                 /* Roaming Number */
703     HF_NULL,                            /* Alert Reason */
704     &hf_map_addrstring,                 /* GMSC Address */
705     &hf_map_rand,                       /* Rand */
706     &hf_map_sres,                       /* Signed Result */
707     &hf_map_kc,                         /* GSM Key Cipher */
708     &hf_map_xres,                       /* Extended Signed Result */
709     &hf_map_ck,                         /* UMTS Ciphering Key */
710     &hf_map_ik,                         /* Integrity Key */
711     &hf_map_autn,                       /* Authentication Token */
712     NULL                                /* NONE */
713 };
714
715
716 #define GSM_MAP_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \
717     { \
718         gint            _ett_param_idx; \
719         guint           _len; \
720         void            (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \
721         int             *_param_hf = NULL; \
722         proto_tree      *_subtree; \
723         gboolean        _def_len; \
724  \
725         if (Ga1 == GSM_MAP_P_NONE) \
726         { \
727             _ett_param_idx = ett_param; \
728             _param_fcn = NULL; \
729             _param_hf = HF_NULL; \
730         } \
731         else \
732         { \
733             _ett_param_idx = ett_param_1[Ga1]; \
734             _param_fcn = param_1_fcn[Ga1]; \
735             _param_hf = param_1_hf[Ga1]; \
736         } \
737  \
738         GSM_MAP_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \
739  \
740         if (_len > 0) \
741         { \
742             if (Ga1 == GSM_MAP_P_NONE || _param_fcn == NULL) \
743             { \
744                 proto_tree_add_text(_subtree, asn1->tvb, \
745                     asn1->offset, _len, "Parameter Data"); \
746  \
747                 asn1->offset += _len; \
748             } \
749             else \
750             { \
751                 (*_param_fcn)(asn1, _subtree, _len, *_param_hf); \
752             } \
753         } \
754  \
755         if (!_def_len) \
756         { \
757             dissect_map_eoc(asn1, Gtree); \
758         } \
759     }
760
761
762 static void
763 param_Identity(ASN1_SCK *asn1, proto_tree *tree)
764 {
765     guint               saved_offset, start_offset;
766     guint               tag, len;
767     gboolean            def_len = FALSE;
768     proto_tree          *subtree;
769
770     saved_offset = asn1->offset;
771     asn1_id_decode1(asn1, &tag);
772
773     switch (tag)
774     {
775     case 0x04:  /* IMSI */
776         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "Identity");
777         break;
778
779     case 0x30:  /* IMSI-WithLMSI */
780
781         GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
782             ett_sequence,
783             &def_len, &len, subtree);
784
785         start_offset = asn1->offset;
786
787         saved_offset = asn1->offset;
788         asn1_id_decode1(asn1, &tag);
789
790         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
791
792         saved_offset = asn1->offset;
793         asn1_id_decode1(asn1, &tag);
794
795         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI");
796
797         dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
798
799         if (!def_len)
800         {
801             dissect_map_eoc(asn1, subtree);
802         }
803         break;
804
805     default:
806         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_NONE, "Identity");
807         break;
808     }
809 }
810
811 static void
812 param_TripletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
813 {
814     guint               saved_offset, orig_offset;
815     guint               tag, len;
816     gboolean            def_len = FALSE;
817     proto_tree          *subtree;
818
819     orig_offset = asn1->offset;
820
821     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
822         (!tcap_check_tag(asn1, 0)))
823     {
824         if ((exp_len != 0) &&
825             ((asn1->offset - orig_offset) >= exp_len))
826         {
827             break;
828         }
829
830         saved_offset = asn1->offset;
831         asn1_id_decode1(asn1, &tag);
832
833         GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
834             ett_sequence,
835             &def_len, &len, subtree);
836
837         saved_offset = asn1->offset;
838         asn1_id_decode1(asn1, &tag);
839
840         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND");
841
842         saved_offset = asn1->offset;
843         asn1_id_decode1(asn1, &tag);
844
845         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SRES, "SRES");
846
847         saved_offset = asn1->offset;
848         asn1_id_decode1(asn1, &tag);
849
850         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_KC, "Kc");
851
852         if (!def_len)
853         {
854             dissect_map_eoc(asn1, subtree);
855         }
856     }
857 }
858
859 static void
860 param_QuintupletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
861 {
862     guint               saved_offset, orig_offset;
863     guint               tag, len;
864     gboolean            def_len = FALSE;
865     proto_tree          *subtree;
866
867     orig_offset = asn1->offset;
868
869     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
870         (!tcap_check_tag(asn1, 0)))
871     {
872         if ((exp_len != 0) &&
873             ((asn1->offset - orig_offset) >= exp_len))
874         {
875             break;
876         }
877
878         saved_offset = asn1->offset;
879         asn1_id_decode1(asn1, &tag);
880
881         GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
882             ett_sequence,
883             &def_len, &len, subtree);
884
885         saved_offset = asn1->offset;
886         asn1_id_decode1(asn1, &tag);
887
888         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND");
889
890         saved_offset = asn1->offset;
891         asn1_id_decode1(asn1, &tag);
892
893         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_XRES, "XRES");
894
895         saved_offset = asn1->offset;
896         asn1_id_decode1(asn1, &tag);
897
898         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_CK, "CK");
899
900         saved_offset = asn1->offset;
901         asn1_id_decode1(asn1, &tag);
902
903         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IK, "IK");
904
905         saved_offset = asn1->offset;
906         asn1_id_decode1(asn1, &tag);
907
908         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_AUTN, "AUTN");
909
910         if (!def_len)
911         {
912             dissect_map_eoc(asn1, subtree);
913         }
914     }
915 }
916
917 static void
918 param_SM_RP_DA(ASN1_SCK *asn1, proto_tree *tree)
919 {
920     guint       saved_offset;
921     guint       tag;
922     gint        idx;
923
924     saved_offset = asn1->offset;
925     asn1_id_decode1(asn1, &tag);
926
927     switch (tag)
928     {
929     case 0x80:  /* IMSI */
930         idx = GSM_MAP_P_IMSI;
931         break;
932
933     case 0x81:  /* LMSI */
934         idx = GSM_MAP_P_LMSI;
935         break;
936
937     case 0x84:  /* AddressString */
938         idx = GSM_MAP_P_SC_ADDR_DA;
939         break;
940
941     default:
942         /*
943          * this occurs in the mobile terminated case for
944          * subsequent messages
945          */
946         idx = GSM_MAP_P_NONE;
947         break;
948     }
949
950     GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-DA");
951 }
952
953 static void
954 param_SM_RP_OA(ASN1_SCK *asn1, proto_tree *tree, int *direction_p)
955 {
956     guint       saved_offset;
957     guint       tag;
958     gint        idx;
959
960     saved_offset = asn1->offset;
961     asn1_id_decode1(asn1, &tag);
962
963     switch (tag)
964     {
965     case 0x82:  /* MSISDN */
966         idx = GSM_MAP_P_MSISDN;
967
968         *direction_p = P2P_DIR_RECV;
969         break;
970
971     case 0x84:  /* AddressString */
972         idx = GSM_MAP_P_SC_ADDR_OA;
973
974         *direction_p = P2P_DIR_SENT;
975         break;
976
977     default:
978         idx = GSM_MAP_P_NONE;
979
980         /*
981          * this occurs in the mobile terminated case for
982          * subsequent messages
983          */
984         *direction_p = P2P_DIR_SENT;
985         break;
986     }
987
988     GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-OA");
989 }
990
991 static void
992 param_SM_RP_UI(ASN1_SCK *asn1, proto_tree *tree)
993 {
994     guint       saved_offset;
995     guint       tag, len;
996     gboolean    def_len = FALSE;
997     proto_tree  *subtree;
998     tvbuff_t    *tpdu_tvb;
999
1000     saved_offset = asn1->offset;
1001     asn1_id_decode1(asn1, &tag);
1002
1003     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "SM-RP-UI",
1004         ett_param_1[GSM_MAP_P_SIG_INFO],
1005         &def_len, &len, subtree);
1006
1007     proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "TPDU");
1008
1009     /*
1010      * dissect the embedded TPDU message
1011      */
1012     tpdu_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len);
1013
1014     dissector_try_port(sms_dissector_table, 0, tpdu_tvb, g_pinfo, g_tree);
1015
1016     asn1->offset += len;
1017
1018     if (!def_len)
1019     {
1020         dissect_map_eoc(asn1, subtree);
1021     }
1022 }
1023
1024 static void
1025 param_LWI_LMSI(ASN1_SCK *asn1, proto_tree *tree)
1026 {
1027     guint       saved_offset, start_offset;
1028     guint       tag, len;
1029     gboolean    def_len = FALSE;
1030     proto_tree  *subtree;
1031
1032     saved_offset = asn1->offset;
1033     asn1_id_decode1(asn1, &tag);
1034
1035     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "LOCATION INFO WITH LMSI",
1036         ett_param_1[GSM_MAP_P_LIWLMSI],
1037         &def_len, &len, subtree);
1038
1039     start_offset = asn1->offset;
1040
1041     saved_offset = asn1->offset;
1042     asn1_id_decode1(asn1, &tag);
1043
1044     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NETNODE_NUM, "NETWORK NODE NUMBER");
1045
1046     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1047
1048     if (!def_len)
1049     {
1050         dissect_map_eoc(asn1, subtree);
1051     }
1052 }
1053
1054
1055 /* MESSAGES */
1056
1057 static void
1058 op_update_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1059 {
1060     guint       saved_offset, start_offset;
1061     guint       tag, len;
1062     gboolean    def_len = FALSE;
1063     proto_tree  *subtree;
1064
1065     exp_len = exp_len;
1066
1067     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1068
1069     saved_offset = asn1->offset;
1070     asn1_id_decode1(asn1, &tag);
1071
1072     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1073     {
1074         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1075
1076         return;
1077     }
1078
1079     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1080         ett_sequence,
1081         &def_len, &len, subtree);
1082
1083     start_offset = asn1->offset;
1084
1085     saved_offset = asn1->offset;
1086     asn1_id_decode1(asn1, &tag);
1087
1088     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1089
1090     saved_offset = asn1->offset;
1091     asn1_id_decode1(asn1, &tag);
1092
1093     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number");
1094
1095     saved_offset = asn1->offset;
1096     asn1_id_decode1(asn1, &tag);
1097
1098     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_VLR_NUMBER, "VLR Number");
1099
1100     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1101
1102     if (!def_len)
1103     {
1104         dissect_map_eoc(asn1, subtree);
1105     }
1106 }
1107
1108 static void
1109 op_update_loc_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1110 {
1111     guint       saved_offset, start_offset;
1112     guint       tag, len;
1113     gboolean    def_len = FALSE;
1114     proto_tree  *subtree;
1115
1116     exp_len = exp_len;
1117
1118     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1119
1120     saved_offset = asn1->offset;
1121     asn1_id_decode1(asn1, &tag);
1122
1123     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1124     {
1125         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
1126
1127         return;
1128     }
1129
1130     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1131         ett_sequence,
1132         &def_len, &len, subtree);
1133
1134     start_offset = asn1->offset;
1135
1136     saved_offset = asn1->offset;
1137     asn1_id_decode1(asn1, &tag);
1138
1139     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
1140
1141     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1142
1143     if (!def_len)
1144     {
1145         dissect_map_eoc(asn1, subtree);
1146     }
1147 }
1148
1149 static void
1150 op_cancel_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1151 {
1152     guint       saved_offset, start_offset;
1153     guint       tag, len;
1154     gboolean    def_len = FALSE;
1155     proto_tree  *subtree;
1156
1157     exp_len = exp_len;
1158
1159     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1160
1161     saved_offset = asn1->offset;
1162     asn1_id_decode1(asn1, &tag);
1163
1164     if (tag != 0xa3)
1165     {
1166         /*
1167          * Hmmm, unexpected
1168          */
1169         return;
1170     }
1171
1172     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Constructor Sequence",
1173         ett_sequence,
1174         &def_len, &len, subtree);
1175
1176     start_offset = asn1->offset;
1177
1178     param_Identity(asn1, subtree);
1179
1180     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1181
1182     if (!def_len)
1183     {
1184         dissect_map_eoc(asn1, subtree);
1185     }
1186 }
1187
1188 static void
1189 op_send_auth_info(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1190 {
1191     guint       saved_offset, start_offset;
1192     guint       tag, len;
1193     gboolean    def_len = FALSE;
1194     proto_tree  *subtree;
1195
1196     exp_len = exp_len;
1197
1198     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1199
1200     saved_offset = asn1->offset;
1201     asn1_id_decode1(asn1, &tag);
1202
1203     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1204     {
1205         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1206
1207         return;
1208     }
1209
1210     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1211         ett_sequence,
1212         &def_len, &len, subtree);
1213
1214     start_offset = asn1->offset;
1215
1216     saved_offset = asn1->offset;
1217     asn1_id_decode1(asn1, &tag);
1218
1219     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1220
1221     saved_offset = asn1->offset;
1222     asn1_id_decode1(asn1, &tag);
1223
1224     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Number Of Requested Vectors");
1225
1226     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1227
1228     if (!def_len)
1229     {
1230         dissect_map_eoc(asn1, subtree);
1231     }
1232 }
1233
1234 static void
1235 op_send_auth_info_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1236 {
1237     guint       saved_offset, start_offset;
1238     guint       tag, len;
1239     gboolean    def_len = FALSE;
1240     proto_tree  *subtree;
1241
1242     exp_len = exp_len;
1243
1244     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1245
1246     saved_offset = asn1->offset;
1247     asn1_id_decode1(asn1, &tag);
1248
1249     if ((tag != 0x30) &&
1250         (tag != 0x31))
1251     {
1252         /*
1253          * Hmmm, unexpected
1254          */
1255         return;
1256     }
1257
1258     GSM_MAP_START_SUBTREE(tree, saved_offset, tag,
1259         (tag == 0x30) ? "TripletList" : "QuintupletList",
1260         ett_sequence,
1261         &def_len, &len, subtree);
1262
1263     start_offset = asn1->offset;
1264
1265     if (tag == 0x30)
1266     {
1267         param_TripletList(asn1, subtree, len);
1268     }
1269     else
1270     {
1271         param_QuintupletList(asn1, subtree, len);
1272     }
1273
1274     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1275
1276     if (!def_len)
1277     {
1278         dissect_map_eoc(asn1, subtree);
1279     }
1280 }
1281
1282 static void
1283 op_restore_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1284 {
1285     guint       saved_offset, start_offset;
1286     guint       tag, len;
1287     gboolean    def_len = FALSE;
1288     proto_tree  *subtree;
1289
1290     exp_len = exp_len;
1291
1292     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1293
1294     saved_offset = asn1->offset;
1295     asn1_id_decode1(asn1, &tag);
1296
1297     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1298     {
1299         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1300
1301         return;
1302     }
1303
1304     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1305         ett_sequence,
1306         &def_len, &len, subtree);
1307
1308     start_offset = asn1->offset;
1309
1310     saved_offset = asn1->offset;
1311     asn1_id_decode1(asn1, &tag);
1312
1313     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1314
1315     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1316
1317     if (!def_len)
1318     {
1319         dissect_map_eoc(asn1, subtree);
1320     }
1321 }
1322
1323 static void
1324 op_restore_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1325 {
1326     guint       saved_offset, start_offset;
1327     guint       tag, len;
1328     gboolean    def_len = FALSE;
1329     proto_tree  *subtree;
1330
1331     exp_len = exp_len;
1332
1333     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1334
1335     saved_offset = asn1->offset;
1336     asn1_id_decode1(asn1, &tag);
1337
1338     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1339     {
1340         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
1341
1342         return;
1343     }
1344
1345     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1346         ett_sequence,
1347         &def_len, &len, subtree);
1348
1349     start_offset = asn1->offset;
1350
1351     saved_offset = asn1->offset;
1352     asn1_id_decode1(asn1, &tag);
1353
1354     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
1355
1356     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1357
1358     if (!def_len)
1359     {
1360         dissect_map_eoc(asn1, subtree);
1361     }
1362 }
1363
1364 static void
1365 op_send_rti(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1366 {
1367     guint       saved_offset, start_offset;
1368     guint       tag, len;
1369     gboolean    def_len = FALSE;
1370     proto_tree  *subtree;
1371
1372     exp_len = exp_len;
1373
1374     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1375
1376     saved_offset = asn1->offset;
1377     asn1_id_decode1(asn1, &tag);
1378
1379     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1380     {
1381         /*
1382          * Hmmm, unexpected
1383          */
1384         return;
1385     }
1386
1387     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1388         ett_sequence,
1389         &def_len, &len, subtree);
1390
1391     start_offset = asn1->offset;
1392
1393     saved_offset = asn1->offset;
1394     asn1_id_decode1(asn1, &tag);
1395
1396     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
1397
1398     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1399
1400     if (!def_len)
1401     {
1402         dissect_map_eoc(asn1, subtree);
1403     }
1404 }
1405
1406 static void
1407 op_send_rti_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1408 {
1409     guint       saved_offset, start_offset;
1410     guint       tag, len;
1411     gboolean    def_len = FALSE;
1412     proto_tree  *subtree;
1413
1414     exp_len = exp_len;
1415
1416     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1417
1418     saved_offset = asn1->offset;
1419     asn1_id_decode1(asn1, &tag);
1420
1421     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1422     {
1423         /*
1424          * Hmmm, unexpected
1425          */
1426         return;
1427     }
1428
1429     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1430         ett_sequence,
1431         &def_len, &len, subtree);
1432
1433     start_offset = asn1->offset;
1434
1435     /*
1436      * spec says [9] but 'real data' show '04' not '89' !
1437      */
1438     if (tcap_check_tag(asn1, 0x04))
1439     {
1440         saved_offset = asn1->offset;
1441         asn1_id_decode1(asn1, &tag);
1442
1443         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1444     }
1445
1446     if (tcap_check_tag(asn1, 0x04))
1447     {
1448         saved_offset = asn1->offset;
1449         asn1_id_decode1(asn1, &tag);
1450
1451         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
1452     }
1453
1454     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1455
1456     if (!def_len)
1457     {
1458         dissect_map_eoc(asn1, subtree);
1459     }
1460 }
1461
1462 static void
1463 op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1464 {
1465     guint       saved_offset, start_offset;
1466     guint       tag, len;
1467     gboolean    def_len = FALSE;
1468     proto_tree  *subtree;
1469
1470     exp_len = exp_len;
1471
1472     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1473
1474     saved_offset = asn1->offset;
1475     asn1_id_decode1(asn1, &tag);
1476
1477     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1478     {
1479         /*
1480          * Hmmm, unexpected
1481          */
1482         return;
1483     }
1484
1485     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1486         ett_sequence,
1487         &def_len, &len, subtree);
1488
1489     start_offset = asn1->offset;
1490
1491     saved_offset = asn1->offset;
1492     asn1_id_decode1(asn1, &tag);
1493
1494     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1495
1496     saved_offset = asn1->offset;
1497     asn1_id_decode1(asn1, &tag);
1498
1499     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number");
1500
1501     if (tcap_check_tag(asn1, 0x82))
1502     {
1503         saved_offset = asn1->offset;
1504         asn1_id_decode1(asn1, &tag);
1505
1506         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
1507     }
1508
1509     if (tcap_check_tag(asn1, 0x84))
1510     {
1511         saved_offset = asn1->offset;
1512         asn1_id_decode1(asn1, &tag);
1513
1514         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI");
1515     }
1516
1517     if (tcap_check_tag(asn1, 0x85))
1518     {
1519         saved_offset = asn1->offset;
1520         asn1_id_decode1(asn1, &tag);
1521
1522         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "GSM Bearer Capability");
1523     }
1524
1525     if (tcap_check_tag(asn1, 0xa6))
1526     {
1527         saved_offset = asn1->offset;
1528         asn1_id_decode1(asn1, &tag);
1529
1530         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Network Signal Info");
1531     }
1532
1533     if (tcap_check_tag(asn1, 0x87))
1534     {
1535         saved_offset = asn1->offset;
1536         asn1_id_decode1(asn1, &tag);
1537
1538         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Suppression Of Announcement");
1539     }
1540
1541     if (tcap_check_tag(asn1, 0x88))
1542     {
1543         saved_offset = asn1->offset;
1544         asn1_id_decode1(asn1, &tag);
1545
1546         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_GMSC_ADDR, "GMSC Address");
1547     }
1548
1549     if (tcap_check_tag(asn1, 0x89))
1550     {
1551         saved_offset = asn1->offset;
1552         asn1_id_decode1(asn1, &tag);
1553
1554         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Call Reference Number");
1555     }
1556
1557     if (tcap_check_tag(asn1, 0x8a))
1558     {
1559         saved_offset = asn1->offset;
1560         asn1_id_decode1(asn1, &tag);
1561
1562         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Interrogation");
1563     }
1564
1565     if (tcap_check_tag(asn1, 0x8b))
1566     {
1567         saved_offset = asn1->offset;
1568         asn1_id_decode1(asn1, &tag);
1569
1570         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Extension Container");
1571     }
1572
1573     if (tcap_check_tag(asn1, 0x8c))
1574     {
1575         saved_offset = asn1->offset;
1576         asn1_id_decode1(asn1, &tag);
1577
1578         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Alerting Pattern");
1579     }
1580
1581     if (tcap_check_tag(asn1, 0x8d))
1582     {
1583         saved_offset = asn1->offset;
1584         asn1_id_decode1(asn1, &tag);
1585
1586         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "CCBS Call");
1587     }
1588
1589     if (tcap_check_tag(asn1, 0x8f))
1590     {
1591         saved_offset = asn1->offset;
1592         asn1_id_decode1(asn1, &tag);
1593
1594         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Supported Camel Phases In GMSC");
1595     }
1596
1597     if (tcap_check_tag(asn1, 0x8e))
1598     {
1599         saved_offset = asn1->offset;
1600         asn1_id_decode1(asn1, &tag);
1601
1602         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Additional Signal Info");
1603     }
1604
1605     if (tcap_check_tag(asn1, 0x90))
1606     {
1607         saved_offset = asn1->offset;
1608         asn1_id_decode1(asn1, &tag);
1609
1610         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Not Supported In GMSC");
1611     }
1612
1613     if (tcap_check_tag(asn1, 0x91))
1614     {
1615         saved_offset = asn1->offset;
1616         asn1_id_decode1(asn1, &tag);
1617
1618         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Pre-paging Supported");
1619     }
1620
1621     if (tcap_check_tag(asn1, 0x92))
1622     {
1623         saved_offset = asn1->offset;
1624         asn1_id_decode1(asn1, &tag);
1625
1626         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Long FTN Supported");
1627     }
1628
1629     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1630
1631     if (!def_len)
1632     {
1633         dissect_map_eoc(asn1, subtree);
1634     }
1635 }
1636
1637 static void
1638 op_provide_rn_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1639 {
1640     guint       saved_offset, start_offset;
1641     guint       tag, len;
1642     gboolean    def_len = FALSE;
1643     proto_tree  *subtree;
1644
1645     exp_len = exp_len;
1646
1647     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1648
1649     saved_offset = asn1->offset;
1650     asn1_id_decode1(asn1, &tag);
1651
1652     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1653     {
1654         GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
1655
1656         return;
1657     }
1658
1659     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1660         ett_sequence,
1661         &def_len, &len, subtree);
1662
1663     start_offset = asn1->offset;
1664
1665     saved_offset = asn1->offset;
1666     asn1_id_decode1(asn1, &tag);
1667
1668     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
1669
1670     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1671
1672     if (!def_len)
1673     {
1674         dissect_map_eoc(asn1, subtree);
1675     }
1676 }
1677
1678 /*
1679  * Description:
1680  *      Generic dissector for Supplementary Services
1681  */
1682 static void
1683 op_ss_generic(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1684 {
1685
1686     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1687
1688     gsm_ss_dissect(asn1, tree, exp_len, g_opr_code, g_comp_type_tag);
1689 }
1690
1691 static void
1692 op_mo_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1693 {
1694     guint       saved_offset, start_offset;
1695     guint       tag, len;
1696     gboolean    def_len = FALSE;
1697     proto_tree  *subtree;
1698
1699     exp_len = exp_len;
1700
1701     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1702
1703     saved_offset = asn1->offset;
1704     asn1_id_decode1(asn1, &tag);
1705
1706     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1707     {
1708         /*
1709          * Hmmm, unexpected
1710          */
1711         return;
1712     }
1713
1714     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1715         ett_sequence,
1716         &def_len, &len, subtree);
1717
1718     start_offset = asn1->offset;
1719
1720     param_SM_RP_DA(asn1, subtree);
1721
1722     param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir);
1723
1724     param_SM_RP_UI(asn1, subtree);
1725
1726     /*
1727      * older versions of GSM MAP had only one ForwardSM message
1728      */
1729     if ((tvb_length_remaining(asn1->tvb, asn1->offset) > (def_len ? 0 : TCAP_EOC_LEN)) &&
1730         (gsm_map_app_context < 3) &&
1731         (g_pinfo->p2p_dir == P2P_DIR_SENT))
1732     {
1733         /*
1734          * 'more messages' for V1 context
1735          */
1736         saved_offset = asn1->offset;
1737         asn1_id_decode1(asn1, &tag);
1738
1739         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send");
1740     }
1741
1742     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1743
1744     if (!def_len)
1745     {
1746         dissect_map_eoc(asn1, subtree);
1747     }
1748 }
1749
1750 static void
1751 op_mt_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1752 {
1753     guint       saved_offset, start_offset;
1754     guint       tag, len;
1755     gboolean    def_len = FALSE;
1756     proto_tree  *subtree;
1757
1758     exp_len = exp_len;
1759
1760     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1761
1762     saved_offset = asn1->offset;
1763     asn1_id_decode1(asn1, &tag);
1764
1765     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1766     {
1767         /*
1768          * Hmmm, unexpected
1769          */
1770         return;
1771     }
1772
1773     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1774         ett_sequence,
1775         &def_len, &len, subtree);
1776
1777     start_offset = asn1->offset;
1778
1779     param_SM_RP_DA(asn1, subtree);
1780
1781     param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir);
1782
1783     param_SM_RP_UI(asn1, subtree);
1784
1785     if (tvb_length_remaining(asn1->tvb, asn1->offset) > 0)
1786     {
1787         /*
1788          * 'more messages'
1789          */
1790         saved_offset = asn1->offset;
1791         asn1_id_decode1(asn1, &tag);
1792
1793         GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send");
1794     }
1795
1796     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1797
1798     if (!def_len)
1799     {
1800         dissect_map_eoc(asn1, subtree);
1801     }
1802 }
1803
1804 static void
1805 op_forward_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1806 {
1807     guint       saved_offset, start_offset;
1808     guint       tag, len;
1809     gboolean    def_len = FALSE;
1810     proto_tree  *subtree;
1811
1812     exp_len = exp_len;
1813
1814     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1815
1816     saved_offset = asn1->offset;
1817     asn1_id_decode1(asn1, &tag);
1818
1819     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1820     {
1821         /*
1822          * Hmmm, unexpected
1823          */
1824         return;
1825     }
1826
1827     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1828         ett_sequence,
1829         &def_len, &len, subtree);
1830
1831     start_offset = asn1->offset;
1832
1833     param_SM_RP_UI(asn1, subtree);
1834
1835     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1836
1837     if (!def_len)
1838     {
1839         dissect_map_eoc(asn1, subtree);
1840     }
1841 }
1842
1843 static void
1844 op_send_rti_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1845 {
1846     guint       saved_offset, start_offset;
1847     guint       tag, len;
1848     gboolean    def_len = FALSE;
1849     proto_tree  *subtree;
1850
1851     exp_len = exp_len;
1852
1853     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1854
1855     saved_offset = asn1->offset;
1856     asn1_id_decode1(asn1, &tag);
1857
1858     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1859     {
1860         /*
1861          * Hmmm, unexpected
1862          */
1863         return;
1864     }
1865
1866     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1867         ett_sequence,
1868         &def_len, &len, subtree);
1869
1870     start_offset = asn1->offset;
1871
1872     saved_offset = asn1->offset;
1873     asn1_id_decode1(asn1, &tag);
1874
1875     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
1876
1877     saved_offset = asn1->offset;
1878     asn1_id_decode1(asn1, &tag);
1879
1880     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_BOOL, "SM-RP-PRI");
1881
1882     saved_offset = asn1->offset;
1883     asn1_id_decode1(asn1, &tag);
1884
1885     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
1886
1887     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1888
1889     if (!def_len)
1890     {
1891         dissect_map_eoc(asn1, subtree);
1892     }
1893 }
1894
1895 static void
1896 op_send_rti_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1897 {
1898     guint       saved_offset, start_offset;
1899     guint       tag, len;
1900     gboolean    def_len = FALSE;
1901     proto_tree  *subtree;
1902
1903     exp_len = exp_len;
1904
1905     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1906
1907     saved_offset = asn1->offset;
1908     asn1_id_decode1(asn1, &tag);
1909
1910     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1911     {
1912         /*
1913          * Hmmm, unexpected
1914          */
1915         return;
1916     }
1917
1918     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1919         ett_sequence,
1920         &def_len, &len, subtree);
1921
1922     start_offset = asn1->offset;
1923
1924     saved_offset = asn1->offset;
1925     asn1_id_decode1(asn1, &tag);
1926
1927     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
1928
1929     param_LWI_LMSI(asn1, subtree);
1930
1931     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1932
1933     if (!def_len)
1934     {
1935         dissect_map_eoc(asn1, subtree);
1936     }
1937 }
1938
1939 static void
1940 op_alert_sc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1941 {
1942     guint       saved_offset, start_offset;
1943     guint       tag, len;
1944     gboolean    def_len = FALSE;
1945     proto_tree  *subtree;
1946
1947     exp_len = exp_len;
1948
1949     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1950
1951     saved_offset = asn1->offset;
1952     asn1_id_decode1(asn1, &tag);
1953
1954     if (TCAP_CONSTRUCTOR(tag) == FALSE)
1955     {
1956         /*
1957          * Hmmm, unexpected
1958          */
1959         return;
1960     }
1961
1962     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1963         ett_sequence,
1964         &def_len, &len, subtree);
1965
1966     start_offset = asn1->offset;
1967
1968     saved_offset = asn1->offset;
1969     asn1_id_decode1(asn1, &tag);
1970
1971     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
1972
1973     saved_offset = asn1->offset;
1974     asn1_id_decode1(asn1, &tag);
1975
1976     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
1977
1978     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
1979
1980     if (!def_len)
1981     {
1982         dissect_map_eoc(asn1, subtree);
1983     }
1984 }
1985
1986 static void
1987 op_ready_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1988 {
1989     guint       saved_offset, start_offset;
1990     guint       tag, len;
1991     gboolean    def_len = FALSE;
1992     proto_tree  *subtree;
1993
1994     exp_len = exp_len;
1995
1996     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1997
1998     saved_offset = asn1->offset;
1999     asn1_id_decode1(asn1, &tag);
2000
2001     if (TCAP_CONSTRUCTOR(tag) == FALSE)
2002     {
2003         /*
2004          * Hmmm, unexpected
2005          */
2006         return;
2007     }
2008
2009     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
2010         ett_sequence,
2011         &def_len, &len, subtree);
2012
2013     start_offset = asn1->offset;
2014
2015     saved_offset = asn1->offset;
2016     asn1_id_decode1(asn1, &tag);
2017
2018     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
2019
2020     saved_offset = asn1->offset;
2021     asn1_id_decode1(asn1, &tag);
2022
2023     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ALERT_REASON, "Alert Reason");
2024
2025     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
2026
2027     if (!def_len)
2028     {
2029         dissect_map_eoc(asn1, subtree);
2030     }
2031 }
2032
2033 static void
2034 op_alert_sc_wr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2035 {
2036     guint       saved_offset, start_offset;
2037     guint       tag, len;
2038     gboolean    def_len = FALSE;
2039     proto_tree  *subtree;
2040
2041     exp_len = exp_len;
2042
2043     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2044
2045     saved_offset = asn1->offset;
2046     asn1_id_decode1(asn1, &tag);
2047
2048     if (TCAP_CONSTRUCTOR(tag) == FALSE)
2049     {
2050         /*
2051          * Hmmm, unexpected
2052          */
2053         return;
2054     }
2055
2056     GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
2057         ett_sequence,
2058         &def_len, &len, subtree);
2059
2060     start_offset = asn1->offset;
2061
2062     saved_offset = asn1->offset;
2063     asn1_id_decode1(asn1, &tag);
2064
2065     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
2066
2067     saved_offset = asn1->offset;
2068     asn1_id_decode1(asn1, &tag);
2069
2070     GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
2071
2072     dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
2073
2074     if (!def_len)
2075     {
2076         dissect_map_eoc(asn1, subtree);
2077     }
2078 }
2079
2080 #define GSM_MAP_NUM_OP (sizeof(gsm_map_opr_code_strings)/sizeof(value_string))
2081 static gint ett_op[GSM_MAP_NUM_OP];
2082 static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
2083     op_update_loc,      /* Update Location */
2084     op_cancel_loc,      /* Cancel Location */
2085     NULL,       /* Purge MS */
2086     NULL,       /* Send Identification */
2087     NULL,       /* Update GPRS Location */
2088     NULL,       /* Detach IMSI */
2089     NULL,       /* Note MM Event */
2090     NULL,       /* Prepare Handover */
2091     NULL,       /* Prepare Subsequent Handover */
2092     NULL,       /* Perform Handover */
2093     NULL,       /* Perform Subsequent Handover */
2094     NULL,       /* Send End Signal */
2095     NULL,       /* Process Access Signalling */
2096     NULL,       /* Forward Access Signalling */
2097     op_send_auth_info,  /* Send Authentication Info */
2098     NULL,       /* Authentication Failure Report */
2099     NULL,       /* Check IMEI */
2100     NULL,       /* Reset */
2101     op_restore_data,    /* Restore Data */
2102     NULL,       /* Forward Check SS Indication */
2103     NULL,       /* Activate Trace Mode */
2104     NULL,       /* Deactivate Trace Mode */
2105     NULL,       /* Send IMSI */
2106     NULL,       /* Trace Subscriber Activity */
2107     NULL,       /* Note Internal Handover */
2108     op_send_rti,        /* Send Routing Info */
2109     op_provide_rn,      /* Provide Roaming Number */
2110     NULL,       /* Provide SIWFS Number */
2111     NULL,       /* SIWFS Signalling Modify */
2112     NULL,       /* Resume Call Handling */
2113     NULL,       /* Set Reporting State */
2114     NULL,       /* Status Report */
2115     NULL,       /* Remote User Free */
2116     NULL,       /* Prepare Group Call */
2117     NULL,       /* Send Group Call End Signalling */
2118     NULL,       /* Process Group Call Signalling */
2119     NULL,       /* Forward Group Call Signalling */
2120     NULL,       /* IST Alert */
2121     NULL,       /* IST Command */
2122     op_ss_generic,      /* Register SS */
2123     op_ss_generic,      /* Erase SS */
2124     op_ss_generic,      /* Activate SS */
2125     op_ss_generic,      /* Deactivate SS */
2126     op_ss_generic,      /* Interrogate SS */
2127     op_ss_generic,      /* Process Unstructured SS Request */
2128     op_ss_generic,      /* Unstructured SS Request */
2129     op_ss_generic,      /* Unstructured SS Notify */
2130     op_ss_generic,      /* Register Password */
2131     op_ss_generic,      /* Get Password */
2132     op_ss_generic,      /* Register CC Entry */
2133     op_ss_generic,      /* Erase CC Entry */
2134     NULL,       /* Begin Subscriber Activity */
2135     op_ss_generic,      /* Process Unstructured SS Data */
2136     op_ss_generic,      /* SS Invocation Notification */
2137     op_mo_forward_sm,   /* MO Forward SM */
2138     op_mt_forward_sm,   /* MT Forward SM */
2139     op_send_rti_sm,     /* Send Routing Info For SM */
2140     NULL,       /* Report SM Delivery Status */
2141     NULL,       /* Inform Service Center */
2142     op_alert_sc,        /* Alert Service Center */
2143     op_ready_sm,        /* Ready For SM */
2144     NULL,       /* Note Subscriber Present */
2145     op_alert_sc_wr,     /* Alert SC Without Result */
2146     NULL,       /* Insert Subscriber Data */
2147     NULL,       /* Delete Subscriber Data */
2148     NULL,       /* Provide Subscriber Info */
2149     NULL,       /* Any Time Interrogation */
2150     NULL,       /* Send Parameters */
2151     NULL,       /* Any Time Subscription Interrogation */
2152     NULL,       /* Any Time Modification */
2153     NULL,       /* Note Subscriber Data Modified */
2154     NULL,       /* Send Routing Info For GPRS */
2155     NULL,       /* Failure Report */
2156     NULL,       /* Note MS Present For GPRS */
2157     NULL,       /* Provide Subscriber Location */
2158     NULL,       /* Send Routing Info For LCS */
2159     NULL,       /* Subscriber Location Report */
2160
2161     NULL        /* NONE */
2162 };
2163
2164 static gint ett_op_rr[GSM_MAP_NUM_OP];
2165 static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
2166     op_update_loc_rr,   /* Update Location */
2167     NULL,       /* Cancel Location */
2168     NULL,       /* Purge MS */
2169     NULL,       /* Send Identification */
2170     NULL,       /* Update GPRS Location */
2171     NULL,       /* Detach IMSI */
2172     NULL,       /* Note MM Event */
2173     NULL,       /* Prepare Handover */
2174     NULL,       /* Prepare Subsequent Handover */
2175     NULL,       /* Perform Handover */
2176     NULL,       /* Perform Subsequent Handover */
2177     NULL,       /* Send End Signal */
2178     NULL,       /* Process Access Signalling */
2179     NULL,       /* Forward Access Signalling */
2180     op_send_auth_info_rr,       /* Send Authentication Info */
2181     NULL,       /* Authentication Failure Report */
2182     NULL,       /* Check IMEI */
2183     NULL,       /* Reset */
2184     op_restore_data_rr, /* Restore Data */
2185     NULL,       /* Forward Check SS Indication */
2186     NULL,       /* Activate Trace Mode */
2187     NULL,       /* Deactivate Trace Mode */
2188     NULL,       /* Send IMSI */
2189     NULL,       /* Trace Subscriber Activity */
2190     NULL,       /* Note Internal Handover */
2191     op_send_rti_rr,     /* Send Routing Info */
2192     op_provide_rn_rr,   /* Provide Roaming Number */
2193     NULL,       /* Provide SIWFS Number */
2194     NULL,       /* SIWFS Signalling Modify */
2195     NULL,       /* Resume Call Handling */
2196     NULL,       /* Set Reporting State */
2197     NULL,       /* Status Report */
2198     NULL,       /* Remote User Free */
2199     NULL,       /* Prepare Group Call */
2200     NULL,       /* Send Group Call End Signalling */
2201     NULL,       /* Process Group Call Signalling */
2202     NULL,       /* Forward Group Call Signalling */
2203     NULL,       /* IST Alert */
2204     NULL,       /* IST Command */
2205     op_ss_generic,      /* Register SS */
2206     op_ss_generic,      /* Erase SS */
2207     op_ss_generic,      /* Activate SS */
2208     op_ss_generic,      /* Deactivate SS */
2209     op_ss_generic,      /* Interrogate SS */
2210     op_ss_generic,      /* Process Unstructured SS Request */
2211     op_ss_generic,      /* Unstructured SS Request */
2212     op_ss_generic,      /* Unstructured SS Notify */
2213     op_ss_generic,      /* Register Password */
2214     op_ss_generic,      /* Get Password */
2215     op_ss_generic,      /* Register CC Entry */
2216     op_ss_generic,      /* Erase CC Entry */
2217     NULL,       /* Begin Subscriber Activity */
2218     op_ss_generic,      /* Process Unstructured SS Data */
2219     op_ss_generic,      /* SS Invocation Notification */
2220     op_forward_sm_rr,   /* MO Forward SM */
2221     op_forward_sm_rr,   /* MT Forward SM */
2222     op_send_rti_sm_rr,  /* Send Routing Info For SM */
2223     NULL,       /* Report SM Delivery Status */
2224     NULL,       /* Inform Service Center */
2225     NULL,       /* Alert Service Center */
2226     NULL,       /* Ready For SM */
2227     NULL,       /* Note Subscriber Present */
2228     NULL,       /* Alert SC Without Result */
2229     NULL,       /* Insert Subscriber Data */
2230     NULL,       /* Delete Subscriber Data */
2231     NULL,       /* Provide Subscriber Info */
2232     NULL,       /* Any Time Interrogation */
2233     NULL,       /* Send Parameters */
2234     NULL,       /* Any Time Subscription Interrogation */
2235     NULL,       /* Any Time Modification */
2236     NULL,       /* Note Subscriber Data Modified */
2237     NULL,       /* Send Routing Info For GPRS */
2238     NULL,       /* Failure Report */
2239     NULL,       /* Note MS Present For GPRS */
2240     NULL,       /* Provide Subscriber Location */
2241     NULL,       /* Send Routing Info For LCS */
2242     NULL,       /* Subscriber Location Report */
2243
2244     NULL        /* NONE */
2245 };
2246
2247
2248 /* GENERIC MAP DISSECTOR FUNCTIONS */
2249
2250 static int
2251 dissect_map_tag(ASN1_SCK *asn1, proto_tree *tree, guint *tag, guchar * str,
2252     proto_item **item_p)
2253 {
2254     guint       saved_offset, real_tag;
2255
2256     saved_offset = asn1->offset;
2257     asn1_id_decode1(asn1, &real_tag);
2258
2259     if ((*tag != (guint) -1) && (real_tag != *tag))
2260     {
2261         asn1->offset = saved_offset;
2262         return(MAP_FAIL);
2263     }
2264
2265     *item_p =
2266         proto_tree_add_text(tree, asn1->tvb,
2267             saved_offset, asn1->offset - saved_offset,
2268             "%s: 0x%02x", str, real_tag);
2269
2270     return(MAP_OK);
2271 }
2272
2273
2274 static int
2275 dissect_map_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
2276 {
2277     guint       saved_offset;
2278
2279     saved_offset = asn1->offset;
2280     *len = 0;
2281     *def_len = FALSE;
2282     asn1_length_decode(asn1, def_len, len);
2283
2284     if (*def_len)
2285     {
2286         proto_tree_add_uint(tree, hf_map_length, asn1->tvb, saved_offset,
2287             asn1->offset - saved_offset, *len);
2288     }
2289     else
2290     {
2291         proto_tree_add_text(tree, asn1->tvb,
2292             saved_offset, asn1->offset - saved_offset, "Length: Indefinite");
2293     }
2294
2295     return(MAP_OK);
2296 }
2297
2298
2299 static int
2300 dissect_map_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, guchar * str)
2301 {
2302     guint       saved_offset;
2303     gint32      invokeId;
2304
2305     saved_offset = asn1->offset;
2306     asn1_int32_value_decode(asn1, len, &invokeId);
2307
2308     proto_tree_add_int_format(tree, hf_map_int, asn1->tvb,
2309         saved_offset, asn1->offset - saved_offset,
2310         invokeId, "%s %d", str, invokeId);
2311
2312     return(MAP_OK);
2313 }
2314
2315
2316 static int
2317 dissect_map_invokeId(ASN1_SCK *asn1, proto_tree *tree)
2318 {
2319     guint       saved_offset = 0;
2320     guint       len;
2321     guint       tag;
2322     proto_item  *item, *null_item;
2323     proto_tree  *subtree;
2324     gboolean    def_len;
2325
2326     if (tcap_check_tag(asn1, TCAP_INVOKE_ID_TAG))
2327     {
2328         saved_offset = asn1->offset;
2329         item =
2330             proto_tree_add_text(tree, asn1->tvb,
2331                 saved_offset, -1, "Invoke Id");
2332
2333         subtree = proto_item_add_subtree(item, ett_component);
2334
2335         tag = -1;
2336         dissect_map_tag(asn1, subtree, &tag, "Invoke Id Tag", &null_item);
2337         dissect_map_len(asn1, subtree, &def_len, &len);
2338         dissect_map_integer(asn1, subtree, len, "Invoke Id:");
2339
2340         proto_item_set_len(item, asn1->offset - saved_offset);
2341     }
2342
2343     return(MAP_OK);
2344 }
2345
2346
2347 static void
2348 dissect_map_problem(ASN1_SCK *asn1, proto_tree *tree)
2349 {
2350     guint       orig_offset, saved_offset, len_offset;
2351     guint       len;
2352     guint       tag;
2353     proto_tree  *subtree;
2354     proto_item  *item = NULL;
2355     gchar       *str = NULL;
2356     gchar       *type_str = NULL;
2357     gint32      spec;
2358     gboolean    def_len;
2359
2360     orig_offset = asn1->offset;
2361     saved_offset = asn1->offset;
2362     asn1_id_decode1(asn1, &tag);
2363
2364     len_offset = asn1->offset;
2365     asn1_length_decode(asn1, &def_len, &len);
2366
2367     item =
2368         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
2369
2370     subtree = proto_item_add_subtree(item, ett_problem);
2371
2372     if (!def_len)
2373     {
2374         len = tcap_find_eoc(asn1);
2375     }
2376
2377     proto_item_set_len(item, (asn1->offset - saved_offset) + len +
2378         (def_len ? 0 : TCAP_EOC_LEN));
2379
2380     if (len != 1)
2381     {
2382         proto_tree_add_text(subtree, asn1->tvb,
2383             asn1->offset, len, "Unknown encoding of Problem Code");
2384
2385         asn1->offset += len;
2386
2387         if (!def_len)
2388         {
2389             asn1_eoc_decode(asn1, -1);
2390         }
2391
2392         return;
2393     }
2394
2395     saved_offset = asn1->offset;
2396     asn1_int32_value_decode(asn1, 1, &spec);
2397
2398     switch (tag)
2399     {
2400     case MAP_GE_PROBLEM_TAG:
2401         type_str = "General Problem";
2402         switch (spec)
2403         {
2404         case 0: str = "Unrecognized Component"; break;
2405         case 1: str = "Mistyped Component"; break;
2406         case 2: str = "Badly Structured Component"; break;
2407         default:
2408             str = "Undefined";
2409             break;
2410         }
2411         break;
2412
2413     case MAP_IN_PROBLEM_TAG:
2414         type_str = "Invoke";
2415         switch (spec)
2416         {
2417         case 0: str = "Duplicate Invoke ID"; break;
2418         case 1: str = "Unrecognized Operation"; break;
2419         case 2: str = "Mistyped Parameter"; break;
2420         case 3: str = "Resource Limitation"; break;
2421         case 4: str = "Initiating Release"; break;
2422         case 5: str = "Unrecognized Linked ID"; break;
2423         case 6: str = "Linked Response Unexpected"; break;
2424         case 7: str = "Unexpected Linked Operation"; break;
2425         default:
2426             str = "Undefined";
2427             break;
2428         }
2429         break;
2430
2431     case MAP_RR_PROBLEM_TAG:
2432         type_str = "Return Result";
2433         switch (spec)
2434         {
2435         case 0: str = "Unrecognized Invoke ID"; break;
2436         case 1: str = "Return Result Unexpected"; break;
2437         case 2: str = "Mistyped Parameter"; break;
2438         default:
2439             str = "Undefined";
2440             break;
2441         }
2442         break;
2443
2444     case MAP_RE_PROBLEM_TAG:
2445         type_str = "Return Error";
2446         switch (spec)
2447         {
2448         case 0: str = "Unrecognized Invoke ID"; break;
2449         case 1: str = "Return Error Unexpected"; break;
2450         case 2: str = "Unrecognized Error"; break;
2451         case 3: str = "Unexpected Error"; break;
2452         case 4: str = "Mistyped Parameter"; break;
2453         default:
2454             str = "Undefined";
2455             break;
2456         }
2457         break;
2458
2459     default:
2460         type_str = "Undefined";
2461         break;
2462     }
2463
2464     proto_tree_add_text(subtree, asn1->tvb,
2465         orig_offset, len_offset - orig_offset,
2466         "%s: %02x", type_str, tag);
2467
2468     if (def_len)
2469     {
2470         proto_tree_add_uint(subtree, hf_map_length, asn1->tvb,
2471             len_offset, saved_offset - len_offset, len);
2472     }
2473     else
2474     {
2475         proto_tree_add_text(subtree, asn1->tvb,
2476             len_offset, saved_offset - len_offset, "Length: Indefinite");
2477     }
2478
2479     proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1,
2480         "Problem Specifier %s", str);
2481 }
2482
2483
2484 static int
2485 dissect_map_lnkId(ASN1_SCK *asn1, proto_tree *tree)
2486 {
2487     guint       saved_offset = 0;
2488     guint       len;
2489     guint       tag;
2490     proto_item  *item, *null_item;
2491     proto_tree  *subtree;
2492     gboolean    def_len;
2493
2494     if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG))
2495     {
2496         saved_offset = asn1->offset;
2497
2498         item =
2499             proto_tree_add_text(tree, asn1->tvb,
2500                 saved_offset, -1, "Linked Id");
2501
2502         subtree = proto_item_add_subtree(item, ett_component);
2503
2504         tag = -1;
2505         dissect_map_tag(asn1, tree, &tag, "Linked Id Tag", &null_item);
2506         dissect_map_len(asn1, tree, &def_len, &len);
2507         dissect_map_integer(asn1, tree, len, "Linked Id:");
2508
2509         proto_item_set_len(item, asn1->offset - saved_offset);
2510     }
2511
2512     return(MAP_OK);
2513 }
2514
2515
2516 static int
2517 dissect_map_opr_code(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint *op_idx_p, guint *opr_code_p)
2518 {
2519     guint                       opr_offset = 0, saved_offset = 0;
2520     guint                       len;
2521     guint                       tag;
2522     gint32                      val;
2523     gchar                       *str = NULL;
2524     proto_item                  *item;
2525     proto_tree                  *subtree;
2526     gboolean                    def_len;
2527
2528     if (tcap_check_tag(asn1, MAP_OPR_CODE_TAG))
2529     {
2530         opr_offset = asn1->offset;
2531
2532         item =
2533             proto_tree_add_text(tree, asn1->tvb, opr_offset, -1,
2534                 "Operation Code");
2535
2536         subtree = proto_item_add_subtree(item, ett_opr_code);
2537
2538         tag = -1;
2539         asn1_id_decode1(asn1, &tag);
2540
2541         proto_tree_add_text(subtree, asn1->tvb,
2542             opr_offset, asn1->offset - opr_offset,
2543             "Operation Code Tag: 0x%02x", tag);
2544
2545         dissect_map_len(asn1, subtree, &def_len, &len);
2546
2547         saved_offset = asn1->offset;
2548         asn1_int32_value_decode(asn1, len, &val);
2549         proto_tree_add_int(subtree, hf_map_opr_code, asn1->tvb, saved_offset,
2550             asn1->offset - saved_offset, val);
2551
2552         proto_item_set_len(item, asn1->offset - opr_offset);
2553
2554         str = my_match_strval(val, gsm_map_opr_code_strings, op_idx_p);
2555
2556         if (NULL == str) return(MAP_FAIL);
2557
2558         if (check_col(pinfo->cinfo, COL_INFO))
2559         {
2560             col_append_fstr(pinfo->cinfo, COL_INFO,  "%s ", str);
2561         }
2562
2563         *opr_code_p = val;
2564     }
2565
2566     return(MAP_OK);
2567 }
2568
2569
2570 static int
2571 dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree)
2572 {
2573     guint       saved_offset;
2574
2575     saved_offset = asn1->offset;
2576
2577     if (tvb_length_remaining(asn1->tvb, saved_offset) <= 0)
2578     {
2579         return(MAP_FAIL);
2580     }
2581
2582     if (!asn1_eoc(asn1, -1))
2583     {
2584         return(MAP_FAIL);
2585     }
2586
2587     asn1_eoc_decode(asn1, -1);
2588
2589     proto_tree_add_text(tree, asn1->tvb,
2590         saved_offset, asn1->offset - saved_offset, "End of Contents");
2591
2592     return(MAP_OK);
2593 }
2594
2595
2596 static void
2597 dissect_map_invoke(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree)
2598 {
2599     proto_tree                  *subtree;
2600     guint                       orig_offset, saved_offset;
2601     guint                       len;
2602     guint                       tag;
2603     proto_item                  *item;
2604     gint                        op_idx;
2605     gboolean                    def_len;
2606     int                         ret;
2607     int                         opr_code_sts;
2608     static gsm_map_tap_rec_t    tap_rec;
2609
2610     orig_offset = asn1->offset;
2611     saved_offset = asn1->offset;
2612     ret = asn1_id_decode1(asn1, &tag);
2613
2614     item =
2615         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
2616
2617     subtree =
2618         proto_item_add_subtree(item, ett_components);
2619
2620     proto_tree_add_text(subtree, asn1->tvb, saved_offset,
2621         asn1->offset - saved_offset,
2622         "Invoke Type Tag: 0x%02x", tag);
2623
2624     dissect_map_len(asn1, subtree, &def_len, &len);
2625
2626     saved_offset = asn1->offset;
2627
2628     dissect_map_invokeId(asn1, subtree);
2629
2630     dissect_map_lnkId(asn1, subtree);
2631
2632     opr_code_sts = dissect_map_opr_code(asn1, pinfo, subtree, &op_idx, &g_opr_code);
2633
2634     if (opr_code_sts == MAP_OK)
2635     {
2636         if (def_len)
2637         {
2638             len -= asn1->offset - saved_offset;
2639         }
2640         else
2641         {
2642             len = tcap_find_eoc(asn1);
2643         }
2644
2645         /*
2646          * decode elements
2647          */
2648         if (op_fcn[op_idx] == NULL)
2649         {
2650             dissect_map_params(asn1, subtree, len);
2651         }
2652         else
2653         {
2654             (*op_fcn[op_idx])(asn1, subtree, len);
2655         }
2656     }
2657
2658     if (!def_len)
2659     {
2660         dissect_map_eoc(asn1, subtree);
2661     }
2662
2663     proto_item_set_len(item, asn1->offset - orig_offset);
2664
2665     if (opr_code_sts == MAP_OK)
2666     {
2667         tap_rec.invoke = TRUE;
2668         tap_rec.opr_code_idx = op_idx;
2669         tap_rec.size = asn1->offset - orig_offset;
2670
2671         tap_queue_packet(gsm_map_tap, pinfo, &tap_rec);
2672     }
2673 }
2674
2675
2676 static void
2677 dissect_map_rr(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gchar *str)
2678 {
2679     guint                       tag, len, comp_len;
2680     gint                        op_idx;
2681     guint                       orig_offset, saved_offset;
2682     proto_item                  *item;
2683     proto_tree                  *seq_subtree, *subtree;
2684     gboolean                    def_len;
2685     gboolean                    comp_def_len;
2686     int                         opr_code_sts;
2687     static gsm_map_tap_rec_t    tap_rec;
2688
2689     tag = -1;
2690     orig_offset = asn1->offset;
2691     saved_offset = asn1->offset;
2692     asn1_id_decode1(asn1, &tag);
2693
2694     item =
2695         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
2696
2697     subtree =
2698         proto_item_add_subtree(item, ett_components);
2699
2700     proto_tree_add_text(subtree, asn1->tvb,
2701         saved_offset, asn1->offset - saved_offset,
2702         "%s: %02x", str, tag);
2703
2704     dissect_map_len(asn1, subtree, &comp_def_len, &comp_len);
2705
2706     saved_offset = asn1->offset;
2707
2708     dissect_map_invokeId(asn1, subtree);
2709
2710     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
2711     {
2712         proto_item_set_len(item, asn1->offset - orig_offset);
2713
2714         return;
2715     }
2716
2717     saved_offset = asn1->offset;
2718
2719     tag = -1;
2720     asn1_id_decode1(asn1, &tag);
2721
2722     opr_code_sts = MAP_FAIL;
2723
2724     if (TCAP_CONSTRUCTOR(tag))
2725     {
2726         GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Sequence",
2727             ett_sequence,
2728             &def_len, &len, seq_subtree);
2729
2730         saved_offset = asn1->offset;
2731
2732         opr_code_sts = dissect_map_opr_code(asn1, pinfo, seq_subtree, &op_idx, &g_opr_code);
2733
2734         if (opr_code_sts == MAP_OK)
2735         {
2736             len -= asn1->offset - saved_offset;
2737
2738             /*
2739              * decode elements
2740              */
2741             if (op_fcn_rr[op_idx] == NULL)
2742             {
2743                 dissect_map_params(asn1, seq_subtree, len);
2744             }
2745             else
2746             {
2747                 (*op_fcn_rr[op_idx])(asn1, seq_subtree, len);
2748             }
2749         }
2750
2751         if (!def_len)
2752         {
2753             dissect_map_eoc(asn1, seq_subtree);
2754         }
2755     }
2756
2757     if (!comp_def_len)
2758     {
2759         dissect_map_eoc(asn1, subtree);
2760     }
2761
2762     proto_item_set_len(item, asn1->offset - orig_offset);
2763
2764     if (opr_code_sts == MAP_OK)
2765     {
2766         tap_rec.invoke = FALSE;
2767         tap_rec.opr_code_idx = op_idx;
2768         tap_rec.size = asn1->offset - orig_offset;
2769
2770         tap_queue_packet(gsm_map_tap, pinfo, &tap_rec);
2771     }
2772 }
2773
2774
2775 static int
2776 dissect_map_re(ASN1_SCK *asn1, proto_tree *tree)
2777 {
2778     guint       tag, len, comp_len;
2779     guint       orig_offset, saved_offset;
2780     proto_item  *item;
2781     proto_tree  *subtree, *temp_subtree;
2782     gboolean    comp_def_len, def_len;
2783     gchar       *str;
2784     gint32      int_val;
2785
2786     tag = -1;
2787     orig_offset = asn1->offset;
2788     saved_offset = asn1->offset;
2789     asn1_id_decode1(asn1, &tag);
2790
2791     item =
2792         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
2793
2794     subtree = proto_item_add_subtree(item, ett_components);
2795
2796     proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset,
2797         "Return Error Type Tag: 0x%02x", tag);
2798
2799     dissect_map_len(asn1, subtree, &comp_def_len, &comp_len);
2800
2801     if (!comp_def_len)
2802     {
2803         comp_len = tcap_find_eoc(asn1);
2804     }
2805
2806     saved_offset = asn1->offset;
2807
2808     dissect_map_invokeId(asn1, subtree);
2809
2810     saved_offset = asn1->offset;
2811     asn1_id_decode1(asn1, &tag);
2812
2813 #define MAP_LOCAL_ERR_CODE_TAG  0x2
2814 #define MAP_GBL_ERR_CODE_TAG    0x6
2815
2816     switch (tag)
2817     {
2818     case MAP_LOCAL_ERR_CODE_TAG:
2819         GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Local Error Code",
2820             ett_err_code,
2821             &def_len, &len, temp_subtree);
2822
2823         if (len > 0)
2824         {
2825             saved_offset = asn1->offset;
2826             asn1_int32_value_decode(asn1, len, &int_val);
2827
2828             str = match_strval(int_val, gsm_ss_err_code_strings);
2829
2830             proto_tree_add_text(temp_subtree, asn1->tvb,
2831                 saved_offset, len, "Error Code: %s (%d)",
2832                 (str == NULL) ? "Unknown Error Code" : str,
2833                 int_val);
2834         }
2835         break;
2836
2837     case MAP_GBL_ERR_CODE_TAG:
2838         GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Global Error Code",
2839             ett_err_code,
2840             &def_len, &len, temp_subtree);
2841
2842         if (len > 0)
2843         {
2844             saved_offset = asn1->offset;
2845             asn1_int32_value_decode(asn1, len, &int_val);
2846
2847             proto_tree_add_text(temp_subtree, asn1->tvb,
2848                 saved_offset, len, "Error Code: %d",
2849                 int_val);
2850         }
2851         break;
2852
2853     default:
2854         GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Unknown Error Code",
2855             ett_err_code,
2856             &def_len, &len, temp_subtree);
2857
2858         if (len > 0)
2859         {
2860             saved_offset = asn1->offset;
2861             asn1_int32_value_decode(asn1, len, &int_val);
2862
2863             proto_tree_add_text(temp_subtree, asn1->tvb,
2864                 saved_offset, len, "Error Code: %d",
2865                 int_val);
2866         }
2867         break;
2868     }
2869
2870     dissect_map_params(asn1, subtree, comp_len - (asn1->offset - saved_offset));
2871
2872     if (!def_len)
2873     {
2874         dissect_map_eoc(asn1, subtree);
2875     }
2876
2877     proto_item_set_len(item, asn1->offset - orig_offset);
2878
2879     return(MAP_OK);
2880 }
2881
2882
2883 static void
2884 dissect_map_reject(ASN1_SCK *asn1, proto_tree *tree)
2885 {
2886     guint       tag, len;
2887     guint       saved_offset;
2888     proto_item  *item;
2889     proto_tree  *subtree;
2890     gboolean    def_len;
2891
2892     tag = -1;
2893
2894     saved_offset = asn1->offset;
2895     asn1_id_decode1(asn1, &tag);
2896
2897     item =
2898         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
2899
2900     subtree = proto_item_add_subtree(item, ett_components);
2901
2902     proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset,
2903         "Reject Type Tag: 0x%02x", tag);
2904
2905     dissect_map_len(asn1, subtree, &def_len, &len);
2906
2907     dissect_map_invokeId(asn1, subtree);
2908     dissect_map_problem(asn1, subtree);
2909
2910     if (!def_len)
2911     {
2912         dissect_map_eoc(asn1, subtree);
2913     }
2914
2915     proto_item_set_len(item, asn1->offset - saved_offset);
2916 }
2917
2918
2919 static void
2920 dissect_map_message(packet_info *pinfo, proto_tree *map_tree, ASN1_SCK *asn1)
2921 {
2922     guint       saved_offset;
2923     gchar       *str = NULL;
2924     static int  i = 0;
2925
2926     saved_offset = asn1->offset;
2927     asn1_id_decode1(asn1, &g_comp_type_tag);
2928     asn1->offset = saved_offset;
2929
2930     str = match_strval(g_comp_type_tag, tcap_component_type_str);
2931
2932     if (NULL == str) return;
2933
2934     if (check_col(pinfo->cinfo, COL_INFO))
2935     {
2936         if (0 == i)
2937         {
2938             col_append_fstr(pinfo->cinfo, COL_INFO,  "%s ", str);
2939         }
2940         else
2941         {
2942             col_append_fstr(pinfo->cinfo, COL_INFO,  "& %s ", str);
2943         }
2944     }
2945
2946     switch(g_comp_type_tag)
2947     {
2948     case TCAP_COMP_INVOKE :
2949         dissect_map_invoke(asn1, pinfo, map_tree);
2950         break;
2951
2952     case TCAP_COMP_RRL :
2953         dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Last) Type Tag");
2954         break;
2955
2956     case TCAP_COMP_RE :
2957         dissect_map_re(asn1, map_tree);
2958         break;
2959
2960     case TCAP_COMP_REJECT :
2961         dissect_map_reject(asn1, map_tree);
2962         break;
2963
2964     case TCAP_COMP_RRN :
2965         dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Not Last) Type Tag");
2966         break;
2967
2968     default:
2969         proto_tree_add_text(map_tree, asn1->tvb, saved_offset, -1,
2970             "Message type not handled, ignoring");
2971         break;
2972     }
2973 }
2974
2975
2976 static void
2977 dissect_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2978 {
2979     proto_item  *ti;
2980     proto_tree  *map_tree;
2981     ASN1_SCK    asn1;
2982     int         offset = 0;
2983
2984     /*
2985      * Make entries in Protocol column on summary display
2986      */
2987     if (check_col(pinfo->cinfo, COL_PROTOCOL))
2988     {
2989         col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM MAP");
2990     }
2991
2992
2993     /* Dissect the packet (even if !tree so can update the INFO column) */
2994     g_pinfo = pinfo;
2995     g_tree = tree;
2996
2997     /* create display subtree for the protocol */
2998     ti = proto_tree_add_item(tree, proto_map, tvb, 0, -1, FALSE);
2999
3000     map_tree = proto_item_add_subtree(ti, ett_map);
3001
3002     asn1_open(&asn1, tvb, offset);
3003
3004     dissect_map_message(pinfo, map_tree, &asn1);
3005
3006     asn1_close(&asn1, &offset);
3007 }
3008
3009
3010 /* Register the protocol with Ethereal */
3011
3012 void
3013 proto_register_map(void)
3014 {
3015     guint               i;
3016     gint                last_offset;
3017
3018     /* Setup list of header fields  See Section 1.6.1 for details*/
3019     static hf_register_info hf[] =
3020     {
3021         { &hf_map_length,
3022             { "Length",         "map.len",
3023             FT_UINT8, BASE_HEX, NULL, 0,
3024             "", HFILL }
3025         },
3026         { &hf_map_opr_code,
3027             { "Operation Code", "map.oprcode",
3028             FT_INT32, BASE_DEC, VALS(gsm_map_opr_code_strings), 0,
3029             "", HFILL }
3030         },
3031         { &hf_map_int,
3032             { "Integer Data",   "map.data",
3033             FT_INT32, BASE_DEC, 0, 0,
3034             "", HFILL }
3035         },
3036         { &hf_map_imsi,
3037             { "IMSI",           "map.imsi",
3038             FT_STRING, BASE_DEC, 0, 0,
3039             "", HFILL }
3040         },
3041         { &hf_map_addrstring,
3042             { "AddressString",  "map.addrstring",
3043             FT_STRING, BASE_DEC, 0, 0,
3044             "", HFILL }
3045         },
3046         { &hf_map_rand,
3047             { "RAND",           "map.rand",
3048             FT_BYTES, BASE_HEX, 0, 0,
3049             "", HFILL }
3050         },
3051         { &hf_map_sres,
3052             { "SRES",           "map.sres",
3053             FT_BYTES, BASE_HEX, 0, 0,
3054             "", HFILL }
3055         },
3056         { &hf_map_kc,
3057             { "Kc",             "map.kc",
3058             FT_BYTES, BASE_HEX, 0, 0,
3059             "", HFILL }
3060         },
3061         { &hf_map_xres,
3062             { "XRES",           "map.xres",
3063             FT_BYTES, BASE_HEX, 0, 0,
3064             "", HFILL }
3065         },
3066         { &hf_map_ck,
3067             { "CK",             "map.ck",
3068             FT_BYTES, BASE_HEX, 0, 0,
3069             "", HFILL }
3070         },
3071         { &hf_map_ik,
3072             { "IK",             "map.ik",
3073             FT_BYTES, BASE_HEX, 0, 0,
3074             "", HFILL }
3075         },
3076         { &hf_map_autn,
3077             { "AUTN",           "map.autn",
3078             FT_BYTES, BASE_HEX, 0, 0,
3079             "", HFILL }
3080         }
3081     };
3082
3083     /* Setup protocol subtree array */
3084 #define NUM_INDIVIDUAL_PARAMS   9
3085     static gint *ett[NUM_INDIVIDUAL_PARAMS+(GSM_MAP_NUM_OP*2)+NUM_PARAM_1];
3086
3087     memset((void *) ett, 0, sizeof(ett));
3088
3089     ett[0] = &ett_map;
3090     ett[1] = &ett_opr_code;
3091     ett[2] = &ett_component;
3092     ett[3] = &ett_components;
3093     ett[4] = &ett_sequence;
3094     ett[5] = &ett_param;
3095     ett[6] = &ett_params;
3096     ett[7] = &ett_problem;
3097     ett[8] = &ett_err_code;
3098
3099     last_offset = NUM_INDIVIDUAL_PARAMS;
3100
3101     for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++)
3102     {
3103         ett_op[i] = -1;
3104         ett[last_offset] = &ett_op[i];
3105     }
3106
3107     for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++)
3108     {
3109         ett_op_rr[i] = -1;
3110         ett[last_offset] = &ett_op_rr[i];
3111     }
3112
3113     for (i=0; i < NUM_PARAM_1; i++, last_offset++)
3114     {
3115         ett_param_1[i] = -1;
3116         ett[last_offset] = &ett_param_1[i];
3117     }
3118
3119     /* Register the protocol name and description */
3120     proto_map =
3121         proto_register_protocol("GSM Mobile Application Part",
3122             "GSM MAP", "gsm_map");
3123
3124     /* Required function calls to register the header fields and subtrees used */
3125     proto_register_field_array(proto_map, hf, array_length(hf));
3126     proto_register_subtree_array(ett, array_length(ett));
3127
3128     sms_dissector_table =
3129         register_dissector_table("gsm_map.sms_tpdu", "GSM SMS TPDU",
3130         FT_UINT8, BASE_DEC);
3131
3132     gsm_map_tap = register_tap("gsm_map");
3133 }
3134
3135 void
3136 proto_reg_handoff_map(void)
3137 {
3138     dissector_handle_t  map_handle;
3139
3140     map_handle = create_dissector_handle(dissect_map, proto_map);
3141     dissector_add("tcap.itu_ssn", 6, map_handle);
3142     dissector_add("tcap.itu_ssn", 7, map_handle);
3143     dissector_add("tcap.itu_ssn", 8, map_handle);
3144     dissector_add("tcap.itu_ssn", 9, map_handle);
3145 }