* Routines for Q.2931 frame disassembly
* Guy Harris <guy@alum.mit.edu>
*
- * $Id: packet-q2931.c,v 1.2 1999/11/25 10:01:18 guy Exp $
+ * $Id: packet-q2931.c,v 1.30 2002/11/10 20:26:24 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* 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.
# include "config.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
#include <stdio.h>
#include <glib.h>
#include <string.h>
-#include "packet.h"
+#include <epan/packet.h>
+#include "oui.h"
+#include "nlpid.h"
+#include "etypes.h"
#include "packet-q931.h"
+#include "packet-arp.h"
/*
* See
*
* 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.
+ * ATM code, and from Q.2931 (and Q.931) itself.
*/
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_flag = -1;
static int hf_q2931_call_ref = -1;
static int hf_q2931_message_type = -1;
static int hf_q2931_message_type_ext = -1;
static gint ett_q2931_ext = -1;
static gint ett_q2931_ie = -1;
static gint ett_q2931_ie_ext = -1;
+static gint ett_q2931_nsap = -1;
+
+static void dissect_q2931_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, guint8 info_element, guint8 info_element_ext);
/*
* Q.2931 message types.
#define Q2931_ADD_PARTY_REJ 0x82
#define Q2931_DROP_PARTY 0x83
#define Q2931_DROP_PARTY_ACK 0x84
+#define Q2931_LEAF_SETUP_FAIL 0x90
+#define Q2931_LEAF_SETUP_REQ 0x91
static const value_string q2931_message_type_vals[] = {
{ Q2931_ALERTING, "ALERTING" },
{ Q2931_ADD_PARTY_REJ, "ADD PARTY REJECT" },
{ Q2931_DROP_PARTY, "DROP PARTY" },
{ Q2931_DROP_PARTY_ACK, "DROP PARTY ACKNOWLEDGE" },
+ { Q2931_LEAF_SETUP_FAIL, "LEAF SETUP FAILURE" },
+ { Q2931_LEAF_SETUP_REQ, "LEAF SETUP REQUEST" },
{ 0, NULL }
};
+static const true_false_string tfs_call_ref_flag = {
+ "Message sent to originating side",
+ "Message sent from originating side"
+};
+
/*
* Bits in the message type extension.
*/
#define Q2931_IE_RESTART_INDICATOR 0x79
#define Q2931_IE_NBAND_LOW_LAYER_COMPAT 0x7C /* Narrowband Low-Layer Compatibility */
#define Q2931_IE_NBAND_HIGH_LAYER_COMPAT 0x7D /* Narrowband High-Layer Compatibility */
+#define Q2931_IE_GENERIC_IDENT_TRANSPORT 0x7F /* Generic identifier transport */
static const value_string q2931_info_element_vals[] = {
{ Q2931_IE_NBAND_BEARER_CAP, "Narrowband bearer capability" },
{ Q2931_IE_RESTART_INDICATOR, "Restart indicator" },
{ Q2931_IE_NBAND_LOW_LAYER_COMPAT, "Narrowband low-layer compatibility" },
{ Q2931_IE_NBAND_HIGH_LAYER_COMPAT, "Narrowband high-layer compatibility" },
+ { Q2931_IE_GENERIC_IDENT_TRANSPORT, "Generic identifier transport" },
{ 0, NULL }
};
};
static void
-dissect_q2931_shift_ie(const u_char *pd, int offset, int len,
+dissect_q2931_shift_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree, guint8 info_element)
{
gboolean non_locking_shift;
guint8 codeset;
+ if (len == 0)
+ return;
non_locking_shift = (info_element == Q2931_IE_BBAND_NLOCKING_SHIFT);
- codeset = pd[offset] & 0x07;
- proto_tree_add_text(tree, offset, 1, "%s shift to codeset %u: %s",
+ codeset = tvb_get_guint8(tvb, offset) & 0x07;
+ proto_tree_add_text(tree, tvb, offset, 1, "%s shift to codeset %u: %s",
(non_locking_shift ? "Non-locking" : "Locking"),
codeset,
val_to_str(codeset, q2931_codeset_vals, "Unknown (0x%02X)"));
{ 0x00, "Null" },
{ 0x01, "64 kbit/s voice-band signal transport (G.711/G.722)" },
{ 0x02, "Circuit transport (I.363)" },
+ { 0x03, "Circuit emulation (asynchronous)" },
{ 0x04, "High-quality audio signal transport (I.363)" },
{ 0x05, "Video signal transport (I.363)" },
{ 0x00, NULL }
static const value_string q2931_aal1_err_correction_method_vals[] = {
{ 0x00, "Null" },
{ 0x01, "FEC method for less sensitive signal transport" },
- { 0x02, "FEC method for delay-sensigive signal transport" },
+ { 0x02, "FEC method for delay-sensitive signal transport" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_aal_mode_vals[] = {
+ { 0x01, "Message" },
+ { 0x02, "Streaming" },
{ 0x00, NULL }
};
};
static void
-dissect_q2931_aal_parameters_ie(const u_char *pd, int offset, int len,
+dissect_q2931_aal_parameters_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 aal_type;
if (len == 0)
return;
- aal_type = pd[offset];
- proto_tree_add_text(tree, offset, 1, "AAL type: %s",
+ aal_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "AAL type: %s",
val_to_str(aal_type, q9231_aal_type_vals, "Unknown (0x%02X)"));
offset += 1;
len -= 1;
*/
if (len > 4)
len = 4;
- proto_tree_add_text(tree, offset, len,
+ proto_tree_add_text(tree, tvb, offset, len,
"User defined AAL information: %s",
- bytes_to_str(&pd[offset], len));
+ tvb_bytes_to_str(tvb, offset, len));
return;
}
while (len != 0) {
- identifier = pd[offset];
+ identifier = tvb_get_guint8(tvb, offset);
switch (identifier) {
case 0x85: /* Subtype identifier for AAL1 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"Subtype: %s",
val_to_str(value, q9231_aal1_subtype_vals,
"Unknown (0x%02X)"));
case 0x86: /* CBR identifier for AAL1 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"CBR rate: %s",
val_to_str(value, q9231_aal1_cbr_rate_vals,
"Unknown (0x%02X)"));
case 0x87: /* Multiplier identifier for AAL1 */
if (len < 3)
return;
- value = pntohs(&pd[offset + 1]);
- proto_tree_add_text(tree, offset, 3,
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
"Multiplier: %u", value);
offset += 3;
len -= 3;
case 0x88: /* Source clock frequency recovery method identifier for AAL1 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"Source clock frequency recovery method: %s",
val_to_str(value, q2931_aal1_src_clk_rec_meth_vals,
"Unknown (0x%02X)"));
case 0x89: /* Error correction method identifier for AAL1 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"Error correction method: %s",
val_to_str(value, q2931_aal1_err_correction_method_vals,
"Unknown (0x%02X)"));
case 0x8A: /* Structured data transfer block size identifier for AAL1 */
if (len < 3)
return;
- value = pntohs(&pd[offset + 1]);
- proto_tree_add_text(tree, offset, 3,
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
"Structured data transfer block size: %u", value);
offset += 3;
len -= 3;
case 0x8B: /* Partially filled cells identifier for AAL1 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"Partially filled cells method: %u octets", value);
offset += 2;
len -= 2;
case 0x8C: /* Forward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
if (len < 3)
return;
- value = pntohs(&pd[offset + 1]);
- proto_tree_add_text(tree, offset, 3,
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
"Forward maximum CPCS-SDU size: %u", value);
offset += 3;
len -= 3;
case 0x81: /* Backward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
if (len < 3)
return;
- value = pntohs(&pd[offset + 1]);
- proto_tree_add_text(tree, offset, 3,
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
"Backward maximum CPCS-SDU size: %u", value);
offset += 3;
len -= 3;
case 0x82: /* MID range identifier for AAL3/4 */
if (len < 5)
return;
- low_mid = pntohs(&pd[offset + 1]);
- high_mid = pntohs(&pd[offset + 3]);
- proto_tree_add_text(tree, offset, 3,
+ low_mid = tvb_get_ntohs(tvb, offset + 1);
+ high_mid = tvb_get_ntohs(tvb, offset + 3);
+ proto_tree_add_text(tree, tvb, offset, 3,
"MID range: %u - %u", low_mid, high_mid);
offset += 5;
len -= 5;
break;
+ case 0x83: /* Mode identifier for AAL3/4 and AAL5 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Mode: %s",
+ val_to_str(value, q2931_aal_mode_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
case 0x84: /* SSCS type identifier for AAL3/4 and AAL5 */
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
"SSCS type: %s",
val_to_str(value, q2931_sscs_type_vals,
"Unknown (0x%02X)"));
break;
default: /* unknown AAL parameter */
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Unknown AAL parameter (0x%02X)",
identifier);
return; /* give up */
/*
* Dissect an ATM traffic descriptor information element.
*/
+#define Q2931_ATM_CR_FW_PEAK_CLP_0 0x82 /* Forward peak cell rate (CLP = 0) */
+#define Q2931_ATM_CR_BW_PEAK_CLP_0 0x83 /* Backward peak cell rate (CLP = 0) */
+#define Q2931_ATM_CR_FW_PEAK_CLP_0_1 0x84 /* Forward peak cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_PEAK_CLP_0_1 0x85 /* Backward peak cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_FW_SUST_CLP_0 0x88 /* Forward sustainable cell rate (CLP = 0) */
+#define Q2931_ATM_CR_BW_SUST_CLP_0 0x89 /* Backward sustainable cell rate (CLP = 0) */
+#define Q2931_ATM_CR_FW_SUST_CLP_0_1 0x90 /* Forward sustainable cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_SUST_CLP_0_1 0x91 /* Backward sustainable cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_FW_MAXB_CLP_0 0xA0 /* Forward maximum burst size (CLP = 0) */
+#define Q2931_ATM_CR_BW_MAXB_CLP_0 0xA1 /* Backward maximum burst size (CLP = 0) */
+#define Q2931_ATM_CR_FW_MAXB_CLP_0_1 0xB0 /* Forward maximum burst size (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_MAXB_CLP_0_1 0xB1 /* Backward maximum burst size (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BEST_EFFORT_IND 0xBE /* Best effort indicator */
+#define Q2931_ATM_CR_TRAFFIC_MGMT_OPT 0xBF /* Traffic management options */
+
+static const value_string q2931_atm_td_subfield_vals[] = {
+ { Q2931_ATM_CR_FW_PEAK_CLP_0, "Forward peak cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_BW_PEAK_CLP_0, "Backward peak cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_FW_PEAK_CLP_0_1, "Forward peak cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_PEAK_CLP_0_1, "Backward peak cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_FW_SUST_CLP_0, "Forward sustainable cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_BW_SUST_CLP_0, "Backward sustainable cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_FW_SUST_CLP_0_1, "Forward sustainable cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_SUST_CLP_0_1, "Backward sustainable cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_FW_MAXB_CLP_0, "Forward maximum burst size (CLP = 0)" },
+ { Q2931_ATM_CR_BW_MAXB_CLP_0, "Backward maximum burst size (CLP = 0)" },
+ { Q2931_ATM_CR_FW_MAXB_CLP_0_1, "Forward maximum burst size (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_MAXB_CLP_0_1, "Backward maximum burst size (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BEST_EFFORT_IND, "Best effort indicator" },
+ { Q2931_ATM_CR_TRAFFIC_MGMT_OPT,"Traffic management options" },
+ { 0x0, NULL }
+};
+
static void
-dissect_q2931_atm_cell_rate_ie(const u_char *pd, int offset, int len,
+dissect_q2931_atm_cell_rate_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 identifier;
guint32 value;
while (len != 0) {
- identifier = pd[offset];
+ identifier = tvb_get_guint8(tvb, offset);
switch (identifier) {
- case 0x82: /* Forward peak cell rate (CLP = 0) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward peak cell rate (CLP = 0): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x83: /* Backward peak cell rate (CLP = 0) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward peak cell rate (CLP = 0): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x84: /* Forward peak cell rate (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward peak cell rate (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x85: /* Backward peak cell rate (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward peak cell rate (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x88: /* Forward sustainable cell rate (CLP = 0) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward sustainable cell rate (CLP = 0): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x89: /* Backward sustainable cell rate (CLP = 0) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward sustainable cell rate (CLP = 0): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x90: /* Forward sustainable cell rate (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward sustainable cell rate (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0x91: /* Backward sustainable cell rate (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward sustainable cell rate (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0xA0: /* Forward maximum burst size (CLP = 0) */
+ case Q2931_ATM_CR_FW_PEAK_CLP_0:
+ case Q2931_ATM_CR_BW_PEAK_CLP_0:
+ case Q2931_ATM_CR_FW_PEAK_CLP_0_1:
+ case Q2931_ATM_CR_BW_PEAK_CLP_0_1:
+ case Q2931_ATM_CR_FW_SUST_CLP_0:
+ case Q2931_ATM_CR_BW_SUST_CLP_0:
+ case Q2931_ATM_CR_FW_SUST_CLP_0_1:
+ case Q2931_ATM_CR_BW_SUST_CLP_0_1:
+ case Q2931_ATM_CR_FW_MAXB_CLP_0:
+ case Q2931_ATM_CR_BW_MAXB_CLP_0:
+ case Q2931_ATM_CR_FW_MAXB_CLP_0_1:
+ case Q2931_ATM_CR_BW_MAXB_CLP_0_1:
if (len < 4)
return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward maximum burst size (CLP = 0): %u cell%s/s",
+ value = tvb_get_ntoh24(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: %u cell%s/s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL),
value, plurality(value, "", "s"));
offset += 4;
len -= 4;
break;
- case 0xA1: /* Backward maximum burst size (CLP = 0) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward maximum burst size (CLP = 0): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0xB0: /* Forward maximum burst size (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Forward maximum burst size (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0xB1: /* Backward maximum burst size (CLP = 0 + 1) */
- if (len < 4)
- return;
- value = (pd[offset + 1] << 16)
- | (pd[offset + 2] << 8)
- | (pd[offset + 3] << 0);
- proto_tree_add_text(tree, offset, 4,
- "Backward maximum burst size (CLP = 0 + 1): %u cell%s/s",
- value, plurality(value, "", "s"));
- offset += 4;
- len -= 4;
- break;
-
- case 0xBE: /* best effort indicator */
+ case Q2931_ATM_CR_BEST_EFFORT_IND:
/* Yes, its value *IS* 0xBE.... */
- proto_tree_add_text(tree, offset, 1,
- "Best effort indicator");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL));
offset += 1;
len -= 1;
break;
- case 0xBF: /* Traffic management options */
+ case Q2931_ATM_CR_TRAFFIC_MGMT_OPT:
if (len < 2)
return;
- value = pd[offset + 1];
- proto_tree_add_text(tree, offset, 2,
- "Traffic management options");
- proto_tree_add_text(tree, offset + 1, 1,
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL));
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
"%s allowed in forward direction",
(value & 0x80) ? "Frame discard" : "No frame discard");
- proto_tree_add_text(tree, offset + 1, 1,
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
"%s allowed in backward direction",
(value & 0x40) ? "Frame discard" : "No frame discard");
- proto_tree_add_text(tree, offset + 1, 1,
- "%s requested in forward direction",
- (value & 0x02) ? "Tagging" : "No tagging");
- proto_tree_add_text(tree, offset + 1, 1,
- "%s requested in backward direction",
- (value & 0x01) ? "Tagging" : "No tagging");
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Tagging %srequested in backward direction",
+ (value & 0x02) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Tagging %srequested in forward direction",
+ (value & 0x01) ? "" : "not ");
offset += 2;
len -= 2;
break;
default: /* unknown ATM traffic descriptor element */
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Unknown ATM traffic descriptor element (0x%02X)",
identifier);
return; /* give up */
{ 0x01, "BCOB-A" },
{ 0x03, "BCOB-C" },
{ 0x10, "BCOB-X" },
+ { 0x18, "Transparent VP Service" },
{ 0x00, NULL }
};
-static const value_string q2931_traffic_type_vals[] = {
- { 0x00, "No indication" },
- { 0x04, "Constant bit rate" },
- { 0x08, "Variable bit rate" },
- { 0x00, NULL }
-};
-
-static const value_string q2931_timing_requirements_vals[] = {
- { 0x00, "No indication" },
- { 0x01, "End-to-end timing required" },
- { 0x02, "End-to-end timing not required" },
+static const value_string q2931_transfer_capability_vals[] = {
+ { 0x00, "No bit rate indication" },
+ { 0x01, "No bit rate indication, end-to-end timing required" },
+ { 0x02, "No bit rate indication, end-to-end timing not required" },
+ { 0x04, "CBR" },
+ { 0x05, "CBR, end-to-end timing required" },
+ { 0x06, "CBR, end-to-end timing not required" },
+ { 0x07, "CBR with CLR commitment on CLP=0+1" },
+ { 0x08, "VBR, no timing requirements indication" },
+ { 0x09, "Real time VBR" },
+ { 0x0A, "Non-real time VBR" },
+ { 0x0B, "Non-real time VBR with CLR commitment on CLP=0+1" },
+ { 0x0C, "ABR" },
{ 0x00, NULL }
};
{ 0x00, NULL }
};
-void
-dissect_q2931_bband_bearer_cap_ie(const u_char *pd, int offset, int len,
+static void
+dissect_q2931_bband_bearer_cap_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Bearer class: %s",
val_to_str(octet & 0x1F, q2931_bearer_class_vals,
"Unknown (0x%02X)"));
if (len == 0)
return;
if (!(octet & Q2931_IE_EXTENSION)) {
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
- "Traffic type: %s",
- val_to_str(octet & 0x1C, q2931_traffic_type_vals,
- "Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
- "Timing requirements: %s",
- val_to_str(octet & 0x03, q2931_timing_requirements_vals,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "ATM Transfer Capability: %s",
+ val_to_str(octet & 0x1F, q2931_transfer_capability_vals,
"Unknown (0x%02X)"));
offset += 1;
len -= 1;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Susceptibility to clipping: %s",
val_to_str(octet & 0x60, q2931_susc_clip_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User-plane connection configuration: %s",
val_to_str(octet & 0x03, q2931_up_conn_config_vals,
"Unknown (0x%02X)"));
{ 0x00, NULL }
};
-void
-dissect_q2931_bband_hi_layer_info_ie(const u_char *pd, int offset, int len,
+static void
+dissect_q2931_bband_hi_layer_info_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"High layer information type: %s",
val_to_str(octet & 0x7F, q2931_hi_layer_info_type_vals,
"Unknown (0x%02X)"));
#define Q2931_UIL3_USER_SPEC 0x10
static const value_string q2931_uil3_vals[] = {
- { 0x02, "Q.931/I.451" },
{ Q2931_UIL3_X25_PL, "X.25, packet layer" },
{ Q2931_UIL3_ISO_8208, "ISO/IEC 8208" },
{ Q2931_UIL3_X223, "X.223/ISO 8878" },
{ 0, NULL }
};
+static const value_string lane_pid_vals[] = {
+ { 0x0001, "LE Configuration Direct/Control Direct/Control Distribute" },
+ { 0x0002, "Ethernet/IEEE 002.3 LE Data Direct" },
+ { 0x0003, "IEEE 802.5 LE Data Direct" },
+ { 0x0004, "Ethernet/IEEE 802.3 LE Multicast Send/Multicast Forward" },
+ { 0x0005, "IEEE 802.5 LE Multicast Send/Multicast Forward" },
+ { 0, NULL },
+};
+
/*
* Dissect a broadband low layer information information element.
*/
-void
-dissect_q2931_bband_low_layer_info_ie(const u_char *pd, int offset, int len,
+static void
+dissect_q2931_bband_low_layer_info_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
guint8 uil2_protocol;
guint8 uil3_protocol;
+ guint8 add_l3_info;
+ guint32 organization_code;
+ guint16 pid;
if (len == 0)
return;
- octet = pd[offset];
+ octet = tvb_get_guint8(tvb, offset);
if ((octet & 0x60) == 0x20) {
/*
* Layer 1 information.
*/
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User information layer 1 protocol: 0x%02X",
octet & 0x1F);
offset += 1;
if (len == 0)
return;
- octet = pd[offset];
+ octet = tvb_get_guint8(tvb, offset);
if ((octet & 0x60) == 0x40) {
/*
* Layer 2 information.
*/
uil2_protocol = octet & 0x1F;
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User information layer 2 protocol: %s",
val_to_str(uil2_protocol, q2931_uil2_vals,
"Unknown (0x%02X)"));
goto l2_done;
if (len == 0)
return;
- octet = pd[offset];
+ octet = tvb_get_guint8(tvb, offset);
if (uil2_protocol == Q2931_UIL2_USER_SPEC) {
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User-specified layer 2 protocol information: 0x%02X",
octet & 0x7F);
} else {
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Mode: %s",
val_to_str(octet & 0x60, q2931_mode_vals,
"Unknown (0x%02X)"));
goto l2_done;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Window size: %u k", octet & 0x7F);
offset += 1;
len -= 1;
if (len == 0)
return;
- octet = pd[offset];
+ octet = tvb_get_guint8(tvb, offset);
if ((octet & 0x60) == 0x60) {
/*
* Layer 3 information.
*/
uil3_protocol = octet & 0x1F;
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User information layer 3 protocol: %s",
val_to_str(uil3_protocol, q2931_uil3_vals,
"Unknown (0x%02X)"));
goto l3_done;
if (len == 0)
return;
- octet = pd[offset];
+ octet = tvb_get_guint8(tvb, offset);
switch (uil3_protocol) {
case Q2931_UIL3_X25_PL:
case Q2931_UIL3_ISO_8208:
case Q2931_UIL3_X223:
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Mode: %s",
val_to_str(octet & 0x60, q2931_mode_vals,
"Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
if (octet & Q2931_IE_EXTENSION)
goto l3_done;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Default packet size: %u", octet & 0x0F);
offset += 1;
len -= 1;
goto l3_done;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Packet window size: %u", octet & 0x7F);
offset += 1;
len -= 1;
break;
case Q2931_UIL3_USER_SPEC:
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Default packet size: %u octets",
1 << (octet & 0x0F));
offset += 1;
break;
case Q2931_UIL3_TR_9577:
- if (len == 0)
+ add_l3_info = (octet & 0x7F) << 1;
+ if (octet & Q2931_IE_EXTENSION)
+ goto l3_done;
+ if (len < 2)
return;
- proto_tree_add_text(tree, offset, len,
+ add_l3_info |= (tvb_get_guint8(tvb, offset + 1) & 0x40) >> 6;
+ proto_tree_add_text(tree, tvb, offset, 2,
"Additional layer 3 protocol information: %s",
- bytes_to_str(&pd[offset], len));
- offset += len;
- len -= len;
+ val_to_str(add_l3_info, nlpid_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ if (add_l3_info == NLPID_SNAP) {
+ if (len < 6)
+ return;
+ offset += 1;
+ len -= 1;
+ organization_code = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Organization Code: 0x%06X (%s)",
+ organization_code,
+ val_to_str(organization_code, oui_vals,
+ "Unknown"));
+ offset += 3;
+ len -= 3;
+
+ if (len < 2)
+ return;
+ pid = tvb_get_ntohs(tvb, offset);
+ switch (organization_code) {
+
+ case OUI_ENCAP_ETHER:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Ethernet type: %s",
+ val_to_str(pid, etype_vals,
+ "Unknown (0x%04X)"));
+ break;
+
+ case OUI_ATM_FORUM:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "LANE Protocol ID: %s",
+ val_to_str(pid, lane_pid_vals,
+ "Unknown (0x%04X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Protocol ID: 0x%04X", pid);
+ break;
+ }
+ }
break;
}
}
;
}
+/*
+ * Dissect a Cause information element.
+ */
+static const value_string q2931_cause_coding_standard_vals[] = {
+ { 0x00, "ITU-T standardized coding" },
+ { 0x20, "ISO/IEC standard" },
+ { 0x40, "National standard" },
+ { 0x60, "Standard defined for the network" },
+ { 0, NULL }
+};
+
+static const value_string q2931_cause_location_vals[] = {
+ { 0x00, "User (U)" },
+ { 0x01, "Private network serving the local user (LPN)" },
+ { 0x02, "Public network serving the local user (LN)" },
+ { 0x03, "Transit network (TN)" },
+ { 0x04, "Public network serving the remote user (RLN)" },
+ { 0x05, "Private network serving the remote user (RPN)" },
+ { 0x07, "International network (INTL)" },
+ { 0x0A, "Network beyond interworking point (BI)" },
+ { 0, NULL }
+};
+
+/*
+ * Cause codes for Cause.
+ */
+#define Q2931_CAUSE_UNALLOC_NUMBER 0x01
+#define Q2931_CAUSE_NO_ROUTE_TO_DEST 0x03
+#define Q2931_CAUSE_CALL_REJECTED 0x15
+#define Q2931_CAUSE_NUMBER_CHANGED 0x16
+#define Q2931_CAUSE_CELL_RATE_UNAVAIL 0x25
+#define Q2931_CAUSE_ACCESS_INFO_DISC 0x2B
+#define Q2931_CAUSE_QOS_UNAVAILABLE 0x31
+#define Q2931_CAUSE_CHAN_NONEXISTENT 0x52
+#define Q2931_CAUSE_INCOMPATIBLE_DEST 0x58
+#define Q2931_CAUSE_MAND_IE_MISSING 0x60
+#define Q2931_CAUSE_MT_NONEX_OR_UNIMPL 0x61
+#define Q2931_CAUSE_IE_NONEX_OR_UNIMPL 0x63
+#define Q2931_CAUSE_INVALID_IE_CONTENTS 0x64
+#define Q2931_CAUSE_MSG_INCOMPAT_W_CS 0x65
+#define Q2931_CAUSE_REC_TIMER_EXP 0x66
+
+static const value_string q2931_cause_code_vals[] = {
+ { Q2931_CAUSE_UNALLOC_NUMBER, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { Q2931_CAUSE_NO_ROUTE_TO_DEST, "No route to destination" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { Q2931_CAUSE_CALL_REJECTED, "Call rejected" },
+ { Q2931_CAUSE_NUMBER_CHANGED, "Number changed" },
+ { 0x17, "User rejects calls with calling line identification restriction" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (incomplete number)" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x23, "Requested VPCI/VCI not available" },
+ { 0x24, "VPCI/VCI assignment failure" },
+ { Q2931_CAUSE_CELL_RATE_UNAVAIL,"User cell rate not available" },
+ { 0x26, "Network out of order" },
+ { 0x29, "Temporary failure" },
+ { Q2931_CAUSE_ACCESS_INFO_DISC, "Access information discarded" },
+ { 0x2D, "No VPCI/VCI available" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { Q2931_CAUSE_QOS_UNAVAILABLE, "Quality of service unavailable" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x49, "Unsupported combination of traffic parameters" },
+ { 0x4E, "AAL parameters cannot be supported" },
+ { 0x51, "Invalid call reference value" },
+ { Q2931_CAUSE_CHAN_NONEXISTENT, "Identified channel does not exist" },
+ { Q2931_CAUSE_INCOMPATIBLE_DEST,"Incompatible destination" },
+ { 0x59, "Invalid endpoint reference" },
+ { 0x5B, "Invalid transit network selection" },
+ { 0x5C, "Too many pending ADD PARTY requests" },
+ { Q2931_CAUSE_MAND_IE_MISSING, "Mandatory information element is missing" },
+ { Q2931_CAUSE_MT_NONEX_OR_UNIMPL,"Message type non-existent or not implemented" },
+ { Q2931_CAUSE_IE_NONEX_OR_UNIMPL,"Information element nonexistant or not implemented" },
+ { Q2931_CAUSE_INVALID_IE_CONTENTS,"Invalid information element contents" },
+ { Q2931_CAUSE_MSG_INCOMPAT_W_CS,"Message not compatible with call state" },
+ { Q2931_CAUSE_REC_TIMER_EXP, "Recovery on timer expiry" },
+ { 0x68, "Incorrect message length" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0, NULL }
+};
+
+static const value_string q2931_cause_condition_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Permanent" },
+ { 0x02, "Transient" },
+ { 0x00, NULL }
+};
+
+#define Q2931_REJ_USER_SPECIFIC 0x00
+#define Q2931_REJ_IE_MISSING 0x04
+#define Q2931_REJ_IE_INSUFFICIENT 0x08
+
+static const value_string q2931_rejection_reason_vals[] = {
+ { 0x00, "User specific" },
+ { 0x04, "Information element missing" },
+ { 0x08, "Information element contents are not sufficient" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_cause_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 cause_value;
+ guint8 rejection_reason;
+ guint8 info_element;
+ guint8 info_element_ext;
+ guint16 info_element_len;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Location: %s",
+ val_to_str(octet & 0x0F, q2931_cause_location_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ cause_value = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Cause value: %s",
+ val_to_str(cause_value, q2931_cause_code_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (cause_value) {
+
+ case Q2931_CAUSE_UNALLOC_NUMBER:
+ case Q2931_CAUSE_NO_ROUTE_TO_DEST:
+ case Q2931_CAUSE_QOS_UNAVAILABLE:
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network service: %s",
+ (octet & 0x80) ? "User" : "Provider");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x40) ? "Abnormal" : "Normal");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q2931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ break;
+
+ case Q2931_CAUSE_CALL_REJECTED:
+ rejection_reason = octet & 0x7C;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rejection reason: %s",
+ val_to_str(octet & 0x7C, q2931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q2931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (rejection_reason) {
+
+ case Q2931_REJ_USER_SPECIFIC:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "User specific diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+
+ case Q2931_REJ_IE_MISSING:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q2931_REJ_IE_INSUFFICIENT:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Insufficient information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+ break;
+
+ case Q2931_CAUSE_NUMBER_CHANGED:
+ /*
+ * UNI 3.1 claims this "is formatted as the called party
+ * number information element, including information
+ * element identifier.
+ */
+ info_element = tvb_get_guint8(tvb, offset);
+ info_element_ext = tvb_get_guint8(tvb, offset + 1);
+ info_element_len = tvb_get_ntohs(tvb, offset + 2);
+ dissect_q2931_ie(tvb, offset, info_element_len, tree,
+ info_element, info_element_ext);
+ break;
+
+ case Q2931_CAUSE_ACCESS_INFO_DISC:
+ case Q2931_CAUSE_INCOMPATIBLE_DEST:
+ case Q2931_CAUSE_MAND_IE_MISSING:
+ case Q2931_CAUSE_IE_NONEX_OR_UNIMPL:
+ case Q2931_CAUSE_INVALID_IE_CONTENTS:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q2931_CAUSE_CELL_RATE_UNAVAIL:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Cell rate subfield identifier: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_atm_td_subfield_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q2931_CAUSE_CHAN_NONEXISTENT:
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "VPCI: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ len -= 2;
+
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "VCI: %u", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case Q2931_CAUSE_MT_NONEX_OR_UNIMPL:
+ case Q2931_CAUSE_MSG_INCOMPAT_W_CS:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Message type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_message_type_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q2931_CAUSE_REC_TIMER_EXP:
+ if (len < 3)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Timer: %.3s", tvb_get_ptr(tvb, offset, 3));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostics: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ }
+}
+
/*
* Dissect a Call state information element.
*/
};
static void
-dissect_q2931_call_state_ie(const u_char *pd, int offset, int len,
+dissect_q2931_call_state_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Call state: %s",
val_to_str(octet & 0x3F, q2931_call_state_vals,
"Unknown (0x%02X)"));
};
static void
-dissect_q2931_number_ie(const u_char *pd, int offset, int len,
+dissect_q2931_number_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
guint8 numbering_plan;
+ proto_item *ti;
+ proto_tree *nsap_tree;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Type of number: %s",
val_to_str(octet & 0x70, q2931_number_type_vals,
"Unknown (0x%02X)"));
numbering_plan = octet & 0x0F;
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Numbering plan: %s",
val_to_str(numbering_plan, q2931_numbering_plan_vals,
"Unknown (0x%02X)"));
if (!(octet & Q2931_IE_EXTENSION)) {
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Presentation indicator: %s",
val_to_str(octet & 0x60, q2931_presentation_indicator_vals,
"Unknown (0x%X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Screening indicator: %s",
val_to_str(octet & 0x03, q2931_screening_indicator_vals,
"Unknown (0x%X)"));
if (len == 0)
return;
- if (numbering_plan == Q2931_ISDN_NUMBERING) {
- proto_tree_add_text(tree, offset, len, "Number: %.*s",
- len, &pd[offset]);
- } else {
- proto_tree_add_text(tree, offset, len, "Number: %s",
- bytes_to_str(&pd[offset], len));
+ switch (numbering_plan) {
+
+ case Q2931_ISDN_NUMBERING:
+ proto_tree_add_text(tree, tvb, offset, len, "Number: %.*s",
+ len, tvb_get_ptr(tvb, offset, len));
+ break;
+
+ case Q2931_NSAP_ADDRESSING:
+ if (len < 20) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Number (too short): %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Number");
+ nsap_tree = proto_item_add_subtree(ti, ett_q2931_nsap);
+ dissect_atm_nsap(tvb, offset, len, nsap_tree);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Number: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
}
}
};
static void
-dissect_q2931_party_subaddr_ie(const u_char *pd, int offset, int len,
+dissect_q2931_party_subaddr_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Type of subaddress: %s",
val_to_str(octet & 0x70, q2931_subaddress_type_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Odd/even indicator: %s",
val_to_str(octet & 0x10, q2931_odd_even_indicator_vals,
NULL));
if (len == 0)
return;
- proto_tree_add_text(tree, offset, len, "Subaddress: %s",
- bytes_to_str(&pd[offset], len));
+ proto_tree_add_text(tree, tvb, offset, len, "Subaddress: %s",
+ tvb_bytes_to_str(tvb, offset, len));
}
/*
static const value_string q2931_preferred_exclusive_vals[] = {
{ 0x00, "Exclusive VPCI; exclusive VCI" },
{ 0x01, "Exclusive VPCI; any VCI" },
+ { 0x04, "Exclusive VPCI; no VCI" },
{ 0x00, NULL }
};
static void
-dissect_q2931_connection_identifier_ie(const u_char *pd, int offset, int len,
+dissect_q2931_connection_identifier_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"VP-associated signalling: %s",
val_to_str(octet & 0x18, q2931_vp_associated_signalling_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Preferred/exclusive: %s",
val_to_str(octet & 0x07, q2931_preferred_exclusive_vals,
"Unknown (0x%02X)"));
if (len < 2)
return;
- proto_tree_add_text(tree, offset, 2, "VPCI: %u",
- pntohs(&pd[offset]));
+ proto_tree_add_text(tree, tvb, offset, 2, "VPCI: %u",
+ tvb_get_ntohs(tvb, offset));
offset += 2;
len -= 2;
if (len < 2)
return;
- proto_tree_add_text(tree, offset, 2, "VCI: %u",
- pntohs(&pd[offset]));
+ proto_tree_add_text(tree, tvb, offset, 2, "VCI: %u",
+ tvb_get_ntohs(tvb, offset));
}
/*
* Dissect an End-to-end transit delay information element.
*/
static void
-dissect_q2931_e2e_transit_delay_ie(const u_char *pd, int offset, int len,
+dissect_q2931_e2e_transit_delay_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 identifier;
guint16 value;
while (len >= 3) {
- identifier = pd[offset];
- value = pntohs(&pd[offset + 1]);
+ identifier = tvb_get_guint8(tvb, offset);
+ value = tvb_get_ntohs(tvb, offset + 1);
switch (identifier) {
case 0x01: /* Cumulative transit delay identifier */
- proto_tree_add_text(tree, offset, 3,
+ proto_tree_add_text(tree, tvb, offset, 3,
"Cumulative transit delay: %u ms", value);
break;
case 0x03: /* Maximum transit delay identifier */
if (value == 0xFFFF) {
- proto_tree_add_text(tree, offset, 3,
+ proto_tree_add_text(tree, tvb, offset, 3,
"Any end-to-end transit delay value acceptable");
} else {
- proto_tree_add_text(tree, offset, 3,
+ proto_tree_add_text(tree, tvb, offset, 3,
"Maximum end-to-end transit delay: %u ms",
value);
}
break;
default: /* Unknown transit delay identifier */
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Unknown transit delay identifier (0x%02X)",
identifier);
return; /* give up */
};
static void
-dissect_q2931_qos_parameter_ie(const u_char *pd, int offset, int len,
+dissect_q2931_qos_parameter_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"QOS class forward: %s",
val_to_str(octet, q2931_qos_parameter_vals,
"Unknown (0x%02X)"));
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"QOS class backward: %s",
val_to_str(octet, q2931_qos_parameter_vals,
"Unknown (0x%02X)"));
};
static void
-dissect_q2931_bband_rpt_indicator(const u_char *pd, int offset, int len,
+dissect_q2931_bband_rpt_indicator(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Broadband repeat indicator: %s",
val_to_str(octet & 0x0F, q2931_bband_rpt_indicator_vals,
"Unknown (0x%02X)"));
};
static void
-dissect_q2931_restart_indicator(const u_char *pd, int offset, int len,
+dissect_q2931_restart_indicator(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Restart indicator: %s",
val_to_str(octet & 0x07, q2931_class_vals,
"Unknown (0x%02X)"));
* Dissect an broadband sending complete information element.
*/
static void
-dissect_q2931_bband_sending_compl_ie(const u_char *pd, int offset, int len,
+dissect_q2931_bband_sending_compl_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 identifier;
while (len != 0) {
- identifier = pd[offset];
+ identifier = tvb_get_guint8(tvb, offset);
switch (identifier) {
case 0xA1: /* Sending complete indication */
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Broadband sending complete indication");
offset += 1;
len -= 1;
break;
default: /* unknown broadband sending complete element */
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Unknown broadband sending complete element (0x%02X)",
identifier);
return; /* give up */
};
static void
-dissect_q2931_transit_network_sel_ie(const u_char *pd, int offset, int len,
+dissect_q2931_transit_network_sel_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Type of network identification: %s",
val_to_str(octet & 0x70, q2931_netid_type_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Network identification plan: %s",
val_to_str(octet & 0x0F, q2931_netid_plan_vals,
"Unknown (0x%02X)"));
if (len == 0)
return;
- proto_tree_add_text(tree, offset, len,
- "Network identification: %.*s", len, &pd[offset]);
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Network identification: %.*s", len, tvb_get_ptr(tvb, offset, len));
}
/*
};
static void
-dissect_q2931_oam_traffic_descriptor_ie(const u_char *pd, int offset, int len,
+dissect_q2931_oam_traffic_descriptor_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
{
guint8 octet;
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Shaping indicator: %s",
val_to_str(octet & 0x60, q2931_shaping_indicator_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Use of end-to-end OAM F5 flow is %s",
(octet & 0x10) ? "mandatory" : "optional");
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"User-Network fault management indicator: %s",
val_to_str(octet & 0x07, q2931_user_net_fault_mgmt_vals,
"Unknown (0x%02X)"));
offset += 1;
len -= 1;
-
if (len == 0)
return;
- octet = pd[offset];
- proto_tree_add_text(tree, offset, 1,
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
"Forward end-to-end OAM F5 flow indicator: %s",
val_to_str(octet & 0x70, q2931_fwd_e2e_oam_f5_flow_indicator_vals,
"Unknown (0x%02X)"));
- proto_tree_add_text(tree, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Backward end-to-end OAM F5 flow indicator: %s",
val_to_str(octet & 0x07, q2931_bwd_e2e_oam_f5_flow_indicator_vals,
"Unknown (0x%02X)"));
}
+/*
+ * Dissect an Endpoint reference information element.
+ */
+static const value_string q2931_endpoint_reference_type_vals[] = {
+ { 0x00, "Locally defined integer" },
+ { 0, NULL }
+};
+
static void
-dissect_q2931_ie(const u_char *pd, int offset, int len,
+dissect_q2931_endpoint_reference_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint16 value;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Endpoint reference type: %s",
+ val_to_str(octet, q2931_endpoint_reference_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len < 2)
+ return;
+ value = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Endpoint reference flag: %s",
+ (value & 0x8000) ? "Message sent to side that originates the endpoint reference" :
+ "Message sent from side that originates the endpoint reference");
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Endpoint reference identifier value: %u",
+ value & 0x7FFF);
+}
+
+/*
+ * Dissect an Endpoint state information element.
+ */
+static const value_string q2931_endpoint_reference_party_state_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "ADD PARTY initiated" },
+ { 0x06, "ADD PARTY received" },
+ { 0x0B, "DROP PARTY initiated" },
+ { 0x0C, "DROP PARTY received" },
+ { 0x0A, "Active" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_endpoint_state_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Endpoint reference party-state: %s",
+ val_to_str(octet & 0x3F, q2931_endpoint_reference_party_state_vals,
+ "Unknown (0x%02X)"));
+}
+
+static void
+dissect_q2931_ie_contents(tvbuff_t *tvb, int offset, int len,
proto_tree *tree, guint8 info_element)
{
switch (info_element) {
case Q2931_IE_BBAND_LOCKING_SHIFT:
case Q2931_IE_BBAND_NLOCKING_SHIFT:
- dissect_q2931_shift_ie(pd, offset, len, tree, info_element);
+ dissect_q2931_shift_ie(tvb, offset, len, tree, info_element);
break;
case Q2931_IE_NBAND_BEARER_CAP:
case Q2931_IE_NBAND_LOW_LAYER_COMPAT:
- dissect_q931_bearer_capability_ie(pd, offset, len, tree);
+ dissect_q931_bearer_capability_ie(tvb, offset, len, tree);
break;
case Q2931_IE_NBAND_HIGH_LAYER_COMPAT:
- dissect_q931_high_layer_compat_ie(pd, offset, len, tree);
+ dissect_q931_high_layer_compat_ie(tvb, offset, len, tree);
break;
case Q2931_IE_PROGRESS_INDICATOR:
- dissect_q931_progress_indicator_ie(pd, offset, len, tree);
+ dissect_q931_progress_indicator_ie(tvb, offset, len, tree);
break;
case Q2931_IE_AAL_PARAMETERS:
- dissect_q2931_aal_parameters_ie(pd, offset, len, tree);
+ dissect_q2931_aal_parameters_ie(tvb, offset, len, tree);
break;
case Q2931_IE_ATM_USER_CELL_RATE:
- dissect_q2931_atm_cell_rate_ie(pd, offset, len, tree);
+ dissect_q2931_atm_cell_rate_ie(tvb, offset, len, tree);
break;
case Q2931_IE_BBAND_BEARER_CAP:
- dissect_q2931_bband_bearer_cap_ie(pd, offset, len, tree);
+ dissect_q2931_bband_bearer_cap_ie(tvb, offset, len, tree);
break;
case Q2931_IE_BBAND_HI_LAYER_INFO:
- dissect_q2931_bband_hi_layer_info_ie(pd, offset, len, tree);
+ dissect_q2931_bband_hi_layer_info_ie(tvb, offset, len, tree);
break;
case Q2931_IE_BBAND_LOW_LAYER_INFO:
- dissect_q2931_bband_low_layer_info_ie(pd, offset, len, tree);
+ dissect_q2931_bband_low_layer_info_ie(tvb, offset, len, tree);
break;
case Q2931_IE_CALL_STATE:
- dissect_q2931_call_state_ie(pd, offset, len, tree);
+ dissect_q2931_call_state_ie(tvb, offset, len, tree);
break;
case Q2931_IE_CALLED_PARTY_NUMBER:
case Q2931_IE_CALLING_PARTY_NUMBER:
- dissect_q2931_number_ie(pd, offset, len, tree);
+ dissect_q2931_number_ie(tvb, offset, len, tree);
break;
case Q2931_IE_CALLED_PARTY_SUBADDR:
case Q2931_IE_CALLING_PARTY_SUBADDR:
- dissect_q2931_party_subaddr_ie(pd, offset, len, tree);
+ dissect_q2931_party_subaddr_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CAUSE:
+ dissect_q2931_cause_ie(tvb, offset, len, tree);
break;
case Q2931_IE_CONNECTION_IDENTIFIER:
- dissect_q2931_connection_identifier_ie(pd, offset, len, tree);
+ dissect_q2931_connection_identifier_ie(tvb, offset, len, tree);
break;
case Q2931_IE_E2E_TRANSIT_DELAY:
- dissect_q2931_e2e_transit_delay_ie(pd, offset, len, tree);
+ dissect_q2931_e2e_transit_delay_ie(tvb, offset, len, tree);
break;
case Q2931_IE_QOS_PARAMETER:
- dissect_q2931_qos_parameter_ie(pd, offset, len, tree);
+ dissect_q2931_qos_parameter_ie(tvb, offset, len, tree);
break;
case Q2931_IE_BBAND_RPT_INDICATOR:
- dissect_q2931_bband_rpt_indicator(pd, offset, len, tree);
+ dissect_q2931_bband_rpt_indicator(tvb, offset, len, tree);
break;
case Q2931_IE_RESTART_INDICATOR:
- dissect_q2931_restart_indicator(pd, offset, len, tree);
+ dissect_q2931_restart_indicator(tvb, offset, len, tree);
break;
case Q2931_IE_BBAND_SENDING_COMPL:
- dissect_q2931_bband_sending_compl_ie(pd, offset, len, tree);
+ dissect_q2931_bband_sending_compl_ie(tvb, offset, len, tree);
break;
case Q2931_IE_TRANSIT_NETWORK_SEL:
- dissect_q2931_transit_network_sel_ie(pd, offset, len, tree);
+ dissect_q2931_transit_network_sel_ie(tvb, offset, len, tree);
break;
case Q2931_IE_OAM_TRAFFIC_DESCRIPTOR:
- dissect_q2931_oam_traffic_descriptor_ie(pd, offset, len, tree);
+ dissect_q2931_oam_traffic_descriptor_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_ENDPOINT_REFERENCE:
+ dissect_q2931_endpoint_reference_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_ENDPOINT_STATE:
+ dissect_q2931_endpoint_state_ie(tvb, offset, len, tree);
break;
}
}
-void
-dissect_q2931(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+static void
+dissect_q2931_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
+ guint8 info_element, guint8 info_element_ext)
{
- proto_tree *q2931_tree = NULL;
proto_item *ti;
- proto_tree *ext_tree;
proto_tree *ie_tree;
proto_tree *ie_ext_tree;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 1+1+2+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, tvb, offset, 1, "Information element: %s",
+ val_to_str(info_element, q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ ti = proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
+ "Information element extension: 0x%02x",
+ info_element_ext);
+ ie_ext_tree = proto_item_add_subtree(ti, ett_q2931_ie_ext);
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_enumerated_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_CODING_STD, 8,
+ coding_std_vals, "Coding standard: %s"));
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_boolean_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_FOLLOW_INST, 8,
+ "Follow explicit error handling instructions",
+ "Regular error handling procedures apply"));
+ if (info_element_ext & Q2931_IE_COMPAT_FOLLOW_INST) {
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_enumerated_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_ACTION_IND, 8,
+ ie_action_ind_vals,
+ "Action indicator: %s"));
+ }
+ proto_tree_add_text(ie_tree, tvb, offset + 2, 2, "Length: %u", len);
+
+ if ((info_element_ext & Q2931_IE_COMPAT_CODING_STD)
+ == Q2931_ITU_STANDARDIZED_CODING) {
+ dissect_q2931_ie_contents(tvb, offset + 4,
+ len, ie_tree, info_element);
+ } else {
+ /*
+ * We don't know how it's encoded, so just
+ * dump it as data and be done with it.
+ */
+ proto_tree_add_text(ie_tree, tvb, offset + 4, len,
+ "Data: %s", tvb_bytes_to_str(tvb, offset + 4, len));
+ }
+}
+
+static void
+dissect_q2931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *q2931_tree = NULL;
+ proto_item *ti;
+ proto_tree *ext_tree;
guint8 call_ref_len;
guint8 call_ref[15];
guint8 message_type;
int codeset;
gboolean non_locking_shift;
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "Q.2931");
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.2931");
if (tree) {
- ti = proto_tree_add_item(tree, proto_q2931, offset,
- END_OF_FRAME, NULL);
+ ti = proto_tree_add_item(tree, proto_q2931, tvb, offset, -1,
+ FALSE);
q2931_tree = proto_item_add_subtree(ti, ett_q2931);
- proto_tree_add_item(q2931_tree, hf_q2931_discriminator, offset, 1, pd[offset]);
+ proto_tree_add_uint(q2931_tree, hf_q2931_discriminator, tvb, offset, 1, tvb_get_guint8(tvb, offset));
}
offset += 1;
- call_ref_len = pd[offset] & 0xF; /* XXX - do as a bit field? */
+ call_ref_len = tvb_get_guint8(tvb, 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);
+ proto_tree_add_uint(q2931_tree, hf_q2931_call_ref_len, tvb, 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);
+ tvb_memcpy(tvb, call_ref, offset, call_ref_len);
+ if (q2931_tree != NULL) {
+ proto_tree_add_boolean(q2931_tree, hf_q2931_call_ref_flag,
+ tvb, offset, 1, (call_ref[0] & 0x80) != 0);
+ call_ref[0] &= 0x7F;
+ proto_tree_add_bytes(q2931_tree, hf_q2931_call_ref, tvb, 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,
+ message_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, 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);
+ proto_tree_add_uint(q2931_tree, hf_q2931_message_type, tvb, offset, 1, message_type);
offset += 1;
- message_type_ext = pd[offset];
+ message_type_ext = tvb_get_guint8(tvb, offset);
if (q2931_tree != NULL) {
- ti = proto_tree_add_item(q2931_tree, hf_q2931_message_type_ext,
+ ti = proto_tree_add_uint(q2931_tree, hf_q2931_message_type_ext, tvb,
offset, 1, message_type_ext);
ext_tree = proto_item_add_subtree(ti, ett_q2931_ext);
- proto_tree_add_item(ext_tree, hf_q2931_message_flag,
+ proto_tree_add_boolean(ext_tree, hf_q2931_message_flag, tvb,
offset, 1, message_type_ext);
if (message_type_ext & Q2931_MSG_TYPE_EXT_FOLLOW_INST) {
- proto_tree_add_item(ext_tree, hf_q2931_message_action_indicator,
+ proto_tree_add_uint(ext_tree, hf_q2931_message_action_indicator, tvb,
offset, 1, message_type_ext);
}
}
offset += 1;
- message_len = pntohs(&pd[offset]);
+ message_len = tvb_get_ntohs(tvb, offset);
if (q2931_tree != NULL)
- proto_tree_add_item(q2931_tree, hf_q2931_message_len, offset, 2, message_len);
+ proto_tree_add_uint(q2931_tree, hf_q2931_message_len, tvb, offset, 2, message_len);
offset += 2;
/*
*/
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 */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ info_element = tvb_get_guint8(tvb, offset);
+ info_element_ext = tvb_get_guint8(tvb, offset + 1);
+ info_element_len = tvb_get_ntohs(tvb, offset + 2);
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 (0x%02X)"));
- ti = proto_tree_add_text(ie_tree, offset + 1, 1,
- "Information element extension: 0x%02x",
- info_element_ext);
- ie_ext_tree = proto_item_add_subtree(ti, ett_q2931_ie_ext);
- proto_tree_add_text(ie_ext_tree, offset + 1, 1,
- decode_enumerated_bitfield(info_element_ext,
- Q2931_IE_COMPAT_CODING_STD, 8,
- coding_std_vals, "Coding standard: %s"));
- proto_tree_add_text(ie_ext_tree, offset + 1, 1,
- decode_boolean_bitfield(info_element_ext,
- Q2931_IE_COMPAT_FOLLOW_INST, 8,
- "Follow explicit error handling instructions",
- "Regular error handling procedures apply"));
- if (info_element_ext & Q2931_IE_COMPAT_FOLLOW_INST) {
- proto_tree_add_text(ie_ext_tree, offset + 1, 1,
- decode_enumerated_bitfield(info_element_ext,
- Q2931_IE_COMPAT_ACTION_IND, 8,
- ie_action_ind_vals,
- "Action indicator: %s"));
- }
- proto_tree_add_text(ie_tree, offset + 2, 2,
- "Length: %u", info_element_len);
-
- if ((info_element_ext & Q2931_IE_COMPAT_CODING_STD)
- == Q2931_ITU_STANDARDIZED_CODING) {
- dissect_q2931_ie(pd, offset + 4,
- info_element_len, ie_tree, info_element);
- } else {
- /*
- * We don't know how it's encoded, so just
- * dump it as data and be done with it.
- */
- proto_tree_add_text(ie_tree, offset + 4,
- info_element_len,
- "Data: %s",
- bytes_to_str(&pd[offset + 4],
- info_element_len));
- }
+ dissect_q2931_ie(tvb, offset, info_element_len,
+ q2931_tree, info_element, info_element_ext);
}
if (non_locking_shift)
codeset = 0;
case Q2931_IE_BBAND_LOCKING_SHIFT:
if (info_element_len >= 1) {
non_locking_shift = FALSE;
- codeset = pd[offset + 4] & 0x07;
+ codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
}
break;
case Q2931_IE_BBAND_NLOCKING_SHIFT:
if (info_element_len >= 1) {
non_locking_shift = TRUE;
- codeset = pd[offset + 4] & 0x07;
+ codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
}
break;
}
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_flag,
- { "Flag", "q2931.message_flag", FT_BOOLEAN, 8, TFS(&tos_msg_flag), Q2931_MSG_TYPE_EXT_FOLLOW_INST,
- "" }},
-
- { &hf_q2931_message_action_indicator,
- { "Action indicator", "q2931.message_action_indicator", FT_UINT8, BASE_DEC, VALS(msg_action_ind_vals), Q2931_MSG_TYPE_EXT_ACTION_IND,
- "" }},
-
- { &hf_q2931_message_len,
- { "Message length", "q2931.message_len", FT_UINT16, BASE_DEC, NULL, 0x0,
- "" }},
-
- };
- static gint *ett[] = {
- &ett_q2931,
- &ett_q2931_ext,
- &ett_q2931_ie,
- &ett_q2931_ie_ext,
- };
-
- 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));
+ static hf_register_info hf[] = {
+ { &hf_q2931_discriminator,
+ { "Protocol discriminator", "q2931.disc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref_len,
+ { "Call reference value length", "q2931.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref_flag,
+ { "Call reference flag", "q2931.call_ref_flag", FT_BOOLEAN, BASE_NONE, TFS(&tfs_call_ref_flag), 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref,
+ { "Call reference value", "q2931.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_type,
+ { "Message type", "q2931.message_type", FT_UINT8, BASE_HEX, VALS(q2931_message_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_type_ext,
+ { "Message type extension", "q2931.message_type_ext", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_flag,
+ { "Flag", "q2931.message_flag", FT_BOOLEAN, 8, TFS(&tos_msg_flag), Q2931_MSG_TYPE_EXT_FOLLOW_INST,
+ "", HFILL }},
+
+ { &hf_q2931_message_action_indicator,
+ { "Action indicator", "q2931.message_action_indicator", FT_UINT8, BASE_DEC, VALS(msg_action_ind_vals), Q2931_MSG_TYPE_EXT_ACTION_IND,
+ "", HFILL }},
+
+ { &hf_q2931_message_len,
+ { "Message length", "q2931.message_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_q2931,
+ &ett_q2931_ext,
+ &ett_q2931_ie,
+ &ett_q2931_ie_ext,
+ &ett_q2931_nsap,
+ };
+
+ proto_q2931 = proto_register_protocol("Q.2931", "Q.2931", "q2931");
+ proto_register_field_array (proto_q2931, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("q2931", dissect_q2931, proto_q2931);
}