2 * Routines for edonkey dissection
3 * Copyright 2003, Xuan Zhang <xz@aemail4u.com>
4 * eDonkey dissector based on protocol descriptions from mldonkey:
5 * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/edonkey-protocol.txt
6 * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/overnet-protocol.txt
8 * $Id: packet-edonkey.c,v 1.1 2003/07/16 21:13:48 guy Exp $
10 * Ethereal - Network traffic analyzer
11 * By Gerald Combs <gerald@ethereal.com>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
40 #include "packet-edonkey.h"
42 static int proto_edonkey = -1;
44 static int hf_edonkey_message = -1;
45 static int hf_edonkey_protocol = -1;
46 static int hf_edonkey_message_length = -1;
47 static int hf_edonkey_message_type = -1;
48 static int hf_edonkey_client_hash = -1;
49 static int hf_edonkey_server_hash = -1;
50 static int hf_edonkey_file_hash = -1;
51 static int hf_edonkey_client_id = -1;
52 static int hf_edonkey_metatag_namesize = -1;
53 static int hf_edonkey_metatag_type = -1;
54 static int hf_edonkey_metatag = -1;
55 static int hf_edonkey_metatag_name = -1;
56 static int hf_edonkey_metatag_id = -1;
57 static int hf_edonkey_search = -1;
58 static int hf_edonkey_ip = -1;
59 static int hf_edonkey_port = -1;
60 static int hf_edonkey_hash = -1;
61 static int hf_edonkey_directory = -1;
62 static int hf_edonkey_string = -1;
63 static int hf_edonkey_string_length = -1;
64 static int hf_edonkey_fileinfo = -1;
65 static int hf_edonkey_clientinfo = -1;
66 static int hf_edonkey_serverinfo = -1;
67 static int hf_overnet_peer = -1;
69 static gint ett_edonkey = -1;
70 static gint ett_edonkey_message = -1;
71 static gint ett_edonkey_metatag = -1;
72 static gint ett_edonkey_search = -1;
73 static gint ett_edonkey_fileinfo = -1;
74 static gint ett_edonkey_serverinfo = -1;
75 static gint ett_edonkey_clientinfo = -1;
76 static gint ett_overnet_peer = -1;
78 static const value_string edonkey_protocols[] = {
79 { EDONKEY_PROTO_EDONKEY, "eDonkey" },
80 { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" },
81 { EDONKEY_PROTO_EMULE_COMP, "eMule Compressed" },
85 static const value_string edonkey_tcp_msgs[] = {
86 { EDONKEY_MSG_HELLO, "Hello" },
87 { EDONKEY_MSG_BAD_PROTO, "Bad Proto" },
88 { EDONKEY_MSG_GET_SERVER_LIST, "Get Server List" },
89 { EDONKEY_MSG_OFFER_FILES, "Offer Files" },
90 { EDONKEY_MSG_SEARCH_FILES, "Search Files" },
91 { EDONKEY_MSG_DISCONNECT, "Disconnect" },
92 { EDONKEY_MSG_GET_SOURCES, "Get Sources" },
93 { EDONKEY_MSG_SEARCH_USER, "Search User" },
94 { EDONKEY_MSG_CLIENT_CB_REQ, "Client Callback Request" },
95 { EDONKEY_MSG_MORE_RESULTS, "More Results" },
96 { EDONKEY_MSG_SERVER_LIST, "Server List" },
97 { EDONKEY_MSG_SEARCH_FILE_RESULTS, "Search File Results" },
98 { EDONKEY_MSG_SERVER_STATUS, "Server Status" },
99 { EDONKEY_MSG_SERVER_CB_REQ, "Server Callback Request" },
100 { EDONKEY_MSG_CALLBACK_FAIL, "Callback Fail" },
101 { EDONKEY_MSG_SERVER_MESSAGE, "Server Message" },
102 { EDONKEY_MSG_ID_CHANGE, "ID Change" },
103 { EDONKEY_MSG_SERVER_INFO_DATA, "Server Info Data" },
104 { EDONKEY_MSG_FOUND_SOURCES, "Found Sources" },
105 { EDONKEY_MSG_SEARCH_USER_RESULTS, "Search User Results" },
106 { EDONKEY_MSG_SENDING_PART, "Sending Part" },
107 { EDONKEY_MSG_REQUEST_PARTS, "Request Parts" },
108 { EDONKEY_MSG_NO_SUCH_FILE, "No Such File" },
109 { EDONKEY_MSG_END_OF_DOWNLOAD, "End of Download" },
110 { EDONKEY_MSG_VIEW_FILES, "View Files" },
111 { EDONKEY_MSG_VIEW_FILES_ANSWER, "View Files Answer" },
112 { EDONKEY_MSG_HELLO_ANSWER, "Hello Answer" },
113 { EDONKEY_MSG_NEW_CLIENT_ID, "New Client ID" },
114 { EDONKEY_MSG_CLIENT_MESSAGE, "Client Message" },
115 { EDONKEY_MSG_FILE_STATUS_REQUEST, "File Status Request" },
116 { EDONKEY_MSG_FILE_STATUS, "File Status" },
117 { EDONKEY_MSG_HASHSET_REQUEST, "Hashset Request" },
118 { EDONKEY_MSG_HASHSET_ANSWER, "Hashset Answer" },
119 { EDONKEY_MSG_SLOT_REQUEST, "Slot Request" },
120 { EDONKEY_MSG_SLOT_GIVEN, "Slot Given" },
121 { EDONKEY_MSG_SLOT_RELEASE, "Slot Release" },
122 { EDONKEY_MSG_SLOT_TAKEN, "Slot Taken" },
123 { EDONKEY_MSG_FILE_REQUEST, "File Request" },
124 { EDONKEY_MSG_FILE_REQUEST_ANSWER, "File Request Answer" },
125 { EDONKEY_MSG_GET_SHARED_DIRS, "Get Shared Directories" },
126 { EDONKEY_MSG_GET_SHARED_FILES, "Get Shared Files" },
127 { EDONKEY_MSG_SHARED_DIRS, "Shared Directores" },
128 { EDONKEY_MSG_SHARED_FILES, "Shared Files" },
129 { EDONKEY_MSG_SHARED_DENIED, "Shared Denied" },
133 static const value_string emule_tcp_msgs[] = {
134 { EMULE_MSG_HELLO, "Hello" },
135 { EMULE_MSG_HELLO_ANSWER, "Hello Answer" },
136 { EMULE_MSG_DATA_COMPRESSED, "Data Compressed" },
137 { EMULE_MSG_QUEUE_RANKING, "Queue Ranking" },
138 { EMULE_MSG_SOURCES_REQUEST, "Sources Request" },
139 { EMULE_MSG_SOURCES_ANSWER, "Sources Answer" },
143 static const value_string edonkey_udp_msgs[] = {
144 { EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST, "Server Status Request" },
145 { EDONKEY_MSG_UDP_SERVER_STATUS, "Server Status" },
146 { EDONKEY_MSG_UDP_SEARCH_FILE, "Search File" },
147 { EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS, "Search File Results" },
148 { EDONKEY_MSG_UDP_GET_SOURCES, "Get Sources" },
149 { EDONKEY_MSG_UDP_FOUND_SOURCES, "Found Sources" },
150 { EDONKEY_MSG_UDP_CALLBACK_REQUEST, "Callback Request" },
151 { EDONKEY_MSG_UDP_CALLBACK_FAIL, "Callback Fail" },
152 { EDONKEY_MSG_UDP_SERVER_LIST, "Server List" },
153 { EDONKEY_MSG_UDP_GET_SERVER_INFO, "Get Server Info" },
154 { EDONKEY_MSG_UDP_SERVER_INFO, "Server Info" },
155 { EDONKEY_MSG_UDP_GET_SERVER_LIST, "Get Server List" },
157 /* eMule Extensions */
158 { EMULE_MSG_UDP_REASKFILEPING, "Reask File Ping" },
159 { EMULE_MSG_UDP_REASKACK, "Reask ACK" },
160 { EMULE_MSG_UDP_FILE_NOT_FOUND, "File not found" },
161 { EMULE_MSG_UDP_QUEUE_FULL, "Queue Full" },
163 /* Overnet Extensions */
164 { OVERNET_MSG_UDP_CONNECT, "Connect" },
165 { OVERNET_MSG_UDP_CONNECT_REPLY, "Connect Reply" },
166 { OVERNET_MSG_UDP_PUBLICIZE, "Publicize" },
167 { OVERNET_MSG_UDP_PUBLICIZE_ACK, "Publicize ACK" },
168 { OVERNET_MSG_UDP_SEARCH, "Search" },
169 { OVERNET_MSG_UDP_SEARCH_NEXT, "Search Next" },
170 { OVERNET_MSG_UDP_SEARCH_INFO, "Search Info" },
171 { OVERNET_MSG_UDP_SEARCH_RESULT, "Search Result" },
172 { OVERNET_MSG_UDP_SEARCH_END, "Search End" },
173 { OVERNET_MSG_UDP_PUBLISH, "Publish" },
174 { OVERNET_MSG_UDP_PUBLISH_ACK, "Publish ACK" },
175 { OVERNET_MSG_UDP_IDENTIFY_REPLY, "Identify Reply" },
176 { OVERNET_MSG_UDP_IDENTIFY_ACK, "Identify ACK" },
177 { OVERNET_MSG_UDP_FIREWALL_CONNECTION, "Firewall Connection" },
178 { OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK, "Firewall Connection ACK" },
179 { OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK, "Firewall Connection NACK" },
180 { OVERNET_MSG_UDP_IP_QUERY, "IP Query" },
181 { OVERNET_MSG_UDP_IP_QUERY_ANSWER, "IP Query Answer" },
182 { OVERNET_MSG_UDP_IP_QUERY_END, "IP Query End" },
183 { OVERNET_MSG_UDP_IDENTIFY, "Identify" },
187 static const value_string edonkey_special_tags[] = {
188 { EDONKEY_STAG_NAME, "Name" },
189 { EDONKEY_STAG_SIZE, "Size" },
190 { EDONKEY_STAG_TYPE, "Type" },
191 { EDONKEY_STAG_FORMAT, "Format" },
192 { EDONKEY_STAG_COLLECTION, "Collection" },
193 { EDONKEY_STAG_PART_PATH, "Part Path" },
194 { EDONKEY_STAG_PART_HASH, "Part Hash" },
195 { EDONKEY_STAG_COPIED, "Copied" },
196 { EDONKEY_STAG_GAP_START, "Gap Start" },
197 { EDONKEY_STAG_GAP_END, "Gap End" },
198 { EDONKEY_STAG_DESCRIPTION, "Description" },
199 { EDONKEY_STAG_PING, "Ping" },
200 { EDONKEY_STAG_FAIL, "Fail" },
201 { EDONKEY_STAG_PREFERENCE, "Preference" },
202 { EDONKEY_STAG_PORT, "Port" },
203 { EDONKEY_STAG_IP, "IP" },
204 { EDONKEY_STAG_VERSION, "Version" },
205 { EDONKEY_STAG_TEMPFILE, "Temporary File" },
206 { EDONKEY_STAG_PRIORITY, "Priority" },
207 { EDONKEY_STAG_STATUS, "Status" },
208 { EDONKEY_STAG_AVAILABILITY, "Availability" },
209 { EDONKEY_STAG_QTIME, "Queue Time" },
210 { EDONKEY_STAG_PARTS, "Parts" },
211 { EMULE_STAG_COMPRESSION, "Compression" },
212 { EMULE_STAG_UDP_CLIENT_PORT, "UDP Client Port" },
213 { EMULE_STAG_UDP_VERSION, "UDP Version" },
214 { EMULE_STAG_SOURCE_EXCHANGE, "Source Exchange" },
215 { EMULE_STAG_COMMENTS, "Comments" },
216 { EMULE_STAG_EXTENDED_REQUEST, "Extended Request" },
217 { EMULE_STAG_COMPATIBLE_CLIENT, "Compatible Client" },
221 static const value_string edonkey_search_ops[] = {
222 { EDONKEY_SEARCH_AND, "AND" },
223 { EDONKEY_SEARCH_OR, "OR" },
224 { EDONKEY_SEARCH_ANDNOT, "AND NOT" },
228 static const value_string edonkey_search_conds[] = {
229 { EDONKEY_SEARCH_MIN, "MIN" },
230 { EDONKEY_SEARCH_MAX, "MAX" },
234 /* Dissects a generic eDonkey list */
235 static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_,
236 int offset, proto_tree *tree,
237 int listnum_length, char* listdesc,
238 int (*item_dissector)(tvbuff_t *, packet_info *, int, proto_tree *))
240 /* <List> ::= <List Size> <Item>* */
242 switch (listnum_length) {
244 listnum = tvb_get_guint8(tvb, offset);
248 listnum = tvb_get_letohs(tvb, offset);
252 listnum = tvb_get_letohl(tvb, offset);
260 proto_tree_add_text(tree, tvb, offset, listnum_length, "%s List Size: %u", listdesc, listnum);
261 offset+=listnum_length;
262 for (i=0; i<listnum; i++)
264 offset = (*item_dissector)(tvb, pinfo, offset, tree);
269 gint lookup_str_index(gchar* str, gint length, const value_string *vs)
273 if (str == NULL) return -1;
275 while (vs[i].strptr) {
276 if (strncasecmp(str, vs[i].strptr, length) == 0)
284 static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint length, guint8 special_tagtype)
287 tag_name = match_strval(special_tagtype, edonkey_special_tags);
288 if (tag_name == NULL) {
290 tag_name = (guchar*) tvb_get_ptr(tvb, start, length);
291 index = lookup_str_index(tag_name, length, edonkey_special_tags);
293 return EDONKEY_STAG_UNKNOWN;
294 else return edonkey_special_tags[index].value;
296 else return special_tagtype;
298 return EDONKEY_STAG_UNKNOWN;
301 static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb,
302 gint start, gint length, guint8 special_tagtype)
305 tag_name = match_strval(special_tagtype, edonkey_special_tags);
306 if (tag_name == NULL) {
307 return proto_tree_add_item(tree, hf_edonkey_metatag_name, tvb, start, length, FALSE);
310 return proto_tree_add_uint_format(tree, hf_edonkey_metatag_id, tvb, start, length,
311 special_tagtype, "Meta Tag Name: %s (0x%02x)",
312 tag_name, special_tagtype);
316 /* Dissects the eDonkey meta tag */
317 static int dissect_edonkey_metatag(tvbuff_t *tvb, packet_info *pinfo _U_,
318 int offset, proto_tree *tree)
320 /* <Meta Tag> ::= <Tag Type (guint8)> <Tag Name> <Tag> */
321 /* <Tag Name> ::= <Tag Name Size (guint16)> <Special Tag> || <String> */
323 proto_tree *metatag_tree;
324 guint8 tag_type, special_tagtype;
325 guint16 tag_name_size, string_length;
326 guint32 tag_length, tag_value_guint32;
329 tag_type = tvb_get_guint8(tvb, offset);
330 tag_name_size = tvb_get_letohs(tvb, offset+1);
331 special_tagtype = tvb_get_guint8(tvb, offset+3);
333 tag_length = 3 + tag_name_size;
334 tag_offset = offset + tag_length;
338 case EDONKEY_MTAG_HASH:
341 ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
342 metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
343 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
344 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
345 edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
346 proto_tree_add_item(metatag_tree, hf_edonkey_hash, tvb, tag_offset, 16, FALSE);
349 case EDONKEY_MTAG_STRING:
350 /* <Tag> ::= <String> */
351 string_length = tvb_get_letohs(tvb, tag_offset);
352 tag_length += 2+string_length;
353 ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
354 metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
355 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
356 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
357 edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
358 proto_tree_add_uint(metatag_tree, hf_edonkey_string_length, tvb, tag_offset, 2, string_length);
359 proto_tree_add_item(metatag_tree, hf_edonkey_string, tvb, tag_offset+2, string_length, FALSE);
362 case EDONKEY_MTAG_DWORD:
363 /* <Tag> ::= guint32 */
365 ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
366 metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
367 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
368 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
369 edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
370 if (edonkey_metatag_name_get_type(tvb, offset+3, tag_name_size, special_tagtype) == EDONKEY_STAG_IP) {
371 proto_tree_add_item(metatag_tree, hf_edonkey_ip, tvb, tag_offset, 4, FALSE);
374 tag_value_guint32 = tvb_get_letohl(tvb, tag_offset);
375 proto_tree_add_text(metatag_tree, tvb, tag_offset, 4, "Meta Tag Value: %u", tag_value_guint32);
379 case EDONKEY_MTAG_FLOAT:
380 /* <Tag> ::= 4 byte float */
382 ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
383 metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
384 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
385 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
386 edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
389 case EDONKEY_MTAG_BOOL: /* <Tag> ::= Boolean ?? bytes*/
390 case EDONKEY_MTAG_BOOL_ARRAY: /* <Tag> ::= ?? */
391 case EDONKEY_MTAG_BLOB: /* <Tag> ::= ?? */
392 case EDONKEY_MTAG_UNKNOWN:
394 /* Unknown tag type - actual tag length is also unknown */
395 ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
396 metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
397 proto_tree_add_text(metatag_tree, tvb, offset, 1, "Unknown Meta Tag Type (0x%02x)", tag_type);
398 proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
399 edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
404 return offset + tag_length;
407 /* Dissects the eDonkey address */
408 static int dissect_edonkey_address(tvbuff_t *tvb, packet_info *pinfo _U_,
409 int offset, proto_tree *tree)
411 /* <Address> ::= <IP> <Port> */
412 /* guint32 ip = tvb_get_letohl(tvb, offset);
413 proto_tree_add_ipv4(tree, hf_edonkey_ip, tvb, offset, 4, ip); */
414 proto_tree_add_item(tree, hf_edonkey_ip, tvb, offset, 4, FALSE);
415 proto_tree_add_item(tree, hf_edonkey_port, tvb, offset+4, 2, TRUE);
419 /* Dissects the eDonkey address list */
420 static int dissect_edonkey_address_list(tvbuff_t *tvb, packet_info *pinfo _U_,
421 int offset, proto_tree *tree)
423 /* <Address List> ::= <List Size (guint8)> <Address>* */
424 return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Address", dissect_edonkey_address);
427 /* Dissects the eMule address list */
428 static int dissect_emule_address_list(tvbuff_t *tvb, packet_info *pinfo _U_,
429 int offset, proto_tree *tree)
431 /* <Address List> ::= <List Size (guint16)> <Address>* */
432 return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Address", dissect_edonkey_address);
435 /* Dissects the eDonkey hash */
436 static int dissect_edonkey_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
437 int offset, proto_tree *tree)
439 /* <hash> ::= HASH (16 word MD4 digest) */
440 proto_tree_add_item(tree, hf_edonkey_hash, tvb, offset, 16, FALSE);
445 /* Dissects the eDonkey hash list */
446 static int dissect_edonkey_hash_list(tvbuff_t *tvb, packet_info *pinfo _U_,
447 int offset, proto_tree *tree)
449 /* <Hash List> ::= <List Size (guint16)> <Hash>* */
450 return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Hash", dissect_edonkey_hash);
453 /* Dissects the eDonkey meta tag list */
454 static int dissect_edonkey_metatag_list(tvbuff_t *tvb, packet_info *pinfo _U_,
455 int offset, proto_tree *tree)
457 /* <Meta Tag List> ::= <List Size (guint32)> <Meta tag>* */
458 return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Meta Tag", dissect_edonkey_metatag);
461 /* Dissects the eDonkey String */
462 static int dissect_edonkey_string(tvbuff_t *tvb, packet_info *pinfo _U_,
463 int offset, proto_tree *tree)
465 /* <String> ::= <String length (guint16)> DATA */
466 guint16 string_length = tvb_get_letohs(tvb, offset);
467 proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length);
468 proto_tree_add_item(tree, hf_edonkey_string, tvb, offset+2, string_length, FALSE);
469 return offset+2+string_length;
472 /* Dissects the eDonkey Directory */
473 static int dissect_edonkey_directory(tvbuff_t *tvb, packet_info *pinfo _U_,
474 int offset, proto_tree *tree)
476 /* <Directory> ::= <String> */
477 guint16 string_length = tvb_get_letohs(tvb, offset);
478 proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length);
479 proto_tree_add_item(tree, hf_edonkey_directory, tvb, offset+2, string_length, FALSE);
480 return offset+2+string_length;
483 /* Dissects the eDonkey Filename */
484 static int dissect_edonkey_file_name(tvbuff_t *tvb, packet_info *pinfo _U_,
485 int offset, proto_tree *tree)
487 /* <Filename> ::= <String> */
488 return dissect_edonkey_string(tvb, pinfo, offset, tree);
491 /* Dissects the eDonkey directory list */
492 static int dissect_edonkey_directory_list(tvbuff_t *tvb, packet_info *pinfo _U_,
493 int offset, proto_tree *tree)
495 /* <Directory List> ::= <List Size (guint32)> <Directory>* */
496 return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Directory", dissect_edonkey_directory);
499 /* Dissects the eDonkey file hash */
500 static int dissect_edonkey_file_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
501 int offset, proto_tree *tree)
503 /* <File hash> ::= HASH (16 word MD4 digest) */
504 proto_tree_add_item(tree, hf_edonkey_file_hash, tvb, offset, 16, FALSE);
508 /* Dissects the eDonkey server hash */
509 static int dissect_edonkey_server_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
510 int offset, proto_tree *tree)
512 /* <Server hash> ::= HASH (16 word MD4 digest) */
513 proto_tree_add_item(tree, hf_edonkey_server_hash, tvb, offset, 16, FALSE);
517 /* Dissects the eDonkey client hash */
518 static int dissect_edonkey_client_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
519 int offset, proto_tree *tree)
521 /* <Client hash> ::= HASH (16 word MD4 digest) */
522 proto_tree_add_item(tree, hf_edonkey_client_hash, tvb, offset, 16, FALSE);
526 /* Dissects the eDonkey client ID */
527 static int dissect_edonkey_client_id(tvbuff_t *tvb, packet_info *pinfo _U_,
528 int offset, proto_tree *tree)
530 /* <Client ID> ::= guint32 */
531 /* guint32 ip = tvb_get_letohl(tvb, offset);
532 proto_tree_add_ipv4(tree, hf_edonkey_client_id, tvb, offset, 4, ip); */
533 proto_tree_add_item(tree, hf_edonkey_client_id, tvb, offset, 4, FALSE);
537 /* Dissects the eDonkey port */
538 static int dissect_edonkey_port(tvbuff_t *tvb, packet_info *pinfo _U_,
539 int offset, proto_tree *tree)
541 /* <Port> ::= guint16 */
542 proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
546 /* Dissects the eDonkey start offset */
547 static int dissect_edonkey_start_offset(tvbuff_t *tvb, packet_info *pinfo _U_,
548 int offset, proto_tree *tree)
550 /* <Start Offset> ::= guint32 */
551 guint32 start = tvb_get_letohl(tvb, offset);
552 proto_tree_add_text(tree, tvb, offset, 4, "Start Offset: %u", start);
556 /* Dissects the eDonkey end offset */
557 static int dissect_edonkey_end_offset(tvbuff_t *tvb, packet_info *pinfo _U_,
558 int offset, proto_tree *tree)
560 /* <End Offset> ::= guint32 */
561 guint32 end = tvb_get_letohl(tvb, offset);
562 proto_tree_add_text(tree, tvb, offset, 4, "End Offset: %u", end);
566 /* Dissects the eDonkey client info */
567 static int dissect_edonkey_client_info(tvbuff_t *tvb, packet_info *pinfo _U_,
568 int offset, proto_tree *tree)
570 /* <Client info> ::= <Client hash> <Client ID> <Port> <Meta tag list> */
572 proto_tree *clientinfo_tree;
573 /* Add subtree for client info */
574 ti = proto_tree_add_item(tree, hf_edonkey_clientinfo, tvb, offset, 0, FALSE);
575 clientinfo_tree = proto_item_add_subtree(ti, ett_edonkey_clientinfo);
576 offset = dissect_edonkey_client_hash(tvb, pinfo, offset, clientinfo_tree);
577 offset = dissect_edonkey_client_id(tvb, pinfo, offset, clientinfo_tree);
578 offset = dissect_edonkey_port(tvb, pinfo, offset, clientinfo_tree);
579 offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, clientinfo_tree);
583 /* Dissects the eDonkey client info list */
584 static int dissect_edonkey_client_info_list(tvbuff_t *tvb, packet_info *pinfo _U_,
585 int offset, proto_tree *tree)
587 /* <Client Info List> ::= <List Size (guint32)> <Client Info>* */
588 return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Client Info", dissect_edonkey_client_info);
591 /* Dissects the eDonkey server info */
592 static int dissect_edonkey_server_info(tvbuff_t *tvb, packet_info *pinfo _U_,
593 int offset, proto_tree *tree)
595 /* <Server info> ::= <Server hash> <Server Address> <Meta tag list> */
597 proto_tree *serverinfo_tree;
598 /* Add subtree for server info */
599 ti = proto_tree_add_item(tree, hf_edonkey_serverinfo, tvb, offset, 0, FALSE);
600 serverinfo_tree = proto_item_add_subtree(ti, ett_edonkey_serverinfo);
601 offset = dissect_edonkey_server_hash(tvb, pinfo, offset, serverinfo_tree);
602 offset = dissect_edonkey_address(tvb, pinfo, offset, serverinfo_tree);
603 offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, serverinfo_tree);
607 /* Dissects the eDonkey file info */
608 static int dissect_edonkey_file_info(tvbuff_t *tvb, packet_info *pinfo _U_,
609 int offset, proto_tree *tree)
611 /* <File info> ::= <File hash> <Client ID> <Port> <Meta tag list> */
613 proto_tree *fileinfo_tree;
614 /* Add subtree for file info */
615 ti = proto_tree_add_item(tree, hf_edonkey_fileinfo, tvb, offset, 0, FALSE);
616 fileinfo_tree = proto_item_add_subtree(ti, ett_edonkey_fileinfo);
617 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, fileinfo_tree);
618 offset = dissect_edonkey_client_id(tvb, pinfo, offset, fileinfo_tree);
619 offset = dissect_edonkey_port(tvb, pinfo, offset, fileinfo_tree);
620 offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, fileinfo_tree);
624 /* Dissects the eDonkey file info list */
625 static int dissect_edonkey_file_info_list(tvbuff_t *tvb, packet_info *pinfo _U_,
626 int offset, proto_tree *tree)
628 /* <File Info List> ::= <List Size (guint32)> <File Info>* */
629 return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "File Info", dissect_edonkey_file_info);
632 /* Dissects the Overnet peer type */
633 static int dissect_overnet_peertype(tvbuff_t *tvb, packet_info *pinfo _U_,
634 int offset, proto_tree *tree)
636 /* <Peer type> ::= guint8 */
637 guint8 peertype = tvb_get_guint8(tvb, offset);
638 proto_tree_add_text(tree, tvb, offset, 1, "Peer Type: %u", peertype);
642 /* Dissects the Overnet peer */
643 static int dissect_overnet_peer(tvbuff_t *tvb, packet_info *pinfo _U_,
644 int offset, proto_tree *tree)
646 /* <Peer> ::= <Hash> <Address> <Peer type> */
648 proto_tree *peer_tree;
649 ti = proto_tree_add_item(tree, hf_overnet_peer, tvb, offset, 16 + 6 + 1, FALSE);
650 peer_tree = proto_item_add_subtree(ti, ett_overnet_peer);
651 offset = dissect_edonkey_hash(tvb, pinfo, offset, peer_tree);
652 offset = dissect_edonkey_address(tvb, pinfo, offset, peer_tree);
653 offset = dissect_overnet_peertype(tvb, pinfo, offset, peer_tree);
657 /* Dissects the eDonkey search query */
658 static int dissect_edonkey_search_query(tvbuff_t *tvb, packet_info *pinfo _U_,
659 int offset, proto_tree *tree)
661 /* <Search Query> ::= <Search Type> <Search> */
663 proto_tree *search_tree;
664 guint8 search_type, operator, special_tagtype, limit_type;
665 guint16 tag_name_size, string_length;
666 guint32 search_length, limit;
667 int string_offset, tag_name_offset;
669 search_type = tvb_get_guint8(tvb, offset);
674 case EDONKEY_SEARCH_BOOL:
675 /* <Search> ::= <Operator> <Search Query> <Search Query> */
677 operator = tvb_get_guint8(tvb, offset+1);
679 /* Add subtree for search entry */
680 ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
681 search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
684 proto_tree_add_text(search_tree, tvb, offset, 2, "Boolean search (0x%02x): %s (0x%02x)",
685 search_type, val_to_str(operator, edonkey_search_ops, "Unknown"), operator);
688 offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
689 offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
692 case EDONKEY_SEARCH_NAME:
693 /* <Search> ::= <String> */
694 string_offset = offset + search_length;
695 string_length = tvb_get_letohs(tvb, string_offset);
696 search_length += 2+string_length;
698 /* Add subtree for search entry */
699 ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
700 search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
703 proto_tree_add_text(search_tree, tvb, offset, 1, "Search by name (0x%02x)", search_type);
704 proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length);
705 proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE);
706 offset += search_length;
709 case EDONKEY_SEARCH_META:
710 /* <Search> ::= <String> <Meta tag Name> */
711 string_offset = offset + search_length;
712 string_length = tvb_get_letohs(tvb, offset+1);
713 search_length += 2+string_length;
715 tag_name_offset = offset + search_length;
716 tag_name_size = tvb_get_letohs(tvb, tag_name_offset);
717 special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2);
718 search_length += 2 + tag_name_size;
720 /* Add subtree for search entry */
721 ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
722 search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
725 proto_tree_add_text(search_tree, tvb, offset, 1, "Search by metadata (0x%02x)", search_type);
726 proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length);
727 proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE);
728 proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size);
729 edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype);
730 offset += search_length;
733 case EDONKEY_SEARCH_LIMIT:
734 /* <Search> ::= <Limit (guint32)> <Minmax> <Meta tag Name> */
735 search_length += 5; /* 4 bytes for the limit, one for the minmax */
736 limit = tvb_get_letohl(tvb, offset+1);
737 limit_type = tvb_get_guint8(tvb, offset+5);
739 tag_name_offset = offset + search_length;
740 tag_name_size = tvb_get_letohs(tvb, tag_name_offset);
741 special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2);
742 search_length += 2 + tag_name_size;
744 /* Add subtree for search entry */
745 ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
746 search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
749 proto_tree_add_text(search_tree, tvb, offset, 6, "Search by limit (0x%02x): %s %u",
750 search_type, val_to_str(limit_type, edonkey_search_conds, "Unknown"), limit);
751 proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size);
752 edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype);
753 offset += search_length;
757 /* Unknown search type - actual search length is also unknown */
758 ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
759 search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
760 proto_tree_add_text(search_tree, tvb, offset, search_length, "Unknown Search (0x%02x)", search_type);
761 offset += search_length;
768 static void dissect_edonkey_tcp_message(guint8 msg_type,
769 tvbuff_t *tvb, packet_info *pinfo _U_,
770 int offset, int length, proto_tree *tree)
772 int msg_start, msg_end, bytes_remaining;
774 guint32 nusers, nfiles;
776 if (tree == NULL) return;
778 bytes_remaining = tvb_reported_length_remaining(tvb, offset);
779 if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
780 if (length <= 0) return;
783 msg_end = offset + length;
786 case EDONKEY_MSG_HELLO:
787 /* Client to Server: <Client Info> */
788 /* Client to Client: 0x10 <Client Info> */
789 hello = tvb_get_guint8(tvb, offset);
790 if (hello == 0x10) /* Hello Client */
792 offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree);
795 case EDONKEY_MSG_HELLO_ANSWER: /* Hello Answer: <Client Info> <Server address> */
796 offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree);
797 offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
800 case EDONKEY_MSG_SERVER_CB_REQ: /* Server Callback Request: <Client address> */
801 offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
804 case EDONKEY_MSG_SERVER_INFO_DATA: /* Server Info Data: <Server Info> */
805 offset = dissect_edonkey_server_info(tvb, pinfo, offset, tree);
808 case EDONKEY_MSG_SERVER_LIST: /* Server List: <Address List> */
809 offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
812 case EDONKEY_MSG_OFFER_FILES: /* Offer Files: <File info List> */
813 case EDONKEY_MSG_VIEW_FILES_ANSWER: /* View Files Answer: <File info list> */
814 offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
817 case EDONKEY_MSG_SEARCH_FILE_RESULTS: /* Search File Results: <File Info list> <More> */
818 offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
819 more = tvb_get_guint8(tvb, offset);
821 proto_tree_add_text(tree, tvb, offset, 1, "More: TRUE (0x%02x)", more);
822 else proto_tree_add_text(tree, tvb, offset, 1, "More: FALSE (0x%02x)", more);
825 case EDONKEY_MSG_SEARCH_FILES: /* Search File: <Search query> */
826 case EDONKEY_MSG_SEARCH_USER: /* Search User: <Search query> */
827 offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree);
830 case EDONKEY_MSG_GET_SOURCES: /* Get Sources: <File Hash> */
831 case EDONKEY_MSG_NO_SUCH_FILE: /* No Such File: <File Hash> */
832 case EDONKEY_MSG_END_OF_DOWNLOAD: /* End of Download: <File Hash> */
833 case EDONKEY_MSG_FILE_STATUS_REQUEST: /* File Status Request: <File Hash> */
834 case EDONKEY_MSG_HASHSET_REQUEST: /* Hashset Request: <File Hash> */
835 case EDONKEY_MSG_SLOT_REQUEST: /* Slot Request: <File Hash> */
836 case EDONKEY_MSG_FILE_REQUEST: /* File Request: <File Hash> */
837 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
840 case EDONKEY_MSG_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */
841 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
842 offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
845 case EDONKEY_MSG_CLIENT_CB_REQ: /* Client Callback Request: <Client ID> */
846 case EDONKEY_MSG_CALLBACK_FAIL: /* Callback Fail: <Client ID> */
847 case EDONKEY_MSG_ID_CHANGE: /* ID Change: <Client ID> */
848 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
851 case EDONKEY_MSG_NEW_CLIENT_ID: /* New Client ID: <Client ID> <Client ID> */
852 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
853 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
856 case EDONKEY_MSG_SERVER_MESSAGE: /* Server Message: <String> */
857 case EDONKEY_MSG_CLIENT_MESSAGE: /* Client Message: <String> */
858 offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
861 case EDONKEY_MSG_SERVER_STATUS: /* Server Status: <Nusers> <Nfiles> */
862 nusers = tvb_get_letohl(tvb, offset);
863 nfiles = tvb_get_letohl(tvb, offset+4);
864 proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers);
865 proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles);
868 case EDONKEY_MSG_FILE_REQUEST_ANSWER: /* File Request Answer: <File hash> <File name> */
869 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
870 offset = dissect_edonkey_file_name(tvb, pinfo, offset, tree);
873 case EDONKEY_MSG_REQUEST_PARTS: /* Request Parts: <File hash> <Start offset>(3) <End offset>(3) */
874 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
875 offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
876 offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
877 offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
878 offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
879 offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
880 offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
883 case EDONKEY_MSG_SENDING_PART: /* Sending Part: <File hash> <Start offset> <End offset> DATA */
884 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
885 offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
886 offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
887 if (msg_end > offset) {
888 bytes_remaining = msg_end - offset;
889 proto_tree_add_text(tree, tvb, offset, bytes_remaining, "Message Data (%d bytes)", bytes_remaining);
894 case EDONKEY_MSG_SEARCH_USER_RESULTS: /* Search User Results: <Client info list> */
895 offset = dissect_edonkey_client_info_list(tvb, pinfo, offset, tree);
898 case EDONKEY_MSG_GET_SHARED_FILES: /* Get Shared Files: <Directory> */
899 offset = dissect_edonkey_directory(tvb, pinfo, offset, tree);
902 case EDONKEY_MSG_SHARED_DIRS: /* Shared Dirs: <Directory List> */
903 offset = dissect_edonkey_directory_list(tvb, pinfo, offset, tree);
906 case EDONKEY_MSG_SHARED_FILES: /* Shared Files: <Directory> <File info list> */
907 offset = dissect_edonkey_directory(tvb, pinfo, offset, tree);
908 offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
911 case EDONKEY_MSG_HASHSET_ANSWER: /* Hashset Answer: <Hash List> */
912 offset = dissect_edonkey_hash_list(tvb, pinfo, offset, tree);
916 proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
922 static void dissect_emule_tcp_message(guint8 msg_type,
923 tvbuff_t *tvb, packet_info *pinfo _U_,
924 int offset, int length, proto_tree *tree)
926 int msg_start, msg_end, bytes_remaining;
927 guint32 packed_length;
928 guint16 version, rank;
930 if (tree == NULL) return;
932 bytes_remaining = tvb_reported_length_remaining(tvb, offset);
933 if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
934 if (length <= 0) return;
937 msg_end = offset + length;
940 case EMULE_MSG_HELLO: /* eMule Hello: <eMule Version> <Meta tag list> */
941 case EMULE_MSG_HELLO_ANSWER: /* eMule Hello Answer: <eMule Version> <Meta tag list> */
942 version = tvb_get_letohs(tvb, offset);
943 proto_tree_add_text(tree, tvb, offset, 2, "Version: %u", version);
944 offset = dissect_edonkey_metatag_list(tvb, pinfo, offset+2, tree);
947 case EMULE_MSG_QUEUE_RANKING: /* eMule Queue Ranking: <eMule Rank (guint16)> */
948 rank = tvb_get_letohs(tvb, offset);
949 proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank);
952 case EMULE_MSG_SOURCES_REQUEST: /* Sources Request: <File Hash> */
953 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
956 case EMULE_MSG_SOURCES_ANSWER: /* Sources Answer: <File Hash> <Address List> */
957 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
958 offset = dissect_emule_address_list(tvb, pinfo, offset, tree);
961 case EMULE_MSG_DATA_COMPRESSED: /* Data Compressed: <File Hash> <Start Offset> <Length (guint32)> <DATA> */
962 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
963 offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
964 packed_length = tvb_get_letohl(tvb, offset);
965 proto_tree_add_text(tree, tvb, offset, packed_length, "Packed Length: %u", packed_length);
967 if (msg_end > offset) {
968 bytes_remaining = msg_end - offset;
969 proto_tree_add_text(tree, tvb, offset, bytes_remaining,
970 "Compressed Message Data (%d bytes)", bytes_remaining);
975 dissect_edonkey_tcp_message(msg_type, tvb, pinfo, offset, length, tree);
981 static void dissect_edonkey_udp_message(guint8 msg_type,
982 tvbuff_t *tvb, packet_info *pinfo _U_,
983 int offset, int length, proto_tree *tree)
985 int msg_start, msg_end, bytes_remaining;
988 guint32 nusers, nfiles;
990 if (tree == NULL) return;
992 bytes_remaining = tvb_reported_length_remaining(tvb, offset);
993 if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
994 if (length <= 0) return;
997 msg_end = offset + length;
1000 /* EDonkey UDP Messages */
1001 case EDONKEY_MSG_UDP_CALLBACK_REQUEST: /* Callback Request: <Address> <Client ID> */
1002 offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
1003 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
1006 case EDONKEY_MSG_UDP_CALLBACK_FAIL: /* Callback Fail: <Client ID> */
1007 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
1010 case EDONKEY_MSG_UDP_SERVER_INFO: /* Server Info: <String> <String>*/
1011 offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
1012 offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
1015 case EDONKEY_MSG_UDP_SERVER_LIST: /* Server List: <Address List> */
1016 offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
1019 case EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS: /* Search File Result: <File Info> */
1020 offset = dissect_edonkey_file_info(tvb, pinfo, offset, tree);
1023 case EDONKEY_MSG_UDP_SEARCH_FILE: /* Search File: <Search query> */
1024 offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree);
1027 case EDONKEY_MSG_UDP_GET_SOURCES: /* Get Sources: <File Hash> */
1028 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1031 case EDONKEY_MSG_UDP_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */
1032 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1033 offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
1036 case EDONKEY_MSG_UDP_SERVER_STATUS: /* Server Status: <guint32> <Nusers> <Nfiles> <Nusersmax> */
1038 nusers = tvb_get_letohl(tvb, offset);
1039 nfiles = tvb_get_letohl(tvb, offset+4);
1040 proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers);
1041 proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles);
1043 if (offset < msg_end) {
1044 nusers = tvb_get_letohl(tvb, offset);
1045 proto_tree_add_text(tree, tvb, offset, 4, "Max number of Users: %u", nusers);
1050 /* Overnet UDP Messages */
1051 case OVERNET_MSG_UDP_CONNECT: /* Connect: <Peer (sender) > */
1052 case OVERNET_MSG_UDP_PUBLICIZE: /* Publicize: <Peer (sender) > */
1053 offset = dissect_overnet_peer(tvb, pinfo, offset, tree);
1056 case OVERNET_MSG_UDP_CONNECT_REPLY: /* Connect Reply: <guint16 Peer List> */
1057 offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Overnet Peer", dissect_overnet_peer);
1060 case OVERNET_MSG_UDP_SEARCH: /* Search: <search type (guint8)> <Hash> */
1061 type = tvb_get_guint8(tvb, offset);
1062 proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type);
1063 offset = dissect_edonkey_hash(tvb, pinfo, offset+1, tree);
1066 case OVERNET_MSG_UDP_SEARCH_INFO:
1067 /* Search Info: <Hash> <search type (guint8)> <min (guint16)> <max (guint16)>*/
1068 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1069 type = tvb_get_guint8(tvb, offset);
1070 min = tvb_get_letohs(tvb, offset+1);
1071 max = tvb_get_letohs(tvb, offset+3);
1072 proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type);
1073 proto_tree_add_text(tree, tvb, offset+1, 4, "Search Range: Min=%u Max=%u", min, max);
1076 case OVERNET_MSG_UDP_SEARCH_NEXT: /* Search Next: <Hash> <guint8 Peer List> */
1077 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1078 offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Overnet Peer", dissect_overnet_peer);
1081 case OVERNET_MSG_UDP_SEARCH_RESULT: /* Search Result: <Hash> <Hash> <Meta tag List> */
1082 case OVERNET_MSG_UDP_PUBLISH: /* Publish: <Hash> <Hash> <Meta tag List> */
1083 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1084 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1085 offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, tree);
1088 case OVERNET_MSG_UDP_SEARCH_END: /* Search End: <Hash> */
1089 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1092 case OVERNET_MSG_UDP_PUBLISH_ACK: /* Publish ACK: <File Hash> */
1093 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1096 case OVERNET_MSG_UDP_IP_QUERY: /* IP Query: <TCP Port> */
1097 proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
1100 case OVERNET_MSG_UDP_IP_QUERY_ANSWER: /* IP Query Answer: <IP> */
1101 offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
1104 case OVERNET_MSG_UDP_IDENTIFY_REPLY: /* Identify Reply: <Contact (sender)> */
1105 /* <Contact> ::= <Hash> <Address> */
1106 offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1107 offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
1110 case OVERNET_MSG_UDP_IDENTIFY_ACK: /* Identify Reply: <TCP Port (sender)> */
1111 proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
1114 case OVERNET_MSG_UDP_FIREWALL_CONNECTION: /* Firewall Connnection Ack: <Hash> <TCP Port> */
1115 offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree);
1116 proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
1119 case OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK: /* Firewall Connnection Ack: <Hash> */
1120 case OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK: /* Firewall Connnection NAck: <Hash> */
1121 offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree);
1125 proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
1131 static void dissect_emule_udp_message(guint8 msg_type,
1132 tvbuff_t *tvb, packet_info *pinfo _U_,
1133 int offset, int length, proto_tree *tree)
1135 int msg_start, msg_end, bytes_remaining;
1138 bytes_remaining = tvb_reported_length_remaining(tvb, offset);
1139 if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
1140 if (length <= 0) return;
1143 msg_end = offset + length;
1146 case EMULE_MSG_UDP_REASKFILEPING: /* Reask File Ping: <File Hash> */
1147 offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1150 case EMULE_MSG_UDP_REASKACK: /* Reask ACK: <eMule Rank> */
1151 rank = tvb_get_letohs(tvb, offset);
1152 proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank);
1156 dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree);
1162 static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1165 proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
1166 int offset, bytes, messages;
1167 guint8 protocol, msg_type;
1169 gchar *protocol_name, *message_name;
1170 void (*dissector)(guint8, tvbuff_t*, packet_info*, int, int, proto_tree*);
1172 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1173 col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
1175 if (check_col(pinfo->cinfo, COL_INFO))
1176 col_clear(pinfo->cinfo, COL_INFO);
1179 ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
1180 edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
1185 while (tvb_length_remaining(tvb, offset) >= EDONKEY_TCP_HEADER_LENGTH) {
1186 protocol = tvb_get_guint8(tvb, offset);
1187 msg_len = tvb_get_letohl(tvb, offset+1);
1189 protocol_name = match_strval(protocol, edonkey_protocols);
1190 if (protocol_name == NULL) {
1191 /* Not a recognized eDonkey protocol - probably a continuation */
1192 if (check_col(pinfo->cinfo, COL_INFO))
1193 col_add_str(pinfo->cinfo, COL_INFO, "eDonkey Continuation");
1195 bytes = tvb_length_remaining(tvb, offset);
1196 proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes);
1201 /* Add edonkey message tree */
1203 ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb,
1204 offset, EDONKEY_TCP_HEADER_LENGTH + msg_len, FALSE);
1205 edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message);
1207 proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol,
1208 "Protocol: %s (0x%02x)", protocol_name, protocol);
1209 proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len);
1213 /* Skip past the EDONKEY Header */
1214 offset += EDONKEY_TCP_HEADER_LENGTH;
1216 if(tvb_reported_length_remaining(tvb, offset) <= 0) {
1217 /* There is not enough space for the msg_type - mark as fragment */
1218 if (check_col(pinfo->cinfo, COL_INFO)) {
1220 col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP Message Fragment", protocol_name);
1221 else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP Message Fragment", protocol_name);
1226 if (check_col(pinfo->cinfo, COL_INFO)) {
1228 col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP", protocol_name);
1229 else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP", protocol_name);
1232 msg_type = tvb_get_guint8(tvb, offset);
1234 case EDONKEY_PROTO_EDONKEY:
1235 message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown");
1236 dissector = dissect_edonkey_tcp_message;
1239 case EDONKEY_PROTO_EMULE_EXT:
1240 message_name = val_to_str(msg_type, emule_tcp_msgs,
1241 val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"));
1242 dissector = dissect_emule_tcp_message;
1246 message_name = "Unknown";
1251 if (check_col(pinfo->cinfo, COL_INFO)) {
1252 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name);
1256 if (edonkey_msg_tree) {
1257 proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset, 1, msg_type,
1258 "Message Type: %s (0x%02x)", message_name, msg_type);
1259 if (dissector && (msg_len > 1))
1260 (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree);
1268 static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1271 proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
1273 guint8 protocol, msg_type;
1274 gchar *protocol_name, *message_name;
1276 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1277 col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
1279 if (check_col(pinfo->cinfo, COL_INFO))
1280 col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message");
1283 ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
1284 edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
1288 /* eDonkey UDP message - Assume that there is one message per packet */
1289 if (tvb_length_remaining(tvb, offset) >= EDONKEY_UDP_HEADER_LENGTH) {
1290 protocol = tvb_get_guint8(tvb, offset);
1291 msg_type = tvb_get_guint8(tvb, offset+1);
1292 protocol_name = val_to_str(protocol, edonkey_protocols, "Unknown");
1293 message_name = val_to_str(msg_type, edonkey_udp_msgs, "Unknown");
1295 if (check_col(pinfo->cinfo, COL_INFO)) {
1296 col_add_fstr(pinfo->cinfo, COL_INFO, "%s UDP: %s", protocol_name, message_name);
1300 ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, offset, -1, FALSE);
1301 edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message);
1303 proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol,
1304 "Protocol: %s (0x%02x)", protocol_name, protocol);
1305 proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset+1, 1, msg_type,
1306 "Message Type: %s (0x%02x)", message_name, msg_type);
1308 offset += EDONKEY_UDP_HEADER_LENGTH;
1311 case EDONKEY_PROTO_EDONKEY:
1312 dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree);
1315 case EDONKEY_PROTO_EMULE_EXT:
1316 dissect_emule_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree);
1326 void proto_register_edonkey(void) {
1328 static hf_register_info hf[] = {
1329 { &hf_edonkey_message,
1330 { "eDonkey Message", "edonkey.message",
1331 FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } },
1332 { &hf_edonkey_protocol,
1333 { "Protocol", "edonkey.protocol",
1334 FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Protocol", HFILL } },
1335 { &hf_edonkey_message_length,
1336 { "Message Length", "edonkey.message.length",
1337 FT_UINT32, BASE_DEC, NULL, 0, "eDonkey Message Length", HFILL } },
1338 { &hf_edonkey_message_type,
1339 { "Message Type", "edonkey.message.type",
1340 FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Message Type", HFILL } },
1341 { &hf_edonkey_client_hash,
1342 { "Client Hash", "edonkey.client_hash",
1343 FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Client Hash", HFILL } },
1344 { &hf_edonkey_server_hash,
1345 { "Server Hash", "edonkey.server_hash",
1346 FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Server Hash", HFILL } },
1347 { &hf_edonkey_file_hash,
1348 { "File Hash", "edonkey.file_hash",
1349 FT_BYTES, BASE_HEX, NULL, 0, "eDonkey File Hash", HFILL } },
1350 { &hf_edonkey_client_id,
1351 { "Client ID", "edonkey.clientid",
1352 FT_IPv4, BASE_DEC, NULL, 0, "eDonkey Client ID", HFILL } },
1354 { "IP", "edonkey.ip",
1355 FT_IPv4, BASE_DEC, NULL, 0, "eDonkey IP", HFILL } },
1357 { "Port", "edonkey.port",
1358 FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Port", HFILL } },
1359 { &hf_edonkey_metatag,
1360 { "eDonkey Meta Tag", "edonkey.metatag",
1361 FT_NONE, BASE_NONE, NULL, 0, "eDonkey Meta Tag", HFILL } },
1362 { &hf_edonkey_metatag_type,
1363 { "Meta Tag Type", "edonkey.metatag.type",
1364 FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag Type", HFILL } },
1365 { &hf_edonkey_metatag_id,
1366 { "Meta Tag ID", "edonkey.metatag.id",
1367 FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag ID", HFILL } },
1368 { &hf_edonkey_metatag_name,
1369 { "Meta Tag Name", "edonkey.metatag.name",
1370 FT_STRING, BASE_NONE, NULL, 0, "eDonkey Meta Tag Name", HFILL } },
1371 { &hf_edonkey_metatag_namesize,
1372 { "Meta Tag Name Size", "edonkey.metatag.namesize",
1373 FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Meta Tag Name Size", HFILL } },
1374 { &hf_edonkey_search,
1375 { "eDonkey Search", "edonkey.search",
1376 FT_NONE, BASE_NONE, NULL, 0, "eDonkey Search", HFILL } },
1378 { "Hash", "edonkey.hash",
1379 FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Hash", HFILL } },
1380 { &hf_edonkey_string,
1381 { "String", "edonkey.string",
1382 FT_STRING, BASE_NONE, NULL, 0, "eDonkey String", HFILL } },
1383 { &hf_edonkey_string_length,
1384 { "String Length", "edonkey.string_length",
1385 FT_UINT16, BASE_DEC, NULL, 0, "eDonkey String Length", HFILL } },
1386 { &hf_edonkey_directory,
1387 { "Directory", "edonkey.directory",
1388 FT_STRING, BASE_NONE, NULL, 0, "eDonkey Directory", HFILL } },
1389 { &hf_edonkey_fileinfo,
1390 { "eDonkey File Info", "edonkey.fileinfo",
1391 FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Info", HFILL } },
1392 { &hf_edonkey_serverinfo,
1393 { "eDonkey Server Info", "edonkey.serverinfo",
1394 FT_NONE, BASE_NONE, NULL, 0, "eDonkey Server Info", HFILL } },
1395 { &hf_edonkey_clientinfo,
1396 { "eDonkey Client Info", "edonkey.clientinfo",
1397 FT_NONE, BASE_NONE, NULL, 0, "eDonkey Client Info", HFILL } },
1399 { "Overnet Peer", "overnet.peer",
1400 FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } },
1403 static gint *ett[] = {
1405 &ett_edonkey_message,
1406 &ett_edonkey_metatag,
1407 &ett_edonkey_search,
1408 &ett_edonkey_fileinfo,
1409 &ett_edonkey_serverinfo,
1410 &ett_edonkey_clientinfo,
1414 proto_edonkey = proto_register_protocol("eDonkey Protocol", "EDONKEY", "edonkey");
1416 proto_register_field_array(proto_edonkey, hf, array_length(hf));
1418 proto_register_subtree_array(ett, array_length(ett));
1419 register_dissector("edonkey.tcp", dissect_edonkey_tcp, proto_edonkey);
1420 register_dissector("edonkey.udp", dissect_edonkey_udp, proto_edonkey);
1423 void proto_reg_handoff_edonkey(void) {
1424 dissector_handle_t edonkey_tcp_handle;
1425 dissector_handle_t edonkey_udp_handle;
1427 edonkey_tcp_handle = find_dissector("edonkey.tcp");
1428 edonkey_udp_handle = find_dissector("edonkey.udp");
1430 dissector_add("tcp.port", 4661, edonkey_tcp_handle);
1431 dissector_add("tcp.port", 4662, edonkey_tcp_handle);
1432 dissector_add("tcp.port", 4663, edonkey_tcp_handle);
1433 dissector_add("udp.port", 4665, edonkey_udp_handle);
1434 dissector_add("udp.port", 4672, edonkey_udp_handle);