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