change QSIG tables structure so as they can be generated automatically from ASN.1...
[obnox/wireshark/wip.git] / asn1 / qsig / packet-qsig-template.c
1 /* packet-qsig.c
2  * Routines for QSIG packet dissection
3  * 2007  Tomas Kukosa
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/strutil.h>
33 #include <epan/emem.h>
34 #include <epan/asn1.h>
35
36 #include "packet-ber.h"
37 #include "packet-qsig.h"
38
39 #define PNAME  "QSIG"
40 #define PSNAME "QSIG"
41 #define PFNAME "qsig"
42
43 /* Shifted codeset values */
44 #define CS0 0x000
45 #define CS1 0x100
46 #define CS2 0x200
47 #define CS3 0x300
48 #define CS4 0x400
49 #define CS5 0x500
50 #define CS6 0x600
51 #define CS7 0x700
52
53 #define QSIG_IE_TRANSIT_COUNTER 0x31
54 #define QSIG_IE_PARTY_CATEGORY  0x32
55
56 static const value_string qsig_str_ie_type_cs4[] = {
57   { QSIG_IE_TRANSIT_COUNTER , "Transit counter" },
58   { 0, NULL}
59 };
60 static const value_string qsig_str_ie_type_cs5[] = {
61   { QSIG_IE_PARTY_CATEGORY  , "Party category" },
62   { 0, NULL}
63 };
64 /* Codeset array */
65 static const value_string *qsig_str_ie_type[] = {
66   NULL,
67   NULL,
68   NULL,
69   NULL,
70   qsig_str_ie_type_cs4,
71   qsig_str_ie_type_cs5,
72   NULL,
73   NULL,
74 };
75
76
77 static const value_string qsig_str_pc[] = {
78   { 0x00 , "unknown" },
79   { 0x01 , "extension" },
80   { 0x02 , "operator" },
81   { 0x03 , "emergency extension" },
82   { 0, NULL}
83 };
84
85 static const value_string qsig_str_service[] = {
86   { 13868, "QSIG-NA" },
87   { 13873, "QSIG-CF" },
88   { 13874, "QSIG-PR" },
89   { 13869, "QSIG-CT" },
90   { 13870, "QSIG-CC" },
91   { 14843, "QSIG-CO" },
92   { 14844, "QSIG-DND(O)" },
93   { 14846, "QSIG-CI" },
94   { 15050, "QSIG-AOC" },
95   { 15052, "QSIG-RE" },
96   { 15054, "QSIG-CINT" },
97   { 15506, "QSIG-MWI" },
98   { 15507, "SYNC-SIG" },
99   { 15772, "QSIG-CMN" },
100   { 15992, "QSIG-CPI(P)" },
101   { 17876, "QSIG-PUMR" },
102   { 17878, "QSIG-PUMCH" },
103   { 19460, "QSIG-SSCT" },
104   { 15429, "QSIG-WTMLR" },
105   { 15431, "QSIG-WTMCH" },
106   { 15433, "QSIG-WTMAU" },
107   { 21407, "QSIG-SD" },
108   { 21889, "QSIG-CIDL" },
109   {   325, "QSIG-SMS" },
110   {   344, "QSIG-MCR" },
111   {  3471, "QSIG-MCM" },
112   {  3472, "QSIG-MID" },
113   {   0, NULL}
114 };
115
116 static const value_string qsig_str_service_name[] = {
117   { 13868, "Name-Operations" },
118   { 13873, "Call-Diversion-Operations" },
119   { 13874, "Path-Replacement-Operations" },
120   { 13869, "Call-Transfer-Operations" },
121   { 13870, "SS-CC-Operations" },
122   { 14843, "Call-Offer-Operations" },
123   { 14844, "Do-Not-Disturb-Operations" },
124   { 14846, "Call-Intrusion-Operations" },
125   { 15050, "SS-AOC-Operation" },
126   { 15052, "Recall-Operation" },
127   { 15054, "Call-Interception-Operations" },
128   { 15506, "SS-MWI-Operations" },
129   { 15507, "Synchronization-Operations" },
130   { 15772, "Common-Information-Operations" },
131   { 15992, "Call-Interruption-Operation" },
132   { 17876, "PUM-Registration-Operation" },
133   { 17878, "Private-User-Mobility-Call-Handling-Operations" },
134   { 19460, "Single-Step-Call-Transfer-Operations" },
135   { 15429, "WTM-Location-Registration-Operations" },
136   { 15431, "Wireless-Terminal-Call-Handling-Operations" },
137   { 15433, "WTM-Authentication-Operations" },
138   { 21407, "SS-SD-Operations" },
139   { 21889, "Call-Identification-and-Call-Linkage-Operations" },
140   {   325, "Short-Message-Service-Operations" },
141   {   344, "SS-MCR-Operations" },
142   {  3471, "SS-MCM-Operations" },
143   {  3472, "SS-MID-Operations" },
144   {   0, NULL}
145 };
146
147 #define NO_SRV (-1)
148 static const gint32 op2srv_tab[] = {
149   /*   0 */ 13868, 
150   /*   1 */ 13868, 
151   /*   2 */ 13868, 
152   /*   3 */ 13868, 
153   /*   4 */ 13874, 
154   /*   5 */ 13874, 
155   /*   6 */ 13874, 
156   /*   7 */ 13869, 
157   /*   8 */ 13869, 
158   /*   9 */ 13869, 
159   /*  10 */ 13869, 
160   /*  11 */ 13869, 
161   /*  12 */ 13869, 
162   /*  13 */ 13869, 
163   /*  14 */ 13869, 
164   /*  15 */ 13873, 
165   /*  16 */ 13873, 
166   /*  17 */ 13873, 
167   /*  18 */ 13873, 
168   /*  19 */ 13873, 
169   /*  20 */ 13873, 
170   /*  21 */ 13873, 
171   /*  22 */ 13873, 
172   /*  23 */ 13873, 
173   /*  24 */ NO_SRV,
174   /*  25 */ NO_SRV,
175   /*  26 */ NO_SRV,
176   /*  27 */ 13870, 
177   /*  28 */ 13870, 
178   /*  29 */ 13870, 
179   /*  30 */ 13870, 
180   /*  31 */ 13870, 
181   /*  32 */ 13870, 
182   /*  33 */ 13870, 
183   /*  34 */ 14843, 
184   /*  35 */ 14844, 
185   /*  36 */ 14844, 
186   /*  37 */ 14844, 
187   /*  38 */ 14844, 
188   /*  39 */ 14844, 
189   /*  40 */ 13870, 
190   /*  41 */ 90001, 
191   /*  42 */ 90001, 
192   /*  43 */ 14846, 
193   /*  44 */ 14846, 
194   /*  45 */ 14846, 
195   /*  46 */ 14846, 
196   /*  47 */ 14846, 
197   /*  48 */ 14846, 
198   /*  49 */ 90001, 
199   /*  50 */ 15429, 
200   /*  51 */ 15429, 
201   /*  52 */ 15429, 
202   /*  53 */ 15429, 
203   /*  54 */ 15431, 
204   /*  55 */ 15431, 
205   /*  56 */ 15431, 
206   /*  57 */ 15052, 
207   /*  58 */ 15052, 
208   /*  59 */ 15050, 
209   /*  60 */ 15050, 
210   /*  61 */ 15050, 
211   /*  62 */ 15050, 
212   /*  63 */ 15050, 
213   /*  64 */ 15050, 
214   /*  65 */ 15050, 
215   /*  66 */ 15054, 
216   /*  67 */ 15054, 
217   /*  68 */ 15054, 
218   /*  69 */ 15054, 
219   /*  70 */ 15054, 
220   /*  71 */ 15431, 
221   /*  72 */ 15433, 
222   /*  73 */ 15433, 
223   /*  74 */ 15433, 
224   /*  75 */ 15433, 
225   /*  76 */ 15433, 
226   /*  77 */ 15433, 
227   /*  78 */ 15507, 
228   /*  79 */ 15507, 
229   /*  80 */  3471, 
230   /*  81 */  3471, 
231   /*  82 */  3471, 
232   /*  83 */ NO_SRV,
233   /*  84 */ 15772, 
234   /*  85 */ 15772, 
235   /*  86 */ 13874, 
236   /*  87 */ 15992, 
237   /*  88 */ 15992, 
238   /*  89 */ 17876, 
239   /*  90 */ 17876, 
240   /*  91 */ 17876, 
241   /*  92 */ 17876, 
242   /*  93 */ 17878, 
243   /*  94 */ 17878, 
244   /*  95 */ 17878, 
245   /*  96 */ 17878, 
246   /*  97 */ 15429, 
247   /*  98 */ 15429, 
248   /*  99 */ 19460, 
249   /* 100 */ 19460, 
250   /* 101 */ 19460, 
251   /* 102 */ 19460, 
252   /* 103 */ 21407, 
253   /* 104 */ 21407, 
254   /* 105 */ 21889, 
255   /* 106 */ 21889, 
256   /* 107 */   325, 
257   /* 108 */   325, 
258   /* 109 */   325, 
259   /* 110 */   325, 
260   /* 111 */   325, 
261   /* 112 */   344, 
262   /* 113 */   344, 
263   /* 114 */   344, 
264   /* 115 */  3471, 
265   /* 116 */  3471, 
266   /* 117 */  3471, 
267   /* 118 */  3471, 
268   /* 119 */  3472, 
269   /* 120 */  3472, 
270 };                                 
271
272 static const value_string qsig_str_operation[] = {
273   {   0, "callingName" },
274   {   1, "calledName" },
275   {   2, "connectedName" },
276   {   3, "busyName" },
277   {   4, "pathReplacePropose" },
278   {   5, "pathReplaceSetup" },
279   {   6, "pathReplaceRetain" },
280   {   7, "callTransferIdentify" },
281   {   8, "callTransferAbandon" },
282   {   9, "callTransferInitiate" },
283   {  10, "callTransferSetup" },
284   {  11, "callTransferActive" },
285   {  12, "callTransferComplete" },
286   {  13, "callTransferUpdate" },
287   {  14, "subaddressTransfer" },
288   {  15, "activateDiversionQ" },
289   {  16, "deactivateDiversionQ" },
290   {  17, "interrogateDiversionQ" },
291   {  18, "checkRestriction" },
292   {  19, "callRerouteing" },
293   {  20, "divertingLegInformation1" },
294   {  21, "divertingLegInformation2" },
295   {  22, "divertingLegInformation3" },
296   {  23, "cfnrDivertedLegFailed" },
297 /*   24 Reserved (corresponding integer value used by ISO for MLPP) */   
298 /*   25 Reserved (corresponding integer value used by ISO for MLPP) */   
299 /*   26 Reserved (corresponding integer value used by ISO for MLPP) */   
300   {  27, "ccnrRequest" },
301   {  28, "ccCancel" },
302   {  29, "ccExecPossible" },
303   {  30, "ccPathReserve" },
304   {  31, "ccRingout" },
305   {  32, "ccSuspend" },
306   {  33, "ccResume" },
307   {  34, "callOfferRequest" },
308   {  35, "doNotDisturbActivateQ" },
309   {  36, "doNotDisturbDeactivateQ" },
310   {  37, "doNotDisturbInterrogateQ" },
311   {  38, "doNotDisturbOverrideQ" },
312   {  39, "doNotDisturbOvrExecuteQ" },
313   {  40, "ccbsRequest" },
314   {  41, "pathRetain" },        /* common for QSIG-CO, QSIG-DND(O), QSIG-CI */
315   {  42, "serviceAvailable" },  /* common for QSIG-CO, QSIG-DND(O), QSIG-CI */
316   {  43, "callIntrusionRequest" },
317   {  44, "callIntrusionGetCIPL" },
318   {  45, "callIntrusionIsolate" },
319   {  46, "callIntrusionForcedRelease" },
320   {  47, "callIntrusionWOBRequest" },
321   {  48, "callIntrusionCompleted" },
322   {  49, "cfbOverride" },       /* common for QSIG-CO, QSIG-CI */
323   {  50, "locUpdate" },
324   {  51, "locDelete" },
325   {  52, "locDeReg" },
326   {  53, "pisnEnquiry" },
327   {  54, "wtmiEnquiry" },
328   {  55, "wtmiDivert" },
329   {  56, "wtmiInform" },
330   {  57, "recallAlerting" },
331   {  58, "recallAnswered" },
332   {  59, "chargeRequest" },
333   {  60, "getFinalCharge" },
334   {  61, "aocFinal" },
335   {  62, "aocInterim" },
336   {  63, "aocRate" },
337   {  64, "aocComplete" },
338   {  65, "aocDivChargeReq" },
339   {  66, "cintLegInformation1" },
340   {  67, "cintLegInformation2" },
341   {  68, "cintCondition" },
342   {  69, "cintDisable" },
343   {  70, "cintEnable" },
344   {  71, "wtmoCall" },
345   {  72, "authWtmUser" },
346   {  73, "getWtatParam" },
347   {  74, "wtatParamEnq" },
348   {  75, "getWtanParam" },
349   {  76, "wtanParamEnq" },
350   {  77, "transferAuthParam" },
351   {  78, "synchronizationRequest" },
352   {  79, "synchronizationInfo" },
353   {  80, "mwiActivate/mCMNewMsg" },        /* common for QSIG-MWI, QSIG-MCM */
354   {  81, "mwiDeactivate/mCMNoNewMsg" },    /* common for QSIG-MWI, QSIG-MCM */
355   {  82, "mwiInterrogate/mCMUpdateReq" },  /* common for QSIG-MWI, QSIG-MCM */
356 /*   83 Reserved (corresponding integer value used by ISO for RRC)      ISO/IEC 13241 */
357   {  84, "cmnRequest" },
358   {  85, "cmnInform" },
359   {  86, "pathReplaceInvite" },
360   {  87, "callInterruptionRequest" },
361   {  88, "callProtectionRequest" },
362   {  89, "pumRegistr" },
363   {  90, "pumDelReg" },
364   {  91, "pumDe-reg" },
365   {  92, "pumInterrog" },
366   {  93, "pumiEnquiry" },
367   {  94, "pumiDivert" },
368   {  95, "pumiInform" },
369   {  96, "pumoCall" },
370   {  97, "getRRCInf" },
371   {  98, "locInfoCheck" },
372   {  99, "ssctInitiate" },
373   { 100, "ssctSetup" },
374   { 101, "ssctPostDial" },
375   { 102, "ssctDigitInfo" },
376   { 103, "display" },
377   { 104, "keypad" },
378   { 105, "callIdentificationAssign" },
379   { 106, "callIdentificationUpdate" },
380   { 107, "smsSubmit" },
381   { 108, "smsDeliver" },
382   { 109, "smsStatusReport" },
383   { 110, "smsCommand" },
384   { 111, "scAlert" },
385   { 112, "mCRequest" },
386   { 113, "mCAlerting" },
387   { 114, "mCInform" },
388   { 115, "mCMUpdate" },
389   { 116, "mCMService" },
390   { 117, "mCMInterrogate" },
391   { 118, "mCMailboxFull" },
392   { 119, "mIDMailboxAuth" },
393   { 120, "mIDMailboxID" },
394   {   0, NULL}
395 };
396                      
397 typedef struct _qsig_op_t {
398   gint32 opcode;
399   new_dissector_t arg_pdu;
400   new_dissector_t res_pdu;
401 } qsig_op_t;
402
403 /* Initialize the protocol and registered fields */
404 int proto_qsig = -1;
405 static int hf_qsig_operation = -1;
406 static int hf_qsig_service = -1;
407 static int hf_qsig_ie_type = -1;
408 static int hf_qsig_ie_type_cs4 = -1;
409 static int hf_qsig_ie_type_cs5 = -1;
410 static int hf_qsig_ie_len = -1;
411 static int hf_qsig_ie_data = -1;
412 static int hf_qsig_tc = -1;
413 static int hf_qsig_pc = -1;
414 #include "packet-qsig-hf.c"
415
416 static int *hf_qsig_ie_type_arr[] = {
417   NULL,
418   NULL,
419   NULL,
420   NULL,
421   &hf_qsig_ie_type_cs4,
422   &hf_qsig_ie_type_cs5,
423   NULL,
424   NULL,
425 };
426
427 /* Initialize the subtree pointers */
428 static gint ett_qsig = -1;
429 static gint ett_qsig_ie = -1;
430 #include "packet-qsig-ett.c"
431
432 /* Preferences */
433
434 /* Subdissectors */
435 static dissector_handle_t data_handle = NULL; 
436
437 /* Gloabl variables */
438
439
440 #include "packet-qsig-fn.c"
441
442 static const qsig_op_t qsig_tab[] = {
443   /*   0 */ {   0, dissect_NameArg_PDU, NULL },
444   /*   1 */ {   1, dissect_NameArg_PDU, NULL },
445   /*   2 */ {   2, dissect_NameArg_PDU, NULL },
446   /*   3 */ {   3, dissect_NameArg_PDU, NULL },
447   /*   4 */ {   4, NULL, NULL },
448   /*   5 */ {   5, NULL, NULL },
449   /*   6 */ {   6, NULL, NULL },
450   /*   7 */ {   7, NULL, NULL },
451   /*   8 */ {   8, NULL, NULL },
452   /*   9 */ {   9, NULL, NULL },
453   /*  10 */ {  10, NULL, NULL },
454   /*  11 */ {  11, NULL, NULL },
455   /*  12 */ {  12, NULL, NULL },
456   /*  13 */ {  13, NULL, NULL },
457   /*  14 */ {  14, NULL, NULL },
458   /*  15 */ {  15, dissect_ARG_activateDiversionQ_PDU, dissect_RES_activateDiversionQ_PDU },
459   /*  16 */ {  16, dissect_ARG_deactivateDiversionQ_PDU, dissect_RES_deactivateDiversionQ_PDU },
460   /*  17 */ {  17, dissect_ARG_interrogateDiversionQ_PDU, dissect_IntResultList_PDU },
461   /*  18 */ {  18, dissect_ARG_checkRestriction_PDU, dissect_RES_checkRestriction_PDU },
462   /*  19 */ {  19, dissect_ARG_callRerouteing_PDU, dissect_RES_callRerouteing_PDU },
463   /*  20 */ {  20, dissect_ARG_divertingLegInformation1_PDU, NULL },
464   /*  21 */ {  21, dissect_ARG_divertingLegInformation2_PDU, NULL },
465   /*  22 */ {  22, dissect_ARG_divertingLegInformation3_PDU, NULL },
466   /*  23 */ {  23, dissect_ARG_cfnrDivertedLegFailed_PDU, NULL },
467   /*  27 */ {  27, NULL, NULL },
468   /*  28 */ {  28, NULL, NULL },
469   /*  29 */ {  29, NULL, NULL },
470   /*  30 */ {  30, NULL, NULL },
471   /*  31 */ {  31, NULL, NULL },
472   /*  32 */ {  32, NULL, NULL },
473   /*  33 */ {  33, NULL, NULL },
474   /*  34 */ {  34, NULL, NULL },
475   /*  35 */ {  35, NULL, NULL },
476   /*  36 */ {  36, NULL, NULL },
477   /*  37 */ {  37, NULL, NULL },
478   /*  38 */ {  38, NULL, NULL },
479   /*  39 */ {  39, NULL, NULL },
480   /*  40 */ {  40, NULL, NULL },
481   /*  41 */ {  41, NULL, NULL },
482   /*  42 */ {  42, NULL, NULL },
483   /*  43 */ {  43, NULL, NULL },
484   /*  44 */ {  44, NULL, NULL },
485   /*  45 */ {  45, NULL, NULL },
486   /*  46 */ {  46, NULL, NULL },
487   /*  47 */ {  47, NULL, NULL },
488   /*  48 */ {  48, NULL, NULL },
489   /*  49 */ {  49, NULL, NULL },
490   /*  50 */ {  50, NULL, NULL },
491   /*  51 */ {  51, NULL, NULL },
492   /*  52 */ {  52, NULL, NULL },
493   /*  53 */ {  53, NULL, NULL },
494   /*  54 */ {  54, NULL, NULL },
495   /*  55 */ {  55, NULL, NULL },
496   /*  56 */ {  56, NULL, NULL },
497   /*  57 */ {  57, NULL, NULL },
498   /*  58 */ {  58, NULL, NULL },
499   /*  59 */ {  59, NULL, NULL },
500   /*  60 */ {  60, NULL, NULL },
501   /*  61 */ {  61, NULL, NULL },
502   /*  62 */ {  62, NULL, NULL },
503   /*  63 */ {  63, NULL, NULL },
504   /*  64 */ {  64, NULL, NULL },
505   /*  65 */ {  65, NULL, NULL },
506   /*  66 */ {  66, NULL, NULL },
507   /*  67 */ {  67, NULL, NULL },
508   /*  68 */ {  68, NULL, NULL },
509   /*  69 */ {  69, NULL, NULL },
510   /*  70 */ {  70, NULL, NULL },
511   /*  71 */ {  71, NULL, NULL },
512   /*  72 */ {  72, NULL, NULL },
513   /*  73 */ {  73, NULL, NULL },
514   /*  74 */ {  74, NULL, NULL },
515   /*  75 */ {  75, NULL, NULL },
516   /*  76 */ {  76, NULL, NULL },
517   /*  77 */ {  77, NULL, NULL },
518   /*  78 */ {  78, NULL, NULL },
519   /*  79 */ {  79, NULL, NULL },
520   /*  80 */ {  80, NULL, NULL },
521   /*  81 */ {  81, NULL, NULL },
522   /*  82 */ {  82, NULL, NULL },
523   /*  84 */ {  84, NULL, NULL },
524   /*  85 */ {  85, NULL, NULL },
525   /*  86 */ {  86, NULL, NULL },
526   /*  87 */ {  87, NULL, NULL },
527   /*  88 */ {  88, NULL, NULL },
528   /*  89 */ {  89, NULL, NULL },
529   /*  90 */ {  90, NULL, NULL },
530   /*  91 */ {  91, NULL, NULL },
531   /*  92 */ {  92, NULL, NULL },
532   /*  93 */ {  93, NULL, NULL },
533   /*  94 */ {  94, NULL, NULL },
534   /*  95 */ {  95, NULL, NULL },
535   /*  96 */ {  96, NULL, NULL },
536   /*  97 */ {  97, NULL, NULL },
537   /*  98 */ {  98, NULL, NULL },
538   /*  99 */ {  99, NULL, NULL },
539   /* 100 */ { 100, NULL, NULL },
540   /* 101 */ { 101, NULL, NULL },
541   /* 102 */ { 102, NULL, NULL },
542   /* 103 */ { 103, NULL, NULL },
543   /* 104 */ { 104, NULL, NULL },
544   /* 105 */ { 105, NULL, NULL },
545   /* 106 */ { 106, NULL, NULL },
546   /* 107 */ { 107, NULL, NULL },
547   /* 108 */ { 108, NULL, NULL },
548   /* 109 */ { 109, NULL, NULL },
549   /* 110 */ { 110, NULL, NULL },
550   /* 111 */ { 111, NULL, NULL },
551   /* 112 */ { 112, NULL, NULL },
552   /* 113 */ { 113, NULL, NULL },
553   /* 114 */ { 114, NULL, NULL },
554   /* 115 */ { 115, NULL, NULL },
555   /* 116 */ { 116, NULL, NULL },
556   /* 117 */ { 117, NULL, NULL },
557   /* 118 */ { 118, NULL, NULL },
558   /* 119 */ { 119, NULL, NULL },
559   /* 120 */ { 120, NULL, NULL },
560 };                                 
561
562 static const qsig_op_t *get_op(gint32 opcode) {
563   int i;
564
565   /* search from the end to get the last occurence if the operation is redefined in some newer specification */
566   for (i = array_length(qsig_tab) - 1; i >= 0; i--)
567     if (qsig_tab[i].opcode == opcode)
568       return &qsig_tab[i];
569   return NULL;
570 }
571
572 static gint32 get_service(gint32 opcode) {
573   if ((opcode <0) || (opcode >= array_length(op2srv_tab)))
574     return NULL;
575   return op2srv_tab[opcode];
576 }
577                   
578 /*--- dissect_qsig_arg ------------------------------------------------------*/
579 static int   
580 dissect_qsig_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
581   int offset;
582   rose_ctx_t *rctx;
583   gint32 opcode, service;
584   const qsig_op_t *op_ptr;
585   const gchar *p;
586   proto_item *ti, *ti_tmp;
587   proto_tree *qsig_tree;
588
589   offset = 0;
590   rctx = get_rose_ctx(pinfo->private_data);
591   DISSECTOR_ASSERT(rctx);
592   if (rctx->d.pdu != 1)  /* invoke */
593     return offset; 
594   if (rctx->d.code != 0)  /* local */
595     return offset; 
596   opcode = rctx->d.code_local;
597   op_ptr = get_op(opcode);
598   if (!op_ptr)
599     return offset; 
600   service = get_service(opcode);
601
602   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
603   qsig_tree = proto_item_add_subtree(ti, ett_qsig); 
604
605   proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
606   p = match_strval(opcode, VALS(qsig_str_operation));
607   if (p) {
608     proto_item_append_text(ti, ": %s", p);
609     proto_item_append_text(rctx->d.code_item, " - %s", p);
610     if (rctx->apdu_depth >= 0)
611       proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
612   }
613
614   ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
615   p = match_strval(service, VALS(qsig_str_service_name));
616   if (p) proto_item_append_text(ti_tmp, " - %s", p);
617
618   if (op_ptr->arg_pdu)
619     offset = op_ptr->arg_pdu(tvb, pinfo, qsig_tree);
620   else 
621     if (tvb_length_remaining(tvb, offset) > 0) {
622       proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ARGUMENT TYPE (QSIG)");
623       offset += tvb_length_remaining(tvb, offset);
624     }
625
626   return offset;
627 }
628
629 /*--- dissect_qsig_res -------------------------------------------------------*/
630 static int
631 dissect_qsig_res(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
632   gint offset;
633   rose_ctx_t *rctx;
634   gint32 opcode, service;
635   const qsig_op_t *op_ptr;
636   const gchar *p;
637   proto_item *ti, *ti_tmp;
638   proto_tree *qsig_tree;
639
640   offset = 0;
641   rctx = get_rose_ctx(pinfo->private_data);
642   DISSECTOR_ASSERT(rctx);
643   if (rctx->d.pdu != 2)  /* returnResult */
644     return offset; 
645   if (rctx->d.code != 0)  /* local */
646     return offset; 
647   opcode = rctx->d.code_local;
648   op_ptr = get_op(opcode);
649   if (!op_ptr)
650     return offset; 
651   service = get_service(opcode);
652
653   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
654   qsig_tree = proto_item_add_subtree(ti, ett_qsig); 
655
656   proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
657   p = match_strval(opcode, VALS(qsig_str_operation));
658   if (p) {
659     proto_item_append_text(ti, ": %s", p);
660     proto_item_append_text(rctx->d.code_item, " - %s", p);
661     if (rctx->apdu_depth >= 0)
662       proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
663   }
664
665   ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
666   p = match_strval(service, VALS(qsig_str_service_name));
667   if (p) proto_item_append_text(ti_tmp, " - %s", p);
668
669   if (op_ptr->res_pdu)
670     offset = op_ptr->res_pdu(tvb, pinfo, qsig_tree);
671   else 
672     if (tvb_length_remaining(tvb, offset) > 0) {
673       proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED RESULT TYPE (QSIG)");
674       offset += tvb_length_remaining(tvb, offset);
675     }
676
677   return offset;
678 }
679
680 /*--- dissect_qsig_transit_counter_ie ---------------------------------------*/
681 static int
682 dissect_qsig_transit_counter_ie(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length  _U_) {
683   proto_tree_add_item(tree, hf_qsig_tc, tvb, offset, 1, FALSE);
684   offset++;
685   return offset;
686 }
687 /*--- dissect_qsig_party_category_ie ----------------------------------------*/
688 static int 
689 dissect_qsig_party_category_ie(tvbuff_t *tvb, int offset, packet_info *pinfo  _U_, proto_tree *tree, int length  _U_) {
690   proto_tree_add_item(tree, hf_qsig_pc, tvb, offset, 1, FALSE);
691   offset++;
692   return offset;
693 }
694
695 /*--- dissect_qsig_ie -------------------------------------------------------*/
696 static void
697 dissect_qsig_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int codeset) {
698   gint offset;
699   proto_item *ti, *ti_ie;
700   proto_tree *ie_tree;
701   guint8 ie_type, ie_len;
702
703   offset = 0;
704
705   ti = proto_tree_add_item_hidden(tree, proto_qsig, tvb, offset, -1, FALSE);
706
707   ie_type = tvb_get_guint8(tvb, offset);
708   ie_len = tvb_get_guint8(tvb, offset + 1);
709
710   ti_ie = proto_tree_add_text(tree, tvb, offset, -1, "%s",
711             val_to_str(ie_type, VALS(qsig_str_ie_type[codeset]), "unknown (0x%02X)"));
712   ie_tree = proto_item_add_subtree(ti_ie, ett_qsig_ie); 
713   proto_tree_add_item(ie_tree, *hf_qsig_ie_type_arr[codeset], tvb, offset, 1, FALSE);
714   proto_tree_add_item_hidden(ie_tree, hf_qsig_ie_type, tvb, offset, 1, FALSE);
715   proto_tree_add_item(ie_tree, hf_qsig_ie_len, tvb, offset + 1, 1, FALSE);
716   offset += 2;
717   if (tvb_length_remaining(tvb, offset) <= 0)
718     return;
719   switch ((codeset << 8) | ie_type) {
720     case CS4 | QSIG_IE_TRANSIT_COUNTER :
721       dissect_qsig_transit_counter_ie(tvb, offset, pinfo, ie_tree, ie_len);
722       break;
723     case CS5 | QSIG_IE_PARTY_CATEGORY :
724       dissect_qsig_party_category_ie(tvb, offset, pinfo, ie_tree, ie_len);
725       break;
726     default:
727       if (ie_len > 0) {
728         if (tree) proto_tree_add_item(ie_tree, hf_qsig_ie_data, tvb, offset, ie_len, FALSE);
729       }
730   }
731 }
732 /*--- dissect_qsig_ie_cs4 ---------------------------------------------------*/
733 static void
734 dissect_qsig_ie_cs4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
735   dissect_qsig_ie(tvb, pinfo, tree, 4);
736 }
737 /*--- dissect_qsig_ie_cs5 ---------------------------------------------------*/
738 static void
739 dissect_qsig_ie_cs5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
740   dissect_qsig_ie(tvb, pinfo, tree, 5);
741 }
742
743 /*--- proto_register_qsig ---------------------------------------------------*/
744 void proto_register_qsig(void) {
745
746   /* List of fields */
747   static hf_register_info hf[] = {
748     { &hf_qsig_operation, { "Operation", "qsig.operation",
749                            FT_UINT8, BASE_DEC, VALS(qsig_str_operation), 0x0,
750                            "Operation", HFILL }},
751     { &hf_qsig_service,   { "Service", "qsig.service",
752                            FT_UINT8, BASE_DEC, VALS(qsig_str_service), 0x0,
753                            "Supplementary Service", HFILL }},
754     { &hf_qsig_ie_type, { "Type", "qsig.ie.type",
755                           FT_UINT8, BASE_HEX, NULL, 0x0,
756                           "Information Element Type", HFILL }},
757     { &hf_qsig_ie_type_cs4, { "Type", "qsig.ie.type.cs4",
758                           FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs4), 0x0,
759                           "Information Element Type (Codeset 4)", HFILL }},
760     { &hf_qsig_ie_type_cs5, { "Type", "qsig.ie.type.cs5",
761                           FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs5), 0x0,
762                           "Information Element Type (Codeset 5)", HFILL }},
763     { &hf_qsig_ie_len,  { "Length", "qsig.ie.len",
764                           FT_UINT8, BASE_DEC, NULL, 0x0,
765                           "Information Element Length", HFILL }},
766     { &hf_qsig_ie_data, { "Data", "qsig.ie.data",
767                           FT_BYTES, BASE_HEX, NULL, 0x0,
768                           "Data", HFILL }},
769     { &hf_qsig_tc,      { "Transit count", "qsig.tc",
770                           FT_UINT8, BASE_DEC, NULL, 0x1F,
771                           "Transit count", HFILL }},
772     { &hf_qsig_pc,      { "Party category", "qsig.pc",
773                           FT_UINT8, BASE_HEX, VALS(qsig_str_pc), 0x07,
774                           "Party category", HFILL }},
775 #include "packet-qsig-hfarr.c"
776   };
777
778   /* List of subtrees */
779   static gint *ett[] = {
780     &ett_qsig,
781     &ett_qsig_ie,
782 #include "packet-qsig-ettarr.c"
783   };
784
785   /* Register protocol and dissector */
786   proto_qsig = proto_register_protocol(PNAME, PSNAME, PFNAME);
787
788   /* Register fields and subtrees */
789   proto_register_field_array(proto_qsig, hf, array_length(hf));
790   proto_register_subtree_array(ett, array_length(ett));
791
792 }
793
794
795 /*--- proto_reg_handoff_qsig ------------------------------------------------*/
796 void proto_reg_handoff_qsig(void) {
797   int i;
798   dissector_handle_t qsig_arg_handle;
799   dissector_handle_t qsig_res_handle;
800   dissector_handle_t qsig_ie_handle;
801
802   data_handle = find_dissector("data");
803
804   if (find_dissector_table("q932.ros.local.arg")) {
805     qsig_arg_handle = new_create_dissector_handle(dissect_qsig_arg, proto_qsig);
806     qsig_res_handle = new_create_dissector_handle(dissect_qsig_res, proto_qsig);
807     for (i=0; i<array_length(qsig_tab); i++) {
808       dissector_add("q932.ros.local.arg", qsig_tab[i].opcode, qsig_arg_handle);
809       dissector_add("q932.ros.local.res", qsig_tab[i].opcode, qsig_res_handle);
810     }
811   }
812
813   qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs4, proto_qsig);
814   /* QSIG-TC - Transit counter */
815   dissector_add("q931.ie", CS4 | QSIG_IE_TRANSIT_COUNTER, qsig_ie_handle);
816
817   qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs5, proto_qsig);
818   /* SSIG-BC - Party category */
819   dissector_add("q931.ie", CS5 | QSIG_IE_PARTY_CATEGORY, qsig_ie_handle);
820
821 }
822
823 /*---------------------------------------------------------------------------*/