aboutsummaryrefslogtreecommitdiffstats
path: root/packet-q931.c
diff options
context:
space:
mode:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-08-05 17:39:23 +0000
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-08-05 17:39:23 +0000
commit9957aab58159c048c226272233637fd1418cf6cd (patch)
treec901890431d390fba63d3f1812ae4381ca5df04b /packet-q931.c
parent3495a90f04bd2d0a340d54d27f2e792eacf56882 (diff)
From Tomas Kukosa:
use the codeset value; allow subdissectors for user-specific IEs, and for codesets, to be registered. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@8138 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'packet-q931.c')
-rw-r--r--packet-q931.c213
1 files changed, 150 insertions, 63 deletions
diff --git a/packet-q931.c b/packet-q931.c
index ab5cc80957..8ce0a3c9bb 100644
--- a/packet-q931.c
+++ b/packet-q931.c
@@ -2,7 +2,7 @@
* Routines for Q.931 frame disassembly
* Guy Harris <guy@alum.mit.edu>
*
- * $Id: packet-q931.c,v 1.56 2003/07/08 07:56:27 guy Exp $
+ * $Id: packet-q931.c,v 1.57 2003/08/05 17:39:23 guy Exp $
*
* Modified by Andreas Sikkema for possible use with H.323
*
@@ -67,6 +67,9 @@ static int hf_q931_redirecting_number = -1;
static gint ett_q931 = -1;
static gint ett_q931_ie = -1;
+static dissector_table_t codeset_dissector_table;
+static dissector_table_t ie_dissector_table;
+
/* desegmentation of Q.931 over TPKT over TCP */
static gboolean q931_desegment = TRUE;
@@ -158,6 +161,16 @@ static const true_false_string tfs_call_ref_flag = {
* Information elements.
*/
+/* Shifted codeset values */
+#define CS0 0x000
+#define CS1 0x100
+#define CS2 0x200
+#define CS3 0x300
+#define CS4 0x400
+#define CS5 0x500
+#define CS6 0x600
+#define CS7 0x700
+
#define Q931_IE_SO_MASK 0x80 /* single-octet/variable-length mask */
/*
* Single-octet IEs.
@@ -261,7 +274,8 @@ static const true_false_string tfs_call_ref_flag = {
/* 0x76 is Redirection Number, but that's also Codeset 0 */
#define Q931_IE_CALL_APPEARANCE 0x7B
-static const value_string q931_info_element_vals[] = {
+/* Codeset 0 */
+static const value_string q931_info_element_vals0[] = {
{ Q931_IE_SEGMENTED_MESSAGE, "Segmented message" },
{ Q931_IE_BEARER_CAPABILITY, "Bearer capability" },
{ Q931_IE_CAUSE, "Cause" },
@@ -305,13 +319,53 @@ static const value_string q931_info_element_vals[] = {
{ Q931_IE_ESCAPE, "Escape" },
{ Q931_IE_CONNECTED_NUMBER, "Connected number" },
{ Q931_IE_CONNECTED_SUBADDR, "Connected subaddress" },
+ { 0, NULL }
+};
+/* Codeset 1 */
+static const value_string q931_info_element_vals1[] = {
+ { 0, NULL }
+};
+/* Codeset 2 */
+static const value_string q931_info_element_vals2[] = {
+ { 0, NULL }
+};
+/* Codeset 3 */
+static const value_string q931_info_element_vals3[] = {
+ { 0, NULL }
+};
+/* Codeset 4 */
+static const value_string q931_info_element_vals4[] = {
+ { 0, NULL }
+};
+/* Codeset 5 */
+static const value_string q931_info_element_vals5[] = {
{ Q931_IE_CHARGING_ADVICE, "Charging advice" },
{ Q931_IE_OPERATOR_SYSTEM_ACCESS, "Operator system access" },
+ { 0, NULL }
+};
+/* Codeset 6 */
+static const value_string q931_info_element_vals6[] = {
{ Q931_IE_REDIRECTING_NUMBER, "Redirecting number" },
{ Q931_IE_REDIRECTING_SUBADDR, "Redirecting subaddress" },
{ Q931_IE_CALL_APPEARANCE, "Call appearance" },
{ 0, NULL }
};
+/* Codeset 7 */
+static const value_string q931_info_element_vals7[] = {
+ { 0, NULL }
+};
+
+/* Codeset array */
+static const value_string *q931_info_element_vals[] = {
+ q931_info_element_vals0,
+ q931_info_element_vals1,
+ q931_info_element_vals2,
+ q931_info_element_vals3,
+ q931_info_element_vals4,
+ q931_info_element_vals5,
+ q931_info_element_vals6,
+ q931_info_element_vals7,
+};
static const value_string q931_congestion_level_vals[] = {
{ 0x0, "Receiver ready" },
@@ -1162,14 +1216,14 @@ dissect_q931_cause_ie(tvbuff_t *tvb, int offset, int len,
case Q931_REJ_IE_MISSING:
proto_tree_add_text(tree, tvb, offset, 1,
"Missing information element: %s",
- val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals,
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
"Unknown (0x%02X)"));
break;
case Q931_REJ_IE_INSUFFICIENT:
proto_tree_add_text(tree, tvb, offset, 1,
"Insufficient information element: %s",
- val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals,
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
"Unknown (0x%02X)"));
break;
@@ -1189,7 +1243,7 @@ dissect_q931_cause_ie(tvbuff_t *tvb, int offset, int len,
do {
proto_tree_add_text(tree, tvb, offset, 1,
"Information element: %s",
- val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals,
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
"Unknown (0x%02X)"));
offset += 1;
len -= 1;
@@ -2262,7 +2316,7 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint16 info_element_len;
int codeset, locked_codeset;
gboolean non_locking_shift;
- tvbuff_t *h225_tvb;
+ tvbuff_t *h225_tvb, *next_tvb;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.931");
@@ -2308,29 +2362,45 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
while (tvb_reported_length_remaining(tvb, offset) > 0) {
info_element = tvb_get_guint8(tvb, offset);
+ /* Check for the codeset shift */
+ if ((info_element & Q931_IE_SO_MASK) &&
+ ((info_element & Q931_IE_SO_IDENTIFIER_MASK) == Q931_IE_SHIFT)) {
+ non_locking_shift = info_element & Q931_IE_SHIFT_NON_LOCKING;
+ codeset = info_element & Q931_IE_SHIFT_CODESET;
+ if (!non_locking_shift)
+ locked_codeset = codeset;
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "%s shift to codeset %u: %s",
+ (non_locking_shift ? "Non-locking" : "Locking"),
+ codeset,
+ val_to_str(codeset, q931_codeset_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ continue;
+ }
+
/*
* Check for the single-octet IEs.
*/
if (info_element & Q931_IE_SO_MASK) {
- switch (info_element & Q931_IE_SO_IDENTIFIER_MASK) {
- case Q931_IE_SHIFT:
- non_locking_shift = info_element & Q931_IE_SHIFT_NON_LOCKING;
- codeset = info_element & Q931_IE_SHIFT_CODESET;
- if (!non_locking_shift)
- locked_codeset = codeset;
- if (q931_tree != NULL) {
- proto_tree_add_text(q931_tree, tvb, offset, 1,
- "%s shift to codeset %u: %s",
- (non_locking_shift ? "Non-locking" : "Locking"),
- codeset,
- val_to_str(codeset, q931_codeset_vals,
- "Unknown (0x%02X)"));
- }
- offset += 1;
- continue;
-
- case Q931_IE_MORE_DATA_OR_SEND_COMP:
+ /* check for subdissectors */
+ if (dissector_get_port_handle(codeset_dissector_table, codeset) ||
+ dissector_get_port_handle(ie_dissector_table, (codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK))) {
+ next_tvb = tvb_new_subset (tvb, offset, 1, 1);
+ if (dissector_try_port(ie_dissector_table, (codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK), next_tvb, pinfo, q931_tree) ||
+ dissector_try_port(codeset_dissector_table, codeset, next_tvb, pinfo, q931_tree)) {
+ offset += 1;
+ codeset = locked_codeset;
+ continue;
+ }
+ }
+
+ switch ((codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK)) {
+
+ case CS0 | Q931_IE_MORE_DATA_OR_SEND_COMP:
switch (info_element) {
case Q931_IE_MORE_DATA:
@@ -2357,7 +2427,7 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
break;
- case Q931_IE_CONGESTION_LEVEL:
+ case CS0 | Q931_IE_CONGESTION_LEVEL:
if (q931_tree != NULL) {
proto_tree_add_text(q931_tree, tvb, offset, 1,
"Congestion level: %s",
@@ -2367,7 +2437,7 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
break;
- case Q931_IE_REPEAT_INDICATOR:
+ case CS0 | Q931_IE_REPEAT_INDICATOR:
if (q931_tree != NULL) {
proto_tree_add_text(q931_tree, tvb, offset, 1,
"Repeat indicator: %s",
@@ -2402,21 +2472,21 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* IE with ASN.1 encoding of the user information.
*/
if (is_tpkt && tvb_bytes_exist(tvb, offset, 4) &&
- tvb_get_guint8(tvb, offset) == Q931_IE_USER_USER &&
+ codeset == 0 && tvb_get_guint8(tvb, offset) == Q931_IE_USER_USER &&
tvb_get_guint8(tvb, offset + 3) == Q931_PROTOCOL_DISCRIMINATOR_ASN1) {
info_element_len = tvb_get_ntohs(tvb, offset + 1);
if (q931_tree != NULL) {
ti = proto_tree_add_text(q931_tree, tvb, offset,
1+2+info_element_len, "%s",
val_to_str(info_element,
- q931_info_element_vals,
+ q931_info_element_vals[codeset],
"Unknown information element (0x%02X)"));
ie_tree = proto_item_add_subtree(ti,
ett_q931_ie);
proto_tree_add_text(ie_tree, tvb, offset, 1,
"Information element: %s",
val_to_str(info_element,
- q931_info_element_vals, "Unknown (0x%02X)"));
+ q931_info_element_vals[codeset], "Unknown (0x%02X)"));
proto_tree_add_text(ie_tree, tvb, offset + 1,
2, "Length: %u", info_element_len);
proto_tree_add_text(ie_tree, tvb, offset + 3,
@@ -2458,192 +2528,205 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
offset += 1 + 2 + info_element_len;
} else {
info_element_len = tvb_get_guint8(tvb, offset + 1);
+
+ /* check for subdissectors */
+ if (dissector_get_port_handle(codeset_dissector_table, codeset) ||
+ dissector_get_port_handle(ie_dissector_table, (codeset << 8) | info_element)) {
+ next_tvb = tvb_new_subset (tvb, offset, info_element_len + 2, info_element_len + 2);
+ if (dissector_try_port(ie_dissector_table, (codeset << 8) | info_element, next_tvb, pinfo, q931_tree) ||
+ dissector_try_port(codeset_dissector_table, codeset, next_tvb, pinfo, q931_tree)) {
+ offset += 2 + info_element_len;;
+ codeset = locked_codeset;
+ continue;
+ }
+ }
+
if (q931_tree != NULL) {
ti = proto_tree_add_text(q931_tree, tvb, offset,
1+1+info_element_len, "%s",
- val_to_str(info_element, q931_info_element_vals,
+ val_to_str(info_element, q931_info_element_vals[codeset],
"Unknown information element (0x%02X)"));
ie_tree = proto_item_add_subtree(ti, ett_q931_ie);
proto_tree_add_text(ie_tree, tvb, offset, 1,
"Information element: %s",
- val_to_str(info_element, q931_info_element_vals,
+ val_to_str(info_element, q931_info_element_vals[codeset],
"Unknown (0x%02X)"));
proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
"Length: %u", info_element_len);
- switch (info_element) {
+ switch ((codeset << 8) | info_element) {
- case Q931_IE_SEGMENTED_MESSAGE:
+ case CS0 | Q931_IE_SEGMENTED_MESSAGE:
dissect_q931_segmented_message_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_BEARER_CAPABILITY:
- case Q931_IE_LOW_LAYER_COMPAT:
+ case CS0 | Q931_IE_BEARER_CAPABILITY:
+ case CS0 | Q931_IE_LOW_LAYER_COMPAT:
dissect_q931_bearer_capability_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_CAUSE:
+ case CS0 | Q931_IE_CAUSE:
dissect_q931_cause_ie(tvb,
offset + 2, info_element_len,
ie_tree,
hf_q931_cause_value);
break;
- case Q931_IE_CALL_STATE:
+ case CS0 | Q931_IE_CALL_STATE:
dissect_q931_call_state_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_CHANNEL_IDENTIFICATION:
+ case CS0 | Q931_IE_CHANNEL_IDENTIFICATION:
dissect_q931_channel_identification_ie(
tvb, offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_PROGRESS_INDICATOR:
+ case CS0 | Q931_IE_PROGRESS_INDICATOR:
dissect_q931_progress_indicator_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_NETWORK_SPECIFIC_FACIL:
- case Q931_IE_TRANSIT_NETWORK_SEL:
+ case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL:
+ case CS0 | Q931_IE_TRANSIT_NETWORK_SEL:
dissect_q931_ns_facilities_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_NOTIFICATION_INDICATOR:
+ case CS0 | Q931_IE_NOTIFICATION_INDICATOR:
dissect_q931_notification_indicator_ie(
tvb, offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_DISPLAY:
+ case CS0 | Q931_IE_DISPLAY:
dissect_q931_ia5_ie(tvb, offset + 2,
info_element_len, ie_tree,
"Display information");
break;
- case Q931_IE_DATE_TIME:
+ case CS0 | Q931_IE_DATE_TIME:
dissect_q931_date_time_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_KEYPAD_FACILITY:
+ case CS0 | Q931_IE_KEYPAD_FACILITY:
dissect_q931_ia5_ie(tvb, offset + 2,
info_element_len, ie_tree,
"Keypad facility");
break;
- case Q931_IE_SIGNAL:
+ case CS0 | Q931_IE_SIGNAL:
dissect_q931_signal_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_INFORMATION_RATE:
+ case CS0 | Q931_IE_INFORMATION_RATE:
dissect_q931_information_rate_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_E2E_TRANSIT_DELAY:
+ case CS0 | Q931_IE_E2E_TRANSIT_DELAY:
dissect_q931_e2e_transit_delay_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_TD_SELECTION_AND_INT:
+ case CS0 | Q931_IE_TD_SELECTION_AND_INT:
dissect_q931_td_selection_and_int_ie(
tvb, offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_PL_BINARY_PARAMETERS:
+ case CS0 | Q931_IE_PL_BINARY_PARAMETERS:
dissect_q931_pl_binary_parameters_ie(
tvb, offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_PL_WINDOW_SIZE:
+ case CS0 | Q931_IE_PL_WINDOW_SIZE:
dissect_q931_pl_window_size_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_PACKET_SIZE:
+ case CS0 | Q931_IE_PACKET_SIZE:
dissect_q931_packet_size_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_CUG:
+ case CS0 | Q931_IE_CUG:
dissect_q931_cug_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_REVERSE_CHARGE_IND:
+ case CS0 | Q931_IE_REVERSE_CHARGE_IND:
dissect_q931_reverse_charge_ind_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_CALLING_PARTY_NUMBER:
+ case CS0 | Q931_IE_CALLING_PARTY_NUMBER:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
hf_q931_calling_party_number);
break;
- case Q931_IE_CONNECTED_NUMBER_DEFAULT:
+ case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
hf_q931_connected_number);
break;
- case Q931_IE_CALLED_PARTY_NUMBER:
+ case CS0 | Q931_IE_CALLED_PARTY_NUMBER:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
hf_q931_called_party_number);
break;
- case Q931_IE_REDIRECTING_NUMBER:
+ case CS0 | Q931_IE_REDIRECTING_NUMBER:
dissect_q931_number_ie(tvb,
offset + 2, info_element_len,
ie_tree,
hf_q931_redirecting_number);
break;
- case Q931_IE_CALLING_PARTY_SUBADDR:
- case Q931_IE_CALLED_PARTY_SUBADDR:
+ case CS0 | Q931_IE_CALLING_PARTY_SUBADDR:
+ case CS0 | Q931_IE_CALLED_PARTY_SUBADDR:
dissect_q931_party_subaddr_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_RESTART_INDICATOR:
+ case CS0 | Q931_IE_RESTART_INDICATOR:
dissect_q931_restart_indicator_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_HIGH_LAYER_COMPAT:
+ case CS0 | Q931_IE_HIGH_LAYER_COMPAT:
dissect_q931_high_layer_compat_ie(tvb,
offset + 2, info_element_len,
ie_tree);
break;
- case Q931_IE_USER_USER:
+ case CS0 | Q931_IE_USER_USER:
dissect_q931_user_user_ie(tvb,
offset + 2, info_element_len,
ie_tree);
@@ -2809,6 +2892,10 @@ proto_register_q931(void)
q931_tpkt_pdu_handle = create_dissector_handle(dissect_q931_tpkt_pdu,
proto_q931);
+ /* subdissector code */
+ codeset_dissector_table = register_dissector_table("q931.codeset", "Q.931 Codeset", FT_UINT8, BASE_HEX);
+ ie_dissector_table = register_dissector_table("q931.ie", "Q.931 IE", FT_UINT16, BASE_HEX);
+
q931_module = prefs_register_protocol(proto_q931, NULL);
prefs_register_bool_preference(q931_module, "desegment_h323_messages",
"Desegment all Q.931 messages spanning multiple TCP segments",