2 * Routines for QSIG packet dissection
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/strutil.h>
33 #include <epan/emem.h>
34 #include <epan/asn1.h>
36 #include "packet-ber.h"
37 #include "packet-qsig.h"
43 /* Shifted codeset values */
53 #define QSIG_IE_TRANSIT_COUNTER 0x31
54 #define QSIG_IE_PARTY_CATEGORY 0x32
56 static const value_string qsig_str_ie_type_cs4[] = {
57 { QSIG_IE_TRANSIT_COUNTER , "Transit counter" },
60 static const value_string qsig_str_ie_type_cs5[] = {
61 { QSIG_IE_PARTY_CATEGORY , "Party category" },
65 static const value_string *qsig_str_ie_type[] = {
77 static const value_string qsig_str_pc[] = {
79 { 0x01 , "extension" },
80 { 0x02 , "operator" },
81 { 0x03 , "emergency extension" },
85 static const value_string qsig_str_service[] = {
92 { 14844, "QSIG-DND(O)" },
94 { 15050, "QSIG-AOC" },
96 { 15054, "QSIG-CINT" },
97 { 15506, "QSIG-MWI" },
98 { 15507, "SYNC-SIG" },
99 { 15772, "QSIG-CMN" },
100 { 15992, "QSIG-CPI(P)" },
101 { 17876, "QSIG-PUMR" },
102 { 17878, "QSIG-PUMCH" },
103 { 19460, "QSIG-SSCT" },
104 { 15429, "QSIG-WTMLR" },
105 { 15431, "QSIG-WTMCH" },
106 { 15433, "QSIG-WTMAU" },
107 { 21407, "QSIG-SD" },
108 { 21889, "QSIG-CIDL" },
111 { 3471, "QSIG-MCM" },
112 { 3472, "QSIG-MID" },
116 static const value_string qsig_str_service_name[] = {
117 { 13868, "Name-Operations" },
118 { 13873, "Call-Diversion-Operations" },
119 { 13874, "Path-Replacement-Operations" },
120 { 13869, "Call-Transfer-Operations" },
121 { 13870, "SS-CC-Operations" },
122 { 14843, "Call-Offer-Operations" },
123 { 14844, "Do-Not-Disturb-Operations" },
124 { 14846, "Call-Intrusion-Operations" },
125 { 15050, "SS-AOC-Operation" },
126 { 15052, "Recall-Operation" },
127 { 15054, "Call-Interception-Operations" },
128 { 15506, "SS-MWI-Operations" },
129 { 15507, "Synchronization-Operations" },
130 { 15772, "Common-Information-Operations" },
131 { 15992, "Call-Interruption-Operation" },
132 { 17876, "PUM-Registration-Operation" },
133 { 17878, "Private-User-Mobility-Call-Handling-Operations" },
134 { 19460, "Single-Step-Call-Transfer-Operations" },
135 { 15429, "WTM-Location-Registration-Operations" },
136 { 15431, "Wireless-Terminal-Call-Handling-Operations" },
137 { 15433, "WTM-Authentication-Operations" },
138 { 21407, "SS-SD-Operations" },
139 { 21889, "Call-Identification-and-Call-Linkage-Operations" },
140 { 325, "Short-Message-Service-Operations" },
141 { 344, "SS-MCR-Operations" },
142 { 3471, "SS-MCM-Operations" },
143 { 3472, "SS-MID-Operations" },
148 static const gint32 op2srv_tab[] = {
272 static const value_string qsig_str_operation[] = {
273 #include "packet-qsig-table10.c"
277 static const value_string qsig_str_error[] = {
278 #include "packet-qsig-table20.c"
282 /* Initialize the protocol and registered fields */
284 static int hf_qsig_operation = -1;
285 static int hf_qsig_service = -1;
286 static int hf_qsig_error = -1;
287 static int hf_qsig_ie_type = -1;
288 static int hf_qsig_ie_type_cs4 = -1;
289 static int hf_qsig_ie_type_cs5 = -1;
290 static int hf_qsig_ie_len = -1;
291 static int hf_qsig_ie_data = -1;
292 static int hf_qsig_tc = -1;
293 static int hf_qsig_pc = -1;
294 #include "packet-qsig-hf.c"
296 static int *hf_qsig_ie_type_arr[] = {
301 &hf_qsig_ie_type_cs4,
302 &hf_qsig_ie_type_cs5,
307 /* Initialize the subtree pointers */
308 static gint ett_qsig = -1;
309 static gint ett_qsig_ie = -1;
310 #include "packet-qsig-ett.c"
315 static dissector_handle_t data_handle = NULL;
317 /* Gloabl variables */
320 #include "packet-qsig-fn.c"
322 typedef struct _qsig_op_t {
324 new_dissector_t arg_pdu;
325 new_dissector_t res_pdu;
328 static const qsig_op_t qsig_op_tab[] = {
329 #include "packet-qsig-table11.c"
332 typedef struct _qsig_err_t {
334 new_dissector_t err_pdu;
337 static const qsig_err_t qsig_err_tab[] = {
338 #include "packet-qsig-table21.c"
341 static const qsig_op_t *get_op(gint32 opcode) {
344 /* search from the end to get the last occurence if the operation is redefined in some newer specification */
345 for (i = array_length(qsig_op_tab) - 1; i >= 0; i--)
346 if (qsig_op_tab[i].opcode == opcode)
347 return &qsig_op_tab[i];
351 static gint32 get_service(gint32 opcode) {
352 if ((opcode < 0) || (opcode >= (int)array_length(op2srv_tab)))
354 return op2srv_tab[opcode];
357 static const qsig_err_t *get_err(gint32 errcode) {
360 /* search from the end to get the last occurence if the operation is redefined in some newer specification */
361 for (i = array_length(qsig_err_tab) - 1; i >= 0; i--)
362 if (qsig_err_tab[i].errcode == errcode)
363 return &qsig_err_tab[i];
367 /*--- dissect_qsig_arg ------------------------------------------------------*/
369 dissect_qsig_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
372 gint32 opcode, service;
373 const qsig_op_t *op_ptr;
375 proto_item *ti, *ti_tmp;
376 proto_tree *qsig_tree;
379 rctx = get_rose_ctx(pinfo->private_data);
380 DISSECTOR_ASSERT(rctx);
381 if (rctx->d.pdu != 1) /* invoke */
383 if (rctx->d.code != 0) /* local */
385 opcode = rctx->d.code_local;
386 op_ptr = get_op(opcode);
389 service = get_service(opcode);
391 ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
392 qsig_tree = proto_item_add_subtree(ti, ett_qsig);
394 proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
395 p = match_strval(opcode, VALS(qsig_str_operation));
397 proto_item_append_text(ti, ": %s", p);
398 proto_item_append_text(rctx->d.code_item, " - %s", p);
399 if (rctx->apdu_depth >= 0)
400 proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
403 ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
404 p = match_strval(service, VALS(qsig_str_service_name));
405 if (p) proto_item_append_text(ti_tmp, " - %s", p);
408 offset = op_ptr->arg_pdu(tvb, pinfo, qsig_tree);
410 if (tvb_length_remaining(tvb, offset) > 0) {
411 proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ARGUMENT TYPE (QSIG)");
412 offset += tvb_length_remaining(tvb, offset);
418 /*--- dissect_qsig_res -------------------------------------------------------*/
420 dissect_qsig_res(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
423 gint32 opcode, service;
424 const qsig_op_t *op_ptr;
426 proto_item *ti, *ti_tmp;
427 proto_tree *qsig_tree;
430 rctx = get_rose_ctx(pinfo->private_data);
431 DISSECTOR_ASSERT(rctx);
432 if (rctx->d.pdu != 2) /* returnResult */
434 if (rctx->d.code != 0) /* local */
436 opcode = rctx->d.code_local;
437 op_ptr = get_op(opcode);
440 service = get_service(opcode);
442 ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
443 qsig_tree = proto_item_add_subtree(ti, ett_qsig);
445 proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
446 p = match_strval(opcode, VALS(qsig_str_operation));
448 proto_item_append_text(ti, ": %s", p);
449 proto_item_append_text(rctx->d.code_item, " - %s", p);
450 if (rctx->apdu_depth >= 0)
451 proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
454 ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
455 p = match_strval(service, VALS(qsig_str_service_name));
456 if (p) proto_item_append_text(ti_tmp, " - %s", p);
459 offset = op_ptr->res_pdu(tvb, pinfo, qsig_tree);
461 if (tvb_length_remaining(tvb, offset) > 0) {
462 proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED RESULT TYPE (QSIG)");
463 offset += tvb_length_remaining(tvb, offset);
469 /*--- dissect_qsig_err ------------------------------------------------------*/
471 dissect_qsig_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
475 const qsig_err_t *err_ptr;
478 proto_tree *qsig_tree;
481 rctx = get_rose_ctx(pinfo->private_data);
482 DISSECTOR_ASSERT(rctx);
483 if (rctx->d.pdu != 3) /* returnError */
485 if (rctx->d.code != 0) /* local */
487 errcode = rctx->d.code_local;
488 err_ptr = get_err(errcode);
492 ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), FALSE);
493 qsig_tree = proto_item_add_subtree(ti, ett_qsig);
495 proto_tree_add_uint(qsig_tree, hf_qsig_error, tvb, 0, 0, errcode);
496 p = match_strval(errcode, VALS(qsig_str_error));
498 proto_item_append_text(ti, ": %s", p);
499 proto_item_append_text(rctx->d.code_item, " - %s", p);
500 if (rctx->apdu_depth >= 0)
501 proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
504 if (err_ptr->err_pdu)
505 offset = err_ptr->err_pdu(tvb, pinfo, qsig_tree);
507 if (tvb_length_remaining(tvb, offset) > 0) {
508 proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ERROR TYPE (QSIG)");
509 offset += tvb_length_remaining(tvb, offset);
515 /*--- dissect_qsig_transit_counter_ie ---------------------------------------*/
517 dissect_qsig_transit_counter_ie(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length _U_) {
518 proto_tree_add_item(tree, hf_qsig_tc, tvb, offset, 1, FALSE);
522 /*--- dissect_qsig_party_category_ie ----------------------------------------*/
524 dissect_qsig_party_category_ie(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length _U_) {
525 proto_tree_add_item(tree, hf_qsig_pc, tvb, offset, 1, FALSE);
530 /*--- dissect_qsig_ie -------------------------------------------------------*/
532 dissect_qsig_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int codeset) {
534 proto_item *ti, *ti_ie;
536 guint8 ie_type, ie_len;
540 ti = proto_tree_add_item_hidden(tree, proto_qsig, tvb, offset, -1, FALSE);
542 ie_type = tvb_get_guint8(tvb, offset);
543 ie_len = tvb_get_guint8(tvb, offset + 1);
545 ti_ie = proto_tree_add_text(tree, tvb, offset, -1, "%s",
546 val_to_str(ie_type, VALS(qsig_str_ie_type[codeset]), "unknown (0x%02X)"));
547 ie_tree = proto_item_add_subtree(ti_ie, ett_qsig_ie);
548 proto_tree_add_item(ie_tree, *hf_qsig_ie_type_arr[codeset], tvb, offset, 1, FALSE);
549 proto_tree_add_item_hidden(ie_tree, hf_qsig_ie_type, tvb, offset, 1, FALSE);
550 proto_tree_add_item(ie_tree, hf_qsig_ie_len, tvb, offset + 1, 1, FALSE);
552 if (tvb_length_remaining(tvb, offset) <= 0)
554 switch ((codeset << 8) | ie_type) {
555 case CS4 | QSIG_IE_TRANSIT_COUNTER :
556 dissect_qsig_transit_counter_ie(tvb, offset, pinfo, ie_tree, ie_len);
558 case CS5 | QSIG_IE_PARTY_CATEGORY :
559 dissect_qsig_party_category_ie(tvb, offset, pinfo, ie_tree, ie_len);
563 if (tree) proto_tree_add_item(ie_tree, hf_qsig_ie_data, tvb, offset, ie_len, FALSE);
567 /*--- dissect_qsig_ie_cs4 ---------------------------------------------------*/
569 dissect_qsig_ie_cs4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
570 dissect_qsig_ie(tvb, pinfo, tree, 4);
572 /*--- dissect_qsig_ie_cs5 ---------------------------------------------------*/
574 dissect_qsig_ie_cs5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
575 dissect_qsig_ie(tvb, pinfo, tree, 5);
578 /*--- proto_register_qsig ---------------------------------------------------*/
579 void proto_register_qsig(void) {
582 static hf_register_info hf[] = {
583 { &hf_qsig_operation, { "Operation", "qsig.operation",
584 FT_UINT8, BASE_DEC, VALS(qsig_str_operation), 0x0,
585 "Operation", HFILL }},
586 { &hf_qsig_service, { "Service", "qsig.service",
587 FT_UINT8, BASE_DEC, VALS(qsig_str_service), 0x0,
588 "Supplementary Service", HFILL }},
589 { &hf_qsig_error, { "Error", "qsig.error",
590 FT_UINT8, BASE_DEC, VALS(qsig_str_error), 0x0,
592 { &hf_qsig_ie_type, { "Type", "qsig.ie.type",
593 FT_UINT8, BASE_HEX, NULL, 0x0,
594 "Information Element Type", HFILL }},
595 { &hf_qsig_ie_type_cs4, { "Type", "qsig.ie.type.cs4",
596 FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs4), 0x0,
597 "Information Element Type (Codeset 4)", HFILL }},
598 { &hf_qsig_ie_type_cs5, { "Type", "qsig.ie.type.cs5",
599 FT_UINT8, BASE_HEX, VALS(qsig_str_ie_type_cs5), 0x0,
600 "Information Element Type (Codeset 5)", HFILL }},
601 { &hf_qsig_ie_len, { "Length", "qsig.ie.len",
602 FT_UINT8, BASE_DEC, NULL, 0x0,
603 "Information Element Length", HFILL }},
604 { &hf_qsig_ie_data, { "Data", "qsig.ie.data",
605 FT_BYTES, BASE_HEX, NULL, 0x0,
607 { &hf_qsig_tc, { "Transit count", "qsig.tc",
608 FT_UINT8, BASE_DEC, NULL, 0x1F,
609 "Transit count", HFILL }},
610 { &hf_qsig_pc, { "Party category", "qsig.pc",
611 FT_UINT8, BASE_HEX, VALS(qsig_str_pc), 0x07,
612 "Party category", HFILL }},
613 #include "packet-qsig-hfarr.c"
616 /* List of subtrees */
617 static gint *ett[] = {
620 #include "packet-qsig-ettarr.c"
623 /* Register protocol and dissector */
624 proto_qsig = proto_register_protocol(PNAME, PSNAME, PFNAME);
626 /* Register fields and subtrees */
627 proto_register_field_array(proto_qsig, hf, array_length(hf));
628 proto_register_subtree_array(ett, array_length(ett));
633 /*--- proto_reg_handoff_qsig ------------------------------------------------*/
634 void proto_reg_handoff_qsig(void) {
636 dissector_handle_t qsig_arg_handle;
637 dissector_handle_t qsig_res_handle;
638 dissector_handle_t qsig_err_handle;
639 dissector_handle_t qsig_ie_handle;
641 data_handle = find_dissector("data");
643 qsig_arg_handle = new_create_dissector_handle(dissect_qsig_arg, proto_qsig);
644 qsig_res_handle = new_create_dissector_handle(dissect_qsig_res, proto_qsig);
645 for (i=0; i<(int)array_length(qsig_op_tab); i++) {
646 dissector_add("q932.ros.local.arg", qsig_op_tab[i].opcode, qsig_arg_handle);
647 dissector_add("q932.ros.local.res", qsig_op_tab[i].opcode, qsig_res_handle);
649 qsig_err_handle = new_create_dissector_handle(dissect_qsig_err, proto_qsig);
650 for (i=0; i<(int)array_length(qsig_err_tab); i++) {
651 dissector_add("q932.ros.local.err", qsig_err_tab[i].errcode, qsig_err_handle);
654 qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs4, proto_qsig);
655 /* QSIG-TC - Transit counter */
656 dissector_add("q931.ie", CS4 | QSIG_IE_TRANSIT_COUNTER, qsig_ie_handle);
658 qsig_ie_handle = create_dissector_handle(dissect_qsig_ie_cs5, proto_qsig);
659 /* SSIG-BC - Party category */
660 dissector_add("q931.ie", CS5 | QSIG_IE_PARTY_CATEGORY, qsig_ie_handle);
664 /*---------------------------------------------------------------------------*/