Convert 'encoding' parameter of certain proto_tree_add_item() calls in asn1 dissectors:
[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/strutil.h>
32 #include <epan/asn1.h>
33
34 #include "packet-ber.h"
35 #include "packet-qsig.h"
36
37 #define PNAME  "QSIG"
38 #define PSNAME "QSIG"
39 #define PFNAME "qsig"
40
41 /* Shifted codeset values */
42 #define CS0 0x000
43 #define CS1 0x100
44 #define CS2 0x200
45 #define CS3 0x300
46 #define CS4 0x400
47 #define CS5 0x500
48 #define CS6 0x600
49 #define CS7 0x700
50
51 #define QSIG_IE_TRANSIT_COUNTER 0x31
52 #define QSIG_IE_PARTY_CATEGORY  0x32
53
54 static const value_string qsig_str_ie_type_cs4[] = {
55   { QSIG_IE_TRANSIT_COUNTER , "Transit counter" },
56   { 0, NULL}
57 };
58 static const value_string qsig_str_ie_type_cs5[] = {
59   { QSIG_IE_PARTY_CATEGORY  , "Party category" },
60   { 0, NULL}
61 };
62 /* Codeset array */
63 static const value_string *qsig_str_ie_type[] = {
64   NULL,
65   NULL,
66   NULL,
67   NULL,
68   qsig_str_ie_type_cs4,
69   qsig_str_ie_type_cs5,
70   NULL,
71   NULL,
72 };
73
74
75 static const value_string qsig_str_pc[] = {
76   { 0x00 , "unknown" },
77   { 0x01 , "extension" },
78   { 0x02 , "operator" },
79   { 0x03 , "emergency extension" },
80   { 0, NULL}
81 };
82
83 static const value_string qsig_str_service[] = {
84   { 13868, "QSIG-NA" },
85   { 13873, "QSIG-CF" },
86   { 13874, "QSIG-PR" },
87   { 13869, "QSIG-CT" },
88   { 13870, "QSIG-CC" },
89   { 14843, "QSIG-CO" },
90   { 14844, "QSIG-DND(O)" },
91   { 14846, "QSIG-CI" },
92   { 15050, "QSIG-AOC" },
93   { 15052, "QSIG-RE" },
94   { 15054, "QSIG-CINT" },
95   { 15506, "QSIG-MWI" },
96   { 15507, "SYNC-SIG" },
97   { 15772, "QSIG-CMN" },
98   { 15992, "QSIG-CPI(P)" },
99   { 17876, "QSIG-PUMR" },
100   { 17878, "QSIG-PUMCH" },
101   { 19460, "QSIG-SSCT" },
102   { 15429, "QSIG-WTMLR" },
103   { 15431, "QSIG-WTMCH" },
104   { 15433, "QSIG-WTMAU" },
105   { 21407, "QSIG-SD" },
106   { 21889, "QSIG-CIDL" },
107   {   325, "QSIG-SMS" },
108   {   344, "QSIG-MCR" },
109   {  3471, "QSIG-MCM" },
110   {  3472, "QSIG-MID" },
111   {   0, NULL}
112 };
113
114 static const value_string qsig_str_service_name[] = {
115   { 13868, "Name-Operations" },
116   { 13873, "Call-Diversion-Operations" },
117   { 13874, "Path-Replacement-Operations" },
118   { 13869, "Call-Transfer-Operations" },
119   { 13870, "SS-CC-Operations" },
120   { 14843, "Call-Offer-Operations" },
121   { 14844, "Do-Not-Disturb-Operations" },
122   { 14846, "Call-Intrusion-Operations" },
123   { 15050, "SS-AOC-Operation" },
124   { 15052, "Recall-Operation" },
125   { 15054, "Call-Interception-Operations" },
126   { 15506, "SS-MWI-Operations" },
127   { 15507, "Synchronization-Operations" },
128   { 15772, "Common-Information-Operations" },
129   { 15992, "Call-Interruption-Operation" },
130   { 17876, "PUM-Registration-Operation" },
131   { 17878, "Private-User-Mobility-Call-Handling-Operations" },
132   { 19460, "Single-Step-Call-Transfer-Operations" },
133   { 15429, "WTM-Location-Registration-Operations" },
134   { 15431, "Wireless-Terminal-Call-Handling-Operations" },
135   { 15433, "WTM-Authentication-Operations" },
136   { 21407, "SS-SD-Operations" },
137   { 21889, "Call-Identification-and-Call-Linkage-Operations" },
138   {   325, "Short-Message-Service-Operations" },
139   {   344, "SS-MCR-Operations" },
140   {  3471, "SS-MCM-Operations" },
141   {  3472, "SS-MID-Operations" },
142   {   0, NULL}
143 };
144
145 #define NO_SRV (-1)
146 static const gint32 op2srv_tab[] = {
147   /*   0 */ 13868,
148   /*   1 */ 13868,
149   /*   2 */ 13868,
150   /*   3 */ 13868,
151   /*   4 */ 13874,
152   /*   5 */ 13874,
153   /*   6 */ 13874,
154   /*   7 */ 13869,
155   /*   8 */ 13869,
156   /*   9 */ 13869,
157   /*  10 */ 13869,
158   /*  11 */ 13869,
159   /*  12 */ 13869,
160   /*  13 */ 13869,
161   /*  14 */ 13869,
162   /*  15 */ 13873,
163   /*  16 */ 13873,
164   /*  17 */ 13873,
165   /*  18 */ 13873,
166   /*  19 */ 13873,
167   /*  20 */ 13873,
168   /*  21 */ 13873,
169   /*  22 */ 13873,
170   /*  23 */ 13873,
171   /*  24 */ NO_SRV,
172   /*  25 */ NO_SRV,
173   /*  26 */ NO_SRV,
174   /*  27 */ 13870,
175   /*  28 */ 13870,
176   /*  29 */ 13870,
177   /*  30 */ 13870,
178   /*  31 */ 13870,
179   /*  32 */ 13870,
180   /*  33 */ 13870,
181   /*  34 */ 14843,
182   /*  35 */ 14844,
183   /*  36 */ 14844,
184   /*  37 */ 14844,
185   /*  38 */ 14844,
186   /*  39 */ 14844,
187   /*  40 */ 13870,
188   /*  41 */ 90001,
189   /*  42 */ 90001,
190   /*  43 */ 14846,
191   /*  44 */ 14846,
192   /*  45 */ 14846,
193   /*  46 */ 14846,
194   /*  47 */ 14846,
195   /*  48 */ 14846,
196   /*  49 */ 90001,
197   /*  50 */ 15429,
198   /*  51 */ 15429,
199   /*  52 */ 15429,
200   /*  53 */ 15429,
201   /*  54 */ 15431,
202   /*  55 */ 15431,
203   /*  56 */ 15431,
204   /*  57 */ 15052,
205   /*  58 */ 15052,
206   /*  59 */ 15050,
207   /*  60 */ 15050,
208   /*  61 */ 15050,
209   /*  62 */ 15050,
210   /*  63 */ 15050,
211   /*  64 */ 15050,
212   /*  65 */ 15050,
213   /*  66 */ 15054,
214   /*  67 */ 15054,
215   /*  68 */ 15054,
216   /*  69 */ 15054,
217   /*  70 */ 15054,
218   /*  71 */ 15431,
219   /*  72 */ 15433,
220   /*  73 */ 15433,
221   /*  74 */ 15433,
222   /*  75 */ 15433,
223   /*  76 */ 15433,
224   /*  77 */ 15433,
225   /*  78 */ 15507,
226   /*  79 */ 15507,
227   /*  80 */  3471,
228   /*  81 */  3471,
229   /*  82 */  3471,
230   /*  83 */ NO_SRV,
231   /*  84 */ 15772,
232   /*  85 */ 15772,
233   /*  86 */ 13874,
234   /*  87 */ 15992,
235   /*  88 */ 15992,
236   /*  89 */ 17876,
237   /*  90 */ 17876,
238   /*  91 */ 17876,
239   /*  92 */ 17876,
240   /*  93 */ 17878,
241   /*  94 */ 17878,
242   /*  95 */ 17878,
243   /*  96 */ 17878,
244   /*  97 */ 15429,
245   /*  98 */ 15429,
246   /*  99 */ 19460,
247   /* 100 */ 19460,
248   /* 101 */ 19460,
249   /* 102 */ 19460,
250   /* 103 */ 21407,
251   /* 104 */ 21407,
252   /* 105 */ 21889,
253   /* 106 */ 21889,
254   /* 107 */   325,
255   /* 108 */   325,
256   /* 109 */   325,
257   /* 110 */   325,
258   /* 111 */   325,
259   /* 112 */   344,
260   /* 113 */   344,
261   /* 114 */   344,
262   /* 115 */  3471,
263   /* 116 */  3471,
264   /* 117 */  3471,
265   /* 118 */  3471,
266   /* 119 */  3472,
267   /* 120 */  3472,
268 };
269
270 static const value_string qsig_str_operation[] = {
271 #include "packet-qsig-table10.c"
272   {   0, NULL}
273 };
274
275 static const value_string qsig_str_error[] = {
276 #include "packet-qsig-table20.c"
277   {   0, NULL}
278 };
279
280 /* Initialize the protocol and registered fields */
281 static int proto_qsig = -1;
282 static int hf_qsig_operation = -1;
283 static int hf_qsig_service = -1;
284 static int hf_qsig_error = -1;
285 static int hf_qsig_ie_type = -1;
286 static int hf_qsig_ie_type_cs4 = -1;
287 static int hf_qsig_ie_type_cs5 = -1;
288 static int hf_qsig_ie_len = -1;
289 static int hf_qsig_ie_data = -1;
290 static int hf_qsig_tc = -1;
291 static int hf_qsig_pc = -1;
292 #include "packet-qsig-hf.c"
293
294 static int *hf_qsig_ie_type_arr[] = {
295   NULL,
296   NULL,
297   NULL,
298   NULL,
299   &hf_qsig_ie_type_cs4,
300   &hf_qsig_ie_type_cs5,
301   NULL,
302   NULL,
303 };
304
305 /* Initialize the subtree pointers */
306 static gint ett_qsig = -1;
307 static gint ett_qsig_ie = -1;
308 static gint ett_qsig_unknown_extension = -1;
309 #include "packet-qsig-ett.c"
310 static gint ett_cnq_PSS1InformationElement = -1;
311
312 /* Preferences */
313
314 /* Subdissectors */
315 static dissector_handle_t q931_ie_handle = NULL;
316
317 /* Global variables */
318 static const char *extension_oid = NULL;
319 static GHashTable *qsig_opcode2oid_hashtable = NULL;
320 static GHashTable *qsig_oid2op_hashtable = NULL;
321
322 /* Dissector tables */
323 static dissector_table_t extension_dissector_table;
324
325 #include "packet-qsig-fn.c"
326
327 typedef struct _qsig_op_t {
328   gint32 opcode;
329   new_dissector_t arg_pdu;
330   new_dissector_t res_pdu;
331 } qsig_op_t;
332
333 static const qsig_op_t qsig_op_tab[] = {
334 #include "packet-qsig-table11.c"
335 };
336
337 typedef struct _qsig_err_t {
338   gint32 errcode;
339   new_dissector_t err_pdu;
340 } qsig_err_t;
341
342 static const qsig_err_t qsig_err_tab[] = {
343 #include "packet-qsig-table21.c"
344 };
345
346 static const qsig_op_t *get_op(gint32 opcode) {
347   int i;
348
349   /* search from the end to get the last occurence if the operation is redefined in some newer specification */
350   for (i = array_length(qsig_op_tab) - 1; i >= 0; i--)
351     if (qsig_op_tab[i].opcode == opcode)
352       return &qsig_op_tab[i];
353   return NULL;
354 }
355
356 static gint32 get_service(gint32 opcode) {
357   if ((opcode < 0) || (opcode >= (int)array_length(op2srv_tab)))
358     return NO_SRV;
359   return op2srv_tab[opcode];
360 }
361
362 static const qsig_err_t *get_err(gint32 errcode) {
363   int i;
364
365   /* search from the end to get the last occurence if the operation is redefined in some newer specification */
366   for (i = array_length(qsig_err_tab) - 1; i >= 0; i--)
367     if (qsig_err_tab[i].errcode == errcode)
368       return &qsig_err_tab[i];
369   return NULL;
370 }
371
372 /*--- dissect_qsig_arg ------------------------------------------------------*/
373 static int
374 dissect_qsig_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
375   int offset;
376   rose_ctx_t *rctx;
377   gint32 opcode = 0, service;
378   const qsig_op_t *op_ptr;
379   const gchar *p;
380   proto_item *ti, *ti_tmp;
381   proto_tree *qsig_tree;
382
383   offset = 0;
384   rctx = get_rose_ctx(pinfo->private_data);
385   DISSECTOR_ASSERT(rctx);
386   if (rctx->d.pdu != 1)  /* invoke */
387     return offset;
388   if (rctx->d.code == 0) {  /* local */
389     opcode = rctx->d.code_local;
390     op_ptr = get_op(opcode);
391   } else if (rctx->d.code == 1) {  /* global */
392     op_ptr = g_hash_table_lookup(qsig_oid2op_hashtable, rctx->d.code_global);
393     if (op_ptr) opcode = op_ptr->opcode;
394   } else {
395     return offset;
396   }
397   if (!op_ptr)
398     return offset;
399   service = get_service(opcode);
400
401   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
402   qsig_tree = proto_item_add_subtree(ti, ett_qsig);
403
404   proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
405   p = match_strval(opcode, VALS(qsig_str_operation));
406   if (p) {
407     proto_item_append_text(ti, ": %s", p);
408     proto_item_append_text(rctx->d.code_item, " - %s", p);
409     if (rctx->apdu_depth >= 0)
410       proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
411   }
412
413   ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
414   p = match_strval(service, VALS(qsig_str_service_name));
415   if (p) proto_item_append_text(ti_tmp, " - %s", p);
416
417   if (op_ptr->arg_pdu)
418     offset = op_ptr->arg_pdu(tvb, pinfo, qsig_tree);
419   else
420     if (tvb_length_remaining(tvb, offset) > 0) {
421       proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ARGUMENT TYPE (QSIG)");
422       offset += tvb_length_remaining(tvb, offset);
423     }
424
425   return offset;
426 }
427
428 /*--- dissect_qsig_res -------------------------------------------------------*/
429 static int
430 dissect_qsig_res(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
431   gint offset;
432   rose_ctx_t *rctx;
433   gint32 opcode, service;
434   const qsig_op_t *op_ptr;
435   const gchar *p;
436   proto_item *ti, *ti_tmp;
437   proto_tree *qsig_tree;
438
439   offset = 0;
440   rctx = get_rose_ctx(pinfo->private_data);
441   DISSECTOR_ASSERT(rctx);
442   if (rctx->d.pdu != 2)  /* returnResult */
443     return offset;
444   if (rctx->d.code != 0)  /* local */
445     return offset;
446   opcode = rctx->d.code_local;
447   op_ptr = get_op(opcode);
448   if (!op_ptr)
449     return offset;
450   service = get_service(opcode);
451
452   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
453   qsig_tree = proto_item_add_subtree(ti, ett_qsig);
454
455   proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
456   p = match_strval(opcode, VALS(qsig_str_operation));
457   if (p) {
458     proto_item_append_text(ti, ": %s", p);
459     proto_item_append_text(rctx->d.code_item, " - %s", p);
460     if (rctx->apdu_depth >= 0)
461       proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
462   }
463
464   ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
465   p = match_strval(service, VALS(qsig_str_service_name));
466   if (p) proto_item_append_text(ti_tmp, " - %s", p);
467
468   if (op_ptr->res_pdu)
469     offset = op_ptr->res_pdu(tvb, pinfo, qsig_tree);
470   else
471     if (tvb_length_remaining(tvb, offset) > 0) {
472       proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED RESULT TYPE (QSIG)");
473       offset += tvb_length_remaining(tvb, offset);
474     }
475
476   return offset;
477 }
478
479 /*--- dissect_qsig_err ------------------------------------------------------*/
480 static int
481 dissect_qsig_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
482   int offset;
483   rose_ctx_t *rctx;
484   gint32 errcode;
485   const qsig_err_t *err_ptr;
486   const gchar *p;
487   proto_item *ti;
488   proto_tree *qsig_tree;
489
490   offset = 0;
491   rctx = get_rose_ctx(pinfo->private_data);
492   DISSECTOR_ASSERT(rctx);
493   if (rctx->d.pdu != 3)  /* returnError */
494     return offset;
495   if (rctx->d.code != 0)  /* local */
496     return offset;
497   errcode = rctx->d.code_local;
498   err_ptr = get_err(errcode);
499   if (!err_ptr)
500     return offset;
501
502   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
503   qsig_tree = proto_item_add_subtree(ti, ett_qsig);
504
505   proto_tree_add_uint(qsig_tree, hf_qsig_error, tvb, 0, 0, errcode);
506   p = match_strval(errcode, VALS(qsig_str_error));
507   if (p) {
508     proto_item_append_text(ti, ": %s", p);
509     proto_item_append_text(rctx->d.code_item, " - %s", p);
510     if (rctx->apdu_depth >= 0)
511       proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
512   }
513
514   if (err_ptr->err_pdu)
515     offset = err_ptr->err_pdu(tvb, pinfo, qsig_tree);
516   else
517     if (tvb_length_remaining(tvb, offset) > 0) {
518       proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ERROR TYPE (QSIG)");
519       offset += tvb_length_remaining(tvb, offset);
520     }
521
522   return offset;
523 }
524
525 /*--- dissect_qsig_transit_counter_ie ---------------------------------------*/
526 static int
527 dissect_qsig_transit_counter_ie(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length  _U_) {
528   proto_tree_add_item(tree, hf_qsig_tc, tvb, offset, 1, ENC_BIG_ENDIAN);
529   offset++;
530   return offset;
531 }
532 /*--- dissect_qsig_party_category_ie ----------------------------------------*/
533 static int
534 dissect_qsig_party_category_ie(tvbuff_t *tvb, int offset, packet_info *pinfo  _U_, proto_tree *tree, int length  _U_) {
535   proto_tree_add_item(tree, hf_qsig_pc, tvb, offset, 1, ENC_BIG_ENDIAN);
536   offset++;
537   return offset;
538 }
539
540 /*--- dissect_qsig_ie -------------------------------------------------------*/
541 static void
542 dissect_qsig_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int codeset) {
543   gint offset;
544   proto_item *ti, *ti_ie, *hidden_item;
545   proto_tree *ie_tree;
546   guint8 ie_type, ie_len;
547
548   offset = 0;
549
550   ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, -1, FALSE);
551   PROTO_ITEM_SET_HIDDEN(ti);
552
553   ie_type = tvb_get_guint8(tvb, offset);
554   ie_len = tvb_get_guint8(tvb, offset + 1);
555
556   ti_ie = proto_tree_add_text(tree, tvb, offset, -1, "%s",
557             val_to_str(ie_type, VALS(qsig_str_ie_type[codeset]), "unknown (0x%02X)"));
558   ie_tree = proto_item_add_subtree(ti_ie, ett_qsig_ie);
559   proto_tree_add_item(ie_tree, *hf_qsig_ie_type_arr[codeset], tvb, offset, 1, FALSE);
560   hidden_item = proto_tree_add_item(ie_tree, hf_qsig_ie_type, tvb, offset, 1, ENC_BIG_ENDIAN);
561   PROTO_ITEM_SET_HIDDEN(hidden_item);
562   proto_tree_add_item(ie_tree, hf_qsig_ie_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
563   offset += 2;
564   if (tvb_length_remaining(tvb, offset) <= 0)
565     return;
566   switch ((codeset << 8) | ie_type) {
567     case CS4 | QSIG_IE_TRANSIT_COUNTER :
568       dissect_qsig_transit_counter_ie(tvb, offset, pinfo, ie_tree, ie_len);
569       break;
570     case CS5 | QSIG_IE_PARTY_CATEGORY :
571       dissect_qsig_party_category_ie(tvb, offset, pinfo, ie_tree, ie_len);
572       break;
573     default:
574       if (ie_len > 0) {
575         if (tree) proto_tree_add_item(ie_tree, hf_qsig_ie_data, tvb, offset, ie_len, ENC_NA);
576       }
577   }
578 }
579 /*--- dissect_qsig_ie_cs4 ---------------------------------------------------*/
580 static void
581 dissect_qsig_ie_cs4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
582   dissect_qsig_ie(tvb, pinfo, tree, 4);
583 }
584 /*--- dissect_qsig_ie_cs5 ---------------------------------------------------*/
585 static void
586 dissect_qsig_ie_cs5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
587   dissect_qsig_ie(tvb, pinfo, tree, 5);
588 }
589
590 /*--- qsig_init_tables ---------------------------------------------------------*/
591 static void qsig_init_tables(void) {
592   guint i;
593   gint opcode, *key;
594   gchar *oid;
595
596   if (qsig_opcode2oid_hashtable)
597     g_hash_table_destroy(qsig_opcode2oid_hashtable);
598   qsig_opcode2oid_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
599
600   if (qsig_oid2op_hashtable)
601     g_hash_table_destroy(qsig_oid2op_hashtable);
602   qsig_oid2op_hashtable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
603
604   /* fill-in global OIDs */
605   for (i=0; i<array_length(qsig_op_tab); i++) {
606     opcode = qsig_op_tab[i].opcode;
607     oid = g_strdup_printf("1.3.12.9.%d", opcode);
608     key = g_malloc(sizeof(gint));
609     *key = opcode;
610     g_hash_table_insert(qsig_opcode2oid_hashtable, key, oid);
611     g_hash_table_insert(qsig_oid2op_hashtable, g_strdup(oid), (gpointer)&qsig_op_tab[i]);
612   }
613
614 }
615
616 /*--- proto_register_qsig ---------------------------------------------------*/
617 void proto_register_qsig(void) {
618
619   /* List of fields */
620   static hf_register_info hf[] = {
621     { &hf_qsig_operation, { "Operation", "qsig.operation",
622                            FT_UINT8, BASE_DEC, VALS(qsig_str_operation), 0x0,
623                            NULL, HFILL }},
624     { &hf_qsig_service,   { "Service", "qsig.service",
625                            FT_UINT8, BASE_DEC, VALS(qsig_str_service), 0x0,
626                            "Supplementary Service", HFILL }},
627     { &hf_qsig_error,     { "Error", "qsig.error",
628                            FT_UINT8, BASE_DEC, VALS(qsig_str_error), 0x0,
629                            NULL, HFILL }},
630     { &hf_qsig_ie_type, { "Type", "qsig.ie.type",
631                           FT_UINT8, BASE_HEX, NULL, 0x0,
632                           "Information Element Type", HFILL }},
633     { &hf_qsig_ie_type_cs4, { "Type", "qsig.ie.type.cs4",
634                           FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs4), 0x0,
635                           "Information Element Type (Codeset 4)", HFILL }},
636     { &hf_qsig_ie_type_cs5, { "Type", "qsig.ie.type.cs5",
637                           FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs5), 0x0,
638                           "Information Element Type (Codeset 5)", HFILL }},
639     { &hf_qsig_ie_len,  { "Length", "qsig.ie.len",
640                           FT_UINT8, BASE_DEC, NULL, 0x0,
641                           "Information Element Length", HFILL }},
642     { &hf_qsig_ie_data, { "Data", "qsig.ie.data",
643                           FT_BYTES, BASE_NONE, NULL, 0x0,
644                           NULL, HFILL }},
645     { &hf_qsig_tc,      { "Transit count", "qsig.tc",
646                           FT_UINT8, BASE_DEC, NULL, 0x1F,
647                           NULL, HFILL }},
648     { &hf_qsig_pc,      { "Party category", "qsig.pc",
649                           FT_UINT8, BASE_HEX, VALS(qsig_str_pc), 0x07,
650                           NULL, HFILL }},
651 #include "packet-qsig-hfarr.c"
652   };
653
654   /* List of subtrees */
655   static gint *ett[] = {
656     &ett_qsig,
657     &ett_qsig_ie,
658     &ett_qsig_unknown_extension,
659 #include "packet-qsig-ettarr.c"
660     &ett_cnq_PSS1InformationElement,
661   };
662
663   /* Register protocol and dissector */
664   proto_qsig = proto_register_protocol(PNAME, PSNAME, PFNAME);
665
666   /* Register fields and subtrees */
667   proto_register_field_array(proto_qsig, hf, array_length(hf));
668   proto_register_subtree_array(ett, array_length(ett));
669
670   /* Register dissector tables */
671   extension_dissector_table = register_dissector_table("qsig.ext", "QSIG Extension", FT_STRING, BASE_NONE);
672
673   qsig_init_tables();
674 }
675
676
677 /*--- proto_reg_handoff_qsig ------------------------------------------------*/
678 void proto_reg_handoff_qsig(void) {
679   int i;
680   gint key;
681   const gchar *oid;
682   dissector_handle_t q931_handle;
683   dissector_handle_t qsig_arg_handle;
684   dissector_handle_t qsig_res_handle;
685   dissector_handle_t qsig_err_handle;
686   dissector_handle_t qsig_ie_handle;
687
688   q931_handle = find_dissector("q931");
689   q931_ie_handle = find_dissector("q931.ie");
690
691   qsig_arg_handle = new_create_dissector_handle(dissect_qsig_arg, proto_qsig);
692   qsig_res_handle = new_create_dissector_handle(dissect_qsig_res, proto_qsig);
693   for (i=0; i<(int)array_length(qsig_op_tab); i++) {
694     dissector_add_uint("q932.ros.local.arg", qsig_op_tab[i].opcode, qsig_arg_handle);
695     dissector_add_uint("q932.ros.local.res", qsig_op_tab[i].opcode, qsig_res_handle);
696     key = qsig_op_tab[i].opcode;
697     oid = g_hash_table_lookup(qsig_opcode2oid_hashtable, &key);
698     if (oid) {
699       dissector_add_string("q932.ros.global.arg", oid, qsig_arg_handle);
700       dissector_add_string("q932.ros.global.res", oid, qsig_res_handle);
701     }
702   }
703   qsig_err_handle = new_create_dissector_handle(dissect_qsig_err, proto_qsig);
704   for (i=0; i<(int)array_length(qsig_err_tab); i++) {
705     dissector_add_uint("q932.ros.local.err", qsig_err_tab[i].errcode, qsig_err_handle);
706   }
707
708   qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs4, proto_qsig);
709   /* QSIG-TC - Transit counter */
710   dissector_add_uint("q931.ie", CS4 | QSIG_IE_TRANSIT_COUNTER, qsig_ie_handle);
711
712   qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs5, proto_qsig);
713   /* SSIG-BC - Party category */
714   dissector_add_uint("q931.ie", CS5 | QSIG_IE_PARTY_CATEGORY, qsig_ie_handle);
715
716   /* RFC 3204, 3.2 QSIG Media Type */
717   dissector_add_string("media_type", "application/qsig", q931_handle);
718
719 }
720
721 /*---------------------------------------------------------------------------*/