diff options
author | Anders Broman <anders.broman@ericsson.com> | 2007-10-27 15:28:35 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2007-10-27 15:28:35 +0000 |
commit | 135ba5aeff64ab5be45f417761fee114e9a498ae (patch) | |
tree | c1537fd4ca9848861e30980cc528c1c08aa6fd73 /epan | |
parent | f209667d9353903369bcbbdfc6c19cd360597595 (diff) |
From Stefano Picerno:
I made some updates to the edonkey dissector.
Most kademlia1 and some kademlia2 messages are now completely decoded.
svn path=/trunk/; revision=23288
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-edonkey.c | 1828 | ||||
-rw-r--r-- | epan/dissectors/packet-edonkey.h | 175 |
2 files changed, 1495 insertions, 508 deletions
diff --git a/epan/dissectors/packet-edonkey.c b/epan/dissectors/packet-edonkey.c index 73864b35e8..72f550d904 100644 --- a/epan/dissectors/packet-edonkey.c +++ b/epan/dissectors/packet-edonkey.c @@ -1,10 +1,13 @@ /* packet-edonkey.c * Routines for edonkey dissection * Copyright 2003, Xuan Zhang <xz@aemail4u.com> + * Copyright 2007, Stefano Picerno <stefano.picerno@gmail.com> * 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 * + * Kademlia dissector based on source code inspection of aMule 2.1.3 and eMule 0.84b + * * $Id$ * * Wireshark - Network traffic analyzer @@ -83,6 +86,20 @@ static int hf_emule_signature = -1; static int hf_emule_sourceOBFU = -1; static int hf_overnet_peer = -1; +static int hf_edonkey_unparsed_data_length = -1; +static int hf_kademlia_unparsed_data_length = -1; +static int hf_kademlia_peer = -1; +static int hf_kademlia_peertype = -1; +static int hf_kademlia_tag_float = -1; +static int hf_kademlia_tag_uint32 = -1; +static int hf_kademlia_tag_uint16 = -1; +static int hf_kademlia_tag_uint8 = -1; +static int hf_kademlia_port = -1; +static int hf_kademlia_tcp_port = -1; +static int hf_kademlia_ip = -1; +static gint ett_edonkey_listitem = -1; +static gint ett_kademlia_search_expression = -1; + static gint ett_edonkey = -1; static gint ett_edonkey_message = -1; static gint ett_edonkey_metatag = -1; @@ -99,127 +116,258 @@ static gint ett_emule_sourceOBFU = -1; /* desegmentation of eDonkey over TCP */ static gboolean edonkey_desegment = TRUE; +static const value_string kademlia_msgs[] = { + { KADEMLIA2_BOOTSTRAP_REQ ,"KADEMLIA2_BOOTSTRAP_REQ" }, + { KADEMLIA2_BOOTSTRAP_RES ,"KADEMLIA2_BOOTSTRAP_RES" }, + { KADEMLIA2_HELLO_REQ ,"KADEMLIA2_HELLO_REQ" }, + { KADEMLIA2_HELLO_RES ,"KADEMLIA2_HELLO_RES" }, + { KADEMLIA2_PUBLISH_KEY_REQ ,"KADEMLIA2_PUBLISH_KEY_REQ" }, + { KADEMLIA2_PUBLISH_NOTES_REQ ,"KADEMLIA2_PUBLISH_NOTES_REQ" }, + { KADEMLIA2_PUBLISH_RES ,"KADEMLIA2_PUBLISH_RES" }, + { KADEMLIA2_PUBLISH_SOURCE_REQ ,"KADEMLIA2_PUBLISH_SOURCE_REQ" }, + { KADEMLIA2_REQ ,"KADEMLIA2_REQ" }, + { KADEMLIA2_RES ,"KADEMLIA2_RES" }, + { KADEMLIA2_SEARCH_KEY_REQ ,"KADEMLIA2_SEARCH_KEY_REQ" }, + { KADEMLIA2_SEARCH_NOTES_REQ ,"KADEMLIA2_SEARCH_NOTES_REQ" }, + { KADEMLIA2_SEARCH_RES ,"KADEMLIA2_SEARCH_RES" }, + { KADEMLIA2_SEARCH_SOURCE_REQ ,"KADEMLIA2_SEARCH_SOURCE_REQ" }, + { KADEMLIA_BOOTSTRAP_REQ ,"KADEMLIA_BOOTSTRAP_REQ" }, + { KADEMLIA_BOOTSTRAP_RES ,"KADEMLIA_BOOTSTRAP_RES" }, + { KADEMLIA_CALLBACK_REQ ,"KADEMLIA_CALLBACK_REQ" }, + { KADEMLIA_FINDBUDDY_REQ ,"KADEMLIA_FINDBUDDY_REQ" }, + { KADEMLIA_FINDBUDDY_RES ,"KADEMLIA_FINDBUDDY_RES" }, + { KADEMLIA_FIREWALLED_ACK_RES ,"KADEMLIA_FIREWALLED_ACK_RES" }, + { KADEMLIA_FIREWALLED_REQ ,"KADEMLIA_FIREWALLED_REQ" }, + { KADEMLIA_FIREWALLED_RES ,"KADEMLIA_FIREWALLED_RES" }, + { KADEMLIA_HELLO_REQ ,"KADEMLIA_HELLO_REQ" }, + { KADEMLIA_HELLO_RES ,"KADEMLIA_HELLO_RES" }, + { KADEMLIA_PUBLISH_NOTES_REQ ,"KADEMLIA_PUBLISH_NOTES_REQ" }, + { KADEMLIA_PUBLISH_NOTES_RES ,"KADEMLIA_PUBLISH_NOTES_RES" }, + { KADEMLIA_PUBLISH_REQ ,"KADEMLIA_PUBLISH_REQ" }, + { KADEMLIA_PUBLISH_RES ,"KADEMLIA_PUBLISH_RES" }, + { KADEMLIA_REQ ,"KADEMLIA_REQ" }, + { KADEMLIA_RES ,"KADEMLIA_RES" }, + { KADEMLIA_SEARCH_NOTES_REQ ,"KADEMLIA_SEARCH_NOTES_REQ" }, + { KADEMLIA_SEARCH_NOTES_RES ,"KADEMLIA_SEARCH_NOTES_RES" }, + { KADEMLIA_SEARCH_REQ ,"KADEMLIA_SEARCH_REQ" }, + { KADEMLIA_SEARCH_RES ,"KADEMLIA_SEARCH_RES" }, + { 0, NULL } +}; + +static const value_string kademlia_tag_types[] = { + { KADEMLIA_TAGTYPE_HASH ,"TAGTYPE_HASH" }, + { KADEMLIA_TAGTYPE_STRING ,"TAGTYPE_STRING" }, + { KADEMLIA_TAGTYPE_UINT32 ,"TAGTYPE_UINT32" }, + { KADEMLIA_TAGTYPE_FLOAT32 ,"TAGTYPE_FLOAT32" }, + { KADEMLIA_TAGTYPE_BOOL ,"TAGTYPE_BOOL" }, + { KADEMLIA_TAGTYPE_BOOLARRAY ,"TAGTYPE_BOOLARRAY" }, + { KADEMLIA_TAGTYPE_BLOB ,"TAGTYPE_BLOB" }, + { KADEMLIA_TAGTYPE_UINT16 ,"TAGTYPE_UINT16" }, + { KADEMLIA_TAGTYPE_UINT8 ,"TAGTYPE_UINT8" }, + { KADEMLIA_TAGTYPE_BSOB ,"TAGTYPE_BSOB" }, + { KADEMLIA_TAGTYPE_UINT64 ,"TAGTYPE_UINT64" }, + + { KADEMLIA_TAGTYPE_STR1 ,"TAGTYPE_STR1" }, + { KADEMLIA_TAGTYPE_STR2 ,"TAGTYPE_STR2" }, + { KADEMLIA_TAGTYPE_STR3 ,"TAGTYPE_STR3" }, + { KADEMLIA_TAGTYPE_STR4 ,"TAGTYPE_STR4" }, + { KADEMLIA_TAGTYPE_STR5 ,"TAGTYPE_STR5" }, + { KADEMLIA_TAGTYPE_STR6 ,"TAGTYPE_STR6" }, + { KADEMLIA_TAGTYPE_STR7 ,"TAGTYPE_STR7" }, + { KADEMLIA_TAGTYPE_STR8 ,"TAGTYPE_STR8" }, + { KADEMLIA_TAGTYPE_STR9 ,"TAGTYPE_STR9" }, + { KADEMLIA_TAGTYPE_STR10 ,"TAGTYPE_STR10" }, + { KADEMLIA_TAGTYPE_STR11 ,"TAGTYPE_STR11" }, + { KADEMLIA_TAGTYPE_STR12 ,"TAGTYPE_STR12" }, + { KADEMLIA_TAGTYPE_STR13 ,"TAGTYPE_STR13" }, + { KADEMLIA_TAGTYPE_STR14 ,"TAGTYPE_STR14" }, + { KADEMLIA_TAGTYPE_STR15 ,"TAGTYPE_STR15" }, + { KADEMLIA_TAGTYPE_STR16 ,"TAGTYPE_STR16" }, + { KADEMLIA_TAGTYPE_STR17 ,"TAGTYPE_STR17" }, + { KADEMLIA_TAGTYPE_STR18 ,"TAGTYPE_STR18" }, + { KADEMLIA_TAGTYPE_STR19 ,"TAGTYPE_STR19" }, + { KADEMLIA_TAGTYPE_STR20 ,"TAGTYPE_STR20" }, + { KADEMLIA_TAGTYPE_STR21 ,"TAGTYPE_STR21" }, + { KADEMLIA_TAGTYPE_STR22 ,"TAGTYPE_STR22" }, + { 0, NULL } +}; + +static const value_string kademlia_tags[] = { + { KADEMLIA_TAG_BUDDYHASH ,"TAG_BUDDYHASH" }, + { KADEMLIA_TAG_CLIENTLOWID ,"TAG_CLIENTLOWID" }, + { KADEMLIA_TAG_COLLECTION ,"TAG_COLLECTION" }, + { KADEMLIA_TAG_COPIED ,"TAG_COPIED" }, + { KADEMLIA_TAG_DESCRIPTION ,"TAG_DESCRIPTION" }, + { KADEMLIA_TAG_ENCRYPTION ,"TAG_ENCRYPTION" }, + { KADEMLIA_TAG_FAIL ,"TAG_FAIL" }, + { KADEMLIA_TAG_FILECOMMENT ,"TAG_FILECOMMENT" }, + { KADEMLIA_TAG_FILE_COUNT ,"TAG_FILE_COUNT" }, + { KADEMLIA_TAG_FILEFORMAT ,"TAG_FILEFORMAT" }, + { KADEMLIA_TAG_FILENAME ,"TAG_FILENAME" }, + { KADEMLIA_TAG_FILERATING ,"TAG_FILERATING" }, + { KADEMLIA_TAG_FILESIZE_HI ,"TAG_FILESIZE_HI" }, + { KADEMLIA_TAG_FILESIZE ,"TAG_FILESIZE" }, + { KADEMLIA_TAG_FILETYPE ,"TAG_FILETYPE" }, + { KADEMLIA_TAG_GAP_END ,"TAG_GAP_END" }, + { KADEMLIA_TAG_GAP_START ,"TAG_GAP_START" }, + { KADEMLIA_TAG_IP_ADDRESS ,"TAG_IP_ADDRESS" }, + { KADEMLIA_TAG_MEDIA_ALBUM ,"TAG_MEDIA_ALBUM" }, + { KADEMLIA_TAG_MEDIA_ARTIST ,"TAG_MEDIA_ARTIST" }, + { KADEMLIA_TAG_MEDIA_BITRATE ,"TAG_MEDIA_BITRATE"}, + { KADEMLIA_TAG_MEDIA_CODEC ,"TAG_MEDIA_CODEC" }, + { KADEMLIA_TAG_MEDIA_LENGTH ,"TAG_MEDIA_LENGTH" }, + { KADEMLIA_TAG_MEDIA_TITLE ,"TAG_MEDIA_TITLE" }, + { KADEMLIA_TAG_PART_HASH ,"TAG_PART_HASH" }, + { KADEMLIA_TAG_PART_PATH ,"TAG_PART_PATH" }, + { KADEMLIA_TAG_PARTS ,"TAG_PARTS" }, + { KADEMLIA_TAG_PERMISSIONS ,"TAG_PERMISSIONS" }, + { KADEMLIA_TAG_PING ,"TAG_PING" }, + { KADEMLIA_TAG_PORT ,"TAG_PORT" }, + { KADEMLIA_TAG_PREFERENCE ,"TAG_PREFERENCE" }, + { KADEMLIA_TAG_PRIORITY ,"TAG_PRIORITY" }, + { KADEMLIA_TAG_QTIME ,"TAG_QTIME" }, + { KADEMLIA_TAG_SERVERIP ,"TAG_SERVERIP" }, + { KADEMLIA_TAG_SERVERPORT ,"TAG_SERVERPORT" }, + { KADEMLIA_TAG_SOURCEIP ,"TAG_SOURCEIP" }, + { KADEMLIA_TAG_SOURCEPORT ,"TAG_SOURCEPORT" }, + { KADEMLIA_TAG_SOURCES ,"TAG_SOURCES" }, + { KADEMLIA_TAG_SOURCETYPE ,"TAG_SOURCETYPE" }, + { KADEMLIA_TAG_SOURCEUPORT ,"TAG_SOURCEUPORT" }, + { KADEMLIA_TAG_STATUS ,"TAG_STATUS" }, + { KADEMLIA_TAG_TEMPFILE ,"TAG_TEMPFILE" }, + { KADEMLIA_TAG_USER_COUNT ,"TAG_USER_COUNT" }, + { KADEMLIA_TAG_VERSION ,"TAG_VERSION" }, + + { 0, NULL } +}; + static const value_string edonkey_protocols[] = { - { EDONKEY_PROTO_EDONKEY, "eDonkey" }, - { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" }, - { EDONKEY_PROTO_EMULE_COMP, "eMule Compressed" }, + { EDONKEY_PROTO_EDONKEY, "eDonkey" }, + { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" }, + { EDONKEY_PROTO_EMULE_COMP, "eMule Compressed" }, + { EDONKEY_PROTO_KADEMLIA, "Kademlia" }, + { EDONKEY_PROTO_KADEMLIA_COMP, "Kademlia Compressed" }, + { EDONKEY_PROTO_ADU_KADEMLIA, "KAdu" }, + { EDONKEY_PROTO_ADU_KADEMLIA_COMP, "KAdu 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_GET_SOURCES_OBFU, "Get Sources Obfuscation" }, - { 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_FOUND_SOURCES_OBFU, "Found Sources Obfuscation"}, - { 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" }, + { 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_GET_SOURCES_OBFU, "Get Sources Obfuscation" }, + { 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_FOUND_SOURCES_OBFU, "Found Sources Obfuscation"}, + { 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" }, - { EMULE_MSG_SIGNATURE, "Signature" }, - { EMULE_MSG_PUBLIC_KEY, "Public Key" }, - { EMULE_MSG_SEC_IDENT_STATE, "Second Identification State" }, - { EMULE_MSG_MULTIPACKET, "MultiPacket" }, - { EMULE_MSG_MULTIPACKET_EXT, "MultiPacketExt" }, - { EMULE_MSG_MULTIPACKET_ANSWER, "MultiPacket Answer" }, - { EMULE_MSG_AICH_REQUEST, "AICH Hashset Request" }, - { EMULE_MSG_AICH_ANSWER, "AICH Hashset Answer" }, - { EMULE_MSG_AICHFILEHASH_ANSWER, "AICH Master Hash Request" }, - { EMULE_MSG_AICHFILEHASH_REQUEST, "AICH Master Hash Answer" }, - { EMULE_MSG_DATA_COMPRESSED_64, "Data Compressed (64bit)" }, - { EMULE_MSG_SENDING_PART_64, "Sending Part (64bit)" }, - { EMULE_MSG_REQUEST_PARTS_64, "Request Parts (64bit)" }, - { 0, NULL } + { EMULE_MSG_HELLO, "Hello" }, + { EMULE_MSG_HELLO_ANSWER, "Hello Answer" }, + { EMULE_MSG_DATA_COMPRESSED, "Data Compressed" }, + { EMULE_MSG_QUEUE_RANKING, "Queue Ranking" }, + { EMULE_MSG_FILE_DESC, "File Description" }, + { EMULE_MSG_SOURCES_REQUEST, "Sources Request" }, + { EMULE_MSG_SOURCES_ANSWER, "Sources Answer" }, + { EMULE_MSG_SIGNATURE, "Signature" }, + { EMULE_MSG_PUBLIC_KEY, "Public Key" }, + { EMULE_MSG_SEC_IDENT_STATE, "Second Identification State" }, + { EMULE_MSG_MULTIPACKET, "MultiPacket" }, + { EMULE_MSG_MULTIPACKET_EXT, "MultiPacketExt" }, + { EMULE_MSG_MULTIPACKET_ANSWER, "MultiPacket Answer" }, + { EMULE_MSG_CALLBACK, "Callback" }, + { EMULE_MSG_AICH_REQUEST, "AICH Hashset Request" }, + { EMULE_MSG_AICH_ANSWER, "AICH Hashset Answer" }, + { EMULE_MSG_AICHFILEHASH_ANSWER, "AICH Master Hash Request" }, + { EMULE_MSG_AICHFILEHASH_REQUEST, "AICH Master Hash Answer" }, + { EMULE_MSG_DATA_COMPRESSED_64, "Data Compressed (64bit)" }, + { EMULE_MSG_SENDING_PART_64, "Sending Part (64bit)" }, + { EMULE_MSG_REQUEST_PARTS_64, "Request Parts (64bit)" }, + { 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" }, + { 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" }, + { 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" }, + { 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 } }; @@ -281,6 +429,16 @@ static const value_string edonkey_search_conds[] = { { 0, NULL } }; +static const value_string kademlia_search_conds[] = { + { 0, "="}, + { 1, ">"}, + { 2, "<"}, + { 3, ">="}, + { 4, "<="}, + { 5, "<>"} +}; + + /* Dissects a generic eDonkey list */ static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, @@ -289,11 +447,23 @@ static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_, { /* <List> ::= <List Size> <Item>* */ guint32 listnum, i; + proto_tree *subtree; + proto_item* ti; + proto_item* list_ti; + int list_start_offset; + + list_start_offset = offset; + switch (listnum_length) { + case -1: case 1: listnum = tvb_get_guint8(tvb, offset); break; + case -2: + listnum = tvb_get_ntohs(tvb, offset); + break; + case 2: listnum = tvb_get_letohs(tvb, offset); break; @@ -302,33 +472,52 @@ static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_, listnum = tvb_get_letohl(tvb, offset); break; + case -4: + listnum = tvb_get_ntohl(tvb, offset); + break; + default: /* Not Supported */ return offset; } + if (listnum_length < 0) + listnum_length = -listnum_length; + + list_ti = proto_tree_add_text(tree, tvb, offset, listnum_length, "%s List Size: %u", listdesc, listnum); + + offset+= listnum_length; - 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); + int item_start_offset; + subtree = proto_item_add_subtree(list_ti, ett_edonkey_listitem ); + + item_start_offset = offset; + ti = proto_tree_add_text(subtree, tvb, item_start_offset, 1, "%s[%u/%u]", listdesc, i+1, listnum); + + subtree = proto_item_add_subtree(ti, ett_edonkey_listitem ); + + offset = (*item_dissector)(tvb, pinfo, offset, subtree); + proto_item_set_len( ti, offset - item_start_offset ); } + + proto_item_set_len(list_ti, offset - list_start_offset ); return offset; } static gint lookup_str_index(gchar* str, gint length, const value_string *vs) { - gint i = 0; + gint i = 0; - if (str == NULL) return -1; + if (str == NULL) return -1; - while (vs[i].strptr) { - if (strncasecmp(str, vs[i].strptr, length) == 0) - return i; - i++; - } + while (vs[i].strptr) { + if (strncasecmp(str, vs[i].strptr, length) == 0) + return i; + i++; + } - return -1; + return -1; } static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint length, guint8 special_tagtype) @@ -337,7 +526,7 @@ static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint leng if (match_strval(special_tagtype, edonkey_special_tags) == NULL) { gint index; - tag_name = tvb_get_ephemeral_string(tvb, start, length); + tag_name = tvb_get_ephemeral_string(tvb, start, length); index = lookup_str_index(tag_name, length, edonkey_special_tags); if (index < 0) return EDONKEY_STAG_UNKNOWN; @@ -349,9 +538,9 @@ static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint leng } static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb, - gint start, gint length, guint8 special_tagtype) + gint start, gint length, guint8 special_tagtype) { - const gchar *tag_name; + const 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); @@ -363,6 +552,51 @@ static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb } } +static int dissect_edonkey_generic_uint64(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree, char* label) +{ + guint64 value = tvb_get_letoh64(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 8, "%s : %" G_GINT64_MODIFIER "u", label, value ); + return offset + 8; +} + +static int dissect_edonkey_generic_uint32(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree, char* label) +{ + guint32 value = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "%s : %u", label, value ); + return offset + 4; +} + +static int dissect_edonkey_generic_uint16(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree, char* label) +{ + guint16 value = tvb_get_letohs(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 2, "%s : %u", label, value ); + return offset + 2; +} + +/* +static int dissect_edonkey_generic_uint8(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree, char* label) +{ + guint16 value = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "%s : %u", label, value ); + return offset + 1; +} +*/ + +static int dissect_kademlia_search_condition(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree ) +{ + guint16 value = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Operator: %s 0x%02X", + val_to_str( value, kademlia_search_conds, "Unknown"), + value); + + return offset + 1; +} + /* Dissects the eDonkey meta tag */ static int dissect_edonkey_metatag(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) @@ -428,16 +662,16 @@ static int dissect_edonkey_metatag(tvbuff_t *tvb, packet_info *pinfo _U_, if (tag_type==real_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, tag_offset-tag_name_size, tag_name_size, special_tagtype); - trans_tagtype = edonkey_metatag_name_get_type(tvb, offset+3, tag_name_size, special_tagtype); + trans_tagtype = edonkey_metatag_name_get_type(tvb, offset+3, tag_name_size, special_tagtype); if (trans_tagtype == EDONKEY_STAG_IP) { proto_tree_add_item(metatag_tree, hf_edonkey_ip, tvb, tag_offset, 4, FALSE); } - else if (trans_tagtype == EMULE_STAG_SERVER_VERSION) { - guint16 maj, min; - min = tvb_get_letohs(tvb, tag_offset); - maj = tvb_get_letohs(tvb, tag_offset+2); - proto_tree_add_text(metatag_tree, tvb, tag_offset, 4, "Meta Tag Value: %u.%u", maj, min); - } + else if (trans_tagtype == EMULE_STAG_SERVER_VERSION) { + guint16 maj, min; + min = tvb_get_letohs(tvb, tag_offset); + maj = tvb_get_letohs(tvb, tag_offset+2); + proto_tree_add_text(metatag_tree, tvb, tag_offset, 4, "Meta Tag Value: %u.%u", maj, min); + } 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); @@ -570,13 +804,101 @@ 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); */ + /* 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; } + +static int dissect_kademlia_port(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_kademlia_port, tvb, offset, 2, TRUE); + return offset +2; +} + +static int dissect_kademlia_tcp_port(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_kademlia_tcp_port, tvb, offset, 2, TRUE); + return offset +2; +} + + +static int dissect_kademlia_ip_address(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_kademlia_ip, tvb, offset, 4, TRUE); + return offset + 4; +} + + +static int dissect_kademlia_address(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Address> ::= <IP> <Port> <Tcp Port>*/ + offset = dissect_kademlia_ip_address( tvb, pinfo, offset, tree ); + + offset = dissect_kademlia_port( tvb, pinfo, offset, tree ); + + offset = dissect_kademlia_tcp_port( tvb, pinfo, offset, tree ); + + return offset; +} + +static int dissect_kademlia_tagname(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <String> ::= <String length (guint16)> DATA */ + const gchar * tagname; + const gchar * tag_full_name = NULL; + gchar temp_tagname_buffer[10]; + + guint16 string_length = tvb_get_letohs(tvb, offset); + + proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length); + + tagname = tvb_get_ephemeral_string( tvb, offset + 2, string_length ); + + if ( tagname && string_length == 1 ) { + guint8 tagname_value = *(guint8*)tagname; + /* lookup tagname */ + tag_full_name = match_strval( tagname_value, kademlia_tags ); + if ( 1 /*!isalnum( tagname_value )*/ ) { + sprintf( temp_tagname_buffer, "0x%02X", tagname_value ); + tagname = temp_tagname_buffer; + } + } + + if (tag_full_name) + proto_tree_add_text(tree, tvb, offset+2, string_length, "Name: %s [%s]", tagname, tag_full_name); + else + proto_tree_add_text(tree, tvb, offset+2, string_length, "Name: %s", tagname); + + return offset+2+string_length; +} + +static int dissect_kademlia_string(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <String> ::= <String length (guint16)> DATA */ + const gchar * tagname; + guint16 string_length = tvb_get_letohs(tvb, offset); + + proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length); + + tagname = tvb_get_ephemeral_string( tvb, offset + 2, string_length ); + + proto_tree_add_text(tree, tvb, offset+2, string_length, "String: %s", tagname); + + return offset+2+string_length; +} + + + + /* Dissects the eDonkey address list */ static int dissect_edonkey_address_list(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) @@ -587,7 +909,7 @@ static int dissect_edonkey_address_list(tvbuff_t *tvb, packet_info *pinfo _U_, /* Dissects the eDonkey hash */ static int dissect_edonkey_hash(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { /* <hash> ::= HASH (16 word MD4 digest) */ proto_tree_add_item(tree, hf_edonkey_hash, tvb, offset, 16, FALSE); @@ -604,7 +926,7 @@ static int dissect_edonkey_file_hash(tvbuff_t *tvb, packet_info *pinfo _U_, } /* Dissects the eMule public key */ -static int dissect_edonkey_public_key(tvbuff_t *tvb, packet_info *pinfo _U_, +static int dissect_edonkey_public_key(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) { guint8 length = tvb_get_guint8(tvb, offset); @@ -615,7 +937,7 @@ static int dissect_edonkey_public_key(tvbuff_t *tvb, packet_info *pinfo _U_, } /* Dissects the eMule signature */ -static int dissect_edonkey_signature(tvbuff_t *tvb, packet_info *pinfo _U_, +static int dissect_edonkey_signature(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) { guint8 length = tvb_get_guint8(tvb, offset); @@ -625,9 +947,18 @@ static int dissect_edonkey_signature(tvbuff_t *tvb, packet_info *pinfo _U_, return offset + length; } +/* Dissects the Kademlia hash*/ +static int dissect_kademlia_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 hash list */ static int dissect_edonkey_hash_list(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { /* <Hash List> ::= <File Hash> <List Size (guint16)> <Hash>* */ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); @@ -674,19 +1005,19 @@ static int dissect_edonkey_file_name(tvbuff_t *tvb, packet_info *pinfo _U_, /* Dissects the eDonkey File Status */ static int dissect_edonkey_file_status(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { - guint16 partcount, arrlen; + guint16 partcount, arrlen; - /* <File Status> ::= <Part Count> <Part Status> */ - partcount = tvb_get_letohs(tvb, offset); - arrlen = (partcount+7)/8; + /* <File Status> ::= <Part Count> <Part Status> */ + partcount = tvb_get_letohs(tvb, offset); + arrlen = (partcount+7)/8; - proto_tree_add_uint(tree, hf_edonkey_part_count, tvb, offset, 2, partcount); - if (partcount>0) { - proto_tree_add_item(tree, hf_edonkey_file_status, tvb, offset+2, arrlen, FALSE); - } - return offset+2+arrlen; + proto_tree_add_uint(tree, hf_edonkey_part_count, tvb, offset, 2, partcount); + if (partcount>0) { + proto_tree_add_item(tree, hf_edonkey_file_status, tvb, offset+2, arrlen, FALSE); + } + return offset+2+arrlen; } @@ -717,7 +1048,7 @@ static int dissect_edonkey_client_hash(tvbuff_t *tvb, packet_info *pinfo _U_, } /* Dissects the eMule sourceOBFU */ -static int dissect_emule_sourceOBFU(tvbuff_t *tvb, packet_info *pinfo _U_, +static int dissect_emule_sourceOBFU(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) { @@ -726,23 +1057,22 @@ static int dissect_emule_sourceOBFU(tvbuff_t *tvb, packet_info *pinfo _U_, guint8 settings = tvb_get_guint8(tvb, offset+6); /* Add subtree for client info */ ti = proto_tree_add_item(tree, hf_emule_sourceOBFU, tvb, offset, 7 + ((settings & 0x08) ? 16 : 0), FALSE); - sourceOBFU_tree = proto_item_add_subtree(ti, ett_emule_sourceOBFU); + sourceOBFU_tree = proto_item_add_subtree(ti, ett_emule_sourceOBFU); proto_tree_add_item(sourceOBFU_tree, hf_edonkey_ip, tvb, offset, 4, FALSE); proto_tree_add_item(sourceOBFU_tree, hf_edonkey_port, tvb, offset+4, 2, TRUE); proto_tree_add_text(sourceOBFU_tree, tvb, offset+6, 1, "Obfuscation Settings: %u", settings); offset += 7; if (settings & 0x08) - offset = dissect_edonkey_client_hash(tvb, pinfo, offset, sourceOBFU_tree); + offset = dissect_edonkey_client_hash(tvb, pinfo, offset, sourceOBFU_tree); return offset; } /* Dissects the eMule sourceOBFU list */ -static int dissect_emule_sourceOBFU_list(tvbuff_t *tvb, packet_info *pinfo _U_, +static int dissect_emule_sourceOBFU_list(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree) { - return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Sources Obfuscation", dissect_emule_sourceOBFU); } @@ -753,17 +1083,17 @@ static int dissect_edonkey_client_id(tvbuff_t *tvb, packet_info *pinfo _U_, { proto_item *ti; /* <Client ID> ::= guint32 */ -/* guint32 ip = tvb_get_letohl(tvb, offset); - proto_tree_add_ipv4(tree, hf_edonkey_client_id, tvb, offset, 4, ip); */ + /* guint32 ip = tvb_get_letohl(tvb, offset); + proto_tree_add_ipv4(tree, hf_edonkey_client_id, tvb, offset, 4, ip); */ ti = proto_tree_add_item(tree, hf_edonkey_client_id, tvb, offset, 4, FALSE); if (fileinfo) { - guint32 ip = tvb_get_letohl(tvb, offset); - guint16 port = tvb_get_letohs(tvb, offset+4); - if (ip==0xfcfcfcfc && port==0xfcfc) { - proto_item_append_text(ti, " (myself, incomplete file)"); - } else if (ip==0xfbfbfbfb && port==0xfbfb) { - proto_item_append_text(ti, " (myself, complete file)"); - } + guint32 ip = tvb_get_letohl(tvb, offset); + guint16 port = tvb_get_letohs(tvb, offset+4); + if (ip==0xfcfcfcfc && port==0xfcfc) { + proto_item_append_text(ti, " (myself, incomplete file)"); + } else if (ip==0xfbfbfbfb && port==0xfbfb) { + proto_item_append_text(ti, " (myself, complete file)"); + } } return offset+4; } @@ -788,7 +1118,7 @@ static int dissect_edonkey_start_offset(tvbuff_t *tvb, packet_info *pinfo _U_, } static int dissect_edonkey_start_offset_64(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { /* <Start Offset> ::= guint64 */ guint64 start = tvb_get_letoh64(tvb, offset); @@ -807,7 +1137,7 @@ static int dissect_edonkey_end_offset(tvbuff_t *tvb, packet_info *pinfo _U_, } static int dissect_edonkey_end_offset_64(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { /* <End Offset> ::= guint64 */ guint64 end = tvb_get_letoh64(tvb, offset); @@ -834,7 +1164,7 @@ static int dissect_edonkey_client_info(tvbuff_t *tvb, packet_info *pinfo _U_, /* 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) + 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); @@ -884,177 +1214,178 @@ static int dissect_edonkey_file_info_list(tvbuff_t *tvb, packet_info *pinfo _U_, return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "File Info", dissect_edonkey_file_info); } + /* Dissects the eMule address list */ static int dissect_emule_address_list(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { /* <Address List> ::= <List Size (guint16)> <Address>* */ return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Address", dissect_edonkey_address); } static int dissect_emule_aich_root_hash(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { - /* <AICH Root Hash> ::= HASH (20 byte SHA1 digest) */ - proto_tree_add_item(tree, hf_emule_aich_root_hash, tvb, offset, 20, FALSE); - return offset + 20; + /* <AICH Root Hash> ::= HASH (20 byte SHA1 digest) */ + proto_tree_add_item(tree, hf_emule_aich_root_hash, tvb, offset, 20, FALSE); + return offset + 20; } static int dissect_emule_aich_hash_list_entry(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { - guint16 hashid; - proto_item *ti; - proto_tree *aichhash_tree; - /* <AICH Hash List Entry> ::= <AICH Hash ID> <AICH Hash> */ - ti = proto_tree_add_item(tree, hf_emule_aich_hash_entry, tvb, offset, 22, FALSE); - aichhash_tree = proto_item_add_subtree(ti, ett_emule_aichhash); - - hashid = tvb_get_letohs(tvb, offset); - proto_tree_add_uint(aichhash_tree, hf_emule_aich_hash_id, tvb, offset, 2, hashid); - proto_tree_add_item(aichhash_tree, hf_emule_aich_hash, tvb, offset+2, 20, FALSE); - return offset + 22; + guint16 hashid; + proto_item *ti; + proto_tree *aichhash_tree; + /* <AICH Hash List Entry> ::= <AICH Hash ID> <AICH Hash> */ + ti = proto_tree_add_item(tree, hf_emule_aich_hash_entry, tvb, offset, 22, FALSE); + aichhash_tree = proto_item_add_subtree(ti, ett_emule_aichhash); + + hashid = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(aichhash_tree, hf_emule_aich_hash_id, tvb, offset, 2, hashid); + proto_tree_add_item(aichhash_tree, hf_emule_aich_hash, tvb, offset+2, 20, FALSE); + return offset + 22; } static int dissect_emule_aich_hash_list(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, proto_tree *tree) + int offset, proto_tree *tree) { - /* <AICH Hash List> ::= <List Size (guint16)> < <AICH Hash ID> <AICH Hash> >* */ - return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "AICH Hash", dissect_emule_aich_hash_list_entry); + /* <AICH Hash List> ::= <List Size (guint16)> < <AICH Hash ID> <AICH Hash> >* */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "AICH Hash", dissect_emule_aich_hash_list_entry); } static int dissect_emule_multipacket(tvbuff_t *tvb, packet_info *pinfo _U_, - int offset, int eoffset, proto_tree *tree, int isext) + int offset, int eoffset, proto_tree *tree, int isext) { - guint8 opcode, nextop; - guint16 namelen, partcount, arrlen, oplen; - guint32 sourcecount; - proto_item *ti; - proto_tree *mp_tree; + guint8 opcode, nextop; + guint16 namelen, partcount, arrlen, oplen; + guint32 sourcecount; + proto_item *ti; + proto_tree *mp_tree; - /* <MultiPacket> ::= <File Hash> <Opcodes>* */ - /* <MultiPacketExt> ::= <File Hash> <FileLength> <Opcodes>* */ - offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + /* <MultiPacket> ::= <File Hash> <Opcodes>* */ + /* <MultiPacketExt> ::= <File Hash> <FileLength> <Opcodes>* */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); - if (isext) { - guint64 filelen = tvb_get_letoh64(tvb, offset); + if (isext) { + guint64 filelen = tvb_get_letoh64(tvb, offset); proto_tree_add_text(tree, tvb, offset, 8, "File Length: %" G_GINT64_MODIFIER "u", filelen); - offset += 8; - } - - while (offset<eoffset) { - opcode = tvb_get_guint8(tvb, offset); - - switch (opcode) { - case EDONKEY_MSG_FILE_STATUS_REQUEST: - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "File Status Request (0x%02x)", opcode); - offset += 1; - break; - case EDONKEY_MSG_FILE_REQUEST: - partcount = 443; /* Invalid */ - sourcecount = 65536; /* Out of range */ - arrlen = 0; - oplen = 1; - - if (offset+2<eoffset) { - nextop = tvb_get_guint8(tvb, offset+1); - if (nextop!=EDONKEY_MSG_FILE_STATUS_REQUEST && - nextop!=EMULE_MSG_SOURCES_REQUEST && - nextop!=EMULE_MSG_AICHFILEHASH_REQUEST) { - - partcount = tvb_get_letohs(tvb, offset+1); - if (partcount<=442) { - arrlen = (partcount+7)/8; - oplen += 2+arrlen; - - if (offset+2+arrlen+2<eoffset) { - nextop = tvb_get_guint8(tvb, offset+2+arrlen+1); - if (nextop!=EDONKEY_MSG_FILE_STATUS_REQUEST && - nextop!=EMULE_MSG_SOURCES_REQUEST && - nextop!=EMULE_MSG_AICHFILEHASH_REQUEST) { - - sourcecount = tvb_get_letohs(tvb, offset+2+arrlen+1); - oplen += 2; - } - } - } - } - } - - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, oplen, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "File Name Request (0x%02x)", opcode); - if (partcount<=442) { - dissect_edonkey_file_status(tvb, pinfo, offset+1, mp_tree); - if (sourcecount<65536) { - proto_tree_add_uint(mp_tree, hf_emule_source_count, tvb, offset+3+arrlen, 2, sourcecount); - } - } - offset += oplen; - break; - case EMULE_MSG_SOURCES_REQUEST: - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "Sources Request (0x%02x)", opcode); - offset += 1; - break; - case EMULE_MSG_AICHFILEHASH_REQUEST: - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "AICH Root Hash Request (0x%02x)", opcode); - offset += 1; - break; - - case EDONKEY_MSG_FILE_STATUS: - partcount = tvb_get_letohs(tvb, offset+1); - arrlen = (partcount+7)/8; - - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 3+arrlen, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + offset += 8; + } - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "File Status (0x%02x)", opcode); - offset = dissect_edonkey_file_status(tvb, pinfo, offset+1, mp_tree); - break; - case EDONKEY_MSG_FILE_REQUEST_ANSWER: - namelen = tvb_get_letohs(tvb, offset+1); + while (offset<eoffset) { + opcode = tvb_get_guint8(tvb, offset); - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 3+namelen, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + switch (opcode) { + case EDONKEY_MSG_FILE_STATUS_REQUEST: + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "File Name (0x%02x)", opcode); - offset = dissect_edonkey_file_name(tvb, pinfo, offset+1, mp_tree); - break; - case EMULE_MSG_AICHFILEHASH_ANSWER: - ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 21, FALSE); - mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - - proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "AICH Root Hash (0x%02x)", opcode); - proto_tree_add_item(mp_tree, hf_emule_aich_root_hash, tvb, offset+1, 20, FALSE); - offset += 21; - break; + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "File Status Request (0x%02x)", opcode); + offset += 1; + break; + case EDONKEY_MSG_FILE_REQUEST: + partcount = 443; /* Invalid */ + sourcecount = 65536; /* Out of range */ + arrlen = 0; + oplen = 1; + + if (offset+2<eoffset) { + nextop = tvb_get_guint8(tvb, offset+1); + if (nextop!=EDONKEY_MSG_FILE_STATUS_REQUEST && + nextop!=EMULE_MSG_SOURCES_REQUEST && + nextop!=EMULE_MSG_AICHFILEHASH_REQUEST) { + + partcount = tvb_get_letohs(tvb, offset+1); + if (partcount<=442) { + arrlen = (partcount+7)/8; + oplen += 2+arrlen; + + if (offset+2+arrlen+2<eoffset) { + nextop = tvb_get_guint8(tvb, offset+2+arrlen+1); + if (nextop!=EDONKEY_MSG_FILE_STATUS_REQUEST && + nextop!=EMULE_MSG_SOURCES_REQUEST && + nextop!=EMULE_MSG_AICHFILEHASH_REQUEST) { + + sourcecount = tvb_get_letohs(tvb, offset+2+arrlen+1); + oplen += 2; + } + } + } + } + } + + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, oplen, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "File Name Request (0x%02x)", opcode); + if (partcount<=442) { + dissect_edonkey_file_status(tvb, pinfo, offset+1, mp_tree); + if (sourcecount<65536) { + proto_tree_add_uint(mp_tree, hf_emule_source_count, tvb, offset+3+arrlen, 2, sourcecount); + } + } + offset += oplen; + break; + case EMULE_MSG_SOURCES_REQUEST: + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "Sources Request (0x%02x)", opcode); + offset += 1; + break; + case EMULE_MSG_AICHFILEHASH_REQUEST: + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 1, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); - default: - /* Unknown opcode means we can't continue parsing the stream */ - proto_tree_add_uint_format(tree, hf_emule_multipacket_opcode, tvb, offset, 1, - opcode, "Unknown MultiPacket opcode (0x%02x)", opcode); - return offset+1; + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "AICH Root Hash Request (0x%02x)", opcode); + offset += 1; + break; + + case EDONKEY_MSG_FILE_STATUS: + partcount = tvb_get_letohs(tvb, offset+1); + arrlen = (partcount+7)/8; + + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 3+arrlen, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "File Status (0x%02x)", opcode); + offset = dissect_edonkey_file_status(tvb, pinfo, offset+1, mp_tree); + break; + case EDONKEY_MSG_FILE_REQUEST_ANSWER: + namelen = tvb_get_letohs(tvb, offset+1); + + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 3+namelen, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "File Name (0x%02x)", opcode); + offset = dissect_edonkey_file_name(tvb, pinfo, offset+1, mp_tree); + break; + case EMULE_MSG_AICHFILEHASH_ANSWER: + ti = proto_tree_add_item(tree, hf_emule_multipacket_entry, tvb, offset, 21, FALSE); + mp_tree = proto_item_add_subtree(ti, ett_emule_multipacket); + + proto_tree_add_uint_format(mp_tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "AICH Root Hash (0x%02x)", opcode); + proto_tree_add_item(mp_tree, hf_emule_aich_root_hash, tvb, offset+1, 20, FALSE); + offset += 21; + break; + + default: + /* Unknown opcode means we can't continue parsing the stream */ + proto_tree_add_uint_format(tree, hf_emule_multipacket_opcode, tvb, offset, 1, + opcode, "Unknown MultiPacket opcode (0x%02x)", opcode); + return offset+1; + } } - } - return offset; + return offset; } /* Dissects the Overnet peer type */ @@ -1082,6 +1413,39 @@ static int dissect_overnet_peer(tvbuff_t *tvb, packet_info *pinfo _U_, return offset; } +static int dissect_kademlia_peertype(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* <Peer type> ::= 1bytes */ + proto_tree_add_item( tree, hf_kademlia_peertype, tvb, offset, 1, FALSE ); + return offset + 1; +} + + +/* Dissects the Kademlia peer */ +static int dissect_kademlia_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_kademlia_peer, tvb, offset, 16 + 4 + 4 + 1, FALSE); + + peer_tree = proto_item_add_subtree(ti, ett_overnet_peer); + + /* 16 */ + offset = dissect_edonkey_hash(tvb, pinfo, offset, peer_tree); + + /* 8 ( 4 ip + 2 tcp port + 2 udp port ) */ + offset = dissect_kademlia_address(tvb, pinfo, offset, peer_tree); + + /* 1 */ + offset = dissect_kademlia_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) @@ -1214,10 +1578,10 @@ static void dissect_edonkey_tcp_message(guint8 msg_type, case EDONKEY_MSG_HELLO: /* Client to Server: <Client Info> */ /* Client to Client: 0x10 <Client Info> <Server address> */ - /* If Hello is sent to server 0x10 before UserHash is skipped, + /* If Hello is sent to server 0x10 before UserHash is skipped, but UserHash might starts with 0x10. To decrease posibility of mistake, we check also 6th and 15h byte of UserHash - - they have constant value. The best way would be to process + they have constant value. The best way would be to process whole packet to check it. */ helloClient = (tvb_get_guint8(tvb, offset) == 0x10 && tvb_get_guint8(tvb, offset + 6) == 0x0E && tvb_get_guint8(tvb, offset + 15) == 0x6F); if (helloClient) { @@ -1286,12 +1650,12 @@ static void dissect_edonkey_tcp_message(guint8 msg_type, offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); break; - case EDONKEY_MSG_FOUND_SOURCES_OBFU: /* Found Sources: <File Hash> <SourceOBFU List> */ + case EDONKEY_MSG_FOUND_SOURCES_OBFU: /* Found Sources: <File Hash> <SourceOBFU List> */ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); - offset = dissect_emule_sourceOBFU_list(tvb, pinfo, offset, tree); - break; + offset = dissect_emule_sourceOBFU_list(tvb, pinfo, offset, tree); + break; - case EDONKEY_MSG_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */ + 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; @@ -1375,7 +1739,14 @@ static void dissect_edonkey_tcp_message(guint8 msg_type, proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length); break; } - return; + + if (offset < msg_end) { + int extra_bytes = msg_end - offset; + /* trailing garbage or broken packet */ + proto_tree_add_uint_format(tree, hf_edonkey_unparsed_data_length, tvb, offset, extra_bytes, extra_bytes, + "Trailing/Undecoded data: %d bytes", extra_bytes ); + } + return; } static void dissect_emule_tcp_message(guint8 msg_type, @@ -1396,8 +1767,8 @@ static void dissect_emule_tcp_message(guint8 msg_type, 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> */ + case EMULE_MSG_HELLO: /* eMule Info: <eMule Version> <Meta tag list> */ + case EMULE_MSG_HELLO_ANSWER: /* eMule Info 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); @@ -1422,14 +1793,16 @@ static void dissect_emule_tcp_message(guint8 msg_type, guint8 state = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "State: %u (%s needed)", state, (state == 0) ? "nothing is" : (state == 1) ? "signature is" : "public key and signature are"); offset++; - rndchallenge = tvb_get_letohl(tvb, offset); + rndchallenge = tvb_get_letohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Rndchallenge: %u", rndchallenge); offset += 4; break; } - case EMULE_MSG_PUBLIC_KEY: + + case EMULE_MSG_PUBLIC_KEY: /* Public Key: <1byte : len> <len bytes: pubkey> */ offset = dissect_edonkey_public_key(tvb, pinfo, offset, tree); + /* offset = dissect_emule_publickey(tvb, pinfo, offset, tree); */ break; case EMULE_MSG_SIGNATURE: @@ -1441,6 +1814,16 @@ static void dissect_emule_tcp_message(guint8 msg_type, } break; + + /* case EMULE_MSG_SIGNATURE: Public Key: <1byte : len> <len bytes: pubkey> */ + /* offset = dissect_emule_publickey(tvb, pinfo, offset, tree); */ + /* break; */ + + /* case EMULE_MSG_SECIDENTSTATE: Public Key: <1byte : len> <len bytes: pubkey> */ + /* offset = dissect_emule_secstate(tvb, pinfo, offset, tree); */ + /* offset = dissect_emule_challenge(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); @@ -1487,10 +1870,16 @@ static void dissect_emule_tcp_message(guint8 msg_type, } break; + case EMULE_MSG_CALLBACK: /* Callback: < hash ><hash> <uint16> */ + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + /* offset = dissect_edonkey_generic_uint16(tvb, pinfo, offset, tree, "uint16" ); */ + break; + case EMULE_MSG_AICH_REQUEST: /* AICH Request: <File Hash> <PartNum> <AICH Hash> */ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); partnum = tvb_get_letohs(tvb, offset); - proto_tree_add_uint(tree, hf_emule_aich_partnum, tvb, offset, 2, partnum); + proto_tree_add_uint(tree, hf_emule_aich_partnum, tvb, offset, 2, partnum); offset += 2; offset = dissect_emule_aich_root_hash(tvb, pinfo, offset, tree); break; @@ -1498,7 +1887,7 @@ static void dissect_emule_tcp_message(guint8 msg_type, case EMULE_MSG_AICH_ANSWER: /* AICH Answer: <File Hash> <PartNum> <AICH Hash> <AICH Hash List> */ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); partnum = tvb_get_letohs(tvb, offset); - proto_tree_add_uint(tree, hf_emule_aich_partnum, tvb, offset, 2, partnum); + proto_tree_add_uint(tree, hf_emule_aich_partnum, tvb, offset, 2, partnum); offset += 2; offset = dissect_emule_aich_root_hash(tvb, pinfo, offset, tree); offset = dissect_emule_aich_hash_list(tvb, pinfo, offset, tree); @@ -1514,10 +1903,10 @@ static void dissect_emule_tcp_message(guint8 msg_type, dissect_edonkey_tcp_message(msg_type, tvb, pinfo, offset, length, tree); break; } - return; + return; } -static void dissect_edonkey_udp_message(guint8 msg_type, +static int dissect_edonkey_udp_message(guint8 msg_type, tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int length, proto_tree *tree) { @@ -1528,11 +1917,11 @@ static void dissect_edonkey_udp_message(guint8 msg_type, guint32 chal; guint32 nusers, nfiles; - if (tree == NULL) return; + if (tree == NULL) return offset; bytes_remaining = tvb_reported_length_remaining(tvb, offset); if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; - if (length <= 0) return; + if (length <= 0) return offset; msg_start = offset; msg_end = offset + length; @@ -1549,28 +1938,28 @@ static void dissect_edonkey_udp_message(guint8 msg_type, break; case EDONKEY_MSG_UDP_GET_SERVER_INFO: /* Get Server Info: <Challenge> */ - if (length>=2) { - ischal = tvb_get_letohs(tvb, offset); - if (ischal==0xf0ff) { - chal = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); - offset += 4; - } else { - offset = dissect_edonkey_string(tvb, pinfo, offset, tree); - } - } + if (length>=2) { + ischal = tvb_get_letohs(tvb, offset); + if (ischal==0xf0ff) { + chal = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); + offset += 4; + } else { + offset = dissect_edonkey_string(tvb, pinfo, offset, tree); + } + } break; case EDONKEY_MSG_UDP_SERVER_INFO: /* Server Info: <String> <String>*/ - ischal = tvb_get_letohs(tvb, offset); - if (ischal==0xf0ff) { - chal = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); - offset = dissect_edonkey_metatag_list(tvb, pinfo, offset+4, tree); - } else { - offset = dissect_edonkey_string(tvb, pinfo, offset, tree); - offset = dissect_edonkey_string(tvb, pinfo, offset, tree); - } + ischal = tvb_get_letohs(tvb, offset); + if (ischal==0xf0ff) { + chal = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); + offset = dissect_edonkey_metatag_list(tvb, pinfo, offset+4, tree); + } else { + 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> */ @@ -1595,14 +1984,14 @@ static void dissect_edonkey_udp_message(guint8 msg_type, break; case EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST: /* Server Status Request: <guint32> */ - chal = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); + chal = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); offset += 4; - break; + break; case EDONKEY_MSG_UDP_SERVER_STATUS: /* Server Status: <guint32> <Nusers> <Nfiles> <Nusersmax> */ - chal = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); + chal = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Challenge: 0x%08x", chal); offset += 4; nusers = tvb_get_letohl(tvb, offset); nfiles = tvb_get_letohl(tvb, offset+4); @@ -1616,7 +2005,7 @@ static void dissect_edonkey_udp_message(guint8 msg_type, } break; - /* Overnet UDP Messages */ + /* 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); @@ -1633,7 +2022,7 @@ static void dissect_edonkey_udp_message(guint8 msg_type, break; case OVERNET_MSG_UDP_SEARCH_INFO: - /* Search Info: <Hash> <search type (guint8)> <min (guint16)> <max (guint16)>*/ + /* 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); @@ -1692,12 +2081,14 @@ static void dissect_edonkey_udp_message(guint8 msg_type, default: proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length); + offset+=length; break; } - return; + + return offset; } -static void dissect_emule_udp_message(guint8 msg_type, +static int dissect_emule_udp_message(guint8 msg_type, tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int length, proto_tree *tree) { @@ -1706,7 +2097,7 @@ static void dissect_emule_udp_message(guint8 msg_type, bytes_remaining = tvb_reported_length_remaining(tvb, offset); if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; - if (length <= 0) return; + if (length <= 0) return offset; msg_start = offset; msg_end = offset + length; @@ -1714,18 +2105,381 @@ static void dissect_emule_udp_message(guint8 msg_type, switch (msg_type) { case EMULE_MSG_UDP_REASKFILEPING: /* Reask File Ping: <File Hash> */ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree); + if ( offset + 2 < msg_end ) { + /* Udp version > 3 */ + offset = dissect_edonkey_file_status( tvb, pinfo, offset, tree ); + } + + if ( msg_end == offset + 2 ) { + /* Udp version > 2 */ + offset = dissect_edonkey_generic_uint16( tvb, pinfo, offset, tree, "Complete Sources" ); + } break; case EMULE_MSG_UDP_REASKACK: /* Reask ACK: <eMule Rank> */ + + if ( offset + 2 < msg_end ) { + /* Udp version > 3 */ + offset = dissect_edonkey_file_status( tvb, pinfo, offset, tree ); + } + rank = tvb_get_letohs(tvb, offset); proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank); + offset += 2; break; default: - dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree); + offset = dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree); + break; + } + return offset; +} + +static int dissect_kademlia_peer_list(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Peer", dissect_kademlia_peer ); +} + +static int dissect_kademlia_tag(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + guint8 type; + const gchar *str_type; + + type = tvb_get_guint8( tvb, offset ); + str_type = match_strval(type, kademlia_tag_types); + if (str_type == NULL) + str_type = "Unknown"; + + proto_tree_add_text( tree, tvb, offset, 1, "Type: %s", str_type ); + offset += 1; + + /* Read tagname */ + offset = dissect_kademlia_tagname( tvb, pinfo, offset, tree ); + + /* Switch on type */ + switch( type ) + { + case KADEMLIA_TAGTYPE_HASH: + offset = dissect_kademlia_hash( tvb, pinfo, offset, tree ); + break; + case KADEMLIA_TAGTYPE_STRING: + offset = dissect_edonkey_string( tvb, pinfo, offset, tree ); + break; + case KADEMLIA_TAGTYPE_UINT8: + proto_tree_add_item( tree, hf_kademlia_tag_uint8, tvb, offset, 1, TRUE); + offset += 1; + break; + case KADEMLIA_TAGTYPE_UINT16: + proto_tree_add_item( tree, hf_kademlia_tag_uint16, tvb, offset, 2, TRUE); + offset += 2; + break; + case KADEMLIA_TAGTYPE_UINT32: + proto_tree_add_item( tree, hf_kademlia_tag_uint32, tvb, offset, 4, TRUE); + offset += 4; + break; + case KADEMLIA_TAGTYPE_FLOAT32: + proto_tree_add_item( tree, hf_kademlia_tag_float, tvb, offset, 4, TRUE); + offset += 4; + break; + } + + return offset; +} + + +static int dissect_kademlia_publish_req_entry(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* Get the hash */ + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + /* Read all the kad tags */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Tag", dissect_kademlia_tag ); +} + + +static int dissect_kademlia_search_result(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + /* Get the hash */ + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + /* Read all the kad tags */ + return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Tag", dissect_kademlia_tag ); +} + +static int dissect_kademlia_search_expression_tree(tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + int op, item_start_offset; + proto_item* ti; + + item_start_offset = offset; + op = tvb_get_guint8(tvb, offset); + ti = proto_tree_add_text(tree, tvb, offset, 1, "SearchExp type: %x ", op); + ++offset; + tree = proto_item_add_subtree( ti, ett_kademlia_search_expression ); + switch( op ) { + case 0: /* Bool op */ + { + int boolop; + char* bool_op_label; + + proto_item_append_text( ti, "[BoolOp]" ); + + boolop = tvb_get_guint8(tvb, offset); + + switch( boolop ) { + case 0: /* AND */ + bool_op_label = "AND"; + break; + case 1: /* OR */ + bool_op_label = "OR"; + break; + case 2: /* NAND */ + bool_op_label = "NAND"; + break; + default: + bool_op_label = "Unknown"; + }; + proto_tree_add_text(tree, tvb, offset, 1, "Bool op: %x [%s]", boolop, bool_op_label ); + ++offset; + + /* Left */ + offset = dissect_kademlia_search_expression_tree( tvb, pinfo, offset, tree ); + /* Right */ + offset = dissect_kademlia_search_expression_tree( tvb, pinfo, offset, tree ); + + break; + } + + case 1: /* String */ + proto_item_append_text( ti, "[String]" ); + offset = dissect_kademlia_string( tvb, pinfo, offset, tree ); + break; + case 2: /* Meta Tag */ + proto_item_append_text( ti, "[MetaTag]" ); + /* tag value */ + offset = dissect_edonkey_string( tvb, pinfo, offset, tree ); + /* tag name */ + offset = dissect_kademlia_tagname( tvb, pinfo, offset, tree ); + break; + case 3: /* Min/Max - 32bit! */ + proto_item_append_text( ti, "[32bitOp]" ); + offset = dissect_edonkey_generic_uint32( tvb, pinfo, offset, tree, "Argument32" ); + offset = dissect_kademlia_search_condition( tvb, pinfo, offset, tree ); + /* tag name */ + offset = dissect_kademlia_tagname( tvb, pinfo, offset, tree ); + break; + case 8: /* Min/Max - 64bit! */ + proto_item_append_text( ti, "[64bitOp]" ); + offset = dissect_edonkey_generic_uint64( tvb, pinfo, offset, tree, "Argument64" ); + + offset = dissect_kademlia_search_condition( tvb, pinfo, offset, tree ); + /* tag name */ + offset = dissect_kademlia_tagname( tvb, pinfo, offset, tree ); + break; + default: + proto_tree_add_text(tree, tvb, offset, 1, "NOT DECODED op %x", op ); + } + proto_item_set_len( ti, offset - item_start_offset ); + return offset; +} + +static int dissect_kademlia2_prolog( tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + int kad_version; + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_tcp_port(tvb, pinfo, offset, tree); + + kad_version = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Kademlia Version: %d", kad_version ); + offset++; + + return offset; +} + +static int dissect_kademlia_uload( tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, proto_tree *tree) +{ + int uLoad; + uLoad = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "uLoad: %d", uLoad ); + return offset +1; + +} +static int dissect_kademlia_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; + + bytes_remaining = tvb_reported_length_remaining(tvb, offset); + if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining; + if (length <= 0) return offset; + + msg_start = offset; + msg_end = offset + length; + + switch (msg_type) { + case KADEMLIA_BOOTSTRAP_REQ:/* <PEER [25]> */ + case KADEMLIA_HELLO_REQ: + case KADEMLIA_HELLO_RES: + offset = dissect_kademlia_peer(tvb, pinfo, offset, tree); + break; + case KADEMLIA2_BOOTSTRAP_REQ: + offset = dissect_kademlia2_prolog( tvb, pinfo, offset, tree ); + break; + + case KADEMLIA2_HELLO_REQ: + case KADEMLIA2_HELLO_RES: + offset = dissect_kademlia2_prolog( tvb, pinfo, offset, tree ); + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Tags", dissect_kademlia_tag ); + break; + case KADEMLIA_BOOTSTRAP_RES: /* <CNT [2]> <PEER [25]>*(CNT) */ + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Peer", dissect_kademlia_peer ); + break; + case KADEMLIA2_BOOTSTRAP_RES: + offset = dissect_kademlia2_prolog( tvb, pinfo, offset, tree ); + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Peer", dissect_kademlia_peer ); + break; + + case KADEMLIA2_SEARCH_SOURCE_REQ: + { + guint16 startPos; + guint64 filesize; + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + /* start pos */ + startPos = tvb_get_letohs( tvb, offset ); + proto_tree_add_text(tree, tvb, offset, 2, "Start position: %d", startPos ); + offset +=2; + /* filesize */ + filesize = tvb_get_letoh64( tvb, offset ); + proto_tree_add_text(tree, tvb, offset, 8, "Filesize: %" G_GINT64_MODIFIER "u", filesize ); + offset +=8; + } + break; + + case KADEMLIA_SEARCH_NOTES_REQ: /* <HASH (key) [16]> */ + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + break; + + case KADEMLIA2_SEARCH_KEY_REQ: + case KADEMLIA2_SEARCH_NOTES_REQ: + + case KADEMLIA_PUBLISH_RES: + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + if (offset<msg_end) { + offset = dissect_kademlia_uload( tvb, pinfo, offset, tree ); + } + break; + case KADEMLIA2_PUBLISH_RES: + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_uload( tvb, pinfo, offset, tree ); + break; + + case KADEMLIA_REQ: /* <TYPE [1]> <HASH (target) [16]> <HASH (receiver) 16> */ + case KADEMLIA2_REQ: + { + int type; + type = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Type: %x", type ); + offset +=1; + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + } + break; + + case KADEMLIA_RES: /* <HASH (target) [16]> <CNT> <PEER [25]>*(CNT) */ + case KADEMLIA2_RES: + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_peer_list( tvb, pinfo, offset, tree ); + break; + + case KADEMLIA_FIREWALLED_RES: /* <IP (sender) [4]> */ + offset = dissect_kademlia_ip_address( tvb, pinfo, offset, tree ); + break; + + case KADEMLIA_FIREWALLED_REQ: /* <TCPPORT (sender) [2]> */ + offset = dissect_kademlia_port( tvb, pinfo, offset, tree ); + break; + case KADEMLIA_CALLBACK_REQ: + case KADEMLIA_FINDBUDDY_REQ: + case KADEMLIA_FINDBUDDY_RES: + /* buddy id */ + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + /* userid */ + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_tcp_port( tvb, pinfo, offset, tree ); break; + case KADEMLIA2_PUBLISH_SOURCE_REQ: + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_kademlia_hash(tvb, pinfo, offset, tree); + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Tag", dissect_kademlia_tag ); + break; + case KADEMLIA_SEARCH_REQ: + { + int restrictive; + /* Target (16bytes) */ + offset = dissect_kademlia_hash( tvb, pinfo, offset, tree ); + /* Restrictive (1 byte) 0/1 */ + restrictive = tvb_get_guint8(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 1, "Restrictive: %x", restrictive ); + offset +=1; + + if ( offset < msg_end && restrictive ) + offset = dissect_kademlia_search_expression_tree( tvb, pinfo, offset, tree ); + } + break; + case KADEMLIA_SEARCH_RES: + /* Target */ + offset = dissect_kademlia_hash( tvb, pinfo, offset, tree ); + /* Results list */ + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Result", dissect_kademlia_search_result ); + break; + case KADEMLIA2_PUBLISH_KEY_REQ: + case KADEMLIA_PUBLISH_REQ: /* 0x40 // <HASH (key) [16]> <CNT1 [2]> (<HASH (target) [16]> <CNT2 [2]> <META>*(CNT2))*(CNT1) */ + { + /* Target */ + offset = dissect_kademlia_hash( tvb, pinfo, offset, tree ); + /* Results list */ + offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "StuffToPublish", dissect_kademlia_publish_req_entry ); + break; + } + } + + return offset; +} + +static int dissect_kademlia_udp_compressed_message(guint8 msg_type, + tvbuff_t *tvb, packet_info *pinfo _U_, + int offset, int length, proto_tree *tree) +{ + tvbuff_t *tvbraw = NULL; + + + tvbraw = tvb_uncompress(tvb, offset, length); + + if (tvbraw) { + proto_item *ti; + proto_tree *emule_zlib_tree; + guint32 raw_length; + + ti = proto_tree_add_item( tree, hf_emule_zlib, tvb, offset, length, FALSE); + raw_length = tvb_length( tvbraw ); + proto_item_set_text( ti, "Compressed Data ( PackedLen: %d UnpackedLen: %d )", length, raw_length ); + + emule_zlib_tree = proto_item_add_subtree(ti, ett_emule_zlib); + tvb_set_child_real_data_tvbuff(tvb, tvbraw); + add_new_data_source(pinfo, tvbraw, "Decompressed Data"); + + dissect_kademlia_udp_message( msg_type, tvbraw, pinfo, 0, raw_length, emule_zlib_tree ); + offset += length; + } else { + proto_tree_add_text( tree, tvb, offset, length, "Broken Compressed data (%d bytes)", length); } - return; + return offset; } @@ -1788,7 +2542,7 @@ static void dissect_edonkey_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tre 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); + "Protocol: %s (0x%02x)", protocol_name, protocol); proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len); } @@ -1822,17 +2576,17 @@ static void dissect_edonkey_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tre break; case EDONKEY_PROTO_EMULE_COMP: - /* - * These ought to be exactly the same as standard eDonkey (0xe5) messages, - * except that the payload (after the type byte) is a zlib compressed - * stream. - */ + /* + * These ought to be exactly the same as standard eDonkey (0xe5) messages, + * except that the payload (after the type byte) is a zlib compressed + * stream. + */ message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"); - tvbraw = tvb_uncompress(tvb, offset+1, msg_len-1); - if (tvbraw) { - dissector = dissect_edonkey_tcp_message; - break; - } + tvbraw = tvb_uncompress(tvb, offset+1, msg_len-1); + if (tvbraw) { + dissector = dissect_edonkey_tcp_message; + break; + } default: message_name = "Unknown"; @@ -1848,25 +2602,25 @@ static void dissect_edonkey_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tre 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)) { - if (!tvbraw) { - (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree); - } else { - ti = proto_tree_add_item(edonkey_msg_tree, hf_emule_zlib, tvb, - offset+1, msg_len-1, FALSE); - emule_zlib_tree = proto_item_add_subtree(ti, ett_emule_zlib); - tvb_set_child_real_data_tvbuff(tvb, tvbraw); - add_new_data_source(pinfo, tvbraw, "Decompressed Data"); - (*dissector)(msg_type, tvbraw, pinfo, 0, tvb_length(tvbraw), emule_zlib_tree); - } - } + if (dissector && (msg_len > 1)) { + if (!tvbraw) { + (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree); + } else { + ti = proto_tree_add_item(edonkey_msg_tree, hf_emule_zlib, tvb, + offset+1, msg_len-1, FALSE); + emule_zlib_tree = proto_item_add_subtree(ti, ett_emule_zlib); + tvb_set_child_real_data_tvbuff(tvb, tvbraw); + add_new_data_source(pinfo, tvbraw, "Decompressed Data"); + (*dissector)(msg_type, tvbraw, pinfo, 0, tvb_length(tvbraw), emule_zlib_tree); + } + } } } static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { if (check_col(pinfo->cinfo, COL_INFO)) - col_clear(pinfo->cinfo, COL_INFO); + col_clear(pinfo->cinfo, COL_INFO); tcp_dissect_pdus(tvb, pinfo, tree, edonkey_desegment, EDONKEY_TCP_HEADER_LENGTH, get_edonkey_tcp_pdu_len, @@ -1898,200 +2652,266 @@ static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t 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 (protocol == EDONKEY_PROTO_KADEMLIA || protocol == EDONKEY_PROTO_KADEMLIA_COMP + || protocol == EDONKEY_PROTO_ADU_KADEMLIA || protocol == EDONKEY_PROTO_ADU_KADEMLIA_COMP) + message_name = val_to_str( msg_type, kademlia_msgs, "Unknown"); + else + 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) { + guint32 remainingLength, extraBytes; + 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, + 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, + 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; + remainingLength = tvb_length_remaining( tvb, offset ); switch (protocol) { case EDONKEY_PROTO_EDONKEY: - dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree); + offset = dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, remainingLength, edonkey_msg_tree); break; case EDONKEY_PROTO_EMULE_EXT: - dissect_emule_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree); + offset = dissect_emule_udp_message(msg_type, tvb, pinfo, offset, remainingLength, edonkey_msg_tree); + break; + + case EDONKEY_PROTO_ADU_KADEMLIA: + case EDONKEY_PROTO_KADEMLIA: + offset = dissect_kademlia_udp_message(msg_type, tvb, pinfo, offset, remainingLength, edonkey_msg_tree); + break; + + case EDONKEY_PROTO_ADU_KADEMLIA_COMP: + case EDONKEY_PROTO_KADEMLIA_COMP: + offset = dissect_kademlia_udp_compressed_message(msg_type, tvb, pinfo, offset, remainingLength, edonkey_msg_tree); break; default: break; } + + extraBytes = tvb_length_remaining( tvb, offset ); + + if ( extraBytes > 0 ) { + /* trailing garbage or broken packet */ + proto_tree_add_uint_format(tree, hf_edonkey_unparsed_data_length, tvb, offset, extraBytes, extraBytes, + "Trailing/Undecoded data: %d bytes", extraBytes ); + } } } } void proto_register_edonkey(void) { - static hf_register_info hf[] = { + static hf_register_info hf[] = { { &hf_edonkey_message, - { "eDonkey Message", "edonkey.message", - FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } }, + { "eDonkey Message", "edonkey.message", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } }, { &hf_edonkey_protocol, - { "Protocol", "edonkey.protocol", - FT_UINT8, BASE_HEX, VALS(edonkey_protocols), 0, "eDonkey Protocol", HFILL } }, + { "Protocol", "edonkey.protocol", + FT_UINT8, BASE_HEX, VALS(edonkey_protocols), 0, "eDonkey Protocol", HFILL } }, { &hf_edonkey_message_length, - { "Message Length", "edonkey.message.length", - FT_UINT32, BASE_DEC, NULL, 0, "eDonkey Message Length", HFILL } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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 } }, + { "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_part_count, - { "Part Count", "edonkey.part_count", - FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Part Count", HFILL } }, - { &hf_edonkey_file_status, - { "File Status", "edonkey.file_status", - FT_BYTES, BASE_HEX, NULL, 0, "eDonkey File Status", HFILL } }, + { "String Length", "edonkey.string_length", + FT_UINT16, BASE_DEC, NULL, 0, "eDonkey String Length", HFILL } }, + { &hf_edonkey_part_count, + { "Part Count", "edonkey.part_count", + FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Part Count", HFILL } }, + { &hf_edonkey_file_status, + { "File Status", "edonkey.file_status", + FT_BYTES, BASE_HEX, NULL, 0, "eDonkey File Status", HFILL } }, { &hf_edonkey_directory, - { "Directory", "edonkey.directory", - FT_STRING, BASE_NONE, NULL, 0, "eDonkey Directory", HFILL } }, + { "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 } }, + { "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 } }, + { "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_emule_public_key, - { "Public Key", "emule.public_key", - FT_BYTES, BASE_HEX, NULL, 0, "eMule Public Key", HFILL } }, - { &hf_emule_signature, - { "Signature", "emule.signature", - FT_BYTES, BASE_HEX, NULL, 0, "eMule Signature", HFILL } }, - { &hf_emule_aich_partnum, - { "Part Number", "emule.aich_partnum", - FT_UINT16, BASE_DEC, NULL, 0, "eMule AICH Part Number", HFILL } }, - { &hf_emule_aich_root_hash, - { "AICH Root Hash", "emule.aich_root_hash", - FT_BYTES, BASE_HEX, NULL, 0, "eMule AICH Root Hash", HFILL } }, - { &hf_emule_aich_hash_entry, - { "AICH Hash Entry", "emule_aich_hash_entry", - FT_NONE, BASE_NONE, NULL, 0, "eMule AICH Hash Entry", HFILL } }, - { &hf_emule_aich_hash_id, - { "AICH Hash ID", "emule.aich_hash_id", - FT_UINT16, BASE_HEX, NULL, 0, "eMule AICH Hash ID", HFILL } }, - { &hf_emule_aich_hash, - { "AICH Hash", "emule.aich_hash", - FT_BYTES, BASE_HEX, NULL, 0, "eMule AICH Hash", HFILL } }, - { &hf_emule_multipacket_entry, - { "eMule MultiPacket Entry", "emule.multipacket_entry", - FT_NONE, BASE_NONE, NULL, 0, "eMule MultiPacket Entry", HFILL } }, - { &hf_emule_multipacket_opcode, - { "MultiPacket Opcode", "emule.multipacket_opcode", - FT_UINT8, BASE_HEX, NULL, 0, "eMule MultiPacket Opcode", HFILL } }, - { &hf_emule_sourceOBFU, - {"Source", "edonkey.source", - FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Source", HFILL } }, - { &hf_emule_source_count, - { "Compeleted Sources Count", "emule.source_count", - FT_UINT16, BASE_DEC, NULL, 0, "eMule Completed Sources Count", HFILL } }, - { &hf_emule_zlib, - { "Compressed Data", "emule.zlib", - FT_NONE, BASE_NONE, NULL, 0, "eMule Compressed Data", HFILL } }, + { "eDonkey Client Info", "edonkey.clientinfo", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey Client Info", HFILL } }, + { &hf_emule_public_key, + { "Public Key", "emule.public_key", + FT_BYTES, BASE_HEX, NULL, 0, "eMule Public Key", HFILL } }, + { &hf_emule_signature, + { "Signature", "emule.signature", + FT_BYTES, BASE_HEX, NULL, 0, "eMule Signature", HFILL } }, + { &hf_emule_aich_partnum, + { "Part Number", "emule.aich_partnum", + FT_UINT16, BASE_DEC, NULL, 0, "eMule AICH Part Number", HFILL } }, + { &hf_emule_aich_root_hash, + { "AICH Root Hash", "emule.aich_root_hash", + FT_BYTES, BASE_HEX, NULL, 0, "eMule AICH Root Hash", HFILL } }, + { &hf_emule_aich_hash_entry, + { "AICH Hash Entry", "emule_aich_hash_entry", + FT_NONE, BASE_NONE, NULL, 0, "eMule AICH Hash Entry", HFILL } }, + { &hf_emule_aich_hash_id, + { "AICH Hash ID", "emule.aich_hash_id", + FT_UINT16, BASE_HEX, NULL, 0, "eMule AICH Hash ID", HFILL } }, + { &hf_emule_aich_hash, + { "AICH Hash", "emule.aich_hash", + FT_BYTES, BASE_HEX, NULL, 0, "eMule AICH Hash", HFILL } }, + { &hf_emule_multipacket_entry, + { "eMule MultiPacket Entry", "emule.multipacket_entry", + FT_NONE, BASE_NONE, NULL, 0, "eMule MultiPacket Entry", HFILL } }, + { &hf_emule_multipacket_opcode, + { "MultiPacket Opcode", "emule.multipacket_opcode", + FT_UINT8, BASE_HEX, NULL, 0, "eMule MultiPacket Opcode", HFILL } }, + { &hf_emule_sourceOBFU, + {"Source", "edonkey.source", + FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Source", HFILL } }, + { &hf_emule_source_count, + { "Compeleted Sources Count", "emule.source_count", + FT_UINT16, BASE_DEC, NULL, 0, "eMule Completed Sources Count", HFILL } }, + { &hf_emule_zlib, + { "Compressed Data", "emule.zlib", + FT_NONE, BASE_NONE, NULL, 0, "eMule Compressed Data", 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_emule_aichhash, - &ett_emule_multipacket, - &ett_emule_zlib, - &ett_overnet_peer, - &ett_emule_sourceOBFU - }; - module_t *edonkey_module; - - 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); - - edonkey_module = prefs_register_protocol(proto_edonkey, NULL); - prefs_register_bool_preference(edonkey_module, "desegment", - "Reassemble eDonkey messages spanning multiple TCP segments", - "Whether the eDonkey dissector should reassemble messages spanning multiple TCP segments." - " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", - &edonkey_desegment); + { "Overnet Peer", "overnet.peer", + FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } }, + + { &hf_kademlia_peertype, + { "Kademlia PeerType", "kademlia.peer.type", + FT_UINT8, BASE_DEC, NULL, 0, "Kademlia Peer Type", HFILL } }, + { &hf_kademlia_peer, + { "Kademlia Peer", "kademlia.peer", + FT_NONE, BASE_NONE, NULL, 0, "Kademlia Peer", HFILL } }, + { &hf_kademlia_tag_float, + { "Float Tag Peer", "kademlia.tag.float", + FT_FLOAT, BASE_NONE, NULL, 0, "Float Tag", HFILL } }, + { &hf_kademlia_tag_uint32, + { "UINT32 Tag Peer", "kademlia.tag.uint32", + FT_UINT32, BASE_DEC, NULL, 0, "UINT32 Tag", HFILL } }, + { &hf_kademlia_tag_uint16, + { "UINT16 Tag Peer", "kademlia.tag.uint16", + FT_UINT16, BASE_DEC, NULL, 0, "UINT16 Tag", HFILL } }, + { &hf_kademlia_tag_uint8, + { "UINT8 Tag Peer", "kademlia.tag.uint8", + FT_UINT8, BASE_DEC, NULL, 0, "UINT8 Tag", HFILL } }, + { &hf_kademlia_port, + { "Port", "kademlia.port", + FT_UINT16, BASE_DEC, NULL, 0, "Kademlia Port", HFILL } }, + { &hf_kademlia_ip, + { "IP", "kademlia.ip", + FT_IPv4, BASE_DEC, NULL, 0, "eDonkey IP", HFILL } }, + { &hf_kademlia_tcp_port, + { "TCP Port", "kademlia.tcp_port", + FT_UINT16, BASE_DEC, NULL, 0, "Kademlia TCP Port", HFILL } }, + { &hf_kademlia_unparsed_data_length, + { "Kademlia unparsed data length", "kademlia.unparsed", + FT_UINT16, BASE_DEC, NULL, 0, "Kademlia trailing data length", HFILL } }, + { &hf_edonkey_unparsed_data_length, + { "eDonkey unparsed data length", "edonkey.unparsed", + FT_UINT32, BASE_DEC, NULL, 0, "eDonkey trailing or unparsed data length", 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_emule_aichhash, + &ett_emule_multipacket, + &ett_emule_zlib, + &ett_overnet_peer, + &ett_emule_sourceOBFU, + &ett_edonkey_listitem, + &ett_kademlia_search_expression + }; + module_t *edonkey_module; + + 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); + + edonkey_module = prefs_register_protocol(proto_edonkey, NULL); + prefs_register_bool_preference(edonkey_module, "desegment", + "Reassemble eDonkey messages spanning multiple TCP segments", + "Whether the eDonkey dissector should reassemble messages spanning multiple TCP segments." + " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", + &edonkey_desegment); } 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_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); + } + +/* vim:set expandtab ts=2 cino=(0 :*/ diff --git a/epan/dissectors/packet-edonkey.h b/epan/dissectors/packet-edonkey.h index 3cb09fdc4e..e171c25a08 100644 --- a/epan/dissectors/packet-edonkey.h +++ b/epan/dissectors/packet-edonkey.h @@ -1,10 +1,13 @@ /* packet-edonkey.h * Declarations for edonkey dissection * Copyright 2003, Xuan Zhang <xz@aemail4u.com> + * Copyright 2007, Stefano Picerno <stefano.picerno@gmail.com> * 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 * + * Kademlia dissector based on source code inspection of aMule 2.1.3 and eMule 0.84b + * * $Id$ * * Wireshark - Network traffic analyzer @@ -28,7 +31,7 @@ void proto_register_edonkey(void); -#define EDONKEY_MAX_SNAP_SIZE 1500 +#define EDONKEY_MAX_SNAP_SIZE 1500 #define EDONKEY_TCP_HEADER_LENGTH 5 #define EDONKEY_UDP_HEADER_LENGTH 2 @@ -52,7 +55,7 @@ void proto_register_edonkey(void); #define EDONKEY_MSG_CLIENT_CB_REQ 0x1c /* define EDONKEY_MSG_UNKNOWN 0x20 */ #define EDONKEY_MSG_MORE_RESULTS 0x21 -#define EDONKEY_MSG_GET_SOURCES_OBFU 0x23 +#define EDONKEY_MSG_GET_SOURCES_OBFU 0x23 #define EDONKEY_MSG_SERVER_LIST 0x32 #define EDONKEY_MSG_SEARCH_FILE_RESULTS 0x33 #define EDONKEY_MSG_SERVER_STATUS 0x34 @@ -63,7 +66,7 @@ void proto_register_edonkey(void); #define EDONKEY_MSG_SERVER_INFO_DATA 0x41 #define EDONKEY_MSG_FOUND_SOURCES 0x42 #define EDONKEY_MSG_SEARCH_USER_RESULTS 0x43 -#define EDONKEY_MSG_FOUND_SOURCES_OBFU 0x44 +#define EDONKEY_MSG_FOUND_SOURCES_OBFU 0x44 /* Client <-> Client */ #define EDONKEY_MSG_HELLO_CLIENT 0x10 /* 0x01 0x10 */ @@ -103,13 +106,15 @@ void proto_register_edonkey(void); #define EMULE_MSG_HELLO_ANSWER 0x02 #define EMULE_MSG_DATA_COMPRESSED 0x40 #define EMULE_MSG_QUEUE_RANKING 0x60 +#define EMULE_MSG_FILE_DESC 0x61 #define EMULE_MSG_SOURCES_REQUEST 0x81 #define EMULE_MSG_SOURCES_ANSWER 0x82 #define EMULE_MSG_PUBLIC_KEY 0x85 #define EMULE_MSG_SIGNATURE 0x86 -#define EMULE_MSG_SEC_IDENT_STATE 0x87 +#define EMULE_MSG_SEC_IDENT_STATE 0x87 #define EMULE_MSG_MULTIPACKET 0x92 #define EMULE_MSG_MULTIPACKET_ANSWER 0x93 +#define EMULE_MSG_CALLBACK 0x99 #define EMULE_MSG_AICH_REQUEST 0x9b #define EMULE_MSG_AICH_ANSWER 0x9c #define EMULE_MSG_AICHFILEHASH_ANSWER 0x9d @@ -239,3 +244,165 @@ void proto_register_edonkey(void); /* EDONKEY SEARCH MIN/MAX */ #define EDONKEY_SEARCH_MIN 0x01 #define EDONKEY_SEARCH_MAX 0x02 + +/* KADEMLIA TAGS */ +#define KADEMLIA_TAGTYPE_HASH 0x01 +#define KADEMLIA_TAGTYPE_STRING 0x02 +#define KADEMLIA_TAGTYPE_UINT32 0x03 +#define KADEMLIA_TAGTYPE_FLOAT32 0x04 +#define KADEMLIA_TAGTYPE_BOOL 0x05 +#define KADEMLIA_TAGTYPE_BOOLARRAY 0x06 +#define KADEMLIA_TAGTYPE_BLOB 0x07 +#define KADEMLIA_TAGTYPE_UINT16 0x08 +#define KADEMLIA_TAGTYPE_UINT8 0x09 +#define KADEMLIA_TAGTYPE_BSOB 0x0A +#define KADEMLIA_TAGTYPE_UINT64 0x0B + +#define KADEMLIA_TAGTYPE_STR1 0x11 +#define KADEMLIA_TAGTYPE_STR2 0x12 +#define KADEMLIA_TAGTYPE_STR3 0x13 +#define KADEMLIA_TAGTYPE_STR4 0x14 +#define KADEMLIA_TAGTYPE_STR5 0x15 +#define KADEMLIA_TAGTYPE_STR6 0x16 +#define KADEMLIA_TAGTYPE_STR7 0x17 +#define KADEMLIA_TAGTYPE_STR8 0x18 +#define KADEMLIA_TAGTYPE_STR9 0x19 +#define KADEMLIA_TAGTYPE_STR10 0x1A +#define KADEMLIA_TAGTYPE_STR11 0x1B +#define KADEMLIA_TAGTYPE_STR12 0x1C +#define KADEMLIA_TAGTYPE_STR13 0x1D +#define KADEMLIA_TAGTYPE_STR14 0x1E +#define KADEMLIA_TAGTYPE_STR15 0x1F +#define KADEMLIA_TAGTYPE_STR16 0x20 +#define KADEMLIA_TAGTYPE_STR17 0x21 +#define KADEMLIA_TAGTYPE_STR18 0x22 +#define KADEMLIA_TAGTYPE_STR19 0x23 +#define KADEMLIA_TAGTYPE_STR20 0x24 +#define KADEMLIA_TAGTYPE_STR21 0x25 +#define KADEMLIA_TAGTYPE_STR22 0x26 + +#define KADEMLIA_TAG_MEDIA_ARTIST 0xD0 /* <string> */ +#define KADEMLIA_TAG_MEDIA_ALBUM 0xD1 /* <string> */ +#define KADEMLIA_TAG_MEDIA_TITLE 0xD2 /* <string> */ +#define KADEMLIA_TAG_MEDIA_LENGTH 0xD3 /* <uint32> !!! */ +#define KADEMLIA_TAG_MEDIA_BITRATE 0xD4 /* <uint32> */ +#define KADEMLIA_TAG_MEDIA_CODEC 0xD5 /* <string> */ +#define KADEMLIA_TAG_USER_COUNT 0xF4 /* <uint32> */ +#define KADEMLIA_TAG_FILE_COUNT 0xF5 /* <uint32> */ +#define KADEMLIA_TAG_FILECOMMENT 0xF6 /* <string> */ +#define KADEMLIA_TAG_FILERATING 0xF7 /* <uint8> */ +#define KADEMLIA_TAG_BUDDYHASH 0xF8 /* <string> */ +#define KADEMLIA_TAG_CLIENTLOWID 0xF9 /* <uint32> */ +#define KADEMLIA_TAG_SERVERPORT 0xFA /* <uint16> */ +#define KADEMLIA_TAG_SERVERIP 0xFB /* <uint32> */ +#define KADEMLIA_TAG_SOURCEUPORT 0xFC /* <uint16> */ +#define KADEMLIA_TAG_SOURCEPORT 0xFD /* <uint16> */ +#define KADEMLIA_TAG_SOURCEIP 0xFE /* <uint32> */ +#define KADEMLIA_TAG_SOURCETYPE 0xFF /* <uint8> */ + +#define EDONKEY_PROTO_ADU_KADEMLIA 0xA4 +#define EDONKEY_PROTO_ADU_KADEMLIA_COMP 0xA5 + +#define EDONKEY_PROTO_KADEMLIA 0xE4 +#define EDONKEY_PROTO_KADEMLIA_COMP 0xE5 + +/* KADEMLIA (opcodes) (udp) */ +#define KADEMLIA_BOOTSTRAP_REQ 0x00 /* <PEER (sender) [25]> */ +#define KADEMLIA2_BOOTSTRAP_REQ 0x01 /* */ + +#define KADEMLIA_BOOTSTRAP_RES 0x08 /* <CNT [2]> <PEER [25]>*(CNT) */ +#define KADEMLIA2_BOOTSTRAP_RES 0x09 /* */ + +#define KADEMLIA_HELLO_REQ 0x10 /* <PEER (sender) [25]> */ +#define KADEMLIA2_HELLO_REQ 0x11 /* */ + +#define KADEMLIA_HELLO_RES 0x18 /* <PEER (receiver) [25]> */ +#define KADEMLIA2_HELLO_RES 0x19 /* */ + +#define KADEMLIA_REQ 0x20 /* <TYPE [1]> <HASH (target) [16]> <HASH (receiver) 16> */ +#define KADEMLIA2_REQ 0x21 /* */ + +#define KADEMLIA_RES 0x28 /* <HASH (target) [16]> <CNT> <PEER [25]>*(CNT) */ +#define KADEMLIA2_RES 0x29 /* */ + +#define KADEMLIA_SEARCH_REQ 0x30 /* <HASH (key) [16]> <ext 0/1 [1]> <SEARCH_TREE>[ext] */ +/*#define UNUSED 0x31 Old Opcode, don't use. */ +#define KADEMLIA_SEARCH_NOTES_REQ 0x32 /* <HASH (key) [16]> */ +#define KADEMLIA2_SEARCH_KEY_REQ 0x33 /* */ +#define KADEMLIA2_SEARCH_SOURCE_REQ 0x34 /* */ +#define KADEMLIA2_SEARCH_NOTES_REQ 0x35 /* */ + +#define KADEMLIA_SEARCH_RES 0x38 /* <HASH (key) [16]> <CNT1 [2]> (<HASH (answer) [16]> <CNT2 [2]> <META>*(CNT2))*(CNT1) */ +/*#define UNUSED 0x39 Old Opcode, don't use. */ +#define KADEMLIA_SEARCH_NOTES_RES 0x3A /* <HASH (key) [16]> <CNT1 [2]> (<HASH (answer) [16]> <CNT2 [2]> <META>*(CNT2))*(CNT1) */ +#define KADEMLIA2_SEARCH_RES 0x3B /* */ + +#define KADEMLIA_PUBLISH_REQ 0x40 /* <HASH (key) [16]> <CNT1 [2]> (<HASH (target) [16]> <CNT2 [2]> <META>*(CNT2))*(CNT1) */ +/*#define UNUSED 0x41 Old Opcode, don't use. */ +#define KADEMLIA_PUBLISH_NOTES_REQ 0x42 /* <HASH (key) [16]> <HASH (target) [16]> <CNT2 [2]> <META>*(CNT2))*(CNT1) */ +#define KADEMLIA2_PUBLISH_KEY_REQ 0x43 /* */ +#define KADEMLIA2_PUBLISH_SOURCE_REQ 0x44 /* */ +#define KADEMLIA2_PUBLISH_NOTES_REQ 0x45 /* */ + +#define KADEMLIA_PUBLISH_RES 0x48 /* <HASH (key) [16]> */ +/*#define UNUSED 0x49 Old Opcode, don't use. */ +#define KADEMLIA_PUBLISH_NOTES_RES 0x4A /* <HASH (key) [16]> */ +#define KADEMLIA2_PUBLISH_RES 0x4B /* */ + +#define KADEMLIA_FIREWALLED_REQ 0x50 /* <TCPPORT (sender) [2]> */ +#define KADEMLIA_FINDBUDDY_REQ 0x51 /* <TCPPORT (sender) [2]> */ +#define KADEMLIA_CALLBACK_REQ 0x52 /* <TCPPORT (sender) [2]> */ + +#define KADEMLIA_FIREWALLED_RES 0x58 /* <IP (sender) [4]> */ +#define KADEMLIA_FIREWALLED_ACK_RES 0x59 /* (null) */ +#define KADEMLIA_FINDBUDDY_RES 0x5A /* <TCPPORT (sender) [2]> */ + +/* KADEMLIA (parameter) */ +#define KADEMLIA_FIND_VALUE 0x02 +#define KADEMLIA_STORE 0x04 +#define KADEMLIA_FIND_NODE 0x0B + +/* Kad search + some unused tags to mirror the ed2k ones. */ +#define KADEMLIA_TAG_FILENAME 0x01 /* <string> */ +#define KADEMLIA_TAG_FILESIZE 0x02 /* <uint32> */ +#define KADEMLIA_TAG_FILESIZE_HI 0x3A /* <uint32> */ +#define KADEMLIA_TAG_FILETYPE 0x03 /* <string> */ +#define KADEMLIA_TAG_FILEFORMAT 0x04 /* <string> */ +#define KADEMLIA_TAG_COLLECTION 0x05 +#define KADEMLIA_TAG_PART_PATH 0x06 /* <string> */ +#define KADEMLIA_TAG_PART_HASH 0x07 +#define KADEMLIA_TAG_COPIED 0x08 /* <uint32> */ +#define KADEMLIA_TAG_GAP_START 0x09 /* <uint32> */ +#define KADEMLIA_TAG_GAP_END 0x0A /* <uint32> */ +#define KADEMLIA_TAG_DESCRIPTION 0x0B /* <string> */ +#define KADEMLIA_TAG_PING 0x0C +#define KADEMLIA_TAG_FAIL 0x0D +#define KADEMLIA_TAG_PREFERENCE 0x0E +#define KADEMLIA_TAG_PORT 0x0F +#define KADEMLIA_TAG_IP_ADDRESS 0x10 +#define KADEMLIA_TAG_VERSION 0x11 /* <string> */ +#define KADEMLIA_TAG_TEMPFILE 0x12 /* <string> */ +#define KADEMLIA_TAG_PRIORITY 0x13 /* <uint32> */ +#define KADEMLIA_TAG_STATUS 0x14 /* <uint32> */ +#define KADEMLIA_TAG_SOURCES 0x15 /* <uint32> */ +#define KADEMLIA_TAG_PERMISSIONS 0x16 +#define KADEMLIA_TAG_QTIME 0x16 +#define KADEMLIA_TAG_PARTS 0x17 +#define KADEMLIA_TAG_MEDIA_ARTIST 0xD0 /* <string> */ +#define KADEMLIA_TAG_MEDIA_ALBUM 0xD1 /* <string> */ +#define KADEMLIA_TAG_MEDIA_TITLE 0xD2 /* <string> */ +#define KADEMLIA_TAG_MEDIA_LENGTH 0xD3 /* <uint32> !!! */ +#define KADEMLIA_TAG_MEDIA_BITRATE 0xD4 /* <uint32> */ +#define KADEMLIA_TAG_MEDIA_CODEC 0xD5 /* <string> */ +#define KADEMLIA_TAG_ENCRYPTION 0xF3 /* <uint8> */ +#define KADEMLIA_TAG_FILERATING 0xF7 /* <uint8> */ +#define KADEMLIA_TAG_BUDDYHASH 0xF8 /* <string> */ +#define KADEMLIA_TAG_CLIENTLOWID 0xF9 /* <uint32> */ +#define KADEMLIA_TAG_SERVERPORT 0xFA /* <uint16> */ +#define KADEMLIA_TAG_SERVERIP 0xFB /* <uint32> */ +#define KADEMLIA_TAG_SOURCEUPORT 0xFC /* <uint16> */ +#define KADEMLIA_TAG_SOURCEPORT 0xFD /* <uint16> */ +#define KADEMLIA_TAG_SOURCEIP 0xFE /* <uint32> */ +#define KADEMLIA_TAG_SOURCETYPE 0xFF /* <uint8> */ + + |