* Routines for Q.931 frame disassembly
* Guy Harris <guy@alum.mit.edu>
*
- * $Id: packet-q931.c,v 1.72 2004/02/21 04:19:12 guy Exp $
+ * $Id: packet-q931.c,v 1.76 2004/04/17 04:43:58 guy Exp $
*
* Modified by Andreas Sikkema for possible use with H.323
*
#include <epan/strutil.h>
#include "nlpid.h"
#include "packet-q931.h"
+#include "packet-e164.h"
#include "prefs.h"
#include "reassemble.h"
static int hf_q931_call_ref = -1;
static int hf_q931_message_type = -1;
static int hf_q931_segment_type = -1;
+static int hf_q931_cause_location = -1;
static int hf_q931_cause_value = -1;
static int hf_q931_number_type = -1;
static int hf_q931_numbering_plan = -1;
static int hf_q931_called_party_number = -1;
static int hf_q931_connected_number = -1;
static int hf_q931_redirecting_number = -1;
+static int hf_q931_screening_ind = -1;
+static int hf_q931_presentation_ind = -1;
static int hf_q931_segments = -1;
static int hf_q931_segment = -1;
&hf_q931_segment_multiple_tails,
&hf_q931_segment_too_long_segment,
&hf_q931_segment_error,
- &hf_q931_reassembled_in,
+ &hf_q931_reassembled_in,
"segments"
};
static dissector_handle_t h225_handle;
static dissector_handle_t q931_tpkt_pdu_handle;
+static void
+dissect_q931_IEs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root_tree,
+ proto_tree *q931_tree, gboolean is_tpkt, int offset, int initial_codeset);
+
/*
* Q.931 message types.
*/
return;
octet = tvb_get_guint8(tvb, offset);
coding_standard = octet & 0x60;
- proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
/*
* We don't know how the cause is encoded,
* so just dump it as data and be done with it.
*/
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
proto_tree_add_text(tree, tvb, offset,
len, "Data: %s",
tvb_bytes_to_str(tvb, offset, len));
return;
}
- proto_tree_add_text(tree, tvb, offset, 1,
- "Location: %s",
- val_to_str(octet & 0x0F, q931_cause_location_vals,
- "Unknown (0x%X)"));
+ proto_tree_add_uint(tree, hf_q931_cause_location, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
offset += 1;
len -= 1;
"Recommendation: %s",
val_to_str(octet & 0x7F, q931_cause_recommendation_vals,
"Unknown (0x%02X)"));
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
offset += 1;
len -= 1;
}
octet = tvb_get_guint8(tvb, offset);
cause_value = octet & 0x7F;
proto_tree_add_uint(tree, hf_cause_value, tvb, offset, 1, cause_value);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
offset += 1;
len -= 1;
static const value_string q931_presentation_indicator_vals[] = {
{ 0x00, "Presentation allowed" },
- { 0x20, "Presentation restricted" },
- { 0x40, "Number not available due to interworking" },
+ { 0x01, "Presentation restricted" },
+ { 0x02, "Number not available due to interworking" },
{ 0, NULL }
};
static void
dissect_q931_number_ie(tvbuff_t *tvb, int offset, int len,
- proto_tree *tree, int hfindex)
+ proto_tree *tree, int hfindex, e164_info_t e164_info)
{
guint8 octet;
+ gint number_plan;
if (len == 0)
return;
octet = tvb_get_guint8(tvb, offset);
+ number_plan = octet & 0x0f;
+ e164_info.nature_of_address = ( octet & 0x70 ) >> 4;
proto_tree_add_uint(tree, hf_q931_numbering_plan, tvb, offset, 1, octet);
proto_tree_add_uint(tree, hf_q931_number_type, tvb, offset, 1, octet);
proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
if (len == 0)
return;
octet = tvb_get_guint8(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 1,
- "Presentation indicator: %s",
- val_to_str(octet & 0x60, q931_presentation_indicator_vals,
- "Unknown (0x%X)"));
- proto_tree_add_text(tree, tvb, offset, 1,
- "Screening indicator: %s",
- val_to_str(octet & 0x03, q931_screening_indicator_vals,
- "Unknown (0x%X)"));
+ proto_tree_add_uint(tree, hf_q931_screening_ind, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_presentation_ind, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
offset += 1;
len -= 1;
}
if (len == 0)
return;
proto_tree_add_item(tree, hfindex, tvb, offset, len, FALSE);
+ proto_item_append_text(proto_tree_get_parent(tree), ": '%s'", tvb_format_text(tvb, offset, len));
+
+ if ( number_plan == 1 ) {
+ if ( e164_info.e164_number_type != NONE ){
+
+ e164_info.E164_number_str = tvb_get_string(tvb, offset, len);
+ e164_info.E164_number_length = len;
+ dissect_e164_number(tvb, tree, offset, len, e164_info);
+ }
+ }
+
}
/*
if (len != 0) {
proto_tree_add_text(tree, tvb, offset, len, "%s: %s", label,
tvb_format_text(tvb, offset, len));
+ proto_item_append_text(proto_tree_get_parent(tree), " '%s'", tvb_format_text(tvb, offset, len));
}
}
*/
if ((message_type != Q931_SEGMENT) || !q931_reassembly ||
(tvb_reported_length_remaining(tvb, offset) <= 4)) {
- dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset);
+ dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset, 0);
return;
}
info_element = tvb_get_guint8(tvb, offset);
info_element_len = tvb_get_guint8(tvb, offset + 1);
if ((info_element != Q931_IE_SEGMENTED_MESSAGE) || (info_element_len < 2)) {
- dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset);
+ dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset, 0);
return;
}
/* Segmented message IE */
val_to_str(info_element, q931_info_element_vals[0], "Unknown (0x%02X)"));
proto_tree_add_text(ie_tree, tvb, offset + 1, 1, "Length: %u", info_element_len);
dissect_q931_segmented_message_ie(tvb, offset + 2, info_element_len, ie_tree);
- more_frags = (tvb_get_guint8(tvb, offset + 2) & 0x7F) != 0;
+ more_frags = (tvb_get_guint8(tvb, offset + 2) & 0x7F) != 0;
segmented_message_type = tvb_get_guint8(tvb, offset + 3);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " of %s",
+ val_to_str(segmented_message_type, q931_message_type_vals, "Unknown message type (0x%02X)"));
+ }
offset += 1 + 1 + info_element_len;
/* Reassembly */
frag_len = tvb_length_remaining(tvb, offset);
} else {
if (tree) proto_tree_add_uint(q931_tree, hf_q931_reassembled_in, tvb, offset, frag_len, fd_head->reassembled_in);
}
- } else {
- if (check_col(pinfo->cinfo, COL_INFO)) {
- col_append_str(pinfo->cinfo, COL_INFO, " [segment]");
- }
}
- if (next_tvb)
- dissect_q931_IEs(next_tvb, pinfo, tree, q931_tree, is_tpkt, 0);
+ if (next_tvb)
+ dissect_q931_IEs(next_tvb, pinfo, tree, q931_tree, is_tpkt, 0, 0);
}
static const value_string q931_codeset_vals[] = {
{ 0x00, NULL },
};
-void
-dissect_q931_IEs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- proto_tree *q931_tree, gboolean is_tpkt, int offset)
+static void
+dissect_q931_IEs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root_tree,
+ proto_tree *q931_tree, gboolean is_tpkt, int offset, int initial_codeset)
{
proto_item *ti;
proto_tree *ie_tree = NULL;
int codeset, locked_codeset;
gboolean non_locking_shift, first_segment;
tvbuff_t *h225_tvb, *next_tvb;
+ e164_info_t e164_info;
+ e164_info.e164_number_type = NONE;
- codeset = locked_codeset = 0; /* start out in codeset 0 */
+ codeset = locked_codeset = initial_codeset;
non_locking_shift = TRUE;
first_segment = FALSE;
while (tvb_reported_length_remaining(tvb, offset) > 0) {
offset + 4, info_element_len - 1,
info_element_len - 1);
call_dissector(h225_handle, h225_tvb,
- pinfo, tree);
+ pinfo, root_tree);
} else {
/*
* No - just show it as "User
break;
case CS0 | Q931_IE_CALLING_PARTY_NUMBER:
+ e164_info.e164_number_type = CALLING_PARTY_NUMBER;
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
- hf_q931_calling_party_number);
+ hf_q931_calling_party_number, e164_info);
break;
case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
- hf_q931_connected_number);
+ hf_q931_connected_number, e164_info);
break;
case CS0 | Q931_IE_CALLED_PARTY_NUMBER:
+ e164_info.e164_number_type = CALLED_PARTY_NUMBER;
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
- hf_q931_called_party_number);
+ hf_q931_called_party_number, e164_info);
break;
case CS0 | Q931_IE_REDIRECTING_NUMBER:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
- hf_q931_redirecting_number);
+ hf_q931_redirecting_number, e164_info);
break;
case CS0 | Q931_IE_CALLING_PARTY_SUBADDR:
dissect_q931_pdu(tvb, pinfo, tree, FALSE);
}
+static void
+dissect_q931_ie_cs0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_IEs(tvb, pinfo, NULL, tree, FALSE, 0, 0);
+}
+
+static void
+dissect_q931_ie_cs7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_IEs(tvb, pinfo, NULL, tree, FALSE, 0, 7);
+}
+
static void
q931_init(void) {
/* Initialize the fragment and reassembly tables */
{ "User information layer 1 protocol", "q931.uil1", FT_UINT8, BASE_HEX,
VALS(q931_uil1_vals), 0x1f,"", HFILL }},
+ { &hf_q931_cause_location,
+ { "Cause location", "q931.cause_location", FT_UINT8, BASE_DEC, VALS(q931_cause_location_vals), 0x0f,
+ "", HFILL }},
+
{ &hf_q931_cause_value,
- { "Cause value", "q931.cause_value", FT_UINT8, BASE_DEC, VALS(q931_cause_code_vals), 0x0,
+ { "Cause value", "q931.cause_value", FT_UINT8, BASE_DEC, VALS(q931_cause_code_vals), 0x7f,
"", HFILL }},
{ &hf_q931_number_type,
{ "Numbering plan", "q931.numbering_plan", FT_UINT8, BASE_HEX, VALS(q931_numbering_plan_vals), 0x0f,
"", HFILL }},
+ { &hf_q931_screening_ind,
+ { "Screening indicator", "q931.screening_ind", FT_UINT8, BASE_HEX, VALS(q931_screening_indicator_vals), 0x03,
+ "", HFILL }},
+
+ { &hf_q931_presentation_ind,
+ { "Presentation indicator", "q931.presentation_ind", FT_UINT8, BASE_HEX, VALS(q931_presentation_indicator_vals), 0x60,
+ "", HFILL }},
+
{ &hf_q931_extension_ind,
{ "Extension indicator", "q931.extension_ind",
FT_BOOLEAN, 8, TFS(&q931_extension_ind_value), 0x80,
register_dissector("q931", dissect_q931, proto_q931);
q931_tpkt_pdu_handle = create_dissector_handle(dissect_q931_tpkt_pdu,
proto_q931);
+ register_dissector("q931.ie", dissect_q931_ie_cs0, proto_q931);
+ register_dissector("q931.ie.cs7", dissect_q931_ie_cs7, proto_q931);
/* subdissector code */
codeset_dissector_table = register_dissector_table("q931.codeset", "Q.931 Codeset", FT_UINT8, BASE_HEX);