connectionless cancel PDU's don't have a dg_server_accepting_cancels field
[obnox/wireshark/wip.git] / packet-gsm_ss.c
1 /* packet-gsm_ss.c
2  * Routines for GSM Supplementary Services dissection
3  *
4  * NOTE:
5  *      Routines are shared by GSM MAP/GSM A dissectors.
6  *      This file provides SHARED routines and is NOT a
7  *      standalone dissector.
8  *
9  * Copyright 2004, Michael Lum <mlum [AT] telostech.com>
10  * In association with Telos Technology Inc.
11  *
12  * Title                3GPP                    Other
13  *
14  *   Reference [1]
15  *   Mobile radio Layer 3 supplementary service specification;
16  *   Formats and coding
17  *   (3GPP TS 24.080 version 4.3.0 Release 4)
18  *
19  * Michael Lum <mlum [AT] telostech.com>,
20  * Created (2004).
21  *
22  * $Id: packet-gsm_ss.c,v 1.3 2004/04/21 05:53:56 guy Exp $
23  *
24  * Ethereal - Network traffic analyzer
25  * By Gerald Combs <gerald@ethereal.com>
26  * Copyright 1998 Gerald Combs
27  *
28  * Copied from packet-gsm_map.c (where "WHATEVER_FILE_YOU_USED"
29  * is a dissector file; if you just copied this from README.developer,
30  * don't bother with the "Copied from" - you don't even need to put
31  * in a "Copied from" if you copied an existing dissector, especially
32  * if the bulk of the code in the new dissector is your code)
33  *
34  * This program is free software; you can redistribute it and/or
35  * modify it under the terms of the GNU General Public License
36  * as published by the Free Software Foundation; either version 2
37  * of the License, or (at your option) any later version.
38  *
39  * This program is distributed in the hope that it will be useful,
40  * but WITHOUT ANY WARRANTY; without even the implied warranty of
41  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42  * GNU General Public License for more details.
43  *
44  * You should have received a copy of the GNU General Public License
45  * along with this program; if not, write to the Free Software
46  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47  */
48
49 #ifdef HAVE_CONFIG_H
50 # include "config.h"
51 #endif
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #include "epan/packet.h"
58 #include "tap.h"
59 #include "asn1.h"
60
61 #include "packet-tcap.h"
62 #include "packet-gsm_sms.h"
63 #include "packet-gsm_ss.h"
64
65
66 const value_string gsm_ss_err_code_strings[] = {
67     { 1,        "Unknown Subscriber" },
68     { 3,        "Unknown MSC" },
69     { 5,        "Unidentified Subscriber" },
70     { 6,        "Absent Subscriber SM" },
71     { 7,        "Unknown Equipment" },
72     { 8,        "Roaming Not Allowed" },
73     { 9,        "Illegal Subscriber" },
74     { 10,       "Bearer Service Not Provisioned" },
75     { 11,       "Teleservice Not Provisioned" },
76     { 12,       "Illegal Equipment" },
77     { 13,       "Call Barred" },
78     { 14,       "Forwarding Violation" },
79     { 15,       "CUG Reject" },
80     { 16,       "Illegal SS Operation" },
81     { 17,       "SS Error Status" },
82     { 18,       "SS Not Available" },
83     { 19,       "SS Subscription Violation" },
84     { 20,       "SS Incompatibility" },
85     { 21,       "Facility Not Supported" },
86     { 25,       "No Handover Number Available" },
87     { 26,       "Subsequent Handover Failure" },
88     { 27,       "Absent Subscriber" },
89     { 28,       "Incompatible Terminal" },
90     { 29,       "Short Term Denial" },
91     { 30,       "Long Term Denial" },
92     { 31,       "Subscriber Busy For MT SMS" },
93     { 32,       "SM Delivery Failure" },
94     { 33,       "Message Waiting List Full" },
95     { 34,       "System Failure" },
96     { 35,       "Data Missing" },
97     { 36,       "Unexpected Data Value" },
98     { 37,       "PW Registration Failure" },
99     { 38,       "Negative PW Check" },
100     { 39,       "No Roaming Number Available" },
101     { 40,       "Tracing Buffer Full" },
102     { 42,       "Target Cell Outside Group Call Area" },
103     { 43,       "Number Of PW Attempts Violation" },
104     { 44,       "Number Changed" },
105     { 45,       "Busy Subscriber" },
106     { 46,       "No Subscriber Reply" },
107     { 47,       "Forwarding Failed" },
108     { 48,       "OR Not Allowed" },
109     { 49,       "ATI Not Allowed" },
110     { 50,       "No Group Call Number Available" },
111     { 51,       "Resource Limitation" },
112     { 52,       "Unauthorized Requesting Network" },
113     { 53,       "Unauthorized LCS Client" },
114     { 54,       "Position Method Failure" },
115     { 58,       "Unknown Or Unreachable LCS Client" },
116     { 59,       "MM Event Not Supported" },
117     { 60,       "ATSI Not Allowed" },
118     { 61,       "ATM Not Allowed" },
119     { 62,       "Information Not Available" },
120     { 71,       "Unknown Alphabet" },
121     { 72,       "USSD Busy" },
122     { 120,      "Nbr Sb Exceeded" },
123     { 121,      "Rejected By User" },
124     { 122,      "Rejected By Network" },
125     { 123,      "Deflection To Served Subscriber" },
126     { 124,      "Special Service Code" },
127     { 125,      "Invalid Deflected To Number" },
128     { 126,      "Max Number Of MPTY Participants Exceeded" },
129     { 127,      "Resources Not Available" },
130     { 0, NULL }
131 };
132
133 const value_string gsm_ss_opr_code_strings[] = {
134     { 10,       "Register SS" },
135     { 11,       "Erase SS" },
136     { 12,       "Activate SS" },
137     { 13,       "Deactivate SS" },
138     { 14,       "Interrogate SS" },
139     { 16,       "Notify SS" },
140     { 17,       "Register Password" },
141     { 18,       "Get Password" },
142     { 19,       "Process Unstructured SS Data" },
143     { 38,       "Forward Check SS Indication" },
144     { 59,       "Process Unstructured SS Request" },
145     { 60,       "Unstructured SS Request" },
146     { 61,       "Unstructured SS Notify" },
147     { 77,       "Erase CC Entry" },
148     { 117,      "Call Deflection" },
149     { 118,      "User User Service" },
150     { 119,      "Access Register CC Entry" },
151     { 120,      "Forward CUG Info" },
152     { 121,      "Split MPTY" },
153     { 122,      "Retrieve MPTY" },
154     { 123,      "Hold MPTY" },
155     { 124,      "Build MPTY" },
156     { 125,      "Forward Charge Advice" },
157     { 126,      "Explicit CT" },
158     { 116,      "LCS Location Notification" },
159     { 115,      "LCS MOLR" },
160
161     { 0, NULL }
162 };
163
164
165 /* never initialize in field array */
166 static int hf_null = -1;
167 #define HF_NULL         &hf_null
168
169 gint gsm_ss_ett[NUM_GSM_SS_ETT];        /* initialization is left to users */
170
171 static gboolean gsm_ss_seven_bit = FALSE;
172 static gboolean gsm_ss_eight_bit = FALSE;
173 static gboolean gsm_ss_ucs2 = FALSE;
174 static gboolean gsm_ss_compressed = FALSE;
175
176
177 typedef struct dgt_set_t
178 {
179     unsigned char out[15];
180 }
181 dgt_set_t;
182
183 #ifdef MLUM
184 static dgt_set_t Dgt_tbcd = {
185     {
186   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
187      '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
188     }
189 };
190 #endif
191
192 static dgt_set_t Dgt_msid = {
193     {
194   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
195      '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
196     }
197 };
198
199
200 /* FORWARD DECLARATIONS */
201
202 static void op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len);
203
204
205 /* GENERIC HELPER FUNCTIONS */
206
207 /*
208  * Unpack BCD input pattern into output ASCII pattern
209  *
210  * Input Pattern is supplied using the same format as the digits
211  *
212  * Returns: length of unpacked pattern
213  */
214 static int
215 my_dgt_tbcd_unpack(
216     char        *out,           /* ASCII pattern out */
217     guchar      *in,            /* packed pattern in */
218     int         num_octs,       /* Number of octets to unpack */
219     dgt_set_t   *dgt            /* Digit definitions */
220     )
221 {
222     int cnt = 0;
223     unsigned char i;
224
225     while (num_octs)
226     {
227         /*
228          * unpack first value in byte
229          */
230         i = *in++;
231         *out++ = dgt->out[i & 0x0f];
232         cnt++;
233
234         /*
235          * unpack second value in byte
236          */
237         i >>= 4;
238
239         if (i == 0x0f)  /* odd number bytes - hit filler */
240             break;
241
242         *out++ = dgt->out[i];
243         cnt++;
244         num_octs--;
245     }
246
247     *out = '\0';
248
249     return(cnt);
250 }
251
252 static gchar *
253 my_match_strval(guint32 val, const value_string *vs, gint *idx)
254 {
255     gint        i = 0;
256
257     while (vs[i].strptr) {
258         if (vs[i].value == val)
259         {
260             *idx = i;
261             return(vs[i].strptr);
262         }
263
264         i++;
265     }
266
267     *idx = -1;
268     return(NULL);
269 }
270
271 /* PARAMETER dissection */
272
273 void
274 param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
275 {
276     guint       saved_offset;
277     gint32      value;
278     guchar      *poctets;
279     gchar       *str = NULL;
280     char        bigbuf[1024];
281
282     saved_offset = asn1->offset;
283     asn1_int32_value_decode(asn1, 1, &value);
284
285     other_decode_bitfield_value(bigbuf, value, 0x80, 8);
286     proto_tree_add_text(tree, asn1->tvb,
287         saved_offset, 1,
288         "%s :  %sxtension",
289         bigbuf, (value & 0x80) ? "No E" : "E");
290
291     switch ((value & 0x70) >> 4)
292     {
293     case 0x00: str = "unknown"; break;
294     case 0x01: str = "International Number"; break;
295     case 0x02: str = "National Significant Number"; break;
296     case 0x03: str = "Network Specific Number"; break;
297     case 0x04: str = "Subscriber Number"; break;
298     case 0x05: str = "Reserved"; break;
299     case 0x06: str = "Abbreviated Number"; break;
300     case 0x07: str = "Reserved for extension"; break;
301     }
302
303     other_decode_bitfield_value(bigbuf, value, 0x70, 8);
304     proto_tree_add_text(tree, asn1->tvb,
305         saved_offset, asn1->offset - saved_offset,
306         "%s :  %s",
307         bigbuf, str);
308
309     switch (value & 0x0f)
310     {
311     case 0x00: str = "unknown"; break;
312     case 0x01: str = "ISDN/Telephony Numbering (Rec ITU-T E.164)"; break;
313     case 0x02: str = "spare"; break;
314     case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
315     case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
316     case 0x05: str = "spare"; break;
317     case 0x06: str = "Land Mobile Numbering (ITU-T Rec. E.212)"; break;
318     case 0x07: str = "spare"; break;
319     case 0x08: str = "National Numbering"; break;
320     case 0x09: str = "Private Numbering"; break;
321     case 0x0f: str = "Reserved for extension"; break;
322     default:
323         str = "Reserved";
324         break;
325     }
326
327     other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
328     proto_tree_add_text(tree, asn1->tvb,
329         saved_offset, asn1->offset - saved_offset,
330         "%s :  %s",
331         bigbuf, str);
332
333     saved_offset = asn1->offset;
334     asn1_string_value_decode(asn1, len - 1, &poctets);
335
336     my_dgt_tbcd_unpack(bigbuf, poctets, len - 1, &Dgt_msid);
337     g_free(poctets);
338
339     if (hf_field == -1)
340     {
341         proto_tree_add_text(tree, asn1->tvb,
342             saved_offset, len - 1, "BCD Digits %s", bigbuf);
343     }
344     else
345     {
346         proto_tree_add_string_format(tree, hf_field, asn1->tvb,
347             saved_offset, len - 1, bigbuf, "BCD Digits %s", bigbuf);
348     }
349 }
350
351 static void
352 param_ssCode(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
353 {
354     guint       saved_offset;
355     gint32      value;
356     gchar       *str = NULL;
357
358     hf_field = hf_field;
359
360     saved_offset = asn1->offset;
361     asn1_int32_value_decode(asn1, len, &value);
362
363     switch (value)
364     {
365     case 0x00:
366         str = "allSS - all SS";
367         break;
368
369     case 0x10:
370         str = "allLineIdentificationSS - all line identification SS";
371         break;
372
373     case 0x11:
374         str = "clip - calling line identification presentation";
375         break;
376
377     case 0x12:
378         str = "clir - calling line identification restriction";
379         break;
380
381     case 0x13:
382         str = "colp - connected line identification presentation";
383         break;
384
385     case 0x14:
386         str = "colr - connected line identification restriction";
387         break;
388
389     case 0x15:
390         str = "mci - malicious call identification";
391         break;
392
393     case 0x18:
394         str = "allNameIdentificationSS - all name indentification SS";
395         break;
396
397     case 0x19:
398         str = "cnap - calling name presentation";
399         break;
400
401     case 0x20:
402         str = "allForwardingSS - all forwarding SS";
403         break;
404
405     case 0x21:
406         str = "cfu - call forwarding unconditional";
407         break;
408
409     case 0x28:
410         str = "allCondForwardingSS - all conditional forwarding SS";
411         break;
412
413     case 0x29:
414         str = "cfb - call forwarding busy";
415         break;
416
417     case 0x2a:
418         str = "cfnry - call forwarding on no reply";
419         break;
420
421     case 0x2b:
422         str = "cfnrc - call forwarding on mobile subscriber not reachable";
423         break;
424
425     case 0x24:
426         str = "cd - call deflection";
427         break;
428
429     case 0x30:
430         str = "allCallOfferingSS - all call offering SS includes also all forwarding SS";
431         break;
432
433     case 0x31:
434         str = "ect - explicit call transfer";
435         break;
436
437     case 0x32:
438         str = "mah - mobile access hunting";
439         break;
440
441     case 0x40:
442         str = "allCallCompletionSS - all Call completion SS";
443         break;
444
445     case 0x41:
446         str = "cw - call waiting";
447         break;
448
449     case 0x42:
450         str = "hold - call hold";
451         break;
452
453     case 0x43:
454         str = "ccbs-A - completion of call to busy subscribers, originating side";
455         break;
456
457     case 0x44:
458         str = "ccbs-B - completion of call to busy subscribers, destination side";
459         break;
460
461     case 0x45:
462         str = "mc - multicall";
463         break;
464
465     case 0x50:
466         str = "allMultiPartySS - all multiparty SS";
467         break;
468
469     case 0x51:
470         str = "multiPTY - multiparty";
471         break;
472
473     case 0x60:
474         str = "allCommunityOfInterestSS - all community of interest SS";
475         break;
476
477     case 0x61:
478         str = "cug - closed user group";
479         break;
480
481     case 0x70:
482         str = "allChargingSS - all charging SS";
483         break;
484
485     case 0x71:
486         str = "aoci - advice of charge information";
487         break;
488
489     case 0x72:
490         str = "aocc - advice of charge charging";
491         break;
492
493     case 0x80:
494         str = "allAdditionalInfoTransferSS - all additional information transfer SS";
495         break;
496
497     case 0x81:
498         str = "uus1 - UUS1 user-to-user signalling";
499         break;
500
501     case 0x82:
502         str = "uus2 - UUS2 user-to-user signalling";
503         break;
504
505     case 0x83:
506         str = "uus3 - UUS3 user-to-user signalling";
507         break;
508
509     case 0x90:
510         str = "allBarringSS - all barring SS";
511         break;
512
513     case 0x91:
514         str = "barringOfOutgoingCalls";
515         break;
516
517     case 0x92:
518         str = "baoc - barring of all outgoing calls";
519         break;
520
521     case 0x93:
522         str = "boic - barring of outgoing international calls";
523         break;
524
525     case 0x94:
526         str = "boicExHC - barring of outgoing international calls except those directed to the home PLMN";
527         break;
528
529     case 0x99:
530         str = "barringOfIncomingCalls";
531         break;
532
533     case 0x9a:
534         str = "baic - barring of all incoming calls";
535         break;
536
537     case 0x9b:
538         str = "bicRoam - barring of incoming calls when roaming outside home PLMN Country";
539         break;
540
541     case 0xf0:
542         str = "allPLMN-specificSS";
543         break;
544
545     case 0xa0:
546         str = "allCallPrioritySS - all call priority SS";
547         break;
548
549     case 0xa1:
550         str = "emlpp - enhanced Multilevel Precedence Pre-emption (EMLPP) service";
551         break;
552
553     case 0xb0:
554         str = "allLCSPrivacyException - all LCS Privacy Exception Classes";
555         break;
556
557     case 0xb1:
558         str = "universal - allow location by any LCS client";
559         break;
560
561     case 0xb2:
562         str = "callrelated - allow location by any value added LCS client to which a call is established from the target MS";
563         break;
564
565     case 0xb3:
566         str = "callunrelated - allow location by designated external value added LCS clients";
567         break;
568
569     case 0xb4:
570         str = "plmnoperator - allow location by designated PLMN operator LCS clients";
571         break;
572
573     case 0xc0:
574         str = "allMOLR-SS - all Mobile Originating Location Request Classes";
575         break;
576
577     case 0xc1:
578         str = "basicSelfLocation - allow an MS to request its own location";
579         break;
580
581     case 0xc2:
582         str = "autonomousSelfLocation - allow an MS to perform self location without interaction with the PLMN for a predetermined period of time";
583         break;
584
585     case 0xc3:
586         str = "transferToThirdParty - allow an MS to request transfer of its location to another LCS client";
587         break;
588
589     default:
590         /*
591          * XXX
592          */
593         str = "reserved for future use";
594         break;
595     }
596
597     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
598 }
599
600 /*
601  * See GSM 03.11
602  */
603 static void
604 param_ssStatus(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
605 {
606     guint       saved_offset;
607     gint32      value;
608     char        bigbuf[1024];
609
610     hf_field = hf_field;
611
612     saved_offset = asn1->offset;
613     asn1_int32_value_decode(asn1, len, &value);
614
615     other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
616     proto_tree_add_text(tree, asn1->tvb,
617         saved_offset, 1,
618         "%s :  Unused",
619         bigbuf);
620
621     /*
622      * Q bit is valid only if A bit is "Active"
623      */
624     other_decode_bitfield_value(bigbuf, value, 0x08, 8);
625     proto_tree_add_text(tree, asn1->tvb,
626         saved_offset, 1,
627         "%s :  Q bit: %s",
628         bigbuf,
629         (value & 0x01) ?
630             ((value & 0x08) ? "Quiescent" : "Operative") : "N/A");
631
632     other_decode_bitfield_value(bigbuf, value, 0x04, 8);
633     proto_tree_add_text(tree, asn1->tvb,
634         saved_offset, 1,
635         "%s :  P bit: %sProvisioned",
636         bigbuf,
637         (value & 0x04) ? "" : "Not ");
638
639     other_decode_bitfield_value(bigbuf, value, 0x02, 8);
640     proto_tree_add_text(tree, asn1->tvb,
641         saved_offset, 1,
642         "%s :  R bit: %sRegistered",
643         bigbuf,
644         (value & 0x02) ? "" : "Not ");
645
646     other_decode_bitfield_value(bigbuf, value, 0x01, 8);
647     proto_tree_add_text(tree, asn1->tvb,
648         saved_offset, 1,
649         "%s :  A bit: %sActive",
650         bigbuf,
651         (value & 0x01) ? "" : "Not ");
652 }
653
654 static void
655 param_bearerservice(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
656 {
657     guint       saved_offset;
658     gint32      value;
659     gchar       *str = NULL;
660
661     hf_field = hf_field;
662
663     saved_offset = asn1->offset;
664     asn1_int32_value_decode(asn1, len, &value);
665
666     switch (value)
667     {
668     case 0x00: str = "allBearerServices"; break;
669     case 0x10: str = "allDataCDA-Services"; break;
670     case 0x11: str = "dataCDA-300bps"; break;
671     case 0x12: str = "dataCDA-1200bps"; break;
672     case 0x13: str = "dataCDA-1200-75bps"; break;
673     case 0x14: str = "dataCDA-2400bps"; break;
674     case 0x15: str = "dataCDA-4800bps"; break;
675     case 0x16: str = "dataCDA-9600bps"; break;
676     case 0x17: str = "general-dataCDA"; break;
677     case 0x18: str = "allDataCDS-Services"; break;
678     case 0x1a: str = "dataCDS-1200bps"; break;
679     case 0x1c: str = "dataCDS-2400bps"; break;
680     case 0x1d: str = "dataCDS-4800bps"; break;
681     case 0x1e: str = "dataCDS-9600bps"; break;
682     case 0x1f: str = "general-dataCDS"; break;
683
684     case 0x20: str = "allPadAccessCA-Services"; break;
685     case 0x21: str = "padAccessCA-300bps"; break;
686     case 0x22: str = "padAccessCA-1200bps"; break;
687     case 0x23: str = "padAccessCA-1200-75bps"; break;
688     case 0x24: str = "padAccessCA-2400bps"; break;
689     case 0x25: str = "padAccessCA-4800bps"; break;
690     case 0x26: str = "padAccessCA-9600bps"; break;
691     case 0x27: str = "general-padAccessCA"; break;
692     case 0x28: str = "allDataPDS-Services"; break;
693     case 0x2c: str = "dataPDS-2400bps"; break;
694     case 0x2d: str = "dataPDS-4800bps"; break;
695     case 0x2e: str = "dataPDS-9600bps"; break;
696     case 0x2f: str = "general-dataPDS"; break;
697
698     case 0x30: str = "allAlternateSpeech-DataCDA"; break;
699     case 0x38: str = "allAlternateSpeech-DataCDS"; break;
700     case 0x40: str = "allSpeechFollowedByDataCDA"; break;
701     case 0x48: str = "allSpeechFollowedByDataCDS"; break;
702
703     case 0x50: str = "allDataCircuitAsynchronous"; break;
704     case 0x60: str = "allAsynchronousServices"; break;
705     case 0x58: str = "allDataCircuitSynchronous"; break;
706     case 0x68: str = "allSynchronousServices"; break;
707
708     case 0xd0: str = "allPLMN-specificBS"; break;
709     case 0xd1: str = "plmn-specificBS-1"; break;
710     case 0xd2: str = "plmn-specificBS-2"; break;
711     case 0xd3: str = "plmn-specificBS-3"; break;
712     case 0xd4: str = "plmn-specificBS-4"; break;
713     case 0xd5: str = "plmn-specificBS-5"; break;
714     case 0xd6: str = "plmn-specificBS-6"; break;
715     case 0xd7: str = "plmn-specificBS-7"; break;
716     case 0xd8: str = "plmn-specificBS-8"; break;
717     case 0xd9: str = "plmn-specificBS-9"; break;
718     case 0xda: str = "plmn-specificBS-A"; break;
719     case 0xdb: str = "plmn-specificBS-B"; break;
720     case 0xdc: str = "plmn-specificBS-C"; break;
721     case 0xdd: str = "plmn-specificBS-D"; break;
722     case 0xde: str = "plmn-specificBS-E"; break;
723     case 0xdf: str = "plmn-specificBS-F"; break;
724
725     default:
726         str = "Undefined";
727         break;
728     }
729
730     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
731 }
732
733 static void
734 param_teleservice(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
735 {
736     guint       saved_offset;
737     gint32      value;
738     gchar       *str = NULL;
739
740     hf_field = hf_field;
741
742     saved_offset = asn1->offset;
743     asn1_int32_value_decode(asn1, len, &value);
744
745     switch (value)
746     {
747     case 0x00: str = "allTeleservices"; break;
748     case 0x10: str = "allSpeechTransmissionServices"; break;
749     case 0x11: str = "telephony"; break;
750     case 0x12: str = "emergencyCalls"; break;
751     case 0x20: str = "allShortMessageServices"; break;
752     case 0x21: str = "shortMessageMT-PP"; break;
753     case 0x22: str = "shortMessageMO-PP"; break;
754     case 0x60: str = "allFacsimileTransmissionServices"; break;
755     case 0x61: str = "facsimileGroup3AndAlterSpeech"; break;
756     case 0x62: str = "automaticFacsimileGroup3"; break;
757     case 0x63: str = "facsimileGroup4"; break;
758
759     case 0x70: str = "allDataTeleservices"; break;
760     case 0x80: str = "allTeleservices-ExeptSMS"; break;
761
762     case 0x90: str = "allVoiceGroupCallServices"; break;
763     case 0x91: str = "voiceGroupCall"; break;
764     case 0x92: str = "voiceBroadcastCall"; break;
765
766     case 0xd0: str = "allPLMN-specificTS"; break;
767     case 0xd1: str = "plmn-specificTS-1"; break;
768     case 0xd2: str = "plmn-specificTS-2"; break;
769     case 0xd3: str = "plmn-specificTS-3"; break;
770     case 0xd4: str = "plmn-specificTS-4"; break;
771     case 0xd5: str = "plmn-specificTS-5"; break;
772     case 0xd6: str = "plmn-specificTS-6"; break;
773     case 0xd7: str = "plmn-specificTS-7"; break;
774     case 0xd8: str = "plmn-specificTS-8"; break;
775     case 0xd9: str = "plmn-specificTS-9"; break;
776     case 0xda: str = "plmn-specificTS-A"; break;
777     case 0xdb: str = "plmn-specificTS-B"; break;
778     case 0xdc: str = "plmn-specificTS-C"; break;
779     case 0xdd: str = "plmn-specificTS-D"; break;
780     case 0xde: str = "plmn-specificTS-E"; break;
781     case 0xdf: str = "plmn-specificTS-F"; break;
782
783     default:
784         str = "Undefined";
785         break;
786     }
787
788     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
789 }
790
791 /*
792  * GSM 03.38
793  * Same as Cell Broadcast
794  */
795 static void
796 param_ussdDCS(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
797 {
798     guint               saved_offset;
799     gint32              value;
800     gchar               *str = NULL;
801     char                bigbuf[1024];
802     proto_tree          *subtree;
803     proto_item          *item;
804
805     hf_field = hf_field;
806
807     gsm_ss_seven_bit = FALSE;
808     gsm_ss_eight_bit = FALSE;
809     gsm_ss_ucs2 = FALSE;
810     gsm_ss_compressed = FALSE;
811
812     saved_offset = asn1->offset;
813     asn1_int32_value_decode(asn1, len, &value);
814
815     item =
816         proto_tree_add_text(tree, asn1->tvb,
817             saved_offset, len,
818             "Data Coding Scheme (%d)",
819             value);
820
821     subtree = proto_item_add_subtree(item, gsm_ss_ett[GSM_SS_ETT_PARAM]);
822
823     if ((value & 0xf0) == 0x00)
824     {
825         /* 0000....  Language using the default alphabet */
826
827         switch (value & 0x0f)
828         {
829         case 0x00: str = "German"; break;
830         case 0x01: str = "English"; break;
831         case 0x02: str = "Italian"; break;
832         case 0x03: str = "French"; break;
833         case 0x04: str = "Spanish"; break;
834         case 0x05: str = "Dutch"; break;
835         case 0x06: str = "Swedish"; break;
836         case 0x07: str = "Danish"; break;
837         case 0x08: str = "Portuguese"; break;
838         case 0x09: str = "Finnish"; break;
839         case 0x0a: str = "Norwegian"; break;
840         case 0x0b: str = "Greek"; break;
841         case 0x0c: str = "Turkish"; break;
842         case 0x0d: str = "Hungarian"; break;
843         case 0x0e: str = "Polish"; break;
844         case 0x0f: str = "Language unspecified"; break;
845         }
846
847         other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
848         proto_tree_add_text(subtree, asn1->tvb,
849             saved_offset, 1,
850             "%s :  %s language using default alphabet",
851             bigbuf,
852             str);
853
854         gsm_ss_seven_bit = TRUE;
855     }
856     else if ((value & 0xf0) == 0x10)
857     {
858         switch (value & 0x0f)
859         {
860         case 0x00: str = "Default alphabet; message preceded by language indication"; break;
861         case 0x01: str = "UCS2; message preceded by language indication"; break;
862         default:
863             str = "Reserved for European languages";
864             break;
865         }
866
867         other_decode_bitfield_value(bigbuf, value, 0xff, 8);
868         proto_tree_add_text(subtree, asn1->tvb,
869             saved_offset, 1,
870             "%s :  %s",
871             bigbuf,
872             str);
873     }
874     else if ((value & 0xf0) == 0x20)
875     {
876         switch (value & 0x0f)
877         {
878         case 0x00: str = "Czech"; break;
879         default:
880             str = "Reserved for European languages using the default alphabet";
881             break;
882         }
883
884         other_decode_bitfield_value(bigbuf, value, 0xff, 8);
885         proto_tree_add_text(subtree, asn1->tvb,
886             saved_offset, 1,
887             "%s :  %s",
888             bigbuf,
889             str);
890     }
891     else if ((value & 0xf0) == 0x30)
892     {
893         other_decode_bitfield_value(bigbuf, value, 0xff, 8);
894         proto_tree_add_text(subtree, asn1->tvb,
895             saved_offset, 1,
896             "%s :  Reserved for European Languages using the default alphabet",
897             bigbuf);
898     }
899     else if ((value & 0xc0) == 0x40)
900     {
901         other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
902         proto_tree_add_text(subtree, asn1->tvb,
903             saved_offset, 1,
904             "%s :  General Data Coding indication",
905             bigbuf);
906
907         gsm_ss_compressed = (value & 0x20) >> 5;
908
909         other_decode_bitfield_value(bigbuf, value, 0x20, 8);
910         proto_tree_add_text(subtree, asn1->tvb,
911             saved_offset, 1,
912             "%s :  Text is %scompressed",
913             bigbuf,
914             gsm_ss_compressed ? "" : "not ");
915
916         other_decode_bitfield_value(bigbuf, value, 0x10, 8);
917         proto_tree_add_text(subtree, asn1->tvb,
918             saved_offset, 1,
919             "%s :  %s",
920             bigbuf,
921             (value & 0x10) ? "Message class is defined below" :
922                 "Reserved, no message class");
923
924         switch ((value & 0x0c) >> 2)
925         {
926         case 0x00: str = "GSM 7 bit default alphabet";
927             gsm_ss_seven_bit = TRUE;
928             break;
929         case 0x01: str = "8 bit data"; break;
930         case 0x02: str = "UCS2 (16 bit)";
931             gsm_ss_ucs2 = TRUE;
932             break;
933         case 0x03: str = "Reserved"; break;
934         }
935
936         other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
937         proto_tree_add_text(subtree, asn1->tvb,
938             saved_offset, 1,
939             "%s :  Character set: %s",
940             bigbuf,
941             str);
942
943         switch (value & 0x03)
944         {
945         case 0x00: str = "Class 0"; break;
946         case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
947         case 0x02: str = "Class 2 (U)SIM specific message"; break;
948         case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
949         }
950
951         other_decode_bitfield_value(bigbuf, value, 0x03, 8);
952         proto_tree_add_text(subtree, asn1->tvb,
953             saved_offset, 1,
954             "%s :  Message Class: %s%s",
955             bigbuf,
956             str,
957             (value & 0x10) ? "" : " (reserved)");
958     }
959     else if ((value & 0xf0) == 0xf0)
960     {
961         other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
962         proto_tree_add_text(subtree, asn1->tvb,
963             saved_offset, 1,
964             "%s :  Data Coding / Message Handling",
965             bigbuf);
966
967         other_decode_bitfield_value(bigbuf, value, 0x08, 8);
968         proto_tree_add_text(subtree, asn1->tvb,
969             saved_offset, 1,
970             "%s :  Reserved",
971             bigbuf);
972
973         gsm_ss_seven_bit = !(gsm_ss_eight_bit = (value & 0x04) ? TRUE : FALSE);
974
975         other_decode_bitfield_value(bigbuf, value, 0x04, 8);
976         proto_tree_add_text(subtree, asn1->tvb,
977             saved_offset, 1,
978             "%s :  Message coding: %s",
979             bigbuf,
980             gsm_ss_eight_bit ? "8 bit data" : "Default alphabet");
981
982         switch (value & 0x03)
983         {
984         case 0x00: str = "No message class"; break;
985         case 0x01: str = "Class 1 user defined"; break;
986         case 0x02: str = "Class 2 user defined"; break;
987         case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
988         }
989
990         other_decode_bitfield_value(bigbuf, value, 0x03, 8);
991         proto_tree_add_text(subtree, asn1->tvb,
992             saved_offset, 1,
993             "%s :  Message Class: %s",
994             bigbuf,
995             str);
996     }
997     else
998     {
999         other_decode_bitfield_value(bigbuf, value, 0xff, 8);
1000         proto_tree_add_text(subtree, asn1->tvb,
1001             saved_offset, 1,
1002             "%s :  Reserved coding groups",
1003             bigbuf);
1004     }
1005 }
1006
1007 static void
1008 param_ussdString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
1009 {
1010     guint               saved_offset;
1011     char                bigbuf[1024];
1012     guint8              fill_bits;
1013     guint32             out_len;
1014     char                *ustr;
1015
1016     hf_field = hf_field;
1017
1018     saved_offset = asn1->offset;
1019
1020     if (gsm_ss_compressed)
1021     {
1022         proto_tree_add_text(tree, asn1->tvb,
1023             saved_offset, len,
1024             "Compressed data");
1025     }
1026     else
1027     {
1028         if (gsm_ss_seven_bit)
1029         {
1030             fill_bits = 0;
1031
1032             out_len =
1033                 gsm_sms_char_7bit_unpack(fill_bits, len, sizeof(bigbuf),
1034                     tvb_get_ptr(asn1->tvb, saved_offset, len), bigbuf);
1035             bigbuf[out_len] = '\0';
1036             gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len);
1037
1038             proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", bigbuf);
1039         }
1040         else if (gsm_ss_eight_bit)
1041         {
1042             proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
1043                 tvb_format_text(asn1->tvb, saved_offset, len));
1044         }
1045         else if (gsm_ss_ucs2)
1046         {
1047             ustr = tvb_fake_unicode(asn1->tvb, saved_offset, len, FALSE);
1048             proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", ustr);
1049             g_free(ustr);
1050         }
1051         else
1052         {
1053             /* don't know what form it is */
1054
1055             proto_tree_add_text(tree, asn1->tvb,
1056                 saved_offset, len,
1057                 "Parameter Data");
1058         }
1059     }
1060
1061     asn1->offset += len;
1062 }
1063
1064 static void
1065 param_ia5String(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
1066 {
1067     guint               saved_offset;
1068
1069     hf_field = hf_field;
1070
1071     saved_offset = asn1->offset;
1072
1073     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
1074         tvb_format_text(asn1->tvb, saved_offset, len));
1075
1076     asn1->offset += len;
1077 }
1078
1079 static void
1080 param_password(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
1081 {
1082     guint               saved_offset;
1083
1084     hf_field = hf_field;
1085
1086     saved_offset = asn1->offset;
1087
1088     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
1089         tvb_format_text(asn1->tvb, saved_offset, len));
1090
1091     asn1->offset += len;
1092 }
1093
1094 static void
1095 param_guidanceInfo(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
1096 {
1097     guint               saved_offset;
1098     gint32              value;
1099     gchar               *str = NULL;
1100
1101     hf_field = hf_field;
1102
1103     saved_offset = asn1->offset;
1104     asn1_int32_value_decode(asn1, 1, &value);
1105
1106     switch (value)
1107     {
1108     case 0: str = "enterPW"; break;
1109     case 1: str = "enterNewPW"; break;
1110     case 2: str = "enterNewPW-Again"; break;
1111     default:
1112         str = "Unknown";
1113         break;
1114     }
1115
1116     proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
1117 }
1118
1119 static void
1120 param_forwardingOpt(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
1121 {
1122     guint               saved_offset;
1123     gint32              value;
1124     char                bigbuf[1024];
1125     gchar               *str = NULL;
1126
1127     hf_field = hf_field;
1128
1129     saved_offset = asn1->offset;
1130     asn1_int32_value_decode(asn1, 1, &value);
1131
1132     other_decode_bitfield_value(bigbuf, value, 0x80, 8);
1133     proto_tree_add_text(tree, asn1->tvb,
1134         saved_offset, 1,
1135         "%s :  %snotification to forwarding party",
1136         bigbuf,
1137         (value & 0x80) ? "" : "no ");
1138
1139     other_decode_bitfield_value(bigbuf, value, 0x40, 8);
1140     proto_tree_add_text(tree, asn1->tvb,
1141         saved_offset, 1,
1142         "%s :  %sredirecting presentation",
1143         bigbuf,
1144         (value & 0x40) ? "" : "no ");
1145
1146     other_decode_bitfield_value(bigbuf, value, 0x20, 8);
1147     proto_tree_add_text(tree, asn1->tvb,
1148         saved_offset, 1,
1149         "%s :  %snotification to calling party",
1150         bigbuf,
1151         (value & 0x20) ? "" : "no ");
1152
1153     other_decode_bitfield_value(bigbuf, value, 0x10, 8);
1154     proto_tree_add_text(tree, asn1->tvb,
1155         saved_offset, 1,
1156         "%s :  unused",
1157         bigbuf);
1158
1159     switch ((value & 0x0c) >> 2)
1160     {
1161     case 0x00: str = "MS not reachable"; break;
1162     case 0x01: str = "MS busy"; break;
1163     case 0x02: str = "No reply"; break;
1164     case 0x03: str = "Unconditional (in SRI result) or Deflection"; break;
1165     }
1166
1167     other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
1168     proto_tree_add_text(tree, asn1->tvb,
1169         saved_offset, 1,
1170         "%s :  forwarding reason, %s (%u)",
1171         bigbuf,
1172         str,
1173         (value & 0x0c) >> 2);
1174
1175     other_decode_bitfield_value(bigbuf, value, 0x03, 8);
1176     proto_tree_add_text(tree, asn1->tvb,
1177         saved_offset, 1,
1178         "%s :  unused",
1179         bigbuf);
1180
1181     asn1->offset += len;
1182 }
1183
1184
1185 typedef enum
1186 {
1187     GSM_SS_P_SS_CODE,                   /* SS-Code */
1188     GSM_SS_P_SS_STATUS,                 /* SS-Status */
1189     GSM_SS_P_BEARERSERVICE,             /* Bearer Service */
1190     GSM_SS_P_TELESERVICE,               /* Tele Service */
1191     GSM_SS_P_FORWARD_TO_NUM,            /* Forward to Number */
1192     GSM_SS_P_LONG_FORWARD_TO_NUM,       /* Long Forward to Number */
1193     GSM_SS_P_USSD_DCS,                  /* USSD Data Coding Scheme */
1194     GSM_SS_P_USSD_STRING,               /* USSD String */
1195     GSM_SS_P_IA5_STRING,                /* IA5 String */
1196     GSM_SS_P_PASSWORD,                  /* Password */
1197     GSM_SS_P_GUIDANCE_INFO,             /* Guidance Info */
1198     GSM_SS_P_FORWARDING_OPT,            /* Forwarding Options */
1199     GSM_SS_P_NONE                       /* NONE */
1200 }
1201 param_idx_t;
1202
1203 #define NUM_PARAM_1 (GSM_SS_P_NONE+1)
1204 static gint ett_param_1[NUM_PARAM_1];
1205 static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = {
1206     param_ssCode,                       /* SS-Code */
1207     param_ssStatus,                     /* SS-Status */
1208     param_bearerservice,                /* Bearer Service */
1209     param_teleservice,                  /* Tele Service */
1210     param_AddressString,                /* Forward to Number */
1211     param_AddressString,                /* Long Forward to Number */
1212     param_ussdDCS,                      /* USSD Data Coding Scheme */
1213     param_ussdString,                   /* USSD String */
1214     param_ia5String,                    /* IA5 String */
1215     param_password,                     /* Password */
1216     param_guidanceInfo,                 /* Guidance Info */
1217     param_forwardingOpt,                /* Forwarding Options */
1218     NULL                                /* NONE */
1219 };
1220
1221 static int *param_1_hf[] = {
1222     HF_NULL,                            /* SS-Code */
1223     HF_NULL,                            /* SS-Status */
1224     HF_NULL,                            /* Bearer Service */
1225     HF_NULL,                            /* Tele Service */
1226     HF_NULL,                            /* Forward to Number */
1227     HF_NULL,                            /* Long Forward to Number */
1228     HF_NULL,                            /* USSD Data Coding Scheme */
1229     HF_NULL,                            /* USSD String */
1230     HF_NULL,                            /* IA5 String */
1231     HF_NULL,                            /* Password */
1232     HF_NULL,                            /* Guidance Info */
1233     HF_NULL,                            /* Forwarding Options */
1234     NULL                                /* NONE */
1235 };
1236
1237 #define GSM_SS_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
1238     { \
1239         guint           _len_offset; \
1240         proto_item      *_item; \
1241  \
1242         _len_offset = asn1->offset; \
1243         asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
1244  \
1245         _item = \
1246             proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
1247  \
1248         _Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
1249  \
1250         proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
1251             _Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
1252  \
1253         if (*_Gdef_len_p) \
1254         { \
1255             proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
1256                 _len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
1257         } \
1258         else \
1259         { \
1260             proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
1261                 _len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
1262  \
1263             *_Glen_p = tcap_find_eoc(asn1); \
1264         } \
1265  \
1266         proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
1267             (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
1268     }
1269
1270 #define GSM_SS_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \
1271     { \
1272         gint            _ett_param_idx; \
1273         guint           _len; \
1274         void            (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \
1275         int             *_param_hf = NULL; \
1276         proto_tree      *_subtree; \
1277         gboolean        _def_len; \
1278  \
1279         if (Ga1 == GSM_SS_P_NONE) \
1280         { \
1281             _ett_param_idx = gsm_ss_ett[GSM_SS_ETT_PARAM]; \
1282             _param_fcn = NULL; \
1283             _param_hf = HF_NULL; \
1284         } \
1285         else \
1286         { \
1287             _ett_param_idx = ett_param_1[Ga1]; \
1288             _param_fcn = param_1_fcn[Ga1]; \
1289             _param_hf = param_1_hf[Ga1]; \
1290         } \
1291  \
1292         GSM_SS_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \
1293  \
1294         if (_len > 0) \
1295         { \
1296             if (Ga1 == GSM_SS_P_NONE || _param_fcn == NULL) \
1297             { \
1298                 proto_tree_add_text(_subtree, asn1->tvb, \
1299                     asn1->offset, _len, "Parameter Data"); \
1300  \
1301                 asn1->offset += _len; \
1302             } \
1303             else \
1304             { \
1305                 (*_param_fcn)(asn1, _subtree, _len, *_param_hf); \
1306             } \
1307         } \
1308  \
1309         if (!_def_len) \
1310         { \
1311             guint       _saved_offset; \
1312  \
1313             _saved_offset = asn1->offset; \
1314             asn1_eoc_decode(asn1, -1); \
1315  \
1316             proto_tree_add_text(Gtree, asn1->tvb, \
1317                 _saved_offset, asn1->offset - _saved_offset, "End of Contents"); \
1318         } \
1319     }
1320
1321
1322 static void
1323 param_forwardingFeature(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1324 {
1325     guint               saved_offset;
1326     guint               tag, len;
1327     gboolean            def_len;
1328     proto_tree          *subtree;
1329
1330     exp_len = exp_len;
1331
1332     saved_offset = asn1->offset;
1333     asn1_id_decode1(asn1, &tag);
1334
1335     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature",
1336         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1337         &def_len, &len, subtree);
1338
1339     if (tcap_check_tag(asn1, 0x82))
1340     {
1341         saved_offset = asn1->offset;
1342         asn1_id_decode1(asn1, &tag);
1343
1344         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
1345     }
1346
1347     if (tcap_check_tag(asn1, 0x83))
1348     {
1349         saved_offset = asn1->offset;
1350         asn1_id_decode1(asn1, &tag);
1351
1352         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
1353     }
1354
1355     if (tcap_check_tag(asn1, 0x84))
1356     {
1357         saved_offset = asn1->offset;
1358         asn1_id_decode1(asn1, &tag);
1359
1360         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
1361     }
1362
1363     if (tcap_check_tag(asn1, 0x85))
1364     {
1365         saved_offset = asn1->offset;
1366         asn1_id_decode1(asn1, &tag);
1367
1368         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number");
1369     }
1370
1371     if (tcap_check_tag(asn1, 0x88))
1372     {
1373         saved_offset = asn1->offset;
1374         asn1_id_decode1(asn1, &tag);
1375
1376         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress");
1377     }
1378
1379     if (tcap_check_tag(asn1, 0x86))
1380     {
1381         saved_offset = asn1->offset;
1382         asn1_id_decode1(asn1, &tag);
1383
1384         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARDING_OPT, "Forwarding Options");
1385     }
1386
1387     if (tcap_check_tag(asn1, 0x87))
1388     {
1389         saved_offset = asn1->offset;
1390         asn1_id_decode1(asn1, &tag);
1391
1392         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time");
1393     }
1394
1395     if (tcap_check_tag(asn1, 0x89))
1396     {
1397         saved_offset = asn1->offset;
1398         asn1_id_decode1(asn1, &tag);
1399
1400         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_LONG_FORWARD_TO_NUM, "Long Forward to Number");
1401     }
1402
1403     if (!def_len)
1404     {
1405         saved_offset = asn1->offset;
1406         asn1_eoc_decode(asn1, -1);
1407
1408         proto_tree_add_text(subtree, asn1->tvb,
1409             saved_offset, asn1->offset - saved_offset, "End of Contents");
1410     }
1411 }
1412
1413 static void
1414 param_forwardingFeatureList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1415 {
1416     guint               saved_offset, start_offset;
1417     guint               tag, len;
1418     gboolean            def_len;
1419     proto_tree          *subtree;
1420
1421     saved_offset = asn1->offset;
1422     asn1_id_decode1(asn1, &tag);
1423
1424     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature List",
1425         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1426         &def_len, &len, subtree);
1427
1428     start_offset = asn1->offset;
1429
1430     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
1431         (!tcap_check_tag(asn1, 0)))
1432     {
1433         if ((exp_len != 0) &&
1434             ((asn1->offset - saved_offset) >= exp_len))
1435         {
1436             break;
1437         }
1438
1439         param_forwardingFeature(asn1, subtree, len - (asn1->offset - start_offset));
1440     }
1441
1442     if (!def_len)
1443     {
1444         saved_offset = asn1->offset;
1445         asn1_eoc_decode(asn1, -1);
1446
1447         proto_tree_add_text(subtree, asn1->tvb,
1448             saved_offset, asn1->offset - saved_offset, "End of Contents");
1449     }
1450 }
1451
1452 static void
1453 param_callBarringFeature(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1454 {
1455     guint               saved_offset;
1456     guint               tag, len;
1457     gboolean            def_len;
1458     proto_tree          *subtree;
1459
1460     exp_len = exp_len;
1461
1462     saved_offset = asn1->offset;
1463     asn1_id_decode1(asn1, &tag);
1464
1465     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Feature",
1466         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1467         &def_len, &len, subtree);
1468
1469     if (tcap_check_tag(asn1, 0x82))
1470     {
1471         saved_offset = asn1->offset;
1472         asn1_id_decode1(asn1, &tag);
1473
1474         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
1475     }
1476
1477     if (tcap_check_tag(asn1, 0x83))
1478     {
1479         saved_offset = asn1->offset;
1480         asn1_id_decode1(asn1, &tag);
1481
1482         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
1483     }
1484
1485     if (tcap_check_tag(asn1, 0x84))
1486     {
1487         saved_offset = asn1->offset;
1488         asn1_id_decode1(asn1, &tag);
1489
1490         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
1491     }
1492
1493     if (!def_len)
1494     {
1495         saved_offset = asn1->offset;
1496         asn1_eoc_decode(asn1, -1);
1497
1498         proto_tree_add_text(subtree, asn1->tvb,
1499             saved_offset, asn1->offset - saved_offset, "End of Contents");
1500     }
1501 }
1502
1503 static void
1504 param_callBarringFeatureList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1505 {
1506     guint               saved_offset, start_offset;
1507     guint               tag, len;
1508     gboolean            def_len;
1509     proto_tree          *subtree;
1510
1511     saved_offset = asn1->offset;
1512     asn1_id_decode1(asn1, &tag);
1513
1514     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Feature List",
1515         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1516         &def_len, &len, subtree);
1517
1518     start_offset = asn1->offset;
1519
1520     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
1521         (!tcap_check_tag(asn1, 0)))
1522     {
1523         if ((exp_len != 0) &&
1524             ((asn1->offset - saved_offset) >= exp_len))
1525         {
1526             break;
1527         }
1528
1529         param_callBarringFeature(asn1, subtree, len - (asn1->offset - start_offset));
1530     }
1531
1532     if (!def_len)
1533     {
1534         saved_offset = asn1->offset;
1535         asn1_eoc_decode(asn1, -1);
1536
1537         proto_tree_add_text(subtree, asn1->tvb,
1538             saved_offset, asn1->offset - saved_offset, "End of Contents");
1539     }
1540 }
1541
1542 static void
1543 param_ssData(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1544 {
1545     guint               saved_offset;
1546
1547     saved_offset = asn1->offset;
1548
1549     /* XXX */
1550     op_generic_ss(asn1, tree, exp_len);
1551 }
1552
1553 static void
1554 param_ssInfo(ASN1_SCK *asn1, proto_tree *tree)
1555 {
1556     guint               saved_offset, start_offset;
1557     guint               tag, len;
1558     gboolean            def_len = FALSE;
1559     proto_tree          *subtree;
1560
1561     saved_offset = asn1->offset;
1562     asn1_id_decode1(asn1, &tag);
1563
1564     switch (tag)
1565     {
1566     case 0xa0:  /* forwardingInfo */
1567         GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Info",
1568             gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1569             &def_len, &len, subtree);
1570
1571         start_offset = asn1->offset;
1572
1573         if (tcap_check_tag(asn1, 0x04))
1574         {
1575             saved_offset = asn1->offset;
1576             asn1_id_decode1(asn1, &tag);
1577
1578             GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
1579         }
1580
1581         param_forwardingFeatureList(asn1, subtree, len - (asn1->offset - start_offset));
1582
1583         if (!def_len)
1584         {
1585             saved_offset = asn1->offset;
1586             asn1_eoc_decode(asn1, -1);
1587
1588             proto_tree_add_text(subtree, asn1->tvb,
1589                 saved_offset, asn1->offset - saved_offset, "End of Contents");
1590         }
1591         break;
1592
1593     case 0xa1:  /* callBarringInfo */
1594         GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Info",
1595             gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1596             &def_len, &len, subtree);
1597
1598         start_offset = asn1->offset;
1599
1600         if (tcap_check_tag(asn1, 0x04))
1601         {
1602             saved_offset = asn1->offset;
1603             asn1_id_decode1(asn1, &tag);
1604
1605             GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
1606         }
1607
1608         param_callBarringFeatureList(asn1, subtree, len - (asn1->offset - start_offset));
1609
1610         if (!def_len)
1611         {
1612             saved_offset = asn1->offset;
1613             asn1_eoc_decode(asn1, -1);
1614
1615             proto_tree_add_text(subtree, asn1->tvb,
1616                 saved_offset, asn1->offset - saved_offset, "End of Contents");
1617         }
1618         break;
1619
1620     case 0xa3:  /* ss-Data */
1621         GSM_SS_START_SUBTREE(tree, saved_offset, tag, "ss-Data",
1622             gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1623             &def_len, &len, subtree);
1624
1625         start_offset = asn1->offset;
1626
1627         param_ssData(asn1, subtree, len - (asn1->offset - start_offset));
1628
1629         if (!def_len)
1630         {
1631             saved_offset = asn1->offset;
1632             asn1_eoc_decode(asn1, -1);
1633
1634             proto_tree_add_text(subtree, asn1->tvb,
1635                 saved_offset, asn1->offset - saved_offset, "End of Contents");
1636         }
1637         break;
1638
1639     default:
1640         GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Unexpected TAG",
1641             gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1642             &def_len, &len, subtree);
1643
1644         op_generic_ss(asn1, subtree, len);
1645
1646         if (!def_len)
1647         {
1648             saved_offset = asn1->offset;
1649             asn1_eoc_decode(asn1, -1);
1650
1651             proto_tree_add_text(subtree, asn1->tvb,
1652                 saved_offset, asn1->offset - saved_offset, "End of Contents");
1653         }
1654         break;
1655     }
1656 }
1657
1658 static void
1659 param_ssForBS(ASN1_SCK *asn1, proto_tree *tree)
1660 {
1661     guint               saved_offset, start_offset;
1662     guint               tag, len, rem_len;
1663     gboolean            def_len = FALSE;
1664     proto_tree          *subtree;
1665
1666     saved_offset = asn1->offset;
1667     asn1_id_decode1(asn1, &tag);
1668
1669     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1670         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1671         &def_len, &len, subtree);
1672
1673     start_offset = asn1->offset;
1674
1675     saved_offset = asn1->offset;
1676     asn1_id_decode1(asn1, &tag);
1677
1678     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
1679
1680     if (tcap_check_tag(asn1, 0x82))
1681     {
1682         saved_offset = asn1->offset;
1683         asn1_id_decode1(asn1, &tag);
1684
1685         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
1686     }
1687
1688     if (tcap_check_tag(asn1, 0x83))
1689     {
1690         saved_offset = asn1->offset;
1691         asn1_id_decode1(asn1, &tag);
1692
1693         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
1694     }
1695
1696     if (tcap_check_tag(asn1, 0x84))
1697     {
1698         saved_offset = asn1->offset;
1699         asn1_id_decode1(asn1, &tag);
1700
1701         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Long FTN supported");
1702     }
1703
1704     rem_len = len - (asn1->offset - start_offset);
1705
1706     if (rem_len > 0)
1707     {
1708         op_generic_ss(asn1, subtree, rem_len);
1709     }
1710
1711     if (!def_len)
1712     {
1713         saved_offset = asn1->offset;
1714         asn1_eoc_decode(asn1, -1);
1715
1716         proto_tree_add_text(subtree, asn1->tvb,
1717             saved_offset, asn1->offset - saved_offset, "End of Contents");
1718     }
1719 }
1720
1721 static void
1722 param_ussdArg(ASN1_SCK *asn1, proto_tree *tree)
1723 {
1724     guint               saved_offset, start_offset;
1725     guint               tag, len, rem_len;
1726     gboolean            def_len = FALSE;
1727     proto_tree          *subtree;
1728
1729     saved_offset = asn1->offset;
1730     asn1_id_decode1(asn1, &tag);
1731
1732     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1733         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1734         &def_len, &len, subtree);
1735
1736     start_offset = asn1->offset;
1737
1738     saved_offset = asn1->offset;
1739     asn1_id_decode1(asn1, &tag);
1740
1741     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_DCS, "USSD Data Coding Scheme");
1742
1743     saved_offset = asn1->offset;
1744     asn1_id_decode1(asn1, &tag);
1745
1746     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_STRING, "USSD String");
1747
1748     rem_len = len - (asn1->offset - start_offset);
1749
1750     if (rem_len > 0)
1751     {
1752         op_generic_ss(asn1, subtree, rem_len);
1753     }
1754
1755     if (!def_len)
1756     {
1757         saved_offset = asn1->offset;
1758         asn1_eoc_decode(asn1, -1);
1759
1760         proto_tree_add_text(subtree, asn1->tvb,
1761             saved_offset, asn1->offset - saved_offset, "End of Contents");
1762     }
1763 }
1764
1765 static void
1766 param_ussdRes(ASN1_SCK *asn1, proto_tree *tree)
1767 {
1768     guint               saved_offset, start_offset;
1769     guint               tag, len, rem_len;
1770     gboolean            def_len = FALSE;
1771     proto_tree          *subtree;
1772
1773     saved_offset = asn1->offset;
1774     asn1_id_decode1(asn1, &tag);
1775
1776     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1777         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1778         &def_len, &len, subtree);
1779
1780     start_offset = asn1->offset;
1781
1782     saved_offset = asn1->offset;
1783     asn1_id_decode1(asn1, &tag);
1784
1785     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_DCS, "USSD Data Coding Scheme");
1786
1787     saved_offset = asn1->offset;
1788     asn1_id_decode1(asn1, &tag);
1789
1790     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_STRING, "USSD String");
1791
1792     rem_len = len - (asn1->offset - start_offset);
1793
1794     if (rem_len > 0)
1795     {
1796         op_generic_ss(asn1, subtree, rem_len);
1797     }
1798
1799     if (!def_len)
1800     {
1801         saved_offset = asn1->offset;
1802         asn1_eoc_decode(asn1, -1);
1803
1804         proto_tree_add_text(subtree, asn1->tvb,
1805             saved_offset, asn1->offset - saved_offset, "End of Contents");
1806     }
1807 }
1808
1809
1810 /* MESSAGES */
1811
1812 static void
1813 op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1814 {
1815     guint       orig_offset, saved_offset, len_offset;
1816     guint       tag, len;
1817     gboolean    def_len = FALSE;
1818     proto_item  *item;
1819     proto_tree  *subtree;
1820
1821     orig_offset = asn1->offset;
1822
1823     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
1824         (!tcap_check_tag(asn1, 0)))
1825     {
1826         if ((exp_len != 0) &&
1827             ((asn1->offset - orig_offset) >= exp_len))
1828         {
1829             break;
1830         }
1831
1832         saved_offset = asn1->offset;
1833         asn1_id_decode1(asn1, &tag);
1834
1835         if (TCAP_CONSTRUCTOR(tag))
1836         {
1837             GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1838                 gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1839                 &def_len, &len, subtree);
1840
1841             op_generic_ss(asn1, subtree, len);
1842
1843             if (!def_len)
1844             {
1845                 saved_offset = asn1->offset;
1846                 asn1_eoc_decode(asn1, -1);
1847
1848                 proto_tree_add_text(subtree, asn1->tvb,
1849                     saved_offset, asn1->offset - saved_offset, "End of Contents");
1850             }
1851             continue;
1852         }
1853
1854         len_offset = asn1->offset;
1855         asn1_length_decode(asn1, &def_len, &len);
1856
1857         if (!def_len)
1858         {
1859             proto_tree_add_text(tree, asn1->tvb,
1860                 saved_offset, len_offset - saved_offset,
1861                 "Tag: 0x%02x", tag);
1862
1863             proto_tree_add_text(tree, asn1->tvb,
1864                 len_offset, asn1->offset - len_offset, "Length: Indefinite");
1865
1866             len = tcap_find_eoc(asn1);
1867
1868             op_generic_ss(asn1, tree, len);
1869
1870             saved_offset = asn1->offset;
1871             asn1_eoc_decode(asn1, -1);
1872
1873             proto_tree_add_text(tree, asn1->tvb,
1874                 saved_offset, asn1->offset - saved_offset, "End of Contents");
1875             continue;
1876         }
1877
1878         item =
1879             proto_tree_add_text(tree, asn1->tvb,
1880                 saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
1881
1882         subtree = proto_item_add_subtree(item, gsm_ss_ett[GSM_SS_ETT_PARAM]);
1883
1884         proto_tree_add_text(subtree, asn1->tvb,
1885             saved_offset, len_offset - saved_offset,
1886             "Tag: 0x%02x", tag);
1887
1888         proto_tree_add_text(subtree, asn1->tvb,
1889             len_offset, asn1->offset - len_offset, "Length: %d", len);
1890
1891         if (len > 0)
1892         {
1893             proto_tree_add_text(subtree, asn1->tvb,
1894                 asn1->offset, len, "Parameter Data");
1895
1896             asn1->offset += len;
1897         }
1898     }
1899 }
1900
1901 static void
1902 op_register_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
1903 {
1904     guint       saved_offset, start_offset;
1905     guint       tag, len, rem_len;
1906     gboolean    def_len = FALSE;
1907     proto_tree  *subtree;
1908
1909     exp_len = exp_len;
1910
1911     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
1912
1913     saved_offset = asn1->offset;
1914     asn1_id_decode1(asn1, &tag);
1915
1916     GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
1917         gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
1918         &def_len, &len, subtree);
1919
1920     start_offset = asn1->offset;
1921
1922     saved_offset = asn1->offset;
1923     asn1_id_decode1(asn1, &tag);
1924
1925     GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
1926
1927     if (tcap_check_tag(asn1, 0x82))
1928     {
1929         saved_offset = asn1->offset;
1930         asn1_id_decode1(asn1, &tag);
1931
1932         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
1933     }
1934
1935     if (tcap_check_tag(asn1, 0x83))
1936     {
1937         saved_offset = asn1->offset;
1938         asn1_id_decode1(asn1, &tag);
1939
1940         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
1941     }
1942
1943     if (tcap_check_tag(asn1, 0x84))
1944     {
1945         saved_offset = asn1->offset;
1946         asn1_id_decode1(asn1, &tag);
1947
1948         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number");
1949     }
1950
1951     if (tcap_check_tag(asn1, 0x86))
1952     {
1953         saved_offset = asn1->offset;
1954         asn1_id_decode1(asn1, &tag);
1955
1956         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress");
1957     }
1958
1959     if (tcap_check_tag(asn1, 0x85))
1960     {
1961         saved_offset = asn1->offset;
1962         asn1_id_decode1(asn1, &tag);
1963
1964         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time");
1965     }
1966
1967     if (tcap_check_tag(asn1, 0x87))
1968     {
1969         saved_offset = asn1->offset;
1970         asn1_id_decode1(asn1, &tag);
1971
1972         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Default Priority");
1973     }
1974
1975     if (tcap_check_tag(asn1, 0x88))
1976     {
1977         saved_offset = asn1->offset;
1978         asn1_id_decode1(asn1, &tag);
1979
1980         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Number Users");
1981     }
1982
1983     if (tcap_check_tag(asn1, 0x89))
1984     {
1985         saved_offset = asn1->offset;
1986         asn1_id_decode1(asn1, &tag);
1987
1988         GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Long FTN supported");
1989     }
1990
1991     rem_len = len - (asn1->offset - start_offset);
1992
1993     if (rem_len > 0)
1994     {
1995         op_generic_ss(asn1, subtree, rem_len);
1996     }
1997
1998     if (!def_len)
1999     {
2000         saved_offset = asn1->offset;
2001         asn1_eoc_decode(asn1, -1);
2002
2003         proto_tree_add_text(subtree, asn1->tvb,
2004             saved_offset, asn1->offset - saved_offset, "End of Contents");
2005     }
2006 }
2007
2008 static void
2009 op_register_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2010 {
2011     guint       saved_offset;
2012
2013     exp_len = exp_len;
2014
2015     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2016
2017     saved_offset = asn1->offset;
2018
2019     param_ssInfo(asn1, tree);
2020 }
2021
2022 static void
2023 op_erase_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2024 {
2025     guint       saved_offset;
2026
2027     exp_len = exp_len;
2028
2029     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2030
2031     saved_offset = asn1->offset;
2032
2033     param_ssForBS(asn1, tree);
2034 }
2035
2036 static void
2037 op_erase_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2038 {
2039     guint       saved_offset;
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
2047     param_ssInfo(asn1, tree);
2048 }
2049
2050 static void
2051 op_activate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2052 {
2053     guint       saved_offset;
2054
2055     exp_len = exp_len;
2056
2057     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2058
2059     saved_offset = asn1->offset;
2060
2061     param_ssForBS(asn1, tree);
2062 }
2063
2064 static void
2065 op_activate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2066 {
2067     guint       saved_offset;
2068
2069     exp_len = exp_len;
2070
2071     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2072
2073     saved_offset = asn1->offset;
2074
2075     param_ssInfo(asn1, tree);
2076 }
2077
2078 static void
2079 op_deactivate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2080 {
2081     guint       saved_offset;
2082
2083     exp_len = exp_len;
2084
2085     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2086
2087     saved_offset = asn1->offset;
2088
2089     param_ssForBS(asn1, tree);
2090 }
2091
2092 static void
2093 op_deactivate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2094 {
2095     guint       saved_offset;
2096
2097     exp_len = exp_len;
2098
2099     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2100
2101     saved_offset = asn1->offset;
2102
2103     param_ssInfo(asn1, tree);
2104 }
2105
2106 static void
2107 op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2108 {
2109     guint       saved_offset;
2110
2111     exp_len = exp_len;
2112
2113     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2114
2115     saved_offset = asn1->offset;
2116
2117     param_ssForBS(asn1, tree);
2118 }
2119
2120 static void
2121 op_interrogate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2122 {
2123     guint       saved_offset;
2124     guint       tag;
2125
2126     exp_len = exp_len;
2127
2128     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2129
2130     saved_offset = asn1->offset;
2131     asn1_id_decode1(asn1, &tag);
2132
2133     switch (tag)
2134     {
2135     case 0x80:  /* SS-Status */
2136         GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
2137         break;
2138
2139     case 0x82:  /* BasicServiceGroupList */
2140         /* XXX */
2141         asn1->offset = saved_offset;
2142         op_generic_ss(asn1, tree, exp_len);
2143         break;
2144
2145     case 0x83:  /* ForwardingFeatureList */
2146         asn1->offset = saved_offset;
2147         param_forwardingFeatureList(asn1, tree, exp_len);
2148         break;
2149
2150     case 0x84:  /* GenericServiceInfo */
2151         /* XXX */
2152         asn1->offset = saved_offset;
2153         op_generic_ss(asn1, tree, exp_len);
2154         break;
2155
2156     default:
2157         asn1->offset = saved_offset;
2158         op_generic_ss(asn1, tree, exp_len);
2159         return;
2160     }
2161 }
2162
2163 static void
2164 op_reg_password(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2165 {
2166     guint       saved_offset;
2167     guint       tag, rem_len;
2168
2169     exp_len = exp_len;
2170
2171     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2172
2173     saved_offset = asn1->offset;
2174     asn1_id_decode1(asn1, &tag);
2175
2176     GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
2177
2178     rem_len = exp_len - (asn1->offset - saved_offset);
2179
2180     if (rem_len > 0)
2181     {
2182         op_generic_ss(asn1, tree, rem_len);
2183     }
2184 }
2185
2186 static void
2187 op_reg_password_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2188 {
2189     guint       saved_offset;
2190     guint       tag, rem_len;
2191
2192     exp_len = exp_len;
2193
2194     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2195
2196     saved_offset = asn1->offset;
2197     asn1_id_decode1(asn1, &tag);
2198
2199     GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_PASSWORD, "New Password");
2200
2201     rem_len = exp_len - (asn1->offset - saved_offset);
2202
2203     if (rem_len > 0)
2204     {
2205         op_generic_ss(asn1, tree, rem_len);
2206     }
2207 }
2208
2209 static void
2210 op_get_password(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2211 {
2212     guint       saved_offset;
2213     guint       tag, rem_len;
2214
2215     exp_len = exp_len;
2216
2217     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2218
2219     saved_offset = asn1->offset;
2220     asn1_id_decode1(asn1, &tag);
2221
2222     GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_GUIDANCE_INFO, "Guidance Info");
2223
2224     rem_len = exp_len - (asn1->offset - saved_offset);
2225
2226     if (rem_len > 0)
2227     {
2228         op_generic_ss(asn1, tree, rem_len);
2229     }
2230 }
2231
2232 static void
2233 op_get_password_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2234 {
2235     guint       saved_offset;
2236     guint       tag, rem_len;
2237
2238     exp_len = exp_len;
2239
2240     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2241
2242     saved_offset = asn1->offset;
2243     asn1_id_decode1(asn1, &tag);
2244
2245     GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_PASSWORD, "Current Password");
2246
2247     rem_len = exp_len - (asn1->offset - saved_offset);
2248
2249     if (rem_len > 0)
2250     {
2251         op_generic_ss(asn1, tree, rem_len);
2252     }
2253 }
2254
2255 static void
2256 op_proc_uss_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2257 {
2258     guint       saved_offset;
2259     guint       tag, rem_len;
2260
2261     exp_len = exp_len;
2262
2263     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2264
2265     saved_offset = asn1->offset;
2266
2267     if (tcap_check_tag(asn1, 0x16))
2268     {
2269         saved_offset = asn1->offset;
2270         asn1_id_decode1(asn1, &tag);
2271
2272         GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData");
2273     }
2274
2275     rem_len = exp_len - (asn1->offset - saved_offset);
2276
2277     if (rem_len > 0)
2278     {
2279         op_generic_ss(asn1, tree, rem_len);
2280     }
2281 }
2282
2283 static void
2284 op_proc_uss_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2285 {
2286     guint       saved_offset;
2287     guint       tag, rem_len;
2288
2289     exp_len = exp_len;
2290
2291     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2292
2293     saved_offset = asn1->offset;
2294
2295     if (tcap_check_tag(asn1, 0x16))
2296     {
2297         saved_offset = asn1->offset;
2298         asn1_id_decode1(asn1, &tag);
2299
2300         GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData");
2301     }
2302
2303     rem_len = exp_len - (asn1->offset - saved_offset);
2304
2305     if (rem_len > 0)
2306     {
2307         op_generic_ss(asn1, tree, rem_len);
2308     }
2309 }
2310
2311 static void
2312 op_proc_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2313 {
2314     guint       saved_offset;
2315
2316     exp_len = exp_len;
2317
2318     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2319
2320     saved_offset = asn1->offset;
2321
2322     param_ussdArg(asn1, tree);
2323 }
2324
2325 static void
2326 op_proc_uss_req_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2327 {
2328     guint       saved_offset;
2329
2330     exp_len = exp_len;
2331
2332     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2333
2334     saved_offset = asn1->offset;
2335
2336     param_ussdRes(asn1, tree);
2337 }
2338
2339 static void
2340 op_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2341 {
2342     guint       saved_offset;
2343
2344     exp_len = exp_len;
2345
2346     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2347
2348     saved_offset = asn1->offset;
2349
2350     param_ussdArg(asn1, tree);
2351 }
2352
2353 static void
2354 op_uss_req_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2355 {
2356     guint       saved_offset;
2357
2358     exp_len = exp_len;
2359
2360     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2361
2362     saved_offset = asn1->offset;
2363
2364     param_ussdRes(asn1, tree);
2365 }
2366
2367 static void
2368 op_uss_notify(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
2369 {
2370     guint       saved_offset;
2371
2372     exp_len = exp_len;
2373
2374     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
2375
2376     saved_offset = asn1->offset;
2377
2378     param_ussdArg(asn1, tree);
2379 }
2380
2381 #define GSM_SS_NUM_OP (sizeof(gsm_ss_opr_code_strings)/sizeof(value_string))
2382 static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
2383     op_register_ss,     /* RegisterSS */
2384     op_erase_ss,        /* EraseSS */
2385     op_activate_ss,     /* ActivateSS */
2386     op_deactivate_ss,   /* DeactivateSS */
2387     op_interrogate_ss,  /* InterrogateSS */
2388     NULL,       /* NotifySS */
2389     op_reg_password,    /* RegisterPassword */
2390     op_get_password,    /* GetPassword */
2391     op_proc_uss_data,   /* ProcessUnstructuredSS-Data */
2392     NULL,       /* ForwardCheckSS-Indication */
2393     op_proc_uss_req,    /* ProcessUnstructuredSS-Request */
2394     op_uss_req,         /* UnstructuredSS-Request */
2395     op_uss_notify,      /* UnstructuredSS-Notify */
2396     NULL,       /* EraseCC-Entry */
2397     NULL,       /* LCS-LocationNotification */
2398     NULL,       /* LCS-MOLR */
2399     NULL,       /* AccessRegisterCCEntry */
2400     NULL,       /* ForwardCUG-Info */
2401     NULL /* NO ARGS */, /* SplitMPTY */
2402     NULL /* NO ARGS */, /* RetrieveMPTY */
2403     NULL /* NO ARGS */, /* HoldMPTY */
2404     NULL /* NO ARGS */, /* BuildMPTY */
2405     NULL,       /* ForwardChargeAdvice */
2406     NULL,       /* ExplicitCT */
2407     NULL,       /* LCS-LocationNotification */
2408     NULL,       /* LCS-MOLR */
2409
2410     NULL        /* NONE */
2411 };
2412
2413 static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
2414     op_register_ss_rr,          /* RegisterSS */
2415     op_erase_ss_rr,             /* EraseSS */
2416     op_activate_ss_rr,          /* ActivateSS */
2417     op_deactivate_ss_rr,        /* DeactivateSS */
2418     op_interrogate_ss_rr,       /* InterrogateSS */
2419     NULL,       /* NotifySS */
2420     op_reg_password_rr,         /* RegisterPassword */
2421     op_get_password_rr,         /* GetPassword */
2422     op_proc_uss_data_rr,        /* ProcessUnstructuredSS-Data */
2423     NULL,       /* ForwardCheckSS-Indication */
2424     op_proc_uss_req_rr,         /* ProcessUnstructuredSS-Request */
2425     op_uss_req_rr,              /* UnstructuredSS-Request */
2426     NULL /* NO ARGS */,         /* UnstructuredSS-Notify */
2427     NULL,       /* EraseCC-Entry */
2428     NULL,       /* LCS Location Notification */
2429     NULL,       /* LCS MOLR */
2430     NULL,       /* AccessRegisterCCEntry */
2431     NULL,       /* ForwardCUG-Info */
2432     NULL,       /* SplitMPTY */
2433     NULL,       /* RetrieveMPTY */
2434     NULL,       /* HoldMPTY */
2435     NULL,       /* BuildMPTY */
2436     NULL /* NO ARGS */,         /* ForwardChargeAdvice */
2437     NULL,       /* ExplicitCT */
2438     NULL,       /* LCS-LocationNotification */
2439     NULL,       /* LCS-MOLR */
2440
2441     NULL        /* NONE */
2442 };
2443
2444 void
2445 gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len,
2446     guint opr_code, guint comp_type_tag)
2447 {
2448     void (*dissect_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint exp_len);
2449     gchar       *str;
2450     gint        op_idx;
2451
2452
2453     dissect_fcn = NULL;
2454
2455     str = my_match_strval(opr_code, gsm_ss_opr_code_strings, &op_idx);
2456
2457     if (str != NULL)
2458     {
2459         switch (comp_type_tag)
2460         {
2461         case TCAP_COMP_INVOKE:
2462             dissect_fcn = op_fcn[op_idx];
2463             break;
2464
2465         case TCAP_COMP_RRL:
2466             dissect_fcn = op_fcn_rr[op_idx];
2467             break;
2468
2469         case TCAP_COMP_RE:
2470             dissect_fcn = NULL;
2471             return;
2472
2473         default:
2474             /*
2475              * no parameters should be present in the component types
2476              * ignore
2477              */
2478             return;
2479         }
2480     }
2481
2482     if (dissect_fcn == NULL)
2483     {
2484         op_generic_ss(asn1, tree, exp_len);
2485     }
2486     else
2487     {
2488         (*dissect_fcn)(asn1, tree, exp_len);
2489     }
2490 }