diff options
author | Guy Harris <guy@alum.mit.edu> | 2005-01-31 00:28:02 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2005-01-31 00:28:02 +0000 |
commit | e2089f3d82967dd087f35d6779d80abdc2d73757 (patch) | |
tree | f78bd527932c5dc209518e1889312b4c05c9c251 /epan/dissectors/packet-gnutella.c | |
parent | a43da7a4ff7a04591e0b2f2f666de7b83d797b20 (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.c | 148 |
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, |