From Tomas Kukosa: reassemble segmented Q.931 messages.

svn path=/trunk/; revision=10124
This commit is contained in:
Guy Harris 2004-02-20 10:34:42 +00:00
parent 257a117d11
commit cea8bc3801
2 changed files with 161 additions and 4 deletions

View File

@ -1040,6 +1040,7 @@ Tomas Kukosa <tomas.kukosa [AT] siemens.com> {
Support in Wiretap for DLT_HHDLC
Fix to summary-printing code to handle reallocated line buffer
Support for registering subdissectors for Q.931 IEs and codesets
Reassembly of segmented Q.931 messages
}
Andreas Stockmeier <a.stockmeier[AT]avm.de> {

View File

@ -2,7 +2,7 @@
* Routines for Q.931 frame disassembly
* Guy Harris <guy@alum.mit.edu>
*
* $Id: packet-q931.c,v 1.69 2004/02/18 20:43:37 guy Exp $
* $Id: packet-q931.c,v 1.70 2004/02/20 10:34:42 guy Exp $
*
* Modified by Andreas Sikkema for possible use with H.323
*
@ -37,6 +37,7 @@
#include "nlpid.h"
#include "packet-q931.h"
#include "prefs.h"
#include "reassemble.h"
#include "lapd_sapi.h"
#include "packet-tpkt.h"
@ -74,9 +75,43 @@ 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_segments = -1;
static int hf_q931_segment = -1;
static int hf_q931_segment_overlap = -1;
static int hf_q931_segment_overlap_conflict = -1;
static int hf_q931_segment_multiple_tails = -1;
static int hf_q931_segment_too_long_segment = -1;
static int hf_q931_segment_error = -1;
static int hf_q931_reassembled_in = -1;
static gint ett_q931 = -1;
static gint ett_q931_ie = -1;
static gint ett_q931_segments = -1;
static gint ett_q931_segment = -1;
static const fragment_items q931_frag_items = {
&ett_q931_segment,
&ett_q931_segments,
&hf_q931_segments,
&hf_q931_segment,
&hf_q931_segment_overlap,
&hf_q931_segment_overlap_conflict,
&hf_q931_segment_multiple_tails,
&hf_q931_segment_too_long_segment,
&hf_q931_segment_error,
&hf_q931_reassembled_in,
"segments"
};
/* Tables for reassembly of fragments. */
static GHashTable *q931_fragment_table = NULL;
static GHashTable *q931_reassembled_table = NULL;
/* Preferences */
static gboolean q931_reassembly = TRUE;
static dissector_table_t codeset_dissector_table;
static dissector_table_t ie_dissector_table;
@ -2285,10 +2320,18 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
{
int offset = 0;
proto_tree *q931_tree = NULL;
proto_item *ti;
proto_tree *ie_tree = NULL;
proto_item *ti, *ti_ie;
guint8 call_ref_len;
guint8 call_ref[15];
guint8 message_type;
guint32 call_ref_val;
guint8 message_type, segmented_message_type;
guint8 info_element;
guint16 info_element_len;
gboolean more_frags;
guint32 frag_len;
fragment_data *fd_head;
tvbuff_t *next_tvb = NULL;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.931");
@ -2305,6 +2348,13 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (q931_tree != NULL)
proto_tree_add_uint(q931_tree, hf_q931_call_ref_len, tvb, offset, 1, call_ref_len);
offset += 1;
switch (call_ref_len) {
case 0: call_ref_val = 0; break;
case 1: call_ref_val = tvb_get_guint8(tvb, offset); break;
case 2: call_ref_val = tvb_get_ntohs(tvb, offset); break;
case 3: call_ref_val = tvb_get_ntoh24(tvb, offset); break;
default: call_ref_val = tvb_get_ntohl(tvb, offset);
}
if (call_ref_len != 0) {
tvb_memcpy(tvb, call_ref, offset, call_ref_len);
if (q931_tree != NULL) {
@ -2329,7 +2379,58 @@ dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/*
* And now for the information elements....
*/
dissect_q931_IEs(tvb, pinfo, tree, q931_tree,is_tpkt, offset);
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);
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);
return;
}
/* Segmented message IE */
ti_ie = proto_tree_add_text(q931_tree, tvb, offset, 1+1+info_element_len, "%s",
val_to_str(info_element, q931_info_element_vals[0], "Unknown information element (0x%02X)"));
ie_tree = proto_item_add_subtree(ti_ie, ett_q931_ie);
proto_tree_add_text(ie_tree, tvb, offset, 1, "Information element: %s",
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;
segmented_message_type = tvb_get_guint8(tvb, offset + 3);
offset += 1 + 1 + info_element_len;
/* Reassembly */
frag_len = tvb_length_remaining(tvb, offset);
fd_head = fragment_add_seq_next(tvb, offset, pinfo, call_ref_val,
q931_fragment_table, q931_reassembled_table,
frag_len, more_frags);
if (fd_head) {
if (pinfo->fd->num == fd_head->reassembled_in) { /* last fragment */
if (fd_head->next != NULL) { /* 2 or more segments */
next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
tvb_set_child_real_data_tvbuff(tvb, next_tvb);
add_new_data_source(pinfo, next_tvb, "Reassembled Q.931 IEs");
/* Show all fragments. */
if (tree) show_fragment_seq_tree(fd_head, &q931_frag_items, q931_tree, pinfo, next_tvb);
} else { /* only 1 segment */
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
}
if (check_col(pinfo->cinfo, COL_INFO)) {
col_add_fstr(pinfo->cinfo, COL_INFO, "%s [reassembled]",
val_to_str(segmented_message_type, q931_message_type_vals, "Unknown message type (0x%02X)"));
}
} 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);
}
static const value_string q931_codeset_vals[] = {
@ -2842,6 +2943,13 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
dissect_q931_pdu(tvb, pinfo, tree, FALSE);
}
static void
q931_init(void) {
/* Initialize the fragment and reassembly tables */
fragment_table_init(&q931_fragment_table);
reassembled_table_init(&q931_reassembled_table);
}
void
proto_register_q931(void)
{
@ -2922,16 +3030,60 @@ proto_register_q931(void)
{ &hf_q931_redirecting_number,
{ "Redirecting party number digits", "q931.redirecting_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
"", HFILL }},
/* desegmentation fields */
{ &hf_q931_segment_overlap,
{ "Segment overlap", "q931.segment.overlap",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Fragment overlaps with other fragments"}
},
{ &hf_q931_segment_overlap_conflict,
{ "Conflicting data in fragment overlap", "q931.segment.overlap.conflict",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Overlapping fragments contained conflicting data"}
},
{ &hf_q931_segment_multiple_tails,
{ "Multiple tail fragments found", "q931.segment.multipletails",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Several tails were found when defragmenting the packet"}
},
{ &hf_q931_segment_too_long_segment,
{ "Segment too long", "q931.segment.toolongfragment",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Segment contained data past end of packet"}
},
{ &hf_q931_segment_error,
{ "Defragmentation error", "q931.segment.error",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"Defragmentation error due to illegal fragments"}
},
{ &hf_q931_segment,
{ "Q.931 Segment", "q931.segment",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"Q.931 Segment"}
},
{ &hf_q931_segments,
{ "Q.931 Segments", "q931.segments",
FT_NONE, BASE_NONE, NULL, 0x0,
"Q.931 Segments"}
},
{ &hf_q931_reassembled_in,
{ "Reassembled Q.931 in frame", "q931.reassembled_in",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"This Q.931 message is reassembled in this frame"}
},
};
static gint *ett[] = {
&ett_q931,
&ett_q931_ie,
&ett_q931_segments,
&ett_q931_segment,
};
module_t *q931_module;
proto_q931 = proto_register_protocol("Q.931", "Q.931", "q931");
proto_register_field_array (proto_q931, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_init_routine(q931_init);
register_dissector("q931", dissect_q931, proto_q931);
q931_tpkt_pdu_handle = create_dissector_handle(dissect_q931_tpkt_pdu,
@ -2946,6 +3098,10 @@ proto_register_q931(void)
"Desegment all Q.931 messages spanning multiple TCP segments",
"Whether the Q.931 dissector should desegment all messages spanning multiple TCP segments",
&q931_desegment);
prefs_register_bool_preference(q931_module, "reassembly",
"Reassembly segmented Q.931 messages",
"Reassembly segmented Q.931 messages (Q.931 - Annex H)",
&q931_reassembly);
}
void