aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-gnutella.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2005-01-31 00:28:02 +0000
committerGuy Harris <guy@alum.mit.edu>2005-01-31 00:28:02 +0000
commite2089f3d82967dd087f35d6779d80abdc2d73757 (patch)
treef78bd527932c5dc209518e1889312b4c05c9c251 /epan/dissectors/packet-gnutella.c
parenta43da7a4ff7a04591e0b2f2f666de7b83d797b20 (diff)
Add a URL for Gnutella specs.
Don't check, in the dissectors for particular Gnutella packets, whether the packet goes past the end of the tvbuff - let that throw an exception so unreassembled packets are shown as such. Clean up indentation. Boost GNUTELLA_MAX_SNAP_SIZE to 4096 (one Gnutella spec suggests that packets should be < 4K), and use it to 1) clamp the length of packets (so we don't do huge reassembly or have problems when the total packet length, including the header, overflows 32 bits) and 2) check the length of packets before using tcp_dissect_pdus(), to distinguish between packets to be reassembled and a transfer stream. Pass the correct value to tcp_dissect_pdus() as the header length. svn path=/trunk/; revision=13211
Diffstat (limited to 'epan/dissectors/packet-gnutella.c')
-rw-r--r--epan/dissectors/packet-gnutella.c148
1 files changed, 73 insertions, 75 deletions
diff --git a/epan/dissectors/packet-gnutella.c b/epan/dissectors/packet-gnutella.c
index d8e848fa3b..c0e6c1a092 100644
--- a/epan/dissectors/packet-gnutella.c
+++ b/epan/dissectors/packet-gnutella.c
@@ -38,12 +38,16 @@
#include "packet-gnutella.h"
#include "packet-tcp.h"
+/*
+ * See
+ *
+ * http://rfc-gnutella.sourceforge.net/developer/index.html
+ */
+
static int proto_gnutella = -1;
static int hf_gnutella_stream = -1;
-static int hf_gnutella_truncated = -1;
-
static int hf_gnutella_header = -1;
static int hf_gnutella_header_id = -1;
static int hf_gnutella_header_payload = -1;
@@ -83,17 +87,7 @@ static int hf_gnutella_push_port = -1;
static gint ett_gnutella = -1;
-static void dissect_gnutella_pong(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
-
- if(offset + size > tvb_length(tvb)) {
- proto_tree_add_item(tree,
- hf_gnutella_truncated,
- tvb,
- offset,
- size,
- FALSE);
- return;
- }
+static void dissect_gnutella_pong(tvbuff_t *tvb, guint offset, proto_tree *tree) {
proto_tree_add_item(tree,
hf_gnutella_pong_port,
@@ -107,7 +101,7 @@ static void dissect_gnutella_pong(tvbuff_t *tvb, guint offset, proto_tree *tree,
tvb,
offset + GNUTELLA_PONG_IP_OFFSET,
GNUTELLA_IP_LENGTH,
- FALSE);
+ FALSE);
proto_tree_add_item(tree,
hf_gnutella_pong_files,
@@ -127,38 +121,28 @@ static void dissect_gnutella_pong(tvbuff_t *tvb, guint offset, proto_tree *tree,
static void dissect_gnutella_query(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
- if(offset + size > tvb_length(tvb)) {
- proto_tree_add_item(tree,
- hf_gnutella_truncated,
- tvb,
- offset,
- size,
- FALSE);
- return;
- }
-
proto_tree_add_item(tree,
hf_gnutella_query_min_speed,
tvb,
offset + GNUTELLA_QUERY_SPEED_OFFSET,
GNUTELLA_SHORT_LENGTH,
- TRUE);
-
- if (size > GNUTELLA_SHORT_LENGTH) {
- proto_tree_add_item(tree,
- hf_gnutella_query_search,
- tvb,
- offset + GNUTELLA_QUERY_SEARCH_OFFSET,
- size - GNUTELLA_SHORT_LENGTH,
- FALSE);
- }
- else {
- proto_tree_add_text(tree,
- tvb,
- offset + GNUTELLA_QUERY_SEARCH_OFFSET,
- 0,
- "Missing data for Query Search.");
- }
+ TRUE);
+
+ if (size > GNUTELLA_SHORT_LENGTH) {
+ proto_tree_add_item(tree,
+ hf_gnutella_query_search,
+ tvb,
+ offset + GNUTELLA_QUERY_SEARCH_OFFSET,
+ size - GNUTELLA_SHORT_LENGTH,
+ FALSE);
+ }
+ else {
+ proto_tree_add_text(tree,
+ tvb,
+ offset + GNUTELLA_QUERY_SEARCH_OFFSET,
+ 0,
+ "Missing data for Query Search.");
+ }
}
static void dissect_gnutella_queryhit(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
@@ -172,16 +156,6 @@ static void dissect_gnutella_queryhit(tvbuff_t *tvb, guint offset, proto_tree *t
int name_at_offset, extra_at_offset;
int cur_char, remaining, used;
- if(offset + size > tvb_length(tvb)) {
- proto_tree_add_item(tree,
- hf_gnutella_truncated,
- tvb,
- offset,
- size,
- FALSE);
- return;
- }
-
hit_count = tvb_get_guint8(tvb, offset + GNUTELLA_QUERYHIT_COUNT_OFFSET);
proto_tree_add_uint(tree,
@@ -317,17 +291,7 @@ static void dissect_gnutella_queryhit(tvbuff_t *tvb, guint offset, proto_tree *t
}
-static void dissect_gnutella_push(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
-
- if(offset + size > tvb_length(tvb)) {
- proto_tree_add_item(tree,
- hf_gnutella_truncated,
- tvb,
- offset,
- size,
- FALSE);
- return;
- }
+static void dissect_gnutella_push(tvbuff_t *tvb, guint offset, proto_tree *tree) {
proto_tree_add_item(tree,
hf_gnutella_push_servent_id,
@@ -366,12 +330,12 @@ get_gnutella_pdu_len(tvbuff_t *tvb, int offset) {
size = tvb_get_letohl(
tvb,
offset + GNUTELLA_HEADER_SIZE_OFFSET);
- if (size > 0x00FFFFFF) {
+ if (size > GNUTELLA_MAX_SNAP_SIZE) {
/*
* XXX - arbitrary limit, preventing overflows and
* attempts to reassemble 4GB of data.
*/
- size = 0x00FFFFFF;
+ size = GNUTELLA_MAX_SNAP_SIZE;
}
/* The size doesn't include the header */
@@ -495,8 +459,7 @@ static void dissect_gnutella_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
dissect_gnutella_pong(
tvb,
GNUTELLA_HEADER_LENGTH,
- gnutella_pong_tree,
- size);
+ gnutella_pong_tree);
break;
case GNUTELLA_PUSH:
pi = proto_tree_add_item(
@@ -512,8 +475,7 @@ static void dissect_gnutella_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
dissect_gnutella_push(
tvb,
GNUTELLA_HEADER_LENGTH,
- gnutella_push_tree,
- size);
+ gnutella_push_tree);
break;
case GNUTELLA_QUERY:
pi = proto_tree_add_item(
@@ -558,14 +520,55 @@ static void dissect_gnutella_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
static void dissect_gnutella(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ proto_item *ti;
+ proto_tree *gnutella_tree = NULL;
+ guint32 size;
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gnutella");
if (check_col(pinfo->cinfo, COL_INFO))
col_clear(pinfo->cinfo, COL_INFO);
- tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 2, get_gnutella_pdu_len,
- dissect_gnutella_pdu);
+ /*
+ * OK, do we have enough data to determine whether this
+ * is Gnutella messages or just a transfer stream?
+ */
+ if (tvb_bytes_exist(tvb, GNUTELLA_HEADER_SIZE_OFFSET, 4)) {
+ /*
+ * Yes - fetch the length and see if it's bigger
+ * than GNUTELLA_MAX_SNAP_SIZE; if it is, we assume
+ * it's a transfer stream.
+ *
+ * Should we also check the payload descriptor?
+ */
+ size = tvb_get_letohl(
+ tvb,
+ GNUTELLA_HEADER_SIZE_OFFSET);
+ if (size > GNUTELLA_MAX_SNAP_SIZE) {
+ if (tree) {
+ ti = proto_tree_add_item(tree,
+ proto_gnutella,
+ tvb,
+ 0,
+ -1,
+ FALSE);
+ gnutella_tree = proto_item_add_subtree(ti,
+ ett_gnutella);
+
+ proto_tree_add_item(gnutella_tree,
+ hf_gnutella_stream,
+ tvb,
+ 0,
+ -1,
+ FALSE);
+ }
+ return;
+ }
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, GNUTELLA_HEADER_SIZE_OFFSET+4,
+ get_gnutella_pdu_len, dissect_gnutella_pdu);
}
void proto_register_gnutella(void) {
@@ -596,11 +599,6 @@ void proto_register_gnutella(void) {
FT_NONE, BASE_NONE, NULL, 0,
"Gnutella QueryHit Payload", HFILL }
},
- { &hf_gnutella_truncated,
- { "Truncated Frame", "gnutella.truncated",
- FT_NONE, BASE_NONE, NULL, 0,
- "The Gnutella Frame Was Truncated", HFILL }
- },
{ &hf_gnutella_stream,
{ "Gnutella Upload / Download Stream", "gnutella.stream",
FT_NONE, BASE_NONE, NULL, 0,