diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-11-09 10:56:33 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-11-09 10:56:33 +0000 |
commit | 01a890cf95e845edf22625a45274115c364f23b2 (patch) | |
tree | 7c9d0a8f4ff08ba78bddcbbc7299fd0fc7831287 | |
parent | 7271ed28941220c5270b2529b932ba25715310bc (diff) |
Tvbuffify the HTTP, NNTP, RSH, RTSP, and Telnet dissectors.
Add "tvb_find_line_end()", to find a CR and/or LF-terminated line in a
tvbuff and return its length and the offset of the character after the
line end, for the use of those dissectors.
Add "tvb_strncaseeql()", which is like "tvb_strneql()" except that it
does a case-insensitive comparison.
svn path=/trunk/; revision=2590
-rw-r--r-- | epan/tvbuff.c | 147 | ||||
-rw-r--r-- | epan/tvbuff.h | 16 | ||||
-rw-r--r-- | packet-http.c | 163 | ||||
-rw-r--r-- | packet-http.h | 4 | ||||
-rw-r--r-- | packet-ipp.c | 5 | ||||
-rw-r--r-- | packet-nntp.c | 141 | ||||
-rw-r--r-- | packet-rsh.c | 60 | ||||
-rw-r--r-- | packet-rtsp.c | 329 | ||||
-rw-r--r-- | packet-telnet.c | 165 |
9 files changed, 632 insertions, 398 deletions
diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 94fbf9bc5a..933c23428f 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -9,7 +9,7 @@ * the data of a backing tvbuff, or can be a composite of * other tvbuffs. * - * $Id: tvbuff.c,v 1.2 2000/10/17 08:50:57 guy Exp $ + * $Id: tvbuff.c,v 1.3 2000/11/09 10:56:33 guy Exp $ * * Copyright (c) 2000 by Gilbert Ramirez <gram@xiexie.org> * @@ -1041,23 +1041,48 @@ tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength) gint tvb_strneql(tvbuff_t *tvb, gint offset, guint8 *str, gint size) { - guint8 *ptr; - - ptr = ensure_contiguous(tvb, offset, size); + guint8 *ptr; - if (ptr) { + ptr = ensure_contiguous(tvb, offset, size); - int cmp = strncmp(ptr, str, size); + if (ptr) { + int cmp = strncmp(ptr, str, size); - return (cmp == 0 ? 0 : -1); /* Make it -1 if comparison failed */ + /* + * Return 0 if equal, -1 otherwise. + */ + return (cmp == 0 ? 0 : -1); + } else { + /* + * Not enough characters in the tvbuff to match the + * string. + */ + return -1; + } +} - } - else { +/* Call strncasecmp after checking if enough chars left, otherwise return -1 */ +gint +tvb_strncaseeql(tvbuff_t *tvb, gint offset, guint8 *str, gint size) +{ + guint8 *ptr; - return -1; /* Not enough chars in the TVB */ + ptr = ensure_contiguous(tvb, offset, size); - } + if (ptr) { + int cmp = strncasecmp(ptr, str, size); + /* + * Return 0 if equal, -1 otherwise. + */ + return (cmp == 0 ? 0 : -1); + } else { + /* + * Not enough characters in the tvbuff to match the + * string. + */ + return -1; + } } /* @@ -1141,3 +1166,103 @@ tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint maxlength, guint8* buffer) return len; } } + +/* + * Given a tvbuff, an offset into the tvbuff, and a length that starts + * at that offset (which may be -1 for "all the way to the end of the + * tvbuff"), find the end of the (putative) line that starts at the + * specified offset in the tvbuff, going no further than the specified + * length. + * + * Return the length of the line (not counting the line terminator at + * the end), or the amount of data remaining in the buffer if we don't + * find a line terminator. + * + * Set "*next_offset" to the offset of the character past the line + * terminator, or past the end of the buffer if we don't find a line + * terminator. + */ +int +tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset) +{ + gint eob_offset; + gint eol_offset; + int linelen; + + if (len == -1) + len = tvb_length_remaining(tvb, offset); + /* + * XXX - what if "len" is still -1, meaning "offset is past the + * end of the tvbuff"? + */ + eob_offset = offset + len; + + eol_offset = tvb_find_guint8(tvb, offset, len, '\n'); + if (eol_offset == -1) { + /* + * No LF - line is presumably continued in next packet. + * We pretend the line runs to the end of the tvbuff. + */ + *next_offset = eob_offset; + linelen = eob_offset - offset; + } else { + /* + * Find the number of bytes between the starting offset + * and the LF. + */ + linelen = eol_offset - offset; + + /* + * Is the LF at the beginning of the line? + */ + if (linelen > 0) { + /* + * No - is it preceded by a carriage return? + * (Perhaps it's supposed to be, but that's not + * guaranteed....) + */ + if (tvb_get_guint8(tvb, eol_offset - 1) == '\r') { + /* + * Yes. The EOL starts with the CR; + * don't count it as part of the data + * in the line. + */ + linelen--; + } else { + /* + * No. The EOL starts with the LF. + */ + + /* + * I seem to remember that we once saw lines + * ending with LF-CR in an HTTP request or + * response, so check if it's *followed* + * by a carriage return. + * + * XXX - what about <LF><CR> with the <LF> + * not preceded by non-LF/non-CR data? + * Should we check for that, or do we + * run the risk of misinterpreting a + * sequence of multiple <CR><LF> as having + * a bunch of <LF><CR> in it? + */ + if (eol_offset + 1 < eob_offset && + tvb_get_guint8(tvb, eol_offset + 1) == '\r') { + /* + * It's <non-LF><LF><CR>; say it ends + * with the CR, and skip past the + * LF. + */ + eol_offset++; + } + } + } + + /* + * Point to the character after the last character. + */ + eol_offset++; + *next_offset = eol_offset; + } + return linelen; +} diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 2b69584f04..813c28e952 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -9,7 +9,7 @@ * the data of a backing tvbuff, or can be a composite of * other tvbuffs. * - * $Id: tvbuff.h,v 1.1 2000/09/27 04:54:54 gram Exp $ + * $Id: tvbuff.h,v 1.2 2000/11/09 10:56:33 guy Exp $ * * Copyright (c) 2000 by Gilbert Ramirez <gram@xiexie.org> * @@ -272,10 +272,24 @@ gint tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint maxlength, guint8* buffe */ gint tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint maxlength, guint8* buffer); +/* + * Given a tvbuff, an offset into the tvbuff, and a length that starts + * at that offset (which may be -1 for "all the way to the end of the + * tvbuff"), find the end of the (putative) line that starts at the + * specified offset in the tvbuff, going no further than the specified + * length. + * + * Return the offset right past the end of the line as the return value, + * and return the offset of the EOL character(s) in "*eol". + */ +gint tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *eol); /* Call strncmp after checking if enough chars left, otherwise return -1 */ gint tvb_strneql(tvbuff_t *tvb, gint offset, guint8 *str, gint size); +/* Call strncasecmp after checking if enough chars left, otherwise return -1 */ +gint tvb_strncaseeql(tvbuff_t *tvb, gint offset, guint8 *str, gint size); + /************** END OF ACCESSORS ****************/ /* Sets pd and offset so that tvbuff's can be used with code diff --git a/packet-http.c b/packet-http.c index cc14608a53..85aa18bb10 100644 --- a/packet-http.c +++ b/packet-http.c @@ -3,7 +3,7 @@ * * Guy Harris <guy@alum.mit.edu> * - * $Id: packet-http.c,v 1.24 2000/10/19 07:38:01 guy Exp $ + * $Id: packet-http.c,v 1.25 2000/11/09 10:56:31 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -62,75 +62,82 @@ static gint ett_http = -1; static int is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type); -void dissect_http(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) +void +dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - gboolean is_ipp = (pi.srcport == 631 || pi.destport == 631); - proto_item *ti; - proto_tree *http_tree; - const u_char *data, *dataend; - const u_char *linep, *lineend, *eol; + gboolean is_ipp = (pinfo->srcport == 631 || pinfo->destport == 631); + proto_tree *http_tree = NULL; + proto_item *ti = NULL; + gint offset = 0; + const u_char *line; + gint next_offset; + const u_char *linep, *lineend; int linelen; u_char c; - http_type_t http_type = HTTP_OTHERS; + http_type_t http_type; + int datalen; - OLD_CHECK_DISPLAY_AS_DATA(proto_http, pd, offset, fd, tree); + CHECK_DISPLAY_AS_DATA(proto_http, tvb, pinfo, tree); - data = &pd[offset]; - dataend = data + END_OF_FRAME; + pinfo->current_proto = is_ipp ? "IPP" : "HTTP"; - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, is_ipp ? "IPP" : "HTTP"); - if (check_col(fd, COL_INFO)) { + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, is_ipp ? "IPP" : "HTTP"); + if (check_col(pinfo->fd, COL_INFO)) { /* - * Put the first line from the buffer into the summary, + * Put the first line from the buffer into the summary * if it's an HTTP request or reply (but leave out the - * "\r\n", or whatever, at the end). + * line terminator). * Otherwise, just call it a continuation. */ - lineend = find_line_end(data, dataend, &eol); - linelen = eol - data; - if (is_http_request_or_reply(data, linelen, &http_type)) - col_add_str(fd, COL_INFO, format_text(data, linelen)); + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset); + line = tvb_get_ptr(tvb, offset, linelen); + if (is_http_request_or_reply(line, linelen, &http_type)) + col_add_str(pinfo->fd, COL_INFO, + format_text(line, linelen)); else - col_add_str(fd, COL_INFO, "Continuation"); + col_add_str(pinfo->fd, COL_INFO, "Continuation"); } if (tree) { - ti = proto_tree_add_item(tree, proto_http, NullTVB, offset, END_OF_FRAME, FALSE); + ti = proto_tree_add_item(tree, proto_http, tvb, offset, + tvb_length_remaining(tvb, offset), FALSE); http_tree = proto_item_add_subtree(ti, ett_http); - while (data < dataend) { + /* + * Process the packet data, a line at a time. + */ + while (tvb_length_remaining(tvb, offset)) { /* * Find the end of the line. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; + linelen = tvb_find_line_end(tvb, offset, -1, + &next_offset); + + /* + * Get a buffer that refers to the line. + */ + line = tvb_get_ptr(tvb, offset, linelen); + lineend = line + linelen; /* * OK, does it look like an HTTP request or * response? */ - if (is_http_request_or_reply(data, linelen, &http_type)) + if (is_http_request_or_reply(line, linelen, &http_type)) goto is_http; /* * No. Does it look like a blank line (as would * appear at the end of an HTTP request)? */ - if (linelen == 1) { - if (*data == '\n') - goto is_http; - } - if (linelen == 2) { - if (strncmp(data, "\r\n", 2) == 0 || - strncmp(data, "\n\r", 2) == 0) - goto is_http; - } + if (linelen == 0) + goto is_http; /* * No. Does it look like a MIME header? */ - linep = data; + linep = line; while (linep < lineend) { c = *linep++; if (!isprint(c)) @@ -184,35 +191,51 @@ void dissect_http(const u_char *pd, int offset, frame_data *fd, proto_tree *tree /* * Put this line. */ - proto_tree_add_text(http_tree, NullTVB, offset, linelen, "%s", - format_text(data, linelen)); - offset += linelen; - data = lineend; + proto_tree_add_text(http_tree, tvb, offset, + next_offset - offset, "%s", + tvb_format_text(tvb, offset, next_offset - offset)); + offset = next_offset; } switch (http_type) { case HTTP_RESPONSE: proto_tree_add_boolean_hidden(http_tree, - hf_http_response, NullTVB, 0, 0, 1); + hf_http_response, tvb, 0, 0, 1); break; case HTTP_REQUEST: proto_tree_add_boolean_hidden(http_tree, - hf_http_request, NullTVB, 0, 0, 1); + hf_http_request, tvb, 0, 0, 1); break; case HTTP_OTHERS: default: break; } + } - if (data < dataend) { - if (is_ipp) - dissect_ipp(pd, offset, fd, tree); - else - old_dissect_data(&pd[offset], offset, fd, http_tree); - } + datalen = tvb_length_remaining(tvb, offset); + if (datalen > 0) { + tvbuff_t *new_tvb = tvb_new_subset(tvb, offset, -1, -1); + const guint8 *pd; + + if (is_ipp) { + /* + * Fix up the top-level item so that it doesn't + * include the IPP stuff. + */ + if (ti != NULL) + proto_item_set_len(ti, offset); + + /* + * Now create a tvbuff for the IPP stuff, and dissect + * it. + */ + tvb_compat(new_tvb, &pd, &offset); + dissect_ipp(pd, offset, pinfo->fd, tree); + } else + dissect_data(new_tvb, pinfo, http_tree); } } @@ -272,31 +295,31 @@ is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type) void proto_register_http(void) { - - static hf_register_info hf[] = { - { &hf_http_response, - { "Response", "http.response", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if HTTP response" }}, - { &hf_http_request, - { "Request", "http.request", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if HTTP request" }}, - }; - static gint *ett[] = { - &ett_http, - }; - - proto_http = proto_register_protocol("Hypertext Transfer Protocol", "http"); - proto_register_field_array(proto_http, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); + static hf_register_info hf[] = { + { &hf_http_response, + { "Response", "http.response", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "TRUE if HTTP response" }}, + { &hf_http_request, + { "Request", "http.request", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "TRUE if HTTP request" }}, + }; + static gint *ett[] = { + &ett_http, + }; + + proto_http = proto_register_protocol("Hypertext Transfer Protocol", + "http"); + proto_register_field_array(proto_http, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_http(void) { - old_dissector_add("tcp.port", TCP_PORT_HTTP, dissect_http); - old_dissector_add("tcp.port", TCP_ALT_PORT_HTTP, dissect_http); - old_dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, dissect_http); - old_dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, dissect_http); + dissector_add("tcp.port", TCP_PORT_HTTP, dissect_http); + dissector_add("tcp.port", TCP_ALT_PORT_HTTP, dissect_http); + dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, dissect_http); + dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, dissect_http); } diff --git a/packet-http.h b/packet-http.h index e9860aa100..5109f5e8fe 100644 --- a/packet-http.h +++ b/packet-http.h @@ -1,6 +1,6 @@ /* packet-http.h * - * $Id: packet-http.h,v 1.2 2000/08/11 13:34:12 deniel Exp $ + * $Id: packet-http.h,v 1.3 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -25,6 +25,6 @@ #ifndef __PACKET_HTTP_H__ #define __PACKET_HTTP_H__ -void dissect_http(const u_char *, int, frame_data *, proto_tree *); +void dissect_http(tvbuff_t *, packet_info *, proto_tree *); #endif diff --git a/packet-ipp.c b/packet-ipp.c index b5b1e49fa2..a265b439b2 100644 --- a/packet-ipp.c +++ b/packet-ipp.c @@ -3,7 +3,7 @@ * * Guy Harris <guy@alum.mit.edu> * - * $Id: packet-ipp.c,v 1.12 2000/08/13 14:08:17 deniel Exp $ + * $Id: packet-ipp.c,v 1.13 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -586,6 +586,5 @@ proto_reg_handoff_ipp(void) Or should the HTTP dissector decide that the payload is IPP based on the MIME headers? */ - old_dissector_add("tcp.port", 631, dissect_http); + dissector_add("tcp.port", 631, dissect_http); } - diff --git a/packet-nntp.c b/packet-nntp.c index 5c8aedeef1..5d2580965d 100644 --- a/packet-nntp.c +++ b/packet-nntp.c @@ -2,7 +2,7 @@ * Routines for nntp packet dissection * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> * - * $Id: packet-nntp.c,v 1.13 2000/09/11 16:16:02 gram Exp $ + * $Id: packet-nntp.c,v 1.14 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -51,104 +51,103 @@ static gint ett_nntp = -1; #define TCP_PORT_NNTP 119 static void -dissect_nntp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) +dissect_nntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gchar *type; - proto_tree *nntp_tree, *ti; - const u_char *data, *dataend; - const u_char *lineend, *eol; + proto_tree *nntp_tree; + proto_item *ti; + gint offset = 0; + const u_char *line; + gint next_offset; int linelen; - int max_data = pi.captured_len - offset; - OLD_CHECK_DISPLAY_AS_DATA(proto_nntp, pd, offset, fd, tree); + CHECK_DISPLAY_AS_DATA(proto_nntp, tvb, pinfo, tree); - data = &pd[offset]; - dataend = data + END_OF_FRAME; - if (dataend > data + max_data) - dataend = data + max_data; - - if (pi.match_port == pi.destport) + if (pinfo->match_port == pinfo->destport) type = "Request"; else type = "Response"; - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "NNTP"); + pinfo->current_proto = "NNTP"; + + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "NNTP"); - if (check_col(fd, COL_INFO)) { + if (check_col(pinfo->fd, COL_INFO)) { /* - * Put the first line from the buffer into the summary. + * Put the first line from the buffer into the summary + * (but leave out the line terminator). */ - lineend = find_line_end(data, dataend, &eol); - linelen = eol - data; - col_add_fstr(fd, COL_INFO, "%s: %s", type, - format_text(data, linelen)); + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset); + line = tvb_get_ptr(tvb, offset, linelen); + col_add_fstr(pinfo->fd, COL_INFO, "%s: %s", type, + format_text(line, linelen)); } if (tree) { - - ti = proto_tree_add_item(tree, proto_nntp, NullTVB, offset, END_OF_FRAME, FALSE); - nntp_tree = proto_item_add_subtree(ti, ett_nntp); - - if (pi.match_port == pi.destport) { - proto_tree_add_boolean_hidden(nntp_tree, hf_nntp_request, NullTVB, 0, 0, TRUE); - } else { - proto_tree_add_boolean_hidden(nntp_tree, hf_nntp_response, NullTVB, 0, 0, TRUE); - } - - /* - * Show the request or response as text, a line at a time. - * XXX - for requests, we could display the stuff after the - * first line, if any, based on what the request was, and - * for responses, we could display it based on what the - * matching request was, although the latter requires us to - * know what the matching request was.... - */ - while (data < dataend) { - /* - * Find the end of the line. - */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; + ti = proto_tree_add_item(tree, proto_nntp, tvb, offset, + tvb_length_remaining(tvb, offset), FALSE); + nntp_tree = proto_item_add_subtree(ti, ett_nntp); + + if (pinfo->match_port == pinfo->destport) { + proto_tree_add_boolean_hidden(nntp_tree, + hf_nntp_request, tvb, 0, 0, TRUE); + } else { + proto_tree_add_boolean_hidden(nntp_tree, + hf_nntp_response, tvb, 0, 0, TRUE); + } /* - * Put this line. + * Show the request or response as text, a line at a time. + * XXX - for requests, we could display the stuff after the + * first line, if any, based on what the request was, and + * for responses, we could display it based on what the + * matching request was, although the latter requires us to + * know what the matching request was.... */ - proto_tree_add_text(nntp_tree, NullTVB, offset, linelen, "%s", - format_text(data, linelen)); - offset += linelen; - data = lineend; - } + while (tvb_length_remaining(tvb, offset)) { + /* + * Find the end of the line. + */ + tvb_find_line_end(tvb, offset, -1, &next_offset); + + /* + * Put this line. + */ + proto_tree_add_text(nntp_tree, tvb, offset, + next_offset - offset, "%s", + tvb_format_text(tvb, offset, next_offset - offset)); + offset = next_offset; + } } } void proto_register_nntp(void) { - - static hf_register_info hf[] = { - { &hf_nntp_response, - { "Response", "nntp.response", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if NNTP response" }}, - - { &hf_nntp_request, - { "Request", "nntp.request", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if NNTP request" }} - }; - static gint *ett[] = { - &ett_nntp, - }; - - proto_nntp = proto_register_protocol("Network News Transfer Protocol", + static hf_register_info hf[] = { + { &hf_nntp_response, + { "Response", "nntp.response", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "TRUE if NNTP response" }}, + + { &hf_nntp_request, + { "Request", "nntp.request", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "TRUE if NNTP request" }} + }; + static gint *ett[] = { + &ett_nntp, + }; + + proto_nntp = proto_register_protocol("Network News Transfer Protocol", "nntp"); - proto_register_field_array(proto_nntp, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array(proto_nntp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_nntp(void) { - old_dissector_add("tcp.port", TCP_PORT_NNTP, dissect_nntp); + dissector_add("tcp.port", TCP_PORT_NNTP, dissect_nntp); } diff --git a/packet-rsh.c b/packet-rsh.c index 2facb05e66..5d558fde03 100644 --- a/packet-rsh.c +++ b/packet-rsh.c @@ -4,7 +4,7 @@ * Robert Tsai <rtsai@netapp.com> * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu> * - * $Id: packet-rsh.c,v 1.4 2000/09/11 16:16:02 gram Exp $ + * $Id: packet-rsh.c,v 1.5 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -48,57 +48,57 @@ static gint ett_rsh = -1; #define TCP_PORT_RSH 514 void -dissect_rsh(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) +dissect_rsh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_item *ti; proto_tree *rsh_tree; - const u_char *data, *dataend; - const u_char *lineend, *eol; + proto_item *ti; + gint offset = 0; + const u_char *line; + gint next_offset; int linelen; - OLD_CHECK_DISPLAY_AS_DATA(proto_rsh, pd, offset, fd, tree); + CHECK_DISPLAY_AS_DATA(proto_rsh, tvb, pinfo, tree); - data = &pd[offset]; - dataend = data + END_OF_FRAME; + pinfo->current_proto = "RSH"; - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "RSH"); - if (check_col(fd, COL_INFO)) { + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "RSH"); + if (check_col(pinfo->fd, COL_INFO)) { /* Put the first line from the buffer into the summary. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; - col_add_str(fd, COL_INFO, format_text(data, linelen)); + tvb_find_line_end(tvb, offset, -1, &next_offset); + linelen = next_offset - offset; /* include the line terminator */ + line = tvb_get_ptr(tvb, offset, linelen); + col_add_str(pinfo->fd, COL_INFO, format_text(line, linelen)); } if (tree) { - ti = proto_tree_add_item(tree, proto_rsh, NullTVB, offset, - END_OF_FRAME, FALSE); + ti = proto_tree_add_item(tree, proto_rsh, tvb, offset, + tvb_length_remaining(tvb, offset), FALSE); rsh_tree = proto_item_add_subtree(ti, ett_rsh); - while (data < dataend) { + /* + * Process the packet data, a line at a time. + */ + while (tvb_length_remaining(tvb, offset)) { /* * Find the end of the line. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; + tvb_find_line_end(tvb, offset, -1, &next_offset); /* * Put this line. */ - proto_tree_add_text(rsh_tree, NullTVB, offset, - linelen, "%s", format_text(data, linelen)); - offset += linelen; - data = lineend; + proto_tree_add_text(rsh_tree, tvb, offset, + next_offset - offset, "%s", + tvb_format_text(tvb, offset, next_offset - offset)); + offset = next_offset; } - if (pi.match_port == pi.destport) + if (pinfo->match_port == pinfo->destport) proto_tree_add_boolean_hidden(rsh_tree, - hf_rsh_request, NullTVB, 0, 0, 1); + hf_rsh_request, tvb, 0, 0, 1); else proto_tree_add_boolean_hidden(rsh_tree, - hf_rsh_response, NullTVB, 0, 0, 1); - - if (data < dataend) - old_dissect_data(&pd[offset], offset, fd, rsh_tree); + hf_rsh_response, tvb, 0, 0, 1); } } @@ -129,5 +129,5 @@ proto_register_rsh(void) void proto_reg_handoff_rsh(void) { - old_dissector_add("tcp.port", TCP_PORT_RSH, dissect_rsh); + dissector_add("tcp.port", TCP_PORT_RSH, dissect_rsh); } diff --git a/packet-rtsp.c b/packet-rtsp.c index 4f64ac2e9d..f945d1ed07 100644 --- a/packet-rtsp.c +++ b/packet-rtsp.c @@ -4,7 +4,7 @@ * Jason Lango <jal@netapp.com> * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu> * - * $Id: packet-rtsp.c,v 1.21 2000/10/21 05:52:22 guy Exp $ + * $Id: packet-rtsp.c,v 1.22 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -54,9 +54,53 @@ static int hf_rtsp_status = -1; #define TCP_PORT_RTSP 554 -static int process_rtsp_request_or_reply(const u_char *data, int offset, +static void process_rtsp_request(tvbuff_t *tvb, int offset, const u_char *data, int linelen, proto_tree *tree); +static void process_rtsp_reply(tvbuff_t *tvb, int offset, const u_char *data, + int linelen, proto_tree *tree); + +typedef enum { + RTSP_REQUEST, + RTSP_REPLY, + NOT_RTSP +} rtsp_type_t; + +static const char *rtsp_methods[] = { + "DESCRIBE", "ANNOUNCE", "GET_PARAMETER", "OPTIONS", + "PAUSE", "PLAY", "RECORD", "REDIRECT", "SETUP", + "SET_PARAMETER", "TEARDOWN" +}; + +#define RTSP_NMETHODS (sizeof rtsp_methods / sizeof rtsp_methods[0]) + +static rtsp_type_t +is_rtsp_request_or_reply(const u_char *line, int linelen) +{ + int ii; + + /* Is this an RTSP reply? */ + if (linelen >= 5 && strncasecmp("RTSP/", line, 5) == 0) { + /* + * Yes. + */ + return RTSP_REPLY; + } + + /* + * Is this an RTSP request? + * Check whether the line begins with one of the RTSP request + * methods. + */ + for (ii = 0; ii < RTSP_NMETHODS; ii++) { + size_t len = strlen(rtsp_methods[ii]); + if (linelen >= len && + strncasecmp(rtsp_methods[ii], line, len) == 0) + return RTSP_REQUEST; + } + return NOT_RTSP; +} + static int is_content_sdp(const u_char *line, int linelen) { @@ -136,84 +180,104 @@ rtsp_create_conversation(const u_char *trans_begin, const u_char *trans_end) conversation_set_dissector(conv, dissect_rtcp); } -static void dissect_rtsp(const u_char *pd, int offset, frame_data *fd, - proto_tree *tree) +static void +dissect_rtsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *rtsp_tree; - proto_item *ti; - const u_char *data, *dataend; - const u_char *linep, *lineend, *eol; + proto_item *ti = NULL; + gint offset = 0; + const u_char *line; + gint next_offset; + const u_char *linep, *lineend; int linelen; u_char c; - int is_sdp = 0; - int end_offset; + int is_sdp = FALSE; + int datalen; - OLD_CHECK_DISPLAY_AS_DATA(proto_rtsp, pd, offset, fd, tree); + CHECK_DISPLAY_AS_DATA(proto_rtsp, tvb, pinfo, tree); - data = &pd[offset]; - dataend = data + END_OF_FRAME; - end_offset = offset + END_OF_FRAME; + pinfo->current_proto = "RTSP"; rtsp_tree = NULL; if (tree) { - ti = proto_tree_add_item(tree, proto_rtsp, NullTVB, offset, - END_OF_FRAME, FALSE); + ti = proto_tree_add_item(tree, proto_rtsp, tvb, offset, + tvb_length_remaining(tvb, offset), FALSE); rtsp_tree = proto_item_add_subtree(ti, ett_rtsp); } - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "RTSP"); - if (check_col(fd, COL_INFO)) { + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "RTSP"); + if (check_col(pinfo->fd, COL_INFO)) { /* * Put the first line from the buffer into the summary - * if it's an RTSP request or reply. Otherwise, just call - * it a continuation. + * if it's an RTSP request or reply (but leave out the + * line terminator). + * Otherwise, just call it a continuation. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; - if (process_rtsp_request_or_reply(data, offset, linelen, - rtsp_tree)) { - col_add_str(fd, COL_INFO, - format_text(data, eol - data)); - } else - col_add_str(fd, COL_INFO, "Continuation"); + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset); + line = tvb_get_ptr(tvb, offset, linelen); + switch (is_rtsp_request_or_reply(line, linelen)) { + + case RTSP_REQUEST: + case RTSP_REPLY: + col_add_str(pinfo->fd, COL_INFO, + format_text(line, linelen)); + break; + + default: + col_add_str(pinfo->fd, COL_INFO, "Continuation"); + break; + } } - if (offset >= end_offset) - goto bad_len; - while (data < dataend) { + /* + * Process the packet data, a line at a time. + */ + while (tvb_length_remaining(tvb, offset)) { /* * Find the end of the line. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset); + + /* + * Get a buffer that refers to the line. + */ + line = tvb_get_ptr(tvb, offset, linelen); + lineend = line + linelen; /* * OK, does it look like an RTSP request or * response? */ - if (process_rtsp_request_or_reply(data, offset, linelen, - rtsp_tree)) + switch (is_rtsp_request_or_reply(line, linelen)) { + + case RTSP_REQUEST: + if (rtsp_tree != NULL) + process_rtsp_request(tvb, offset, line, linelen, + rtsp_tree); + goto is_rtsp; + + case RTSP_REPLY: + if (rtsp_tree != NULL) + process_rtsp_reply(tvb, offset, line, linelen, + rtsp_tree); goto is_rtsp; + case NOT_RTSP: + break; + } + /* * No. Does it look like a blank line (as would * appear at the end of an RTSP request)? */ - if (linelen == 1) { - if (*data == '\n') - goto is_rtsp; - } - if (linelen == 2) { - if (strncmp(data, "\r\n", 2) == 0 || - strncmp(data, "\n\r", 2) == 0) - goto is_rtsp; - } + if (linelen == 0) + goto is_rtsp; /* Yes. */ /* * No. Does it look like a MIME header? */ - linep = data; + linep = line; while (linep < lineend) { c = *linep++; if (!isprint(c)) @@ -249,8 +313,8 @@ static void dissect_rtsp(const u_char *pd, int offset, frame_data *fd, * This ends the token; we consider * this to be a MIME header. */ - if (is_content_sdp(data, linelen)) - is_sdp = 1; + if (is_content_sdp(line, linelen)) + is_sdp = TRUE; goto is_rtsp; } } @@ -267,103 +331,114 @@ static void dissect_rtsp(const u_char *pd, int offset, frame_data *fd, * Put this line. */ if (rtsp_tree) { - proto_tree_add_text(rtsp_tree, NullTVB, offset, linelen, "%s", - format_text(data, linelen)); + proto_tree_add_text(rtsp_tree, tvb, offset, + next_offset - offset, "%s", + tvb_format_text(tvb, offset, next_offset - offset)); } if (linelen > strlen(rtsp_transport) && - strncasecmp(data, rtsp_transport, + strncasecmp(line, rtsp_transport, strlen(rtsp_transport)) == 0) - rtsp_create_conversation(data, data + linelen); - offset += linelen; - data = lineend; + rtsp_create_conversation(line, line + linelen); + offset = next_offset; } + datalen = tvb_length_remaining(tvb, offset); if (is_sdp) { - dissect_sdp(pd, offset, fd, tree); - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "RTSP/SDP"); - } - else if (data < dataend) { - proto_tree_add_text(rtsp_tree, NullTVB, offset, END_OF_FRAME, - "Data (%d bytes)", END_OF_FRAME); + if (datalen > 0) { + tvbuff_t *new_tvb = tvb_new_subset(tvb, offset, -1, -1); + const guint8 *pd; + + /* + * Fix up the top-level item so that it doesn't + * include the SDP stuff. + */ + if (ti != NULL) + proto_item_set_len(ti, offset); + + /* + * Now create a tvbuff for the SDP stuff, and dissect + * it. + */ + tvb_compat(new_tvb, &pd, &offset); + dissect_sdp(pd, offset, pinfo->fd, tree); + } + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "RTSP/SDP"); + } else { + if (datalen > 0) { + proto_tree_add_text(rtsp_tree, tvb, offset, datalen, + "Data (%d bytes)", datalen); + } } - return; - -bad_len: - proto_tree_add_text(rtsp_tree, NullTVB, end_offset, 0, - "Unexpected end of packet"); } -const char *rtsp_methods[] = { - "DESCRIBE", "ANNOUNCE", "GET_PARAMETER", "OPTIONS", - "PAUSE", "PLAY", "RECORD", "REDIRECT", "SETUP", - "SET_PARAMETER", "TEARDOWN" -}; -const int rtsp_nmethods = sizeof(rtsp_methods) / sizeof(*rtsp_methods); - -static int -process_rtsp_request_or_reply(const u_char *data, int offset, int linelen, - proto_tree *tree) +static void +process_rtsp_request(tvbuff_t *tvb, int offset, const u_char *data, + int linelen, proto_tree *tree) { - int ii; const u_char *lineend = data + linelen; - - /* Reply */ - if (linelen >= 5 && !strncasecmp("RTSP/", data, 5)) { - if (tree) { - /* status code */ - const u_char *status = data; - const u_char *status_start; - unsigned int status_i = 0; - while (status < lineend && !isspace(*status)) - status++; - while (status < lineend && isspace(*status)) - status++; - status_start = status; - while (status < lineend && isdigit(*status)) - status_i = status_i * 10 + *status++ - '0'; - proto_tree_add_uint_hidden(tree, hf_rtsp_status, NullTVB, - offset + (status_start - data), - status - status_start, status_i); - } - return TRUE; - } + int ii; + const u_char *url; + const u_char *url_start; + u_char *tmp_url; /* Request Methods */ - for (ii = 0; ii < rtsp_nmethods; ii++) { + for (ii = 0; ii < RTSP_NMETHODS; ii++) { size_t len = strlen(rtsp_methods[ii]); if (linelen >= len && !strncasecmp(rtsp_methods[ii], data, len)) break; } - if (ii == rtsp_nmethods) - return FALSE; - - if (tree) { - const u_char *url; - const u_char *url_start; - u_char *tmp_url; - - /* method name */ - proto_tree_add_string_hidden(tree, hf_rtsp_method, NullTVB, offset, - strlen(rtsp_methods[ii]), rtsp_methods[ii]); - - /* URL */ - url = data; - while (url < lineend && !isspace(*url)) - url++; - while (url < lineend && isspace(*url)) - url++; - url_start = url; - while (url < lineend && !isspace(*url)) - url++; - tmp_url = g_malloc(url - url_start + 1); - memcpy(tmp_url, url_start, url - url_start); - tmp_url[url - url_start] = 0; - proto_tree_add_string_hidden(tree, hf_rtsp_url, NullTVB, - offset + (url_start - data), url - url_start, tmp_url); - g_free(tmp_url); + if (ii == RTSP_NMETHODS) { + /* + * We got here because "is_rtsp_request_or_reply()" returned + * RTSP_REQUEST, so we know one of the request methods + * matched, so we "can't get here". + */ + g_assert_not_reached(); } - return TRUE; + + /* Method name */ + proto_tree_add_string_hidden(tree, hf_rtsp_method, tvb, offset, + strlen(rtsp_methods[ii]), rtsp_methods[ii]); + + /* URL */ + url = data; + while (url < lineend && !isspace(*url)) + url++; + while (url < lineend && isspace(*url)) + url++; + url_start = url; + while (url < lineend && !isspace(*url)) + url++; + tmp_url = g_malloc(url - url_start + 1); + memcpy(tmp_url, url_start, url - url_start); + tmp_url[url - url_start] = 0; + proto_tree_add_string_hidden(tree, hf_rtsp_url, tvb, + offset + (url_start - data), url - url_start, tmp_url); + g_free(tmp_url); +} + +static void +process_rtsp_reply(tvbuff_t *tvb, int offset, const u_char *data, + int linelen, proto_tree *tree) +{ + const u_char *lineend = data + linelen; + const u_char *status = data; + const u_char *status_start; + unsigned int status_i; + + /* status code */ + while (status < lineend && !isspace(*status)) + status++; + while (status < lineend && isspace(*status)) + status++; + status_start = status; + status_i = 0; + while (status < lineend && isdigit(*status)) + status_i = status_i * 10 + *status++ - '0'; + proto_tree_add_uint_hidden(tree, hf_rtsp_status, tvb, + offset + (status_start - data), + status - status_start, status_i); } void @@ -390,5 +465,5 @@ proto_register_rtsp(void) void proto_reg_handoff_rtsp(void) { - old_dissector_add("tcp.port", TCP_PORT_RTSP, dissect_rtsp); + dissector_add("tcp.port", TCP_PORT_RTSP, dissect_rtsp); } diff --git a/packet-telnet.c b/packet-telnet.c index 11e41912ff..d5ca334044 100644 --- a/packet-telnet.c +++ b/packet-telnet.c @@ -2,7 +2,7 @@ * Routines for telnet packet dissection * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> * - * $Id: packet-telnet.c,v 1.17 2000/09/29 19:06:12 guy Exp $ + * $Id: packet-telnet.c,v 1.18 2000/11/09 10:56:32 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -121,171 +121,175 @@ static const char *options[] = { #define NOPTIONS (sizeof options / sizeof options[0]) static int -telnet_sub_option(proto_tree *telnet_tree, const u_char *pd, - int start_offset) +telnet_sub_option(proto_tree *telnet_tree, tvbuff_t *tvb, int start_offset) { proto_tree *ti, *option_tree; int offset = start_offset; + guint8 opt_byte; int subneg_len, req; - gboolean not_found = TRUE; const u_char *opt; + guint len; offset += 2; /* skip IAC and SB */ /* Figure out the option and type */ - if (pd[offset] > NOPTIONS) + opt_byte = tvb_get_guint8(tvb, offset); + if (opt_byte > NOPTIONS) opt = "<unknown option>"; else - opt = options[pd[offset]]; + opt = options[opt_byte]; offset++; - req = pd[offset]; + req = tvb_get_guint8(tvb, offset); offset++; - while (offset < pi.captured_len && not_found) { - if (pd[offset] == TN_IAC) - not_found = FALSE; - else - offset++; + /* Search for an IAC. */ + len = tvb_length_remaining(tvb, offset); + offset = tvb_find_guint8(tvb, offset, len, TN_IAC); + if (offset == -1) { + /* None found - run to the end of the packet. */ + offset += len; } subneg_len = offset - start_offset; - ti = proto_tree_add_text(telnet_tree, NullTVB, start_offset, subneg_len, + ti = proto_tree_add_text(telnet_tree, tvb, start_offset, subneg_len, "Suboption Begin: %s", opt); option_tree = proto_item_add_subtree(ti, ett_telnet_subopt); - proto_tree_add_text(option_tree, NullTVB, start_offset + 2, 2, + proto_tree_add_text(option_tree, tvb, start_offset + 2, 2, "%s %s", (req ? "Send your" : "Here's my"), opt); if (req == 0) { /* Add the value */ - proto_tree_add_text(option_tree, NullTVB, start_offset + 4, subneg_len - 4, - "Value: %s", format_text(&pd[start_offset + 4], subneg_len - 4)); + proto_tree_add_text(option_tree, tvb, start_offset + 4, subneg_len - 4, + "Value: %s", tvb_format_text(tvb, start_offset + 4, subneg_len - 4)); } return offset; } static int -telnet_will_wont_do_dont(proto_tree *telnet_tree, const u_char *pd, +telnet_will_wont_do_dont(proto_tree *telnet_tree, tvbuff_t *tvb, int start_offset, char *type) { int offset = start_offset; + guint8 opt_byte; const char *opt; offset += 2; /* skip IAC and WILL,WONT,DO,DONT} */ - if (pd[offset] > NOPTIONS) + opt_byte = tvb_get_guint8(tvb, offset); + if (opt_byte > NOPTIONS) opt = "<unknown option>"; else - opt = options[pd[offset]]; + opt = options[opt_byte]; offset++; - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 3, + proto_tree_add_text(telnet_tree, tvb, start_offset, 3, "Command: %s %s", type, opt); return offset; } static int -telnet_command(proto_tree *telnet_tree, const u_char *pd, int start_offset) +telnet_command(proto_tree *telnet_tree, tvbuff_t *tvb, int start_offset) { int offset = start_offset; u_char optcode; offset += 1; /* skip IAC */ - optcode = pd[offset]; + optcode = tvb_get_guint8(tvb, offset); offset++; switch(optcode) { case TN_EOF: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: End of File"); break; case TN_SUSP: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Suspend Current Process"); break; case TN_ABORT: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Abort Process"); break; case TN_EOR: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: End of Record"); break; case TN_SE: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Suboption End"); break; case TN_NOP: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: No Operation"); break; case TN_DM: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Data Mark"); break; case TN_BRK: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Break"); break; case TN_IP: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Interrupt Process"); break; case TN_AO: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Abort Output"); break; case TN_AYT: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Are You There?"); break; case TN_EC: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Escape Character"); break; case TN_EL: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Erase Line"); break; case TN_GA: - proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2, + proto_tree_add_text(telnet_tree, tvb, start_offset, 2, "Command: Go Ahead"); break; case TN_SB: - offset = telnet_sub_option(telnet_tree, pd, start_offset); + offset = telnet_sub_option(telnet_tree, tvb, start_offset); break; case TN_WILL: - offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset, + offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset, "Will"); break; case TN_WONT: - offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset, + offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset, "Won't"); break; case TN_DO: - offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset, + offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset, "Do"); break; case TN_DONT: - offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset, + offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset, "Don't"); break; } @@ -294,86 +298,81 @@ telnet_command(proto_tree *telnet_tree, const u_char *pd, int start_offset) } static void -telnet_add_text(proto_tree *tree, tvbuff_t *tvb, const u_char *pd, - int offset, int len) +telnet_add_text(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { - const u_char *data, *dataend; - const u_char *lineend, *eol; + gint next_offset; int linelen; - data = &pd[offset]; - dataend = data + len; - while (data < dataend) { + while (len != 0 && tvb_length_remaining(tvb, offset)) { /* * Find the end of the line. */ - lineend = find_line_end(data, dataend, &eol); - linelen = lineend - data; + tvb_find_line_end(tvb, offset, len, &next_offset); + linelen = next_offset - offset; - proto_tree_add_text(tree, NullTVB, offset, linelen, - "Data: %s", format_text(data, linelen)); + proto_tree_add_text(tree, tvb, offset, linelen, + "Data: %s", + tvb_format_text(tvb, offset, linelen)); offset += linelen; - data = lineend; + len -= linelen; } } static void -dissect_telnet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) +dissect_telnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *telnet_tree, *ti; - OLD_CHECK_DISPLAY_AS_DATA(proto_telnet, pd, offset, fd, tree); + CHECK_DISPLAY_AS_DATA(proto_telnet, tvb, pinfo, tree); - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "TELNET"); + pinfo->current_proto = "TELNET"; - if (check_col(fd, COL_INFO)) - col_add_fstr(fd, COL_INFO, "Telnet Data ..."); + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "TELNET"); + + if (check_col(pinfo->fd, COL_INFO)) + col_add_fstr(pinfo->fd, COL_INFO, "Telnet Data ..."); if (tree) { - int data_offset; + gint offset = 0; + guint len; int data_len; + gint iac_offset; - ti = proto_tree_add_item(tree, proto_telnet, NullTVB, offset, END_OF_FRAME, FALSE); + ti = proto_tree_add_item(tree, proto_telnet, tvb, offset, + tvb_length_remaining(tvb, offset), FALSE); telnet_tree = proto_item_add_subtree(ti, ett_telnet); - data_offset = offset; - data_len = 0; - /* * Scan through the buffer looking for an IAC byte. */ - while (offset < pi.captured_len) { - if (pd[offset] == TN_IAC) { + while ((len = tvb_length_remaining(tvb, offset)) != 0) { + iac_offset = tvb_find_guint8(tvb, offset, len, TN_IAC); + if (iac_offset != -1) { /* * We found an IAC byte. * If there's any data before it, add that data to the * tree, a line at a time. */ - if (data_len > 0) { - telnet_add_text(telnet_tree, NullTVB, pd, data_offset, data_len); - data_len = 0; - data_offset = offset; - } + data_len = iac_offset - offset; + if (data_len > 0) + telnet_add_text(telnet_tree, tvb, offset, data_len); /* * Now interpret the command. */ - offset = telnet_command(telnet_tree, pd, offset); - data_offset = offset; + offset = telnet_command(telnet_tree, tvb, iac_offset); } else { - data_len++; - offset++; + /* + * We found no IAC byte, so what remains in the buffer + * is the last of the data in the packet. + * Add it to the tree, a line at a time, and then quit. + */ + telnet_add_text(telnet_tree, tvb, offset, len); + break; } } - - /* - * We've reached the end of the buffer. - * If there's any data left, add it to the tree. - */ - if (data_len > 0) - telnet_add_text(telnet_tree, NullTVB, pd, data_offset, data_len); } } @@ -397,5 +396,5 @@ proto_register_telnet(void) void proto_reg_handoff_telnet(void) { - old_dissector_add("tcp.port", TCP_PORT_TELNET, dissect_telnet); + dissector_add("tcp.port", TCP_PORT_TELNET, dissect_telnet); } |