Ethereal-dev: [Ethereal-dev] eDonkey Protocol Dissector
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Xuan Zhang <xz@xxxxxxxxxxxx>
Date: Wed, 16 Jul 2003 13:43:30 -0700 (PDT)
I'm attaching a patch for a protocol dissector for the file-sharing programs using the eDonkey2000 and Overnet networks. The dissector is based on the protocol descriptions from MLDonkey. _____________________________________________________________ !!!!FAST, FREE AND HOT!!!! for the best free email site on the web http://www.aemail4u.com _____________________________________________________________ Select your own custom email address for FREE! Get you@xxxxxxxxxxxxxx, No Ads, 6MB, IMAP, POP, SMTP & more! http://www.everyone.net/selectmail?campaign=tag
Index: Makefile.am =================================================================== RCS file: /cvsroot/ethereal/Makefile.am,v retrieving revision 1.600 diff -u -r1.600 Makefile.am --- Makefile.am 16 Jul 2003 09:23:55 -0000 1.600 +++ Makefile.am 16 Jul 2003 19:59:53 -0000 @@ -184,6 +184,7 @@ packet-eap.c \ packet-eapol.c \ packet-echo.c \ + packet-edonkey.c \ packet-eigrp.c \ packet-enc.c \ packet-enip.c \ Index: Makefile.nmake =================================================================== RCS file: /cvsroot/ethereal/Makefile.nmake,v retrieving revision 1.318 diff -u -r1.318 Makefile.nmake --- Makefile.nmake 16 Jul 2003 09:23:55 -0000 1.318 +++ Makefile.nmake 16 Jul 2003 19:59:53 -0000 @@ -125,6 +125,7 @@ packet-eap.c \ packet-eapol.c \ packet-echo.c \ + packet-edonkey.c \ packet-eigrp.c \ packet-enc.c \ packet-enip.c \ Index: packet-edonkey.c =================================================================== RCS file: packet-edonkey.c diff -N packet-edonkey.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packet-edonkey.c 16 Jul 2003 19:59:54 -0000 @@ -0,0 +1,1435 @@ +/* packet-edonkey.c + * Routines for edonkey dissection + * Copyright 2003, Xuan Zhang <xz@xxxxxxxxxxxx> + * eDonkey dissector based on protocol descriptions from mldonkey: + * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/edonkey-protocol.txt + * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/overnet-protocol.txt + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * 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> + +#include <epan/packet.h> +#include "packet-edonkey.h" + +static int proto_edonkey = -1; + +static int hf_edonkey_message = -1; +static int hf_edonkey_protocol = -1; +static int hf_edonkey_message_length = -1; +static int hf_edonkey_message_type = -1; +static int hf_edonkey_client_hash = -1; +static int hf_edonkey_server_hash = -1; +static int hf_edonkey_file_hash = -1; +static int hf_edonkey_client_id = -1; +static int hf_edonkey_metatag_namesize = -1; +static int hf_edonkey_metatag_type = -1; +static int hf_edonkey_metatag = -1; +static int hf_edonkey_metatag_name = -1; +static int hf_edonkey_metatag_id = -1; +static int hf_edonkey_search = -1; +static int hf_edonkey_ip = -1; +static int hf_edonkey_port = -1; +static int hf_edonkey_hash = -1; +static int hf_edonkey_directory = -1; +static int hf_edonkey_string = -1; +static int hf_edonkey_string_length = -1; +static int hf_edonkey_fileinfo = -1; +static int hf_edonkey_clientinfo = -1; +static int hf_edonkey_serverinfo = -1; +static int hf_overnet_peer = -1; + +static gint ett_edonkey = -1; +static gint ett_edonkey_message = -1; +static gint ett_edonkey_metatag = -1; +static gint ett_edonkey_search = -1; +static gint ett_edonkey_fileinfo = -1; +static gint ett_edonkey_serverinfo = -1; +static gint ett_edonkey_clientinfo = -1; +static gint ett_overnet_peer = -1; + +static const value_string edonkey_protocols[] = { + { EDONKEY_PROTO_EDONKEY, "eDonkey" }, + { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" }, + { EDONKEY_PROTO_EMULE_COMP, "eMule Compressed" }, + { 0, NULL } +}; + +static const value_string edonkey_tcp_msgs[] = { + { EDONKEY_MSG_HELLO, "Hello" }, + { EDONKEY_MSG_BAD_PROTO, "Bad Proto" }, + { EDONKEY_MSG_GET_SERVER_LIST, "Get Server List" }, + { EDONKEY_MSG_OFFER_FILES, "Offer Files" }, + { EDONKEY_MSG_SEARCH_FILES, "Search Files" }, + { EDONKEY_MSG_DISCONNECT, "Disconnect" }, + { EDONKEY_MSG_GET_SOURCES, "Get Sources" }, + { EDONKEY_MSG_SEARCH_USER, "Search User" }, + { EDONKEY_MSG_CLIENT_CB_REQ, "Client Callback Request" }, + { EDONKEY_MSG_MORE_RESULTS, "More Results" }, + { EDONKEY_MSG_SERVER_LIST, "Server List" }, + { EDONKEY_MSG_SEARCH_FILE_RESULTS, "Search File Results" }, + { EDONKEY_MSG_SERVER_STATUS, "Server Status" }, + { EDONKEY_MSG_SERVER_CB_REQ, "Server Callback Request" }, + { EDONKEY_MSG_CALLBACK_FAIL, "Callback Fail" }, + { EDONKEY_MSG_SERVER_MESSAGE, "Server Message" }, + { EDONKEY_MSG_ID_CHANGE, "ID Change" }, + { EDONKEY_MSG_SERVER_INFO_DATA, "Server Info Data" }, + { EDONKEY_MSG_FOUND_SOURCES, "Found Sources" }, + { EDONKEY_MSG_SEARCH_USER_RESULTS, "Search User Results" }, + { EDONKEY_MSG_SENDING_PART, "Sending Part" }, + { EDONKEY_MSG_REQUEST_PARTS, "Request Parts" }, + { EDONKEY_MSG_NO_SUCH_FILE, "No Such File" }, + { EDONKEY_MSG_END_OF_DOWNLOAD, "End of Download" }, + { EDONKEY_MSG_VIEW_FILES, "View Files" }, + { EDONKEY_MSG_VIEW_FILES_ANSWER, "View Files Answer" }, + { EDONKEY_MSG_HELLO_ANSWER, "Hello Answer" }, + { EDONKEY_MSG_NEW_CLIENT_ID, "New Client ID" }, + { EDONKEY_MSG_CLIENT_MESSAGE, "Client Message" }, + { EDONKEY_MSG_FILE_STATUS_REQUEST, "File Status Request" }, + { EDONKEY_MSG_FILE_STATUS, "File Status" }, + { EDONKEY_MSG_HASHSET_REQUEST, "Hashset Request" }, + { EDONKEY_MSG_HASHSET_ANSWER, "Hashset Answer" }, + { EDONKEY_MSG_SLOT_REQUEST, "Slot Request" }, + { EDONKEY_MSG_SLOT_GIVEN, "Slot Given" }, + { EDONKEY_MSG_SLOT_RELEASE, "Slot Release" }, + { EDONKEY_MSG_SLOT_TAKEN, "Slot Taken" }, + { EDONKEY_MSG_FILE_REQUEST, "File Request" }, + { EDONKEY_MSG_FILE_REQUEST_ANSWER, "File Request Answer" }, + { EDONKEY_MSG_GET_SHARED_DIRS, "Get Shared Directories" }, + { EDONKEY_MSG_GET_SHARED_FILES, "Get Shared Files" }, + { EDONKEY_MSG_SHARED_DIRS, "Shared Directores" }, + { EDONKEY_MSG_SHARED_FILES, "Shared Files" }, + { EDONKEY_MSG_SHARED_DENIED, "Shared Denied" }, + { 0, NULL } +}; + +static const value_string emule_tcp_msgs[] = { + { EMULE_MSG_HELLO, "Hello" }, + { EMULE_MSG_HELLO_ANSWER, "Hello Answer" }, + { EMULE_MSG_DATA_COMPRESSED, "Data Compressed" }, + { EMULE_MSG_QUEUE_RANKING, "Queue Ranking" }, + { EMULE_MSG_SOURCES_REQUEST, "Sources Request" }, + { EMULE_MSG_SOURCES_ANSWER, "Sources Answer" }, + { 0, NULL } +}; + +static const value_string edonkey_udp_msgs[] = { + { EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST, "Server Status Request" }, + { EDONKEY_MSG_UDP_SERVER_STATUS, "Server Status" }, + { EDONKEY_MSG_UDP_SEARCH_FILE, "Search File" }, + { EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS, "Search File Results" }, + { EDONKEY_MSG_UDP_GET_SOURCES, "Get Sources" }, + { EDONKEY_MSG_UDP_FOUND_SOURCES, "Found Sources" }, + { EDONKEY_MSG_UDP_CALLBACK_REQUEST, "Callback Request" }, + { EDONKEY_MSG_UDP_CALLBACK_FAIL, "Callback Fail" }, + { EDONKEY_MSG_UDP_SERVER_LIST, "Server List" }, + { EDONKEY_MSG_UDP_GET_SERVER_INFO, "Get Server Info" }, + { EDONKEY_MSG_UDP_SERVER_INFO, "Server Info" }, + { EDONKEY_MSG_UDP_GET_SERVER_LIST, "Get Server List" }, + + /* eMule Extensions */ + { EMULE_MSG_UDP_REASKFILEPING, "Reask File Ping" }, + { EMULE_MSG_UDP_REASKACK, "Reask ACK" }, + { EMULE_MSG_UDP_FILE_NOT_FOUND, "File not found" }, + { EMULE_MSG_UDP_QUEUE_FULL, "Queue Full" }, + + /* Overnet Extensions */ + { OVERNET_MSG_UDP_CONNECT, "Connect" }, + { OVERNET_MSG_UDP_CONNECT_REPLY, "Connect Reply" }, + { OVERNET_MSG_UDP_PUBLICIZE, "Publicize" }, + { OVERNET_MSG_UDP_PUBLICIZE_ACK, "Publicize ACK" }, + { OVERNET_MSG_UDP_SEARCH, "Search" }, + { OVERNET_MSG_UDP_SEARCH_NEXT, "Search Next" }, + { OVERNET_MSG_UDP_SEARCH_INFO, "Search Info" }, + { OVERNET_MSG_UDP_SEARCH_RESULT, "Search Result" }, + { OVERNET_MSG_UDP_SEARCH_END, "Search End" }, + { OVERNET_MSG_UDP_PUBLISH, "Publish" }, + { OVERNET_MSG_UDP_PUBLISH_ACK, "Publish ACK" }, + { OVERNET_MSG_UDP_IDENTIFY_REPLY, "Identify Reply" }, + { OVERNET_MSG_UDP_IDENTIFY_ACK, "Identify ACK" }, + { OVERNET_MSG_UDP_FIREWALL_CONNECTION, "Firewall Connection" }, + { OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK, "Firewall Connection ACK" }, + { OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK, "Firewall Connection NACK" }, + { OVERNET_MSG_UDP_IP_QUERY, "IP Query" }, + { OVERNET_MSG_UDP_IP_QUERY_ANSWER, "IP Query Answer" }, + { OVERNET_MSG_UDP_IP_QUERY_END, "IP Query End" }, + { OVERNET_MSG_UDP_IDENTIFY, "Identify" }, + { 0, NULL } +}; + +static const value_string edonkey_special_tags[] = { + { EDONKEY_STAG_NAME, "Name" }, + { EDONKEY_STAG_SIZE, "Size" }, + { EDONKEY_STAG_TYPE, "Type" }, + { EDONKEY_STAG_FORMAT, "Format" }, + { EDONKEY_STAG_COLLECTION, "Collection" }, + { EDONKEY_STAG_PART_PATH, "Part Path" }, + { EDONKEY_STAG_PART_HASH, "Part Hash" }, + { EDONKEY_STAG_COPIED, "Copied" }, + { EDONKEY_STAG_GAP_START, "Gap Start" }, + { EDONKEY_STAG_GAP_END, "Gap End" }, + { EDONKEY_STAG_DESCRIPTION, "Description" }, + { EDONKEY_STAG_PING, "Ping" }, + { EDONKEY_STAG_FAIL, "Fail" }, + { EDONKEY_STAG_PREFERENCE, "Preference" }, + { EDONKEY_STAG_PORT, "Port" }, + { EDONKEY_STAG_IP, "IP" }, + { EDONKEY_STAG_VERSION, "Version" }, + { EDONKEY_STAG_TEMPFILE, "Temporary File" }, + { EDONKEY_STAG_PRIORITY, "Priority" }, + { EDONKEY_STAG_STATUS, "Status" }, + { EDONKEY_STAG_AVAILABILITY, "Availability" }, + { EDONKEY_STAG_QTIME, "Queue Time" }, + { EDONKEY_STAG_PARTS, "Parts" }, + { EMULE_STAG_COMPRESSION, "Compression" }, + { EMULE_STAG_UDP_CLIENT_PORT, "UDP Client Port" }, + { EMULE_STAG_UDP_VERSION, "UDP Version" }, + { EMULE_STAG_SOURCE_EXCHANGE, "Source Exchange" }, + { EMULE_STAG_COMMENTS, "Comments" }, + { EMULE_STAG_EXTENDED_REQUEST, "Extended Request" }, + { EMULE_STAG_COMPATIBLE_CLIENT, "Compatible Client" }, + { 0, NULL } +}; + +static const value_string edonkey_search_ops[] = { + { EDONKEY_SEARCH_AND, "AND" }, + { EDONKEY_SEARCH_OR, "OR" }, + { EDONKEY_SEARCH_ANDNOT, "AND NOT" }, + { 0, NULL } +}; + +static const value_string edonkey_search_conds[] = { + { EDONKEY_SEARCH_MIN, "MIN" }, + { EDONKEY_SEARCH_MAX, "MAX" }, + { 0, NULL } +}; + +/* Dissects a generic eDonkey list */ +static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree, + int listnum_length, char* listdesc, + int (*item_dissector)(tvbuff_t *, packet_info *, int, proto_tree *)) +{ + /* <List> ::= <List Size> <Item>* */ + guint32 listnum, i; + switch (listnum_length) { + case 1: + listnum = tvb_get_guint8(tvb, offset); + break; + + case 2: + listnum = tvb_get_letohs(tvb, offset); + break; + + case 4: + listnum = tvb_get_letohl(tvb, offset); + break; + + default: + /* Not Supported */ + return offset; + } + + proto_tree_add_text(tree, tvb, offset, listnum_length, "%s List Size: %u", listdesc, listnum); + offset+=listnum_length; + for (i=0; i<listnum; i++) + { + offset = (*item_dissector)(tvb, pinfo, offset, tree); + } + return offset; +} + +gint lookup_str_index(gchar* str, gint length, const value_string *vs) +{ + gint i = 0; + + if (str == NULL) return -1; + + while (vs[i].strptr) { + if (strncasecmp(str, vs[i].strptr, length) == 0) + return i; + i++; + } + + return -1; +} + +static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint length, guint8 special_tagtype) +{ + guchar *tag_name; + tag_name = match_strval(special_tagtype, edonkey_special_tags); + if (tag_name == NULL) { + gint index; + tag_name = (guchar*) tvb_get_ptr(tvb, start, length); + index = lookup_str_index(tag_name, length, edonkey_special_tags); + if (index < 0) + return EDONKEY_STAG_UNKNOWN; + else return edonkey_special_tags[index].value; + } + else return special_tagtype; + + return EDONKEY_STAG_UNKNOWN; +} + +static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb, + gint start, gint length, guint8 special_tagtype) +{ + gchar *tag_name; + tag_name = match_strval(special_tagtype, edonkey_special_tags); + if (tag_name == NULL) { + return proto_tree_add_item(tree, hf_edonkey_metatag_name, tvb, start, length, FALSE); + } + else { + return proto_tree_add_uint_format(tree, hf_edonkey_metatag_id, tvb, start, length, + special_tagtype, "Meta Tag Name: %s (0x%02x)", + tag_name, special_tagtype); + } +} + +/* Dissects the eDonkey meta tag */ +static int dissect_edonkey_metatag(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Meta Tag> ::= <Tag Type (guint8)> <Tag Name> <Tag> */ + /* <Tag Name> ::= <Tag Name Size (guint16)> <Special Tag> || <String> */ + proto_item *ti; + proto_tree *metatag_tree; + guint8 tag_type, special_tagtype; + guint16 tag_name_size, string_length; + guint32 tag_length, tag_value_guint32; + int tag_offset; + + tag_type = tvb_get_guint8(tvb, offset); + tag_name_size = tvb_get_letohs(tvb, offset+1); + special_tagtype = tvb_get_guint8(tvb, offset+3); + + tag_length = 3 + tag_name_size; + tag_offset = offset + tag_length; + + switch (tag_type) + { + case EDONKEY_MTAG_HASH: + /* <Tag> ::= HASH */ + tag_length += 16; + ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE); + metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size); + edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype); + proto_tree_add_item(metatag_tree, hf_edonkey_hash, tvb, tag_offset, 16, FALSE); + break; + + case EDONKEY_MTAG_STRING: + /* <Tag> ::= <String> */ + string_length = tvb_get_letohs(tvb, tag_offset); + tag_length += 2+string_length; + ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE); + metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size); + edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype); + proto_tree_add_uint(metatag_tree, hf_edonkey_string_length, tvb, tag_offset, 2, string_length); + proto_tree_add_item(metatag_tree, hf_edonkey_string, tvb, tag_offset+2, string_length, FALSE); + break; + + case EDONKEY_MTAG_DWORD: + /* <Tag> ::= guint32 */ + tag_length += 4; + ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE); + metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size); + edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype); + if (edonkey_metatag_name_get_type(tvb, offset+3, tag_name_size, special_tagtype) == EDONKEY_STAG_IP) { + proto_tree_add_item(metatag_tree, hf_edonkey_ip, tvb, tag_offset, 4, FALSE); + } + else { + tag_value_guint32 = tvb_get_letohl(tvb, tag_offset); + proto_tree_add_text(metatag_tree, tvb, tag_offset, 4, "Meta Tag Value: %u", tag_value_guint32); + } + break; + + case EDONKEY_MTAG_FLOAT: + /* <Tag> ::= 4 byte float */ + tag_length += 4; + ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE); + metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size); + edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype); + break; + + case EDONKEY_MTAG_BOOL: /* <Tag> ::= Boolean ?? bytes*/ + case EDONKEY_MTAG_BOOL_ARRAY: /* <Tag> ::= ?? */ + case EDONKEY_MTAG_BLOB: /* <Tag> ::= ?? */ + case EDONKEY_MTAG_UNKNOWN: + default: + /* Unknown tag type - actual tag length is also unknown */ + ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE); + metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag); + proto_tree_add_text(metatag_tree, tvb, offset, 1, "Unknown Meta Tag Type (0x%02x)", tag_type); + proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size); + edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype); + break; + + } + + return offset + tag_length; +} + +/* Dissects the eDonkey address */ +static int dissect_edonkey_address(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Address> ::= <IP> <Port> */ +/* guint32 ip = tvb_get_letohl(tvb, offset); + proto_tree_add_ipv4(tree, hf_edonkey_ip, tvb, offset, 4, ip); */ + proto_tree_add_item(tree, hf_edonkey_ip, tvb, offset, 4, FALSE); + proto_tree_add_item(tree, hf_edonkey_port, tvb, offset+4, 2, TRUE); + return offset+6; +} + +/* Dissects the eDonkey address list */ +static int dissect_edonkey_address_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Address List> ::= <List Size (guint8)> <Address>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Address", dissect_edonkey_address); +} + +/* Dissects the eMule address list */ +static int dissect_emule_address_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Address List> ::= <List Size (guint16)> <Address>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Address", dissect_edonkey_address); +} + +/* Dissects the eDonkey hash */ +static int dissect_edonkey_hash(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <hash> ::= HASH (16 word MD4 digest) */ + proto_tree_add_item(tree, hf_edonkey_hash, tvb, offset, 16, FALSE); + return offset+16; +} + + +/* Dissects the eDonkey hash list */ +static int dissect_edonkey_hash_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Hash List> ::= <List Size (guint16)> <Hash>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Hash", dissect_edonkey_hash); +} + +/* Dissects the eDonkey meta tag list */ +static int dissect_edonkey_metatag_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Meta Tag List> ::= <List Size (guint32)> <Meta tag>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Meta Tag", dissect_edonkey_metatag); +} + +/* Dissects the eDonkey String */ +static int dissect_edonkey_string(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <String> ::= <String length (guint16)> DATA */ + guint16 string_length = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length); + proto_tree_add_item(tree, hf_edonkey_string, tvb, offset+2, string_length, FALSE); + return offset+2+string_length; +} + +/* Dissects the eDonkey Directory */ +static int dissect_edonkey_directory(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Directory> ::= <String> */ + guint16 string_length = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length); + proto_tree_add_item(tree, hf_edonkey_directory, tvb, offset+2, string_length, FALSE); + return offset+2+string_length; +} + +/* Dissects the eDonkey Filename */ +static int dissect_edonkey_file_name(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Filename> ::= <String> */ + return dissect_edonkey_string(tvb, pinfo, offset, tree); +} + +/* Dissects the eDonkey directory list */ +static int dissect_edonkey_directory_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Directory List> ::= <List Size (guint32)> <Directory>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Directory", dissect_edonkey_directory); +} + +/* Dissects the eDonkey file hash */ +static int dissect_edonkey_file_hash(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <File hash> ::= HASH (16 word MD4 digest) */ + proto_tree_add_item(tree, hf_edonkey_file_hash, tvb, offset, 16, FALSE); + return offset+16; +} + +/* Dissects the eDonkey server hash */ +static int dissect_edonkey_server_hash(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Server hash> ::= HASH (16 word MD4 digest) */ + proto_tree_add_item(tree, hf_edonkey_server_hash, tvb, offset, 16, FALSE); + return offset+16; +} + +/* Dissects the eDonkey client hash */ +static int dissect_edonkey_client_hash(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Client hash> ::= HASH (16 word MD4 digest) */ + proto_tree_add_item(tree, hf_edonkey_client_hash, tvb, offset, 16, FALSE); + return offset+16; +} + +/* Dissects the eDonkey client ID */ +static int dissect_edonkey_client_id(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Client ID> ::= guint32 */ +/* guint32 ip = tvb_get_letohl(tvb, offset); + proto_tree_add_ipv4(tree, hf_edonkey_client_id, tvb, offset, 4, ip); */ + proto_tree_add_item(tree, hf_edonkey_client_id, tvb, offset, 4, FALSE); + return offset+4; +} + +/* Dissects the eDonkey port */ +static int dissect_edonkey_port(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Port> ::= guint16 */ + proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE); + return offset+2; +} + +/* Dissects the eDonkey start offset */ +static int dissect_edonkey_start_offset(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Start Offset> ::= guint32 */ + guint32 start = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Start Offset: %u", start); + return offset+4; +} + +/* Dissects the eDonkey end offset */ +static int dissect_edonkey_end_offset(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <End Offset> ::= guint32 */ + guint32 end = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "End Offset: %u", end); + return offset+4; +} + +/* Dissects the eDonkey client info */ +static int dissect_edonkey_client_info(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Client info> ::= <Client hash> <Client ID> <Port> <Meta tag list> */ + proto_item *ti; + proto_tree *clientinfo_tree; + /* Add subtree for client info */ + ti = proto_tree_add_item(tree, hf_edonkey_clientinfo, tvb, offset, 0, FALSE); + clientinfo_tree = proto_item_add_subtree(ti, ett_edonkey_clientinfo); + offset = dissect_edonkey_client_hash(tvb, pinfo, offset, clientinfo_tree); + offset = dissect_edonkey_client_id(tvb, pinfo, offset, clientinfo_tree); + offset = dissect_edonkey_port(tvb, pinfo, offset, clientinfo_tree); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, clientinfo_tree); + return offset; +} + +/* Dissects the eDonkey client info list */ +static int dissect_edonkey_client_info_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Client Info List> ::= <List Size (guint32)> <Client Info>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Client Info", dissect_edonkey_client_info); +} + +/* Dissects the eDonkey server info */ +static int dissect_edonkey_server_info(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Server info> ::= <Server hash> <Server Address> <Meta tag list> */ + proto_item *ti; + proto_tree *serverinfo_tree; + /* Add subtree for server info */ + ti = proto_tree_add_item(tree, hf_edonkey_serverinfo, tvb, offset, 0, FALSE); + serverinfo_tree = proto_item_add_subtree(ti, ett_edonkey_serverinfo); + offset = dissect_edonkey_server_hash(tvb, pinfo, offset, serverinfo_tree); + offset = dissect_edonkey_address(tvb, pinfo, offset, serverinfo_tree); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, serverinfo_tree); + return offset; +} + +/* Dissects the eDonkey file info */ +static int dissect_edonkey_file_info(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <File info> ::= <File hash> <Client ID> <Port> <Meta tag list> */ + proto_item *ti; + proto_tree *fileinfo_tree; + /* Add subtree for file info */ + ti = proto_tree_add_item(tree, hf_edonkey_fileinfo, tvb, offset, 0, FALSE); + fileinfo_tree = proto_item_add_subtree(ti, ett_edonkey_fileinfo); + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, fileinfo_tree); + offset = dissect_edonkey_client_id(tvb, pinfo, offset, fileinfo_tree); + offset = dissect_edonkey_port(tvb, pinfo, offset, fileinfo_tree); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, fileinfo_tree); + return offset; +} + +/* Dissects the eDonkey file info list */ +static int dissect_edonkey_file_info_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <File Info List> ::= <List Size (guint32)> <File Info>* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "File Info", dissect_edonkey_file_info); +} + +/* Dissects the Overnet peer type */ +static int dissect_overnet_peertype(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Peer type> ::= guint8 */ + guint8 peertype = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Peer Type: %u", peertype); + return offset+1; +} + +/* Dissects the Overnet peer */ +static int dissect_overnet_peer(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Peer> ::= <Hash> <Address> <Peer type> */ + proto_item *ti; + proto_tree *peer_tree; + ti = proto_tree_add_item(tree, hf_overnet_peer, tvb, offset, 16 + 6 + 1, FALSE); + peer_tree = proto_item_add_subtree(ti, ett_overnet_peer); + offset = dissect_edonkey_hash(tvb, pinfo, offset, peer_tree); + offset = dissect_edonkey_address(tvb, pinfo, offset, peer_tree); + offset = dissect_overnet_peertype(tvb, pinfo, offset, peer_tree); + return offset; +} + +/* Dissects the eDonkey search query */ +static int dissect_edonkey_search_query(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Search Query> ::= <Search Type> <Search> */ + proto_item *ti; + proto_tree *search_tree; + guint8 search_type, operator, special_tagtype, limit_type; + guint16 tag_name_size, string_length; + guint32 search_length, limit; + int string_offset, tag_name_offset; + + search_type = tvb_get_guint8(tvb, offset); + search_length = 1; + + switch (search_type) + { + case EDONKEY_SEARCH_BOOL: + /* <Search> ::= <Operator> <Search Query> <Search Query> */ + search_length += 1; + operator = tvb_get_guint8(tvb, offset+1); + + /* Add subtree for search entry */ + ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE); + search_tree = proto_item_add_subtree(ti, ett_edonkey_search); + + /* Add query info */ + proto_tree_add_text(search_tree, tvb, offset, 2, "Boolean search (0x%02x): %s (0x%02x)", + search_type, val_to_str(operator, edonkey_search_ops, "Unknown"), operator); + + offset+=2; + offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree); + offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree); + break; + + case EDONKEY_SEARCH_NAME: + /* <Search> ::= <String> */ + string_offset = offset + search_length; + string_length = tvb_get_letohs(tvb, string_offset); + search_length += 2+string_length; + + /* Add subtree for search entry */ + ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE); + search_tree = proto_item_add_subtree(ti, ett_edonkey_search); + + /* Add query info */ + proto_tree_add_text(search_tree, tvb, offset, 1, "Search by name (0x%02x)", search_type); + proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length); + proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE); + offset += search_length; + break; + + case EDONKEY_SEARCH_META: + /* <Search> ::= <String> <Meta tag Name> */ + string_offset = offset + search_length; + string_length = tvb_get_letohs(tvb, offset+1); + search_length += 2+string_length; + + tag_name_offset = offset + search_length; + tag_name_size = tvb_get_letohs(tvb, tag_name_offset); + special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2); + search_length += 2 + tag_name_size; + + /* Add subtree for search entry */ + ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE); + search_tree = proto_item_add_subtree(ti, ett_edonkey_search); + + /* Add query info */ + proto_tree_add_text(search_tree, tvb, offset, 1, "Search by metadata (0x%02x)", search_type); + proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length); + proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE); + proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size); + edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype); + offset += search_length; + break; + + case EDONKEY_SEARCH_LIMIT: + /* <Search> ::= <Limit (guint32)> <Minmax> <Meta tag Name> */ + search_length += 5; /* 4 bytes for the limit, one for the minmax */ + limit = tvb_get_letohl(tvb, offset+1); + limit_type = tvb_get_guint8(tvb, offset+5); + + tag_name_offset = offset + search_length; + tag_name_size = tvb_get_letohs(tvb, tag_name_offset); + special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2); + search_length += 2 + tag_name_size; + + /* Add subtree for search entry */ + ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE); + search_tree = proto_item_add_subtree(ti, ett_edonkey_search); + + /* Add query info */ + proto_tree_add_text(search_tree, tvb, offset, 6, "Search by limit (0x%02x): %s %u", + search_type, val_to_str(limit_type, edonkey_search_conds, "Unknown"), limit); + proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size); + edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype); + offset += search_length; + break; + + default: + /* Unknown search type - actual search length is also unknown */ + ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE); + search_tree = proto_item_add_subtree(ti, ett_edonkey_search); + proto_tree_add_text(search_tree, tvb, offset, search_length, "Unknown Search (0x%02x)", search_type); + offset += search_length; + break; + } + + return offset; +} + +static void dissect_edonkey_tcp_message(guint8 msg_type, + tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, int length, proto_tree *tree) +{ + int msg_start, msg_end, bytes_remaining; + guint8 hello, more; + guint32 nusers, nfiles; + + if (tree == NULL) return; + + bytes_remaining = tvb_reported_length_remaining(tvb, offset); + if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; + if (length <= 0) return; + + msg_start = offset; + msg_end = offset + length; + + switch (msg_type) { + case EDONKEY_MSG_HELLO: + /* Client to Server: <Client Info> */ + /* Client to Client: 0x10 <Client Info> */ + hello = tvb_get_guint8(tvb, offset); + if (hello == 0x10) /* Hello Client */ + offset += 1; + offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_HELLO_ANSWER: /* Hello Answer: <Client Info> <Server address> */ + offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree); + offset = dissect_edonkey_address(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SERVER_CB_REQ: /* Server Callback Request: <Client address> */ + offset = dissect_edonkey_address(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SERVER_INFO_DATA: /* Server Info Data: <Server Info> */ + offset = dissect_edonkey_server_info(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SERVER_LIST: /* Server List: <Address List> */ + offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_OFFER_FILES: /* Offer Files: <File info List> */ + case EDONKEY_MSG_VIEW_FILES_ANSWER: /* View Files Answer: <File info list> */ + offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SEARCH_FILE_RESULTS: /* Search File Results: <File Info list> <More> */ + offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree); + more = tvb_get_guint8(tvb, offset); + if (more) + proto_tree_add_text(tree, tvb, offset, 1, "More: TRUE (0x%02x)", more); + else proto_tree_add_text(tree, tvb, offset, 1, "More: FALSE (0x%02x)", more); + break; + + case EDONKEY_MSG_SEARCH_FILES: /* Search File: <Search query> */ + case EDONKEY_MSG_SEARCH_USER: /* Search User: <Search query> */ + offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_GET_SOURCES: /* Get Sources: <File Hash> */ + case EDONKEY_MSG_NO_SUCH_FILE: /* No Such File: <File Hash> */ + case EDONKEY_MSG_END_OF_DOWNLOAD: /* End of Download: <File Hash> */ + case EDONKEY_MSG_FILE_STATUS_REQUEST: /* File Status Request: <File Hash> */ + case EDONKEY_MSG_HASHSET_REQUEST: /* Hashset Request: <File Hash> */ + case EDONKEY_MSG_SLOT_REQUEST: /* Slot Request: <File Hash> */ + case EDONKEY_MSG_FILE_REQUEST: /* File Request: <File Hash> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_CLIENT_CB_REQ: /* Client Callback Request: <Client ID> */ + case EDONKEY_MSG_CALLBACK_FAIL: /* Callback Fail: <Client ID> */ + case EDONKEY_MSG_ID_CHANGE: /* ID Change: <Client ID> */ + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_NEW_CLIENT_ID: /* New Client ID: <Client ID> <Client ID> */ + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SERVER_MESSAGE: /* Server Message: <String> */ + case EDONKEY_MSG_CLIENT_MESSAGE: /* Client Message: <String> */ + offset = dissect_edonkey_string(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SERVER_STATUS: /* Server Status: <Nusers> <Nfiles> */ + nusers = tvb_get_letohl(tvb, offset); + nfiles = tvb_get_letohl(tvb, offset+4); + proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers); + proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles); + break; + + case EDONKEY_MSG_FILE_REQUEST_ANSWER: /* File Request Answer: <File hash> <File name> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_file_name(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_REQUEST_PARTS: /* Request Parts: <File hash> <Start offset>(3) <End offset>(3) */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SENDING_PART: /* Sending Part: <File hash> <Start offset> <End offset> DATA */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree); + offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree); + if (msg_end > offset) { + bytes_remaining = msg_end - offset; + proto_tree_add_text(tree, tvb, offset, bytes_remaining, "Message Data (%d bytes)", bytes_remaining); + } + break; + + + case EDONKEY_MSG_SEARCH_USER_RESULTS: /* Search User Results: <Client info list> */ + offset = dissect_edonkey_client_info_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_GET_SHARED_FILES: /* Get Shared Files: <Directory> */ + offset = dissect_edonkey_directory(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SHARED_DIRS: /* Shared Dirs: <Directory List> */ + offset = dissect_edonkey_directory_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_SHARED_FILES: /* Shared Files: <Directory> <File info list> */ + offset = dissect_edonkey_directory(tvb, pinfo, offset, tree); + offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_HASHSET_ANSWER: /* Hashset Answer: <Hash List> */ + offset = dissect_edonkey_hash_list(tvb, pinfo, offset, tree); + break; + + default: + proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length); + break; + } + return; +} + +static void dissect_emule_tcp_message(guint8 msg_type, + tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, int length, proto_tree *tree) +{ + int msg_start, msg_end, bytes_remaining; + guint32 packed_length; + guint16 version, rank; + + if (tree == NULL) return; + + bytes_remaining = tvb_reported_length_remaining(tvb, offset); + if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; + if (length <= 0) return; + + msg_start = offset; + msg_end = offset + length; + + switch (msg_type) { + case EMULE_MSG_HELLO: /* eMule Hello: <eMule Version> <Meta tag list> */ + case EMULE_MSG_HELLO_ANSWER: /* eMule Hello Answer: <eMule Version> <Meta tag list> */ + version = tvb_get_letohs(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 2, "Version: %u", version); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset+2, tree); + break; + + case EMULE_MSG_QUEUE_RANKING: /* eMule Queue Ranking: <eMule Rank (guint16)> */ + rank = tvb_get_letohs(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank); + break; + + case EMULE_MSG_SOURCES_REQUEST: /* Sources Request: <File Hash> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + break; + + case EMULE_MSG_SOURCES_ANSWER: /* Sources Answer: <File Hash> <Address List> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_emule_address_list(tvb, pinfo, offset, tree); + break; + + case EMULE_MSG_DATA_COMPRESSED: /* Data Compressed: <File Hash> <Start Offset> <Length (guint32)> <DATA> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree); + packed_length = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, packed_length, "Packed Length: %u", packed_length); + offset += 4; + if (msg_end > offset) { + bytes_remaining = msg_end - offset; + proto_tree_add_text(tree, tvb, offset, bytes_remaining, + "Compressed Message Data (%d bytes)", bytes_remaining); + } + break; + + default: + dissect_edonkey_tcp_message(msg_type, tvb, pinfo, offset, length, tree); + break; + } + return; +} + +static void dissect_edonkey_udp_message(guint8 msg_type, + tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, int length, proto_tree *tree) +{ + int msg_start, msg_end, bytes_remaining; + guint8 type; + guint16 min, max; + guint32 nusers, nfiles; + + if (tree == NULL) return; + + bytes_remaining = tvb_reported_length_remaining(tvb, offset); + if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; + if (length <= 0) return; + + msg_start = offset; + msg_end = offset + length; + + switch (msg_type) { + /* EDonkey UDP Messages */ + case EDONKEY_MSG_UDP_CALLBACK_REQUEST: /* Callback Request: <Address> <Client ID> */ + offset = dissect_edonkey_address(tvb, pinfo, offset, tree); + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_CALLBACK_FAIL: /* Callback Fail: <Client ID> */ + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_SERVER_INFO: /* Server Info: <String> <String>*/ + offset = dissect_edonkey_string(tvb, pinfo, offset, tree); + offset = dissect_edonkey_string(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_SERVER_LIST: /* Server List: <Address List> */ + offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS: /* Search File Result: <File Info> */ + offset = dissect_edonkey_file_info(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_SEARCH_FILE: /* Search File: <Search query> */ + offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_GET_SOURCES: /* Get Sources: <File Hash> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree); + break; + + case EDONKEY_MSG_UDP_SERVER_STATUS: /* Server Status: <guint32> <Nusers> <Nfiles> <Nusersmax> */ + offset += 4; + nusers = tvb_get_letohl(tvb, offset); + nfiles = tvb_get_letohl(tvb, offset+4); + proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers); + proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles); + offset += 8; + if (offset < msg_end) { + nusers = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Max number of Users: %u", nusers); + offset += 4; + } + break; + + /* Overnet UDP Messages */ + case OVERNET_MSG_UDP_CONNECT: /* Connect: <Peer (sender) > */ + case OVERNET_MSG_UDP_PUBLICIZE: /* Publicize: <Peer (sender) > */ + offset = dissect_overnet_peer(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_CONNECT_REPLY: /* Connect Reply: <guint16 Peer List> */ + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Overnet Peer", dissect_overnet_peer); + break; + + case OVERNET_MSG_UDP_SEARCH: /* Search: <search type (guint8)> <Hash> */ + type = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type); + offset = dissect_edonkey_hash(tvb, pinfo, offset+1, tree); + break; + + case OVERNET_MSG_UDP_SEARCH_INFO: + /* Search Info: <Hash> <search type (guint8)> <min (guint16)> <max (guint16)>*/ + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + type = tvb_get_guint8(tvb, offset); + min = tvb_get_letohs(tvb, offset+1); + max = tvb_get_letohs(tvb, offset+3); + proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type); + proto_tree_add_text(tree, tvb, offset+1, 4, "Search Range: Min=%u Max=%u", min, max); + break; + + case OVERNET_MSG_UDP_SEARCH_NEXT: /* Search Next: <Hash> <guint8 Peer List> */ + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Overnet Peer", dissect_overnet_peer); + break; + + case OVERNET_MSG_UDP_SEARCH_RESULT: /* Search Result: <Hash> <Hash> <Meta tag List> */ + case OVERNET_MSG_UDP_PUBLISH: /* Publish: <Hash> <Hash> <Meta tag List> */ + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_SEARCH_END: /* Search End: <Hash> */ + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_PUBLISH_ACK: /* Publish ACK: <File Hash> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_IP_QUERY: /* IP Query: <TCP Port> */ + proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE); + break; + + case OVERNET_MSG_UDP_IP_QUERY_ANSWER: /* IP Query Answer: <IP> */ + offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_IDENTIFY_REPLY: /* Identify Reply: <Contact (sender)> */ + /* <Contact> ::= <Hash> <Address> */ + offset = dissect_edonkey_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_address(tvb, pinfo, offset, tree); + break; + + case OVERNET_MSG_UDP_IDENTIFY_ACK: /* Identify Reply: <TCP Port (sender)> */ + proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE); + break; + + case OVERNET_MSG_UDP_FIREWALL_CONNECTION: /* Firewall Connnection Ack: <Hash> <TCP Port> */ + offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree); + proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE); + break; + + case OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK: /* Firewall Connnection Ack: <Hash> */ + case OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK: /* Firewall Connnection NAck: <Hash> */ + offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree); + break; + + default: + proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length); + break; + } + return; +} + +static void dissect_emule_udp_message(guint8 msg_type, + tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, int length, proto_tree *tree) +{ + int msg_start, msg_end, bytes_remaining; + guint16 rank; + + bytes_remaining = tvb_reported_length_remaining(tvb, offset); + if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; + if (length <= 0) return; + + msg_start = offset; + msg_end = offset + length; + + switch (msg_type) { + case EMULE_MSG_UDP_REASKFILEPING: /* Reask File Ping: <File Hash> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + break; + + case EMULE_MSG_UDP_REASKACK: /* Reask ACK: <eMule Rank> */ + rank = tvb_get_letohs(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank); + break; + + default: + dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree); + break; + } + return; +} + +static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; + int offset, bytes, messages; + guint8 protocol, msg_type; + guint32 msg_len; + gchar *protocol_name, *message_name; + void (*dissector)(guint8, tvbuff_t*, packet_info*, int, int, proto_tree*); + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + if (tree) { + ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE); + edonkey_tree = proto_item_add_subtree(ti, ett_edonkey); + } + + offset = 0; + messages = 0; + while (tvb_length_remaining(tvb, offset) >= EDONKEY_TCP_HEADER_LENGTH) { + protocol = tvb_get_guint8(tvb, offset); + msg_len = tvb_get_letohl(tvb, offset+1); + + protocol_name = match_strval(protocol, edonkey_protocols); + if (protocol_name == NULL) { + /* Not a recognized eDonkey protocol - probably a continuation */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_str(pinfo->cinfo, COL_INFO, "eDonkey Continuation"); + if (edonkey_tree) { + bytes = tvb_length_remaining(tvb, offset); + proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes); + } + return; + } + + /* Add edonkey message tree */ + if (edonkey_tree) { + ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, + offset, EDONKEY_TCP_HEADER_LENGTH + msg_len, FALSE); + edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message); + + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol, + "Protocol: %s (0x%02x)", protocol_name, protocol); + proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len); + } + + + /* Skip past the EDONKEY Header */ + offset += EDONKEY_TCP_HEADER_LENGTH; + + if(tvb_reported_length_remaining(tvb, offset) <= 0) { + /* There is not enough space for the msg_type - mark as fragment */ + if (check_col(pinfo->cinfo, COL_INFO)) { + if (messages == 0) + col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP Message Fragment", protocol_name); + else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP Message Fragment", protocol_name); + } + return; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (messages == 0) + col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP", protocol_name); + else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP", protocol_name); + } + + msg_type = tvb_get_guint8(tvb, offset); + switch (protocol) { + case EDONKEY_PROTO_EDONKEY: + message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"); + dissector = dissect_edonkey_tcp_message; + break; + + case EDONKEY_PROTO_EMULE_EXT: + message_name = val_to_str(msg_type, emule_tcp_msgs, + val_to_str(msg_type, edonkey_tcp_msgs, "Unknown")); + dissector = dissect_emule_tcp_message; + break; + + default: + message_name = "Unknown"; + dissector = NULL; + break; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name); + } + + + if (edonkey_msg_tree) { + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset, 1, msg_type, + "Message Type: %s (0x%02x)", message_name, msg_type); + if (dissector && (msg_len > 1)) + (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree); + } + + offset += msg_len; + messages++; + } +} + +static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; + int offset; + guint8 protocol, msg_type; + gchar *protocol_name, *message_name; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message"); + + if (tree) { + ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE); + edonkey_tree = proto_item_add_subtree(ti, ett_edonkey); + } + + offset = 0; + /* eDonkey UDP message - Assume that there is one message per packet */ + if (tvb_length_remaining(tvb, offset) >= EDONKEY_UDP_HEADER_LENGTH) { + protocol = tvb_get_guint8(tvb, offset); + msg_type = tvb_get_guint8(tvb, offset+1); + protocol_name = val_to_str(protocol, edonkey_protocols, "Unknown"); + message_name = val_to_str(msg_type, edonkey_udp_msgs, "Unknown"); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "%s UDP: %s", protocol_name, message_name); + } + + if (edonkey_tree) { + ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, offset, -1, FALSE); + edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message); + + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol, + "Protocol: %s (0x%02x)", protocol_name, protocol); + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset+1, 1, msg_type, + "Message Type: %s (0x%02x)", message_name, msg_type); + + offset += EDONKEY_UDP_HEADER_LENGTH; + + switch (protocol) { + case EDONKEY_PROTO_EDONKEY: + dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree); + break; + + case EDONKEY_PROTO_EMULE_EXT: + dissect_emule_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree); + break; + + default: + break; + } + } + } +} + +void proto_register_edonkey(void) { + + static hf_register_info hf[] = { + { &hf_edonkey_message, + { "eDonkey Message", "edonkey.message", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } }, + { &hf_edonkey_protocol, + { "Protocol", "edonkey.protocol", + FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Protocol", HFILL } }, + { &hf_edonkey_message_length, + { "Message Length", "edonkey.message.length", + FT_UINT32, BASE_DEC, NULL, 0, "eDonkey Message Length", HFILL } }, + { &hf_edonkey_message_type, + { "Message Type", "edonkey.message.type", + FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Message Type", HFILL } }, + { &hf_edonkey_client_hash, + { "Client Hash", "edonkey.client_hash", + FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Client Hash", HFILL } }, + { &hf_edonkey_server_hash, + { "Server Hash", "edonkey.server_hash", + FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Server Hash", HFILL } }, + { &hf_edonkey_file_hash, + { "File Hash", "edonkey.file_hash", + FT_BYTES, BASE_HEX, NULL, 0, "eDonkey File Hash", HFILL } }, + { &hf_edonkey_client_id, + { "Client ID", "edonkey.clientid", + FT_IPv4, BASE_DEC, NULL, 0, "eDonkey Client ID", HFILL } }, + { &hf_edonkey_ip, + { "IP", "edonkey.ip", + FT_IPv4, BASE_DEC, NULL, 0, "eDonkey IP", HFILL } }, + { &hf_edonkey_port, + { "Port", "edonkey.port", + FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Port", HFILL } }, + { &hf_edonkey_metatag, + { "eDonkey Meta Tag", "edonkey.metatag", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Meta Tag", HFILL } }, + { &hf_edonkey_metatag_type, + { "Meta Tag Type", "edonkey.metatag.type", + FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag Type", HFILL } }, + { &hf_edonkey_metatag_id, + { "Meta Tag ID", "edonkey.metatag.id", + FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag ID", HFILL } }, + { &hf_edonkey_metatag_name, + { "Meta Tag Name", "edonkey.metatag.name", + FT_STRING, BASE_NONE, NULL, 0, "eDonkey Meta Tag Name", HFILL } }, + { &hf_edonkey_metatag_namesize, + { "Meta Tag Name Size", "edonkey.metatag.namesize", + FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Meta Tag Name Size", HFILL } }, + { &hf_edonkey_search, + { "eDonkey Search", "edonkey.search", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Search", HFILL } }, + { &hf_edonkey_hash, + { "Hash", "edonkey.hash", + FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Hash", HFILL } }, + { &hf_edonkey_string, + { "String", "edonkey.string", + FT_STRING, BASE_NONE, NULL, 0, "eDonkey String", HFILL } }, + { &hf_edonkey_string_length, + { "String Length", "edonkey.string_length", + FT_UINT16, BASE_DEC, NULL, 0, "eDonkey String Length", HFILL } }, + { &hf_edonkey_directory, + { "Directory", "edonkey.directory", + FT_STRING, BASE_NONE, NULL, 0, "eDonkey Directory", HFILL } }, + { &hf_edonkey_fileinfo, + { "eDonkey File Info", "edonkey.fileinfo", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Info", HFILL } }, + { &hf_edonkey_serverinfo, + { "eDonkey Server Info", "edonkey.serverinfo", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Server Info", HFILL } }, + { &hf_edonkey_clientinfo, + { "eDonkey Client Info", "edonkey.clientinfo", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Client Info", HFILL } }, + { &hf_overnet_peer, + { "Overnet Peer", "overnet.peer", + FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } }, + }; + + static gint *ett[] = { + &ett_edonkey, + &ett_edonkey_message, + &ett_edonkey_metatag, + &ett_edonkey_search, + &ett_edonkey_fileinfo, + &ett_edonkey_serverinfo, + &ett_edonkey_clientinfo, + &ett_overnet_peer + }; + + proto_edonkey = proto_register_protocol("eDonkey Protocol", "EDONKEY", "edonkey"); + + proto_register_field_array(proto_edonkey, hf, array_length(hf)); + + proto_register_subtree_array(ett, array_length(ett)); + register_dissector("edonkey.tcp", dissect_edonkey_tcp, proto_edonkey); + register_dissector("edonkey.udp", dissect_edonkey_udp, proto_edonkey); +} + +void proto_reg_handoff_edonkey(void) { + dissector_handle_t edonkey_tcp_handle; + dissector_handle_t edonkey_udp_handle; + + edonkey_tcp_handle = find_dissector("edonkey.tcp"); + edonkey_udp_handle = find_dissector("edonkey.udp"); + + dissector_add("tcp.port", 4661, edonkey_tcp_handle); + dissector_add("tcp.port", 4662, edonkey_tcp_handle); + dissector_add("tcp.port", 4663, edonkey_tcp_handle); + dissector_add("udp.port", 4665, edonkey_udp_handle); + dissector_add("udp.port", 4672, edonkey_udp_handle); +} Index: packet-edonkey.h =================================================================== RCS file: packet-edonkey.h diff -N packet-edonkey.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packet-edonkey.h 16 Jul 2003 19:59:54 -0000 @@ -0,0 +1,209 @@ +/* packet-edonkey.h + * Declarations for edonkey dissection + * Copyright 2003, Xuan Zhang <xz@xxxxxxxxxxxx> + * eDonkey dissector based on protocol descriptions from mldonkey: + * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/edonkey-protocol.txt + * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/overnet-protocol.txt + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * 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. + */ + +void proto_register_edonkey(void); + +#define EDONKEY_MAX_SNAP_SIZE 1500 +#define EDONKEY_TCP_HEADER_LENGTH 5 +#define EDONKEY_UDP_HEADER_LENGTH 2 + +/* Definitions for EDONKEY protocols */ +#define EDONKEY_PROTO_EDONKEY 0xe3 /* eDonkey */ +#define EDONKEY_PROTO_EMULE_EXT 0xc5 /* eMule extensions */ +#define EDONKEY_PROTO_EMULE_COMP 0xd4 /* eMule compressed (data is zlib compressed) */ + +/* Definitions for EDONKEY messages */ +/* EDONKEY TCP MESSAGES */ +/* Client <-> Server */ +#define EDONKEY_MSG_HELLO 0x01 +#define EDONKEY_MSG_BAD_PROTO 0x05 +#define EDONKEY_MSG_GET_SERVER_LIST 0x14 +#define EDONKEY_MSG_OFFER_FILES 0x15 +#define EDONKEY_MSG_SEARCH_FILES 0x16 +#define EDONKEY_MSG_DISCONNECT 0x18 +#define EDONKEY_MSG_GET_SOURCES 0x19 +#define EDONKEY_MSG_SEARCH_USER 0x1a +/* define EDONKEY_MSG_UNKNOWN 0x1b */ +#define EDONKEY_MSG_CLIENT_CB_REQ 0x1c +/* define EDONKEY_MSG_UNKNOWN 0x20 */ +#define EDONKEY_MSG_MORE_RESULTS 0x21 +#define EDONKEY_MSG_SERVER_LIST 0x32 +#define EDONKEY_MSG_SEARCH_FILE_RESULTS 0x33 +#define EDONKEY_MSG_SERVER_STATUS 0x34 +#define EDONKEY_MSG_SERVER_CB_REQ 0x35 +#define EDONKEY_MSG_CALLBACK_FAIL 0x36 +#define EDONKEY_MSG_SERVER_MESSAGE 0x38 +#define EDONKEY_MSG_ID_CHANGE 0x40 +#define EDONKEY_MSG_SERVER_INFO_DATA 0x41 +#define EDONKEY_MSG_FOUND_SOURCES 0x42 +#define EDONKEY_MSG_SEARCH_USER_RESULTS 0x43 + +/* Client <-> Client */ +#define EDONKEY_MSG_HELLO_CLIENT 0x10 /* 0x01 0x10 */ +#define EDONKEY_MSG_SENDING_PART 0x46 +#define EDONKEY_MSG_REQUEST_PARTS 0x47 +#define EDONKEY_MSG_NO_SUCH_FILE 0x48 +#define EDONKEY_MSG_END_OF_DOWNLOAD 0x49 +#define EDONKEY_MSG_VIEW_FILES 0x4a +#define EDONKEY_MSG_VIEW_FILES_ANSWER 0x4b +#define EDONKEY_MSG_HELLO_ANSWER 0x4c +#define EDONKEY_MSG_NEW_CLIENT_ID 0x4d +#define EDONKEY_MSG_CLIENT_MESSAGE 0x4e +#define EDONKEY_MSG_FILE_STATUS_REQUEST 0x4f +#define EDONKEY_MSG_FILE_STATUS 0x50 +#define EDONKEY_MSG_HASHSET_REQUEST 0x51 +#define EDONKEY_MSG_HASHSET_ANSWER 0x52 +/*#define EDONKEY_MSG_UNKNOWN 0x53 */ +#define EDONKEY_MSG_SLOT_REQUEST 0x54 +#define EDONKEY_MSG_SLOT_GIVEN 0x55 +#define EDONKEY_MSG_SLOT_RELEASE 0x56 +#define EDONKEY_MSG_SLOT_TAKEN 0x57 +#define EDONKEY_MSG_FILE_REQUEST 0x58 +#define EDONKEY_MSG_FILE_REQUEST_ANSWER 0x59 +/*#define EDONKEY_MSG_UNKNOWN 0x5b*/ +#define EDONKEY_MSG_GET_SHARED_DIRS 0x5d +#define EDONKEY_MSG_GET_SHARED_FILES 0x5e +#define EDONKEY_MSG_SHARED_DIRS 0x5f +#define EDONKEY_MSG_SHARED_FILES 0x60 +#define EDONKEY_MSG_SHARED_DENIED 0x61 + +/* OVERNET EXTENSIONS */ +/*#define OVERNET_MSG_UNKNOWN 0x62*/ +/*#define OVERNET_MSG_UNKNOWN 0x63*/ + +/* EMULE EXTENSIONS */ +#define EMULE_MSG_HELLO 0x01 +#define EMULE_MSG_HELLO_ANSWER 0x02 +#define EMULE_MSG_DATA_COMPRESSED 0x40 +#define EMULE_MSG_QUEUE_RANKING 0x60 +#define EMULE_MSG_SOURCES_REQUEST 0x81 +#define EMULE_MSG_SOURCES_ANSWER 0x82 + +/* EDONKEY UDP MESSAGES */ +#define EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST 0x96 +#define EDONKEY_MSG_UDP_SERVER_STATUS 0x97 +#define EDONKEY_MSG_UDP_SEARCH_FILE 0x98 +#define EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS 0x99 +#define EDONKEY_MSG_UDP_GET_SOURCES 0x9a +#define EDONKEY_MSG_UDP_FOUND_SOURCES 0x9b +#define EDONKEY_MSG_UDP_CALLBACK_REQUEST 0x9c +#define EDONKEY_MSG_UDP_CALLBACK_FAIL 0x9e +/* #define EDONKEY_MSG_UDP_UNKNOWN 0xa0 */ +#define EDONKEY_MSG_UDP_SERVER_LIST 0xa1 +#define EDONKEY_MSG_UDP_GET_SERVER_INFO 0xa2 +#define EDONKEY_MSG_UDP_SERVER_INFO 0xa3 +#define EDONKEY_MSG_UDP_GET_SERVER_LIST 0xa4 + +/* EMULE UDP EXTENSIONS */ +#define EMULE_MSG_UDP_REASKFILEPING 0x90 +#define EMULE_MSG_UDP_REASKACK 0x91 +#define EMULE_MSG_UDP_FILE_NOT_FOUND 0x92 +#define EMULE_MSG_UDP_QUEUE_FULL 0x93 + +/* OVERNET UDP EXTENSIONS */ +#define OVERNET_MSG_UDP_CONNECT 0x0a +#define OVERNET_MSG_UDP_CONNECT_REPLY 0x0b +#define OVERNET_MSG_UDP_PUBLICIZE 0x0c +#define OVERNET_MSG_UDP_PUBLICIZE_ACK 0x0d +#define OVERNET_MSG_UDP_SEARCH 0x0e +#define OVERNET_MSG_UDP_SEARCH_NEXT 0x0f +#define OVERNET_MSG_UDP_SEARCH_INFO 0x10 +#define OVERNET_MSG_UDP_SEARCH_RESULT 0x11 +#define OVERNET_MSG_UDP_SEARCH_END 0x12 +#define OVERNET_MSG_UDP_PUBLISH 0x13 +#define OVERNET_MSG_UDP_PUBLISH_ACK 0x14 +#define OVERNET_MSG_UDP_IDENTIFY_REPLY 0x15 +#define OVERNET_MSG_UDP_IDENTIFY_ACK 0x16 +#define OVERNET_MSG_UDP_FIREWALL_CONNECTION 0x18 +#define OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK 0x19 +#define OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK 0x1a +#define OVERNET_MSG_UDP_IP_QUERY 0x1b +#define OVERNET_MSG_UDP_IP_QUERY_ANSWER 0x1c +#define OVERNET_MSG_UDP_IP_QUERY_END 0x1d +#define OVERNET_MSG_UDP_IDENTIFY 0x1e +/*#define OVERNET_MSG_UDP_UNKNOWN 0x21 */ + +/* EDONKEY META TAG TYPES */ +#define EDONKEY_MTAG_UNKNOWN 0x00 +#define EDONKEY_MTAG_HASH 0x01 +#define EDONKEY_MTAG_STRING 0x02 +#define EDONKEY_MTAG_DWORD 0x03 +#define EDONKEY_MTAG_FLOAT 0x04 +#define EDONKEY_MTAG_BOOL 0x05 +#define EDONKEY_MTAG_BOOL_ARRAY 0x06 +#define EDONKEY_MTAG_BLOB 0x07 + +/* EDONKEY SPECIAL TAGS */ +#define EDONKEY_STAG_UNKNOWN 0x00 +#define EDONKEY_STAG_NAME 0x01 +#define EDONKEY_STAG_SIZE 0x02 +#define EDONKEY_STAG_TYPE 0x03 +#define EDONKEY_STAG_FORMAT 0x04 +#define EDONKEY_STAG_COLLECTION 0x05 +#define EDONKEY_STAG_PART_PATH 0x06 +#define EDONKEY_STAG_PART_HASH 0x07 +#define EDONKEY_STAG_COPIED 0x08 +#define EDONKEY_STAG_GAP_START 0x09 +#define EDONKEY_STAG_GAP_END 0x0a +#define EDONKEY_STAG_DESCRIPTION 0x0b +#define EDONKEY_STAG_PING 0x0c +#define EDONKEY_STAG_FAIL 0x0d +#define EDONKEY_STAG_PREFERENCE 0x0e +#define EDONKEY_STAG_PORT 0x0f +#define EDONKEY_STAG_IP 0x10 +#define EDONKEY_STAG_VERSION 0x11 +#define EDONKEY_STAG_TEMPFILE 0x12 +#define EDONKEY_STAG_PRIORITY 0x13 +#define EDONKEY_STAG_STATUS 0x14 +#define EDONKEY_STAG_AVAILABILITY 0x15 +#define EDONKEY_STAG_QTIME 0x16 +#define EDONKEY_STAG_PARTS 0x17 + +/* EMULE SPECIAL TAGS */ +#define EMULE_STAG_COMPRESSION 0x20 +#define EMULE_STAG_UDP_CLIENT_PORT 0x21 +#define EMULE_STAG_UDP_VERSION 0x22 +#define EMULE_STAG_SOURCE_EXCHANGE 0x23 +#define EMULE_STAG_COMMENTS 0x24 +#define EMULE_STAG_EXTENDED_REQUEST 0x25 +#define EMULE_STAG_COMPATIBLE_CLIENT 0x26 + +/* EDONKEY SEARCH TYPES */ +#define EDONKEY_SEARCH_BOOL 0x00 +#define EDONKEY_SEARCH_NAME 0x01 +#define EDONKEY_SEARCH_META 0x02 +#define EDONKEY_SEARCH_LIMIT 0x03 + +/* EDONKEY SEARCH OPERATORS */ +#define EDONKEY_SEARCH_AND 0x00 +#define EDONKEY_SEARCH_OR 0x01 +#define EDONKEY_SEARCH_ANDNOT 0x02 + +/* EDONKEY SEARCH MIN/MAX */ +#define EDONKEY_SEARCH_MIN 0x01 +#define EDONKEY_SEARCH_MAX 0x02
- Follow-Ups:
- Re: [Ethereal-dev] eDonkey Protocol Dissector
- From: Guy Harris
- Re: [Ethereal-dev] eDonkey Protocol Dissector
- Prev by Date: [Ethereal-dev] RE:[drb@xxxxxxx: Bug#199763: ethereal: UI issuesincurrent version]
- Next by Date: Re: [Ethereal-dev] eDonkey Protocol Dissector
- Previous by thread: [Ethereal-dev] RE:[drb@xxxxxxx: Bug#199763: ethereal: UI issuesincurrent version]
- Next by thread: Re: [Ethereal-dev] eDonkey Protocol Dissector
- Index(es):