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