Ethereal-dev: [Ethereal-dev] New dissector Gnutella
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: ENDOH Akira <endoh@xxxxxxxxxxxxxx>
Date: Tue, 15 May 2001 20:08:56 +0900
Hello, I wrote a new dissector for Gnutella Protocol. I referred to the document `The Gnutella Protocol Specification v0.4' written by Clip2 (http://www.clip2.com/). Since Gnutella applications use HTTP to transfer files, I want to use dissect_http() function in my dissector. But in packet-http.c, dissect_http() is declared with `static' keyword, and I can't call dissect_http() in my dissector. I use dissect_data() instead of dissect_http(). If my dissector can call dissect_http(), a few changes (in line 149, 225 and 226) make Ethereal to dissect Gnutella file transfer as HTTP. Regards, ---- endoh ------------------------ /* packet-gnutella.c * Routines for Gnutella Protocol dissection * By ENDOH Akira <endoh@xxxxxxxxxxxxxx> * * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxx> * Copyright 1998 Gerald Combs * * Reference to `The Gnutella Protocol Specification v0.4': Clip2 * Copied from doc/README.developer * * To do: * - clean up the code * - fix up the bug caused by the descriptor which has invalid(?) length * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <glib.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> #endif #ifdef NEED_SNPRINTF_H # include "snprintf.h" #endif #include "strutil.h" #include "packet.h" #define Ping 0x00 #define Pong 0x01 #define Push 0x40 #define Query 0x80 #define QueryHit 0x81 #define DESC_PING_LEN 0 #define DESC_PONG_LEN 14 #define DESC_QUERY_MIN_LEN 4 #define DESC_QUERYHIT_MIN_LEN 27 /* sizeof(QueryHit w/o ResultSets & Trailler) */ #define DESC_PUSH_LEN 26 #define RSET_LEN 11 static const value_string payload_descriptor_val[] = { {Ping, "Ping"}, {Pong, "Pong"}, {Push, "Push"}, {Query, "Query"}, {QueryHit, "Query Hit"} }; #define TCP_PORT_GNUTELLA 6346 static int proto_gnutella = -1; static int hf_gnutella_descriptor_id = -1; static int hf_gnutella_payload_descriptor = -1; static int hf_gnutella_ttl = -1; static int hf_gnutella_hops = -1; static int hf_gnutella_payload_length = -1; static int hf_gnutella_pong_port = -1; static int hf_gnutella_pong_address = -1; static int hf_gnutella_pong_nfs = -1; static int hf_gnutella_pong_nks = -1; static int hf_gnutella_push_sid = -1; static int hf_gnutella_push_findex = -1; static int hf_gnutella_push_address = -1; static int hf_gnutella_push_port = -1; static int hf_gnutella_query_ms = -1; static int hf_gnutella_query_sc = -1; static int hf_gnutella_queryhit_noh = -1; static int hf_gnutella_queryhit_port = -1; static int hf_gnutella_queryhit_address = -1; static int hf_gnutella_queryhit_speed = -1; static int hf_gnutella_queryhit_sid = -1; static int hf_gnutella_resultset_findex = -1; static int hf_gnutella_resultset_fsize = -1; static int hf_gnutella_resultset_fname = -1; static int hf_gnutella_trailer_vcode = -1; static int hf_gnutella_trailer_odsize = -1; static int hf_gnutella_trailer_odata = -1; static int hf_gnutella_trailer_flag_upspeed = -1; static int hf_gnutella_trailer_flag_huped = -1; static int hf_gnutella_trailer_flag_busy = -1; static int hf_gnutella_trailer_flag_push = -1; static int hf_gnutella_trailer_pdata = -1; static gint ett_gnutella = -1; static gint ett_gnutella_desc = -1; static gint ett_pong = -1; static gint ett_push = -1; static gint ett_query = -1; static gint ett_queryhit = -1; static gint ett_resultset = -1; static gint ett_trailer = -1; static gint ett_odata = -1; static int descriptor = 0; static const true_false_string flags_set_truth = { "Set", "Not set" }; typedef enum _gnutella_proto_t { GNUTELLA_CONNECT, GNUTELLA_OK, GNUTELLA_GIV, GNUTELLA_DESC, HTTP } gnutella_proto_t; static guint dissect_desc_header(tvbuff_t*, proto_tree*, int); static void dissect_pong(tvbuff_t*, proto_tree*, guint); static void dissect_push(tvbuff_t*, proto_tree*, guint); static void dissect_query(tvbuff_t*, proto_tree*, guint, guint); static void dissect_queryhit(tvbuff_t*, proto_tree*, guint, guint); static guint dissect_resultset(tvbuff_t*, proto_tree*, guint, int); static guint dissect_trailer(tvbuff_t*, proto_tree*, guint, guint); static void dissect_odata(tvbuff_t*, proto_tree*, guint); static gnutella_proto_t distinguish_protocol(tvbuff_t*); static int is_descriptor(tvbuff_t*, guint); /* static int ping_len_check(tvbuff_t*, guint); */ static int pong_len_check(tvbuff_t*, guint); static int query_len_check(tvbuff_t*, guint); static int queryhit_len_check(tvbuff_t*, guint); static int push_len_check(tvbuff_t*, guint); /* void dissect_http(tvbuff_t*, packet_info*, proto_tree*); */ static void dissect_gnutella(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti = NULL; proto_tree *gnutella_tree; tvbuff_t *next_tvb; guint offset = 0, len = tvb_length(tvb), i; const gint8 *buf; CHECK_DISPLAY_AS_DATA(proto_gnutella, tvb, pinfo, tree); pinfo->current_proto = "Gnutella"; if (check_col(pinfo->fd, COL_PROTOCOL)) col_add_str(pinfo->fd, COL_PROTOCOL, "Gnutella"); switch (distinguish_protocol(tvb)) { case GNUTELLA_CONNECT: buf = tvb_get_ptr(tvb, 0, len); if (check_col(pinfo->fd, COL_INFO)) col_add_str(pinfo->fd, COL_INFO, format_text(buf, len-2)); if (tree) { ti = proto_tree_add_item(tree, proto_gnutella, tvb, 0, len, FALSE); gnutella_tree = proto_item_add_subtree(ti, ett_gnutella); proto_tree_add_text(gnutella_tree, tvb, 0, len, format_text(buf, len)); } break; case GNUTELLA_OK: if (check_col(pinfo->fd, COL_INFO)) col_add_str(pinfo->fd, COL_INFO, "GNUTELLA OK"); offset = 13; if (tree) { ti = proto_tree_add_item(tree, proto_gnutella, tvb, 0, len, FALSE); gnutella_tree = proto_item_add_subtree(ti, ett_gnutella); proto_tree_add_text(gnutella_tree, tvb, 0, offset, "GNUTELLA OK\\n\\n"); } if (descriptor == 0) break; case GNUTELLA_DESC: if (check_col(pinfo->fd, COL_INFO)) { if (offset == 0) col_add_fstr(pinfo->fd, COL_INFO, "Descriptor - Containing %d descriptor%s", descriptor, descriptor>1?"s":""); else col_append_fstr(pinfo->fd, COL_INFO, "; Descriptor - Containing %d descriptor%s", descriptor, descriptor>1?"s":""); } if (tree) { if (offset == 0) ti = proto_tree_add_item(tree, proto_gnutella, tvb, 0, len, FALSE); i = 0; while (offset < len) { gnutella_tree = proto_item_add_subtree(ti, ett_gnutella); next_tvb = tvb_new_subset(tvb, offset, -1, -1); offset += dissect_desc_header(next_tvb, gnutella_tree, i); i++; tvb_free(next_tvb); } } break; case GNUTELLA_GIV: buf = tvb_get_ptr(tvb, 0, len); if (check_col(pinfo->fd, COL_INFO)) col_add_str(pinfo->fd, COL_INFO, format_text(buf, len-2)); if (tree) { ti = proto_tree_add_item(tree, proto_gnutella, tvb, 0, len, FALSE); gnutella_tree = proto_item_add_subtree(ti, ett_gnutella); proto_tree_add_text(gnutella_tree, tvb, 0, len, format_text(buf, len)); } break; case HTTP: /*dissect_http(tvb, pinfo, tree);*/ dissect_data(tvb, 0, pinfo, tree); } } static guint dissect_desc_header(tvbuff_t *tvb, proto_tree *tree, int descriptor_num) { proto_item *ti; proto_tree *gnutella_desc_tree; const guint8* ptr; guint32 desc_pay_len; guint offset = 0; int payload_desc; if (tree) { tvb_memcpy(tvb, (guint8*)&desc_pay_len, 19, 4); payload_desc = tvb_get_guint8(tvb, 16); ti = proto_tree_add_text(tree, tvb, offset, desc_pay_len + 23, "Descriptor %d (%s - %d byte)", descriptor_num+1, match_strval(payload_desc ,payload_descriptor_val), desc_pay_len+23); gnutella_desc_tree = proto_item_add_subtree(ti, ett_gnutella_desc); ptr = tvb_get_ptr(tvb, offset, 23); proto_tree_add_bytes(gnutella_desc_tree, hf_gnutella_descriptor_id, tvb, offset, 16, ptr); offset += 16; proto_tree_add_text(gnutella_desc_tree, tvb, offset, 1, "Payload Descriptor: %2x (%s)", payload_desc, match_strval(payload_desc ,payload_descriptor_val)); proto_tree_add_uint_hidden(gnutella_desc_tree, hf_gnutella_payload_descriptor, tvb, offset, 1, (guint32)payload_desc); offset += 1; proto_tree_add_uint(gnutella_desc_tree, hf_gnutella_ttl, tvb, offset, 1, (guint32)tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_uint(gnutella_desc_tree, hf_gnutella_hops, tvb, offset, 1, (guint32)tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_uint_format(gnutella_desc_tree, hf_gnutella_payload_length, tvb, offset, 4, desc_pay_len, "Payload Length: %d byte", desc_pay_len); offset += 4; switch (payload_desc) { case 0x01: dissect_pong(tvb, gnutella_desc_tree, offset); break; case 0x40: dissect_push(tvb, gnutella_desc_tree, offset); break; case 0x80: dissect_query(tvb, gnutella_desc_tree, offset, desc_pay_len); break; case 0x81: dissect_queryhit(tvb, gnutella_desc_tree, offset, desc_pay_len); } } offset += desc_pay_len; return offset; } static void dissect_pong(tvbuff_t *tvb, proto_tree *tree, guint offset) { proto_item *ti; proto_tree *pong_tree; guint32 i; if (tree) { if (!pong_len_check(tvb, offset)) { ti = proto_tree_add_text(tree, tvb, offset, tvb_get_letohl(tvb, offset - 4), "Descriptor Payload (Pong) - malformed descriptor"); return; } ti = proto_tree_add_text(tree, tvb, offset, 14, "Descriptor Payload (Pong)"); pong_tree = proto_item_add_subtree(ti, ett_pong); i = tvb_get_letohs(tvb, offset); proto_tree_add_uint_format(pong_tree, hf_gnutella_pong_port, tvb, offset, 2, i, "Port: %d", i); offset += 2; proto_tree_add_ipv4(pong_tree, hf_gnutella_pong_address, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; proto_tree_add_uint(pong_tree, hf_gnutella_pong_nfs, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; proto_tree_add_uint(pong_tree, hf_gnutella_pong_nks, tvb, offset, 4, tvb_get_letohl(tvb, offset)); } } static void dissect_push(tvbuff_t *tvb, proto_tree *tree, guint offset) { proto_item *ti; proto_tree *push_tree; if (tree) { if (!push_len_check(tvb, offset)) { ti = proto_tree_add_text(tree, tvb, offset, tvb_get_letohl(tvb, offset-4), "Descriptor Payload (Push) - malformed descriptor"); return; } ti = proto_tree_add_text(tree, tvb, offset, 26, "Descriptor Payload (Push)"); push_tree = proto_item_add_subtree(ti, ett_push); proto_tree_add_bytes(push_tree, hf_gnutella_push_sid, tvb, offset, 16, tvb_get_ptr(tvb, offset, 16)); offset += 16; proto_tree_add_uint(push_tree, hf_gnutella_push_findex, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; proto_tree_add_ipv4(push_tree, hf_gnutella_push_address, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; proto_tree_add_uint(push_tree, hf_gnutella_push_port, tvb, offset, 2, tvb_get_letohs(tvb, offset)); offset += 2; } } static void dissect_query(tvbuff_t *tvb, proto_tree *tree, guint offset, guint len) { proto_item *ti; proto_tree *query_tree; guint32 i; if (tree) { if (!query_len_check(tvb, offset)) { ti = proto_tree_add_text(tree, tvb, offset, tvb_get_letohl(tvb, offset - 4), "Descriptor Payload (Query) - malformed descriptor"); return; } ti = proto_tree_add_text(tree, tvb, offset, len, "Descriptor Payload (Query)"); query_tree = proto_item_add_subtree(ti, ett_query); i = (guint32)tvb_get_letohs(tvb, offset); proto_tree_add_uint_format(query_tree, hf_gnutella_query_ms, tvb, offset, 2, i, "Mimum Speed: %d Kbytes / sec", i); offset += 2; proto_tree_add_string(query_tree, hf_gnutella_query_sc, tvb, offset, len-2, tvb_get_ptr(tvb, offset, len-3)); } } static void dissect_queryhit(tvbuff_t *tvb, proto_tree *tree, guint offset, guint len) { proto_item *ti; proto_tree *queryhit_tree; guint32 i; int result_num; if (tree) { if (!queryhit_len_check(tvb, offset)) { ti = proto_tree_add_text(tree, tvb, offset, tvb_get_letohl(tvb, offset - 4), "Descriptor Payload (QueryHit) - malformed descriptor"); return; } ti = proto_tree_add_text(tree, tvb, offset, len, "Descriptor Payload (QueryHit)"); queryhit_tree = proto_item_add_subtree(ti, ett_queryhit); proto_tree_add_uint(queryhit_tree, hf_gnutella_queryhit_noh, tvb, offset, 1, result_num = tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_uint(queryhit_tree, hf_gnutella_queryhit_port, tvb, offset, 2, tvb_get_letohs(tvb, offset)); offset += 2; proto_tree_add_ipv4(queryhit_tree, hf_gnutella_queryhit_address, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; i = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(queryhit_tree, hf_gnutella_queryhit_speed, tvb, offset, 4, i, "Speed: %d Kbytes / sec", i); offset += 4; for (i = 1; i <= result_num; i++) { offset = dissect_resultset(tvb, queryhit_tree, offset, i); } if (offset+16 < len+23) { offset = dissect_trailer(tvb, queryhit_tree, offset, len); } proto_tree_add_bytes(queryhit_tree, hf_gnutella_queryhit_sid, tvb, offset, 16, tvb_get_ptr(tvb, offset, 16)); } } static guint dissect_resultset(tvbuff_t *tvb, proto_tree *tree, guint offset, int result_num) { proto_item *ti; proto_tree *resultset_tree; guint32 fname_len = 0, fsize; guint16 gi; if (tree) { while ((gi = tvb_get_letohs(tvb, offset + 8 + fname_len)) != 0) fname_len++; fname_len += 2; ti = proto_tree_add_text(tree, tvb, offset, fname_len + 8, "Result Set %d", result_num); resultset_tree = proto_item_add_subtree(ti, ett_resultset); proto_tree_add_uint(resultset_tree, hf_gnutella_resultset_findex, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; fsize = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(resultset_tree, hf_gnutella_resultset_fsize, tvb, offset, 4, fsize, "File Size: %d byte", fsize); offset += 4; proto_tree_add_string(resultset_tree, hf_gnutella_resultset_fname, tvb, offset, fname_len, tvb_get_ptr(tvb, offset, fname_len)); offset += fname_len; } return offset; } static guint dissect_trailer(tvbuff_t *tvb, proto_tree *tree, guint offset, guint len) { proto_item *ti; proto_tree *trailer_tree; guint8 datasize; guint i; if (tree) { ti = proto_tree_add_text(tree, tvb, offset, len + 23 - offset - 16, "Trailer"); trailer_tree = proto_item_add_subtree(ti, ett_trailer); proto_tree_add_uint(trailer_tree, hf_gnutella_trailer_vcode, tvb, offset, 4, tvb_get_letohl(tvb, offset)); offset += 4; datasize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(trailer_tree, hf_gnutella_trailer_odsize, tvb, offset, 1, datasize); offset += 1; for(i = 0; i < datasize; i++){ dissect_odata(tvb, trailer_tree, offset); offset++; } datasize = len + 23 - offset - 16; proto_tree_add_bytes(trailer_tree, hf_gnutella_trailer_pdata, tvb, offset, datasize, tvb_get_ptr(tvb, offset, datasize)); offset += datasize; } return offset; } static void dissect_odata(tvbuff_t *tvb, proto_tree *tree, guint offset) { proto_item *ti; proto_tree *trailer_tree; guint8 flag; if (tree) { flag = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(tree, tvb, offset, 1, "Open Data (0x%02x)",flag); trailer_tree = proto_item_add_subtree(ti, ett_odata); proto_tree_add_boolean(trailer_tree, hf_gnutella_trailer_flag_upspeed, tvb, offset, 1, flag); proto_tree_add_boolean(trailer_tree, hf_gnutella_trailer_flag_huped, tvb, offset, 1, flag); proto_tree_add_boolean(trailer_tree, hf_gnutella_trailer_flag_busy, tvb, offset, 1, flag); proto_tree_add_boolean(trailer_tree, hf_gnutella_trailer_flag_push, tvb, offset, 1, flag); } } void proto_register_gnutella(void) { static hf_register_info hf[] = { { &hf_gnutella_descriptor_id, { "Descriptor ID", "gnutella.descriptor_id", FT_BYTES, BASE_HEX, NULL, 0, "Uniquerly identifying the descriptor on the network" } }, { &hf_gnutella_payload_descriptor, { "Payload Descriptor", "gnutella.payload_descriptor", FT_UINT8, BASE_HEX, NULL, 0, "type of descriptor" } }, { &hf_gnutella_ttl, { "TTL", "gnutella.ttl", FT_UINT8, BASE_DEC, NULL, 0, "The number of times this packet will be forwarded" } }, { &hf_gnutella_hops, { "Hops", "gnutella.hops", FT_UINT8, BASE_DEC, NULL, 0, "The number of times this descriptor has been forwarded" } }, { &hf_gnutella_payload_length, { "Payload Length", "gnutella.payload_length", FT_UINT32, BASE_DEC, NULL, 0, "The length of the descriptor following this field" } }, { &hf_gnutella_pong_port, { " Port", "gnutella.pong_port", FT_UINT16, BASE_DEC, NULL, 0, "Port number on which the servent can accept incoming connections" } }, { &hf_gnutella_pong_address, { "IP Address", "gnutella.pong_address", FT_IPv4, BASE_NONE, NULL, 0, "IP address of the servent" } }, { &hf_gnutella_pong_nfs, { "Number of Files Shared", "gnutella.pong_nfs", FT_UINT32, BASE_DEC, NULL, 0, "Number of files which the servent is sharing" } }, { &hf_gnutella_pong_nks, { "Number of Kilobytes Shared", "gnutella.pong_nks", FT_UINT32, BASE_DEC, NULL, 0, "Number of Kilobytes of data which the servent is sharing" } }, { &hf_gnutella_push_sid, { "Servent Identifier", "gnutella.push_sid", FT_BYTES, BASE_DEC, NULL, 0, "Uniquerly identifying the descriptor on the network" } }, { &hf_gnutella_push_findex, { "File Index", "gnutella.push_findex", FT_UINT32, BASE_HEX, NULL, 0, "Uniquely identifying the file to be pushed" } }, { &hf_gnutella_push_address, { "IP Address", "gnutella.push_address", FT_IPv4, BASE_NONE, NULL, 0, "IP address of the servent" } }, { &hf_gnutella_push_port, { "Port", "gnutella.push_port", FT_UINT16, BASE_DEC, NULL, 0, "Port number to which the file should be pushed" } }, { &hf_gnutella_query_ms, { "Minimum Speed", "gnutella.query_ms", FT_UINT16, BASE_DEC, NULL, 0, "The minimum speed of servents that should respond to this query" } }, { &hf_gnutella_query_sc, { "Search Criteria", "gnutella.query_sc", FT_STRING, BASE_NONE, NULL, 0, "Search Criteria" } }, { &hf_gnutella_queryhit_noh, { "Number of Hits", "gnutella.queryhit_noh", FT_UINT8, BASE_DEC, NULL, 0, "Number of hits (result set) in this packet" } }, { &hf_gnutella_queryhit_port, { "Port", "gnutella.queryhit_port", FT_UINT16, BASE_DEC, NULL, 0, "Port number on which the servent can accept incoming connections" } }, { &hf_gnutella_queryhit_address, { "IP Address", "gnutella.queryhit_address", FT_IPv4, BASE_NONE, NULL, 0, "IP address of the servent" } }, { &hf_gnutella_queryhit_speed, { "Speed", "gnutella.queryhit_speed", FT_UINT32, BASE_DEC, NULL, 0, "Speed of the responding servent" } }, { &hf_gnutella_queryhit_sid, { "Servent Identifier", "gnutella.queryhit_sid", FT_BYTES, BASE_HEX, NULL, 0, "Uniquely identifying the servent on the network" } }, { &hf_gnutella_resultset_findex, { "File Index", "gnutella.resultset_findex", FT_UINT32, BASE_HEX, NULL, 0, "Uniquery identifying the file on responding servent" } }, { &hf_gnutella_resultset_fsize, { "File Size", "gnutella.resultset_fsize", FT_UINT32, BASE_DEC, NULL, 0, "Size of the file" } }, { &hf_gnutella_resultset_fname, { "File Name", "gnutella.resultset_fname", FT_STRING, BASE_NONE, NULL, 0, "Name of the file" } }, { &hf_gnutella_trailer_vcode, { "Vendor Code", "gnutella.trailer_vcode", FT_UINT32, BASE_HEX, NULL, 0, "Vendor code of the servent responding this packet" } }, { &hf_gnutella_trailer_odsize, { "Open Data Size", "gnutella.trailer_odsize", FT_UINT8, BASE_DEC, NULL, 0, "Length of the Open Data field" } }, { &hf_gnutella_trailer_odata, { "Open Data", "gnutella.trailer_odata", FT_UINT8, BASE_DEC, NULL, 0, "Trailler Open Data" } }, { &hf_gnutella_trailer_flag_upspeed, { "flagUploadSpeed", "gnutella.trailer_flagupspeed", FT_BOOLEAN, 8, TFS(&flags_set_truth), 16, "" } }, { &hf_gnutella_trailer_flag_huped, { "flagHaveUploaded", "gnutella.trailer_flaghuploaded", FT_BOOLEAN, 8, TFS(&flags_set_truth), 8, "" } }, { &hf_gnutella_trailer_flag_busy, { "flagBusy", "gnutella.trailer_busy", FT_BOOLEAN, 8, TFS(&flags_set_truth), 4, "" } }, { &hf_gnutella_trailer_flag_push, { "flagPush", "gnutella.trailer_push", FT_BOOLEAN, 8, TFS(&flags_set_truth), 1, "" } }, { &hf_gnutella_trailer_pdata, { "Private Data", "gnutella.trailer_pdata", FT_BYTES, BASE_HEX, NULL, 0, "Trailer private data" } }, }; static gint *ett[] = { &ett_gnutella, &ett_gnutella_desc, &ett_pong, &ett_push, &ett_query, &ett_queryhit, &ett_resultset, &ett_trailer, &ett_odata }; proto_gnutella = proto_register_protocol("Gnutella Protocol","Gnutella", "gnutella"); proto_register_field_array(proto_gnutella, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_gnutella(void) { dissector_add("tcp.port", TCP_PORT_GNUTELLA, dissect_gnutella, proto_gnutella); } static gnutella_proto_t distinguish_protocol(tvbuff_t* tvb) { guint offset = 0, len = tvb_length(tvb); guint8 str_tmp[23]; descriptor = 0; if (len >= 21) { strcpy(str_tmp, "GNUTELLA CONNECT"); str_tmp[21] = str_tmp[22] = 0x0a; if (tvb_strneql(tvb, 0, str_tmp, 16) == 0 && tvb_strneql(tvb, len-2, str_tmp+21, 2) == 0) return GNUTELLA_CONNECT; } if (len >= 13) { strcpy(str_tmp, "GNUTELLA OK"); str_tmp[11] = str_tmp[12] = 0x0a; if (tvb_strneql(tvb, 0, str_tmp, 13) == 0){ if (len == 13 || (descriptor = is_descriptor(tvb, 13))) return GNUTELLA_OK; } } if (len >= 11) { if (tvb_strneql(tvb, 0, "GIV ", 4) == 0) /*if (tvb_find_line_end(tvb, 0, -1, &eol) == len-1) if (tvb_get_guint8(tvb, eol) == 0x0a)*/ return GNUTELLA_GIV; } descriptor = is_descriptor(tvb, offset); if (descriptor) return GNUTELLA_DESC; return HTTP; /* probably.... */ } static int is_descriptor(tvbuff_t* tvb, guint offset) { guint32 payload_length; guint len = tvb_length(tvb); int descriptor_num = 0; while (len > offset) { if (len >= offset + 23) { payload_length = tvb_get_letohl(tvb, offset+19); offset += (23 + payload_length); descriptor_num++; } else break; } return (len == offset)?descriptor_num:0; } /* static int ping_len_check(tvbuff_t* tvb, guint offset) { return (tvb_get_letohl(tvb, offset-4) == DESC_PING_LEN); } */ static int pong_len_check(tvbuff_t* tvb, guint offset) { return (tvb_get_letohl(tvb, offset-4) == DESC_PONG_LEN); } static int query_len_check(tvbuff_t* tvb, guint offset) { return (tvb_get_letohl(tvb, offset - 4) >= DESC_QUERY_MIN_LEN); } static int queryhit_len_check(tvbuff_t* tvb, guint offset) { guint8 noh = tvb_get_guint8(tvb, offset); int rlen = tvb_get_letohl(tvb, offset - 4) - DESC_QUERYHIT_MIN_LEN; int i, j, flag; for (j = 1; j <= noh; j++) { rlen -= 9; /* sizeof(findex+fsize) + 1 = 9 */ if(rlen <= 0) return 0; offset += 8; flag = 0; for (i = 1; i <= rlen-2; i++) if (tvb_get_letohs(tvb, offset+i) == 0x0000) { flag = 1; break; } if (!flag) return 0; /* invalid ResultSet tailend */ rlen -= i + 1; if (rlen < 0) return 0; offset += i + 1; } if (rlen > 0) if (rlen < 7) return 0; /* too short Trailler */ return 1; } static int push_len_check(tvbuff_t* tvb, guint offset) { return (tvb_get_letohl(tvb, offset-4) == DESC_PUSH_LEN); } ------- end of file ---------
- Prev by Date: Re: [Ethereal-dev] TCP-Clear protocol
- Next by Date: [Ethereal-dev] Bugs in osi_utils.c
- Previous by thread: Re: [Ethereal-dev] TCP-Clear protocol
- Next by thread: [Ethereal-dev] Bugs in osi_utils.c
- Index(es):