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