aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Kukosa <tomas.kukosa@siemens.com>2005-09-05 13:25:49 +0000
committerTomas Kukosa <tomas.kukosa@siemens.com>2005-09-05 13:25:49 +0000
commit03a6f6286bebd6d9e743b1ef62259f6c8a02f37c (patch)
tree74a428baf568120d47cc04985b7a2c39ac0e13db
parent44b2d9d828ab8ce9436317c4ae48b8a56a10b42d (diff)
the first attempt at SIP reassembly
svn path=/trunk/; revision=15685
-rw-r--r--epan/dissectors/packet-sip.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c
index b4c6eeba78..3a0a114108 100644
--- a/epan/dissectors/packet-sip.c
+++ b/epan/dissectors/packet-sip.c
@@ -403,6 +403,7 @@ static gboolean global_sip_raw_text = FALSE;
/* strict_sip_version determines whether the SIP dissector enforces
* the SIP version to be "SIP/2.0". */
static gboolean strict_sip_version = TRUE;
+static gboolean sip_desegment = FALSE;
static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, gboolean is_heur);
@@ -947,6 +948,65 @@ dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
return tvb_length(tvb);
}
+static guint
+get_sip_pdu_len(tvbuff_t *tvb, int begin_offset) {
+ int offset;
+ gint next_offset, linelen, content_length;
+ line_type_t line_type;
+ guint tvb_len, token_1_len;
+
+ tvb_len = tvb_length_remaining(tvb, begin_offset);
+ offset = begin_offset;
+ linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
+ line_type = sip_parse_line(tvb, linelen, &token_1_len);
+ if (line_type == OTHER_LINE) return tvb_len;
+ offset = next_offset;
+ content_length = -1;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ gint line_end_offset;
+ gint colon_offset;
+ gint semi_colon_offset;
+ gint hf_index;
+ gint value_offset;
+ guchar c;
+ char *value;
+
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ if (linelen == 0) {
+ /*
+ * This is a blank line separating the
+ * message header from the message body.
+ */
+ if (content_length >= 0)
+ return next_offset + content_length;
+ else
+ return tvb_len;
+ }
+ line_end_offset = offset + linelen;
+ colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
+ if (colon_offset == -1) return tvb_len;
+ hf_index = sip_is_known_sip_header(tvb, offset, colon_offset - offset);
+ if (hf_index == POS_CONTENT_LENGTH) {
+ /* Skip whitespace after the colon. */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset &&
+ ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t'))
+ value_offset++;
+ /* Fetch the value. */
+ value = tvb_get_ephemeral_string(tvb, value_offset, line_end_offset - value_offset);
+ content_length = atoi(value);
+ }
+ offset = next_offset;
+ }
+ return tvb_len;
+}
+
+static void
+dissect_sip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_sip_common(tvb, pinfo, tree, TRUE);
+}
+
static void
dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@@ -957,7 +1017,15 @@ dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
call_dissector(sigcomp_handle, tvb, pinfo, tree);
return;
}
- dissect_sip_common(tvb, pinfo, tree, TRUE);
+ if (sip_desegment) {
+ tcp_dissect_pdus(tvb, pinfo, tree,
+ sip_desegment, /* desegment or not */
+ 36, /* fixed-length part of the PDU */
+ get_sip_pdu_len, /* routine to get the length of the PDU */
+ dissect_sip_pdu); /* routine to dissect a PDU */
+ } else {
+ dissect_sip_common(tvb, pinfo, tree, TRUE);
+ }
}
static gboolean
@@ -2622,6 +2690,10 @@ void proto_register_sip(void)
"Disable it to allow SIP traffic with a different version "
"to be dissected as SIP.",
&strict_sip_version);
+ prefs_register_bool_preference(sip_module, "desegment",
+ "Desegment SIP messages",
+ "Whether the SIP dissector should desegment all messages spanning multiple TCP segments",
+ &sip_desegment);
register_init_routine(&sip_init_protocol);