diff options
author | Guy Harris <guy@alum.mit.edu> | 2003-09-26 21:32:38 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2003-09-26 21:32:38 +0000 |
commit | ae3aa9d05b81f0e9e3bd742a29ef60f79d85c367 (patch) | |
tree | 3ba44983b2948d1969543b21fe78b82f256dca4d /packet-sip.c | |
parent | f3832721d9eecbe400b9707ef9f9e4b22fdbda91 (diff) | |
download | wireshark-ae3aa9d05b81f0e9e3bd742a29ef60f79d85c367.tar.gz |
For (non-heuristic) SIP-over-TCP, dissect stuff that's neither a request
nor a response as continuation data. For SIP-over-everything-else,
reject it.
Parse the headers regardless of whether we're building a protocol tree
or not; if we're not, we just do it to look for a blank line separating
the headers from the body. Do that instead of scanning for the message
body separately.
When scanning for a colon, don't scan past the end of the line.
svn path=/trunk/; revision=8549
Diffstat (limited to 'packet-sip.c')
-rw-r--r-- | packet-sip.c | 249 |
1 files changed, 118 insertions, 131 deletions
diff --git a/packet-sip.c b/packet-sip.c index 59234f8d88..ea8370ff42 100644 --- a/packet-sip.c +++ b/packet-sip.c @@ -17,7 +17,7 @@ * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi> * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com> * - * $Id: packet-sip.c,v 1.43 2003/09/26 20:00:38 guy Exp $ + * $Id: packet-sip.c,v 1.44 2003/09/26 21:32:38 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -260,57 +260,26 @@ typedef enum { /* global_sip_raw_text determines whether we are going to display */ /* the raw text of the SIP message, much like the MEGACO dissector does. */ - static gboolean global_sip_raw_text = FALSE; - static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_heur); -static line_type_t sip_parse_line(tvbuff_t *tvb, gint eol, guint *token_1_len); +static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen, + guint *token_1_len); static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset, guint meth_len); -static gint sip_get_msg_offset(tvbuff_t *tvb, int offset); static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len); -void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len); -void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree); +static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, + guint meth_len); +static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree); +static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree); static dissector_handle_t sdp_handle; -static dissector_handle_t data_handle; - -static void -tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree); - #define SIP2_HDR "SIP/2.0" #define SIP2_HDR_LEN (strlen (SIP2_HDR)) - - -/* Copied from MGCP dissector, prints whole message in raw text */ - -static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree){ - - proto_tree *raw_tree; - proto_item *ti; - gint tvb_linebegin,tvb_lineend,tvb_len,linelen; - - ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE); - raw_tree = proto_item_add_subtree(ti, ett_raw_text); - - tvb_linebegin = 0; - tvb_len = tvb_length(tvb); - - do { - tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,FALSE); - linelen = tvb_lineend - tvb_linebegin; - proto_tree_add_text(raw_tree, tvb, tvb_linebegin, linelen, - "%s", tvb_format_text(tvb,tvb_linebegin, - linelen)); - tvb_linebegin = tvb_lineend; - } while ( tvb_lineend < tvb_len ); -} - /* Code to actually dissect the packets */ static int dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) @@ -320,23 +289,31 @@ dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) return tvb_length(tvb); } +static void +dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_sip_common(tvb, pinfo, tree, TRUE); +} + static gboolean dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - return dissect_sip_common(tvb, pinfo, tree, TRUE); + return dissect_sip_common(tvb, pinfo, tree, FALSE); } static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - gboolean is_heur) + gboolean dissect_other_as_continuation) { int offset; - gint eol, next_offset, msg_offset; + gint next_offset, linelen; line_type_t line_type; tvbuff_t *next_tvb; gboolean is_known_request; char *descr; guint token_1_len; + proto_item *ts = NULL, *ti, *th = NULL; + proto_tree *sip_tree, *reqresp_tree, *hdr_tree = NULL; /* * Note that "tvb_find_line_end()" will return a value that @@ -347,28 +324,22 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, * "sip_parse_line()" won't throw an exception. */ offset = 0; - eol = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE); - line_type = sip_parse_line(tvb, eol, &token_1_len); + 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) { /* * This is neither a SIP request nor response. */ - if (is_heur) { + if (!dissect_other_as_continuation) { /* - * This is a heuristic dissector, which means we get - * all the UDP and TCP traffic not sent to a known - * dissector and not claimed by a heuristic dissector - * called before us! - * - * Therefore, we reject this as not being for us. + * We were asked to reject this. */ return FALSE; - } else { - /* - * Just dissect it as data. - */ - goto bad; } + + /* + * Just dissect it as a continuation. + */ } if (check_col(pinfo->cinfo, COL_PROTOCOL)) @@ -382,7 +353,7 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", descr, - tvb_format_text(tvb, 0, eol - SIP2_HDR_LEN - 1)); + tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1)); } break; @@ -390,7 +361,7 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, descr = "Status"; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s", - tvb_format_text(tvb, SIP2_HDR_LEN + 1, eol - SIP2_HDR_LEN - 1)); + tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1)); } break; @@ -401,18 +372,14 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); break; } - msg_offset = sip_get_msg_offset(tvb, offset); if (tree) { - proto_item *ti, *th; - proto_tree *sip_tree, *reqresp_tree, *hdr_tree; - - ti = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE); - sip_tree = proto_item_add_subtree(ti, ett_sip); + ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE); + sip_tree = proto_item_add_subtree(ts, ett_sip); ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset, "%s line: %s", descr, - tvb_format_text(tvb, 0, eol)); + tvb_format_text(tvb, 0, linelen)); reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp); switch (line_type) { @@ -426,28 +393,46 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, break; case OTHER_LINE: - break; + proto_tree_add_text(sip_tree, tvb, 0, -1, + "Continuation data"); + return TRUE; } offset = next_offset; - th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, msg_offset - offset, FALSE); + th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1, + FALSE); hdr_tree = proto_item_add_subtree(th, ett_sip_hdr); + } - /* - 2 since we have a CRLF separating the message-body */ - while (msg_offset - 2 > (int) offset) { - gint line_end_offset; - gint colon_offset; - gint header_len; - gint hf_index; - gint value_offset; - guchar c; - size_t value_len; - char *value; - - eol = tvb_find_line_end(tvb, offset, -1, &next_offset, - FALSE); - line_end_offset = offset + eol; - colon_offset = tvb_find_guint8(tvb, offset, -1, ':'); + /* + * Process the headers - if we're not building a protocol tree, + * we just do this to find the blank line separating the + * headers from the message body. + */ + next_offset = offset; + while (tvb_reported_length_remaining(tvb, offset) > 0) { + gint line_end_offset; + gint colon_offset; + gint header_len; + gint hf_index; + gint value_offset; + guchar c; + size_t value_len; + 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. + */ + break; + } + if (tree) { + line_end_offset = offset + linelen; + colon_offset = tvb_find_guint8(tvb, offset, linelen, + ':'); if (colon_offset == -1) { /* * Malformed header - no colon after the @@ -455,7 +440,7 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, */ proto_tree_add_text(hdr_tree, tvb, offset, next_offset - offset, "%s", - tvb_format_text(tvb, offset, eol)); + tvb_format_text(tvb, offset, linelen)); } else { header_len = colon_offset - offset; hf_index = sip_is_known_sip_header(tvb, @@ -464,7 +449,7 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, if (hf_index == -1) { proto_tree_add_text(hdr_tree, tvb, offset, next_offset - offset, "%s", - tvb_format_text(tvb, offset, eol)); + tvb_format_text(tvb, offset, linelen)); } else { /* * Skip whitespace after the colon. @@ -490,33 +475,35 @@ dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, hf_header_array[hf_index], tvb, offset, next_offset - offset, value, "%s", - tvb_format_text(tvb, offset, eol)); + tvb_format_text(tvb, offset, linelen)); g_free(value); } } - - offset = next_offset; } - offset += 2; /* Skip the CRLF mentioned above */ + offset = next_offset; } - if (tvb_offset_exists(tvb, msg_offset)) { - next_tvb = tvb_new_subset(tvb, msg_offset, -1, -1); + if (tvb_offset_exists(tvb, next_offset)) { + /* + * There's a message body starting at "next_offset". + * Set the length of the SIP portion and of the + * header item. + */ + proto_item_set_end(ts, tvb, next_offset); + proto_item_set_end(th, tvb, next_offset); + next_tvb = tvb_new_subset(tvb, next_offset, -1, -1); call_dissector(sdp_handle, next_tvb, pinfo, tree); } - if(global_sip_raw_text) - tvb_raw_text_add(tvb, tree); - return TRUE; - bad: - next_tvb = tvb_new_subset(tvb, offset, -1, -1); - call_dissector(data_handle,next_tvb, pinfo, tree); + if (global_sip_raw_text) + tvb_raw_text_add(tvb, tree); return TRUE; } /* Display filter for SIP Request-Line */ -void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len) +static void +dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len) { char *string; @@ -530,7 +517,8 @@ void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len) } /* Display filter for SIP Status-Line */ -void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree) +static void +dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree) { char string[3+1]; @@ -546,32 +534,6 @@ void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree) 3, string); } -/* Returns the offset to the start of the optional message-body, or - * an offset just past the end of the packet if not found. - */ -static gint sip_get_msg_offset(tvbuff_t *tvb, int offset) -{ - gint linelen, next_offset; - - while (tvb_offset_exists(tvb, offset)) { - linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, - FALSE); - /* - * If the line length is 0, this is a blank line; - * we're done. - */ - if (linelen == 0) - break; - offset = next_offset; - } - - /* - * Return the offset just past the line we just processed (or - * past the end of the buffer if we didn't find a blank line). - */ - return next_offset; -} - /* From section 4.1 of RFC 2543: * * Request-Line = Method SP Request-URI SP SIP-Version CRLF @@ -581,7 +543,7 @@ static gint sip_get_msg_offset(tvbuff_t *tvb, int offset) * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF */ static line_type_t -sip_parse_line(tvbuff_t *tvb, gint eol, guint *token_1_lenp) +sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp) { gint space_offset; guint token_1_len; @@ -616,7 +578,7 @@ sip_parse_line(tvbuff_t *tvb, gint eol, guint *token_1_lenp) } token_2_len = space_offset - token_2_start; token_3_start = space_offset + 1; - token_3_len = eol - token_3_start; + token_3_len = linelen - token_3_start; *token_1_lenp = token_1_len; @@ -714,6 +676,30 @@ static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len) return -1; } +/* + * Display the entire message as raw text. + */ +static void +tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree) +{ + proto_tree *raw_tree; + proto_item *ti; + int offset, next_offset, linelen; + + ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE); + raw_tree = proto_item_add_subtree(ti, ett_raw_text); + + offset = 0; + + while (tvb_offset_exists(tvb, offset)) { + tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); + linelen = next_offset - offset; + proto_tree_add_text(raw_tree, tvb, offset, linelen, + "%s", tvb_format_text(tvb, offset, linelen)); + offset = next_offset; + } +} + /* Register the protocol with Ethereal */ void proto_register_sip(void) { @@ -1021,19 +1007,20 @@ void proto_register_sip(void) void proto_reg_handoff_sip(void) { - dissector_handle_t sip_handle; + dissector_handle_t sip_handle, sip_tcp_handle; sip_handle = new_create_dissector_handle(dissect_sip, proto_sip); - dissector_add("tcp.port", TCP_PORT_SIP, sip_handle); dissector_add("udp.port", UDP_PORT_SIP, sip_handle); - heur_dissector_add( "udp", dissect_sip_heur, proto_sip ); - heur_dissector_add( "tcp", dissect_sip_heur, proto_sip ); - heur_dissector_add( "sctp", dissect_sip_heur, proto_sip ); + sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip); + dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle); + + heur_dissector_add("udp", dissect_sip_heur, proto_sip); + heur_dissector_add("tcp", dissect_sip_heur, proto_sip); + heur_dissector_add("sctp", dissect_sip_heur, proto_sip); /* * Get a handle for the SDP dissector. */ sdp_handle = find_dissector("sdp"); - data_handle = find_dissector("data"); } |