/* packet-q2931.c * Routines for Q.2931 frame disassembly * Guy Harris * * $Id: packet-q2931.c,v 1.1 1999/11/19 09:55:37 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1998 * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include #include #include #include "packet.h" /* * See * * http://www.protocols.com/pbook/atmsig.htm * * for some information on Q.2931, although, alas, not the actual message * type and information element values - those I got from the FreeBSD 3.2 * ATM code. */ static int proto_q2931 = -1; static int hf_q2931_discriminator = -1; static int hf_q2931_call_ref_len = -1; static int hf_q2931_call_ref = -1; static int hf_q2931_message_type = -1; static int hf_q2931_message_type_ext = -1; static int hf_q2931_message_len = -1; static gint ett_q2931 = -1; static gint ett_q2931_ie = -1; /* * Q.2931 message types. */ #define Q2931_ALERTING 0x01 #define Q2931_CALL_PROCEEDING 0x02 #define Q2931_CONNECT 0x07 #define Q2931_CONNECT_ACK 0x0F #define Q2931_PROGRESS 0x03 #define Q2931_SETUP 0x05 #define Q2931_SETUP_ACK 0x0B #define Q2931_RELEASE 0x4D #define Q2931_RELEASE_COMPLETE 0x5A #define Q2931_RESTART 0x46 #define Q2931_RESTART_ACK 0x4E #define Q2931_INFORMATION 0x7B #define Q2931_NOTIFY 0x6E #define Q2931_STATUS 0x7D #define Q2931_STATUS_ENQUIRY 0x75 #define Q2931_ADD_PARTY 0x80 #define Q2931_ADD_PARTY_ACK 0x81 #define Q2931_ADD_PARTY_REJ 0x82 #define Q2931_DROP_PARTY 0x83 #define Q2931_DROP_PARTY_ACK 0x84 static const value_string q2931_message_type_vals[] = { { Q2931_ALERTING, "ALERTING" }, { Q2931_CALL_PROCEEDING, "CALL PROCEEDING" }, { Q2931_CONNECT, "CONNECT" }, { Q2931_CONNECT_ACK, "CONNECT ACKNOWLEDGE" }, { Q2931_PROGRESS, "PROGRESS" }, { Q2931_SETUP, "SETUP" }, { Q2931_SETUP_ACK, "SETUP ACKNOWLEDGE" }, { Q2931_RELEASE, "RELEASE" }, { Q2931_RELEASE_COMPLETE, "RELEASE COMPLETE" }, { Q2931_RESTART, "RESTART" }, { Q2931_RESTART_ACK, "RESTART ACKNOWLEDGE" }, { Q2931_INFORMATION, "INFORMATION" }, { Q2931_NOTIFY, "NOTIFY" }, { Q2931_STATUS, "STATUS" }, { Q2931_STATUS_ENQUIRY, "STATUS ENQUIRY" }, { Q2931_ADD_PARTY, "ADD PARTY" }, { Q2931_ADD_PARTY_ACK, "ADD PARTY ACKNOWLEDGE" }, { Q2931_ADD_PARTY_REJ, "ADD PARTY REJECT" }, { Q2931_DROP_PARTY, "DROP PARTY" }, { Q2931_DROP_PARTY_ACK, "DROP PARTY ACKNOWLEDGE" }, { 0, NULL } }; /* * Information elements. */ #define Q2931_IE_CAUSE 0x08 #define Q2931_IE_CALL_STATE 0x14 #define Q2931_IE_ENDPOINT_REFERENCE 0x54 #define Q2931_IE_ENDPOINT_STATE 0x55 #define Q2931_IE_AAL_PARAMETERS 0x58 #define Q2931_IE_ATM_USER_CELL_RATE 0x59 #define Q2931_IE_CONNECTION_IDENTIFIER 0x5A #define Q2931_IE_QOS_PARAMETER 0x5C /* Quality of Service parameter */ #define Q2931_IE_BBAND_HI_LAYER_INFO 0x5D /* Broadband high-layer information */ #define Q2931_IE_BBAND_BRER_CAPACITY 0x5E /* Broadband bearer capacity */ #define Q2931_IE_BBAND_LOW_LAYER_INFO 0x5F /* Broadband low-layer information */ #define Q2931_IE_BBAND_LOCKING_SHIFT 0x60 /* Broadband locking shift */ #define Q2931_IE_BBAND_NLOCKING_SHIFT 0x61 /* Broadband non-locking shift */ #define Q2931_IE_BBAND_SENDING_COMPL 0x62 /* Broadband sending complete */ #define Q2931_IE_BBAND_RPT_INDICATOR 0x63 /* Broadband repeat indicator */ #define Q2931_IE_CALLING_PARTY_NUMBER 0x6C /* Calling Party Number */ #define Q2931_IE_CALLING_PARTY_SUBADDR 0x6D /* Calling Party Subaddress */ #define Q2931_IE_CALLED_PARTY_NUMBER 0x70 /* Called Party Number */ #define Q2931_IE_CALLED_PARTY_SUBADDR 0x71 /* Called Party Subaddress */ #define Q2931_IE_TRANSIT_NETWORK_SEL 0x78 /* Transit Network Selection */ #define Q2931_IE_RESTART_INDICATOR 0x79 static const value_string q2931_info_element_vals[] = { { Q2931_IE_CAUSE, "Cause" }, { Q2931_IE_CALL_STATE, "Call state" }, { Q2931_IE_ENDPOINT_REFERENCE, "Endpoint reference" }, { Q2931_IE_ENDPOINT_STATE, "Endpoint state" }, { Q2931_IE_AAL_PARAMETERS, "AAL parameters" }, { Q2931_IE_ATM_USER_CELL_RATE, "ATM user cell rate" }, { Q2931_IE_CONNECTION_IDENTIFIER, "Connection identifier" }, { Q2931_IE_QOS_PARAMETER, "Quality of service parameter" }, { Q2931_IE_BBAND_HI_LAYER_INFO, "Broadband high-layer information" }, { Q2931_IE_BBAND_BRER_CAPACITY, "Broadband bearer capacity" }, { Q2931_IE_BBAND_LOW_LAYER_INFO, "Broadband low-layer information" }, { Q2931_IE_BBAND_LOCKING_SHIFT, "Broadband locking shift" }, { Q2931_IE_BBAND_NLOCKING_SHIFT, "Broadband non-locking shift" }, { Q2931_IE_BBAND_SENDING_COMPL, "Broadband sending complete" }, { Q2931_IE_BBAND_RPT_INDICATOR, "Broadband repeat indicator" }, { Q2931_IE_CALLING_PARTY_NUMBER, "Calling party number" }, { Q2931_IE_CALLING_PARTY_SUBADDR, "Calling party subaddress" }, { Q2931_IE_CALLED_PARTY_NUMBER, "Called party number" }, { Q2931_IE_CALLED_PARTY_SUBADDR, "Called party subaddress" }, { Q2931_IE_TRANSIT_NETWORK_SEL, "Transit network selection" }, { Q2931_IE_RESTART_INDICATOR, "Restart indicator" }, { 0, NULL } }; void dissect_q2931(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { proto_tree *q2931_tree = NULL; proto_item *ti; proto_tree *ie_tree; guint8 call_ref_len; guint8 call_ref[15]; guint8 message_type; guint8 message_type_ext; guint16 message_len; guint8 info_element; guint8 info_element_ext; guint16 info_element_len; int codeset; int non_locking_shift; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "Q.2931"); if (tree) { ti = proto_tree_add_item(tree, proto_q2931, offset, END_OF_FRAME, NULL); q2931_tree = proto_item_add_subtree(ti, ett_q2931); proto_tree_add_item(q2931_tree, hf_q2931_discriminator, offset, 1, pd[offset]); } offset += 1; call_ref_len = pd[offset] & 0xF; /* XXX - do as a bit field? */ if (q2931_tree != NULL) proto_tree_add_item(q2931_tree, hf_q2931_call_ref_len, offset, 1, call_ref_len); offset += 1; if (call_ref_len != 0) { /* XXX - split this into flag and value */ memcpy(call_ref, &pd[offset], call_ref_len); if (q2931_tree != NULL) proto_tree_add_item(q2931_tree, hf_q2931_call_ref, offset, call_ref_len, call_ref); offset += call_ref_len; } message_type = pd[offset]; if (check_col(fd, COL_INFO)) { col_add_str(fd, COL_INFO, val_to_str(message_type, q2931_message_type_vals, "Unknown message type (0x%02X)")); } if (q2931_tree != NULL) proto_tree_add_item(q2931_tree, hf_q2931_message_type, offset, 1, message_type); offset += 1; message_type_ext = pd[offset]; if (q2931_tree != NULL) proto_tree_add_item(q2931_tree, hf_q2931_message_type_ext, offset, 1, message_type_ext); offset += 1; message_len = pntohs(&pd[offset]); if (q2931_tree != NULL) proto_tree_add_item(q2931_tree, hf_q2931_message_len, offset, 2, message_len); offset += 2; /* * And now for the information elements.... */ codeset = 0; /* start out in codeset 0 */ non_locking_shift = TRUE; while (IS_DATA_IN_FRAME(offset)) { info_element = pd[offset]; if (!BYTES_ARE_IN_FRAME(offset + 1, 1)) break; /* ran past end of frame */ info_element_ext = pd[offset + 1]; if (!BYTES_ARE_IN_FRAME(offset + 2, 2)) break; /* ran past end of frame */ info_element_len = pntohs(&pd[offset + 2]); if (!BYTES_ARE_IN_FRAME(offset + 4, info_element_len)) break; /* ran past end of frame */ if (q2931_tree != NULL) { ti = proto_tree_add_text(q2931_tree, offset, 1+1+2+info_element_len, "%s", val_to_str(info_element, q2931_info_element_vals, "Unknown information element (0x%02X)")); ie_tree = proto_item_add_subtree(ti, ett_q2931_ie); proto_tree_add_text(ie_tree, offset, 1, "Information element: %s", val_to_str(info_element, q2931_info_element_vals, "Unknown")); proto_tree_add_text(ie_tree, offset + 1, 1, "Information element extension: 0x%02x", info_element_ext); proto_tree_add_text(ie_tree, offset + 2, 2, "Length: %u", info_element_len); } offset += 1 + 1 + 2 + info_element_len; } } void proto_register_q2931(void) { static hf_register_info hf[] = { { &hf_q2931_discriminator, { "Protocol discriminator", "q2931.disc", FT_UINT8, BASE_HEX, NULL, 0x0, "" }}, { &hf_q2931_call_ref_len, { "Call reference value length", "q2931.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, { &hf_q2931_call_ref, { "Call reference value", "q2931.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0, "" }}, { &hf_q2931_message_type, { "Message type", "q2931.message_type", FT_UINT8, BASE_HEX, VALS(q2931_message_type_vals), 0x0, "" }}, { &hf_q2931_message_type_ext, { "Message type extension", "q2931.message_type_ext", FT_UINT8, BASE_HEX, NULL, 0x0, "" }}, { &hf_q2931_message_len, { "Message length", "q2931.message_len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }}, }; static gint *ett[] = { &ett_q2931, &ett_q2931_ie, }; proto_q2931 = proto_register_protocol ("Q.2931", "q2931"); proto_register_field_array (proto_q2931, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); }