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