From Yuriy Sidelnikov: handle the case where a presentation selector
[obnox/wireshark/wip.git] / packet-edonkey.c
1 /* packet-edonkey.c
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
7  *
8  * $Id: packet-edonkey.c,v 1.1 2003/07/16 21:13:48 guy Exp $
9  *
10  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
12  * Copyright 1998 Gerald Combs
13  *
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.
18  *
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.
23  *
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.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include "packet-edonkey.h"
41
42 static int proto_edonkey = -1;
43
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;
68
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;
77
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"         },
82     { 0,                                 NULL                       }
83 };
84
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"            },
130     { 0,                                 NULL                       }
131 };
132
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"           },
140     { 0,                                 NULL                       }
141 };
142
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"          },
156
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"               },
162
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"                 },
184     { 0,                                        NULL                       }
185 };
186
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"         },
218     { 0,                                NULL                        }
219 };
220
221 static const value_string edonkey_search_ops[] = {
222     { EDONKEY_SEARCH_AND,               "AND"                       },
223     { EDONKEY_SEARCH_OR,                "OR"                        },
224     { EDONKEY_SEARCH_ANDNOT,            "AND NOT"                   },
225     { 0,                                NULL                        }
226 };
227
228 static const value_string edonkey_search_conds[] = {
229     { EDONKEY_SEARCH_MIN,               "MIN"                       },
230     { EDONKEY_SEARCH_MAX,               "MAX"                       },
231     { 0,                                NULL                        }
232 };
233
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 *))
239 {
240     /* <List> ::= <List Size> <Item>* */
241     guint32 listnum, i;
242     switch (listnum_length) {
243         case 1: 
244             listnum = tvb_get_guint8(tvb, offset);
245             break;
246
247         case 2: 
248             listnum = tvb_get_letohs(tvb, offset);
249             break;
250
251         case 4: 
252             listnum = tvb_get_letohl(tvb, offset);
253             break;
254
255         default:
256             /* Not Supported */
257             return offset;
258     }
259
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++) 
263     {
264         offset = (*item_dissector)(tvb, pinfo, offset, tree);
265     }
266     return offset;
267 }
268
269 gint lookup_str_index(gchar* str, gint length, const value_string *vs) 
270 {
271   gint i = 0;
272
273   if (str == NULL) return -1;
274
275   while (vs[i].strptr) {
276       if (strncasecmp(str, vs[i].strptr, length) == 0)
277           return i;
278       i++;
279   }
280
281   return -1;
282 }
283
284 static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint length, guint8 special_tagtype) 
285 {
286         guchar  *tag_name;
287     tag_name = match_strval(special_tagtype, edonkey_special_tags);
288     if (tag_name == NULL) {
289         gint index;
290                 tag_name = (guchar*) tvb_get_ptr(tvb, start, length);
291         index = lookup_str_index(tag_name, length, edonkey_special_tags);
292         if (index < 0) 
293             return EDONKEY_STAG_UNKNOWN;
294         else return edonkey_special_tags[index].value;
295     }
296     else return special_tagtype;
297
298     return EDONKEY_STAG_UNKNOWN;
299 }
300
301 static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb,
302                                             gint start, gint length, guint8 special_tagtype)
303 {
304         gchar   *tag_name;
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);
308     }
309     else {
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);
313     }
314 }
315
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)
319 {
320     /* <Meta Tag> ::= <Tag Type (guint8)> <Tag Name> <Tag> */
321     /* <Tag Name> ::= <Tag Name Size (guint16)> <Special Tag> || <String> */
322     proto_item *ti;
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;
327     int tag_offset;
328
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);
332     
333     tag_length = 3 + tag_name_size;
334     tag_offset = offset + tag_length;
335     
336     switch (tag_type)
337     {        
338         case EDONKEY_MTAG_HASH:
339             /* <Tag> ::= HASH */
340             tag_length += 16;
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);
347             break;
348             
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);
360             break;
361
362         case EDONKEY_MTAG_DWORD:
363             /* <Tag> ::= guint32 */
364             tag_length += 4;
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);
372             }
373             else {
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);
376             }
377             break;
378
379         case EDONKEY_MTAG_FLOAT:
380             /* <Tag> ::=  4 byte float */
381             tag_length += 4;
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);
387             break;
388
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:
393         default:
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);
400             break;
401         
402     }
403     
404     return offset + tag_length;
405 }
406
407 /* Dissects the eDonkey address */
408 static int dissect_edonkey_address(tvbuff_t *tvb, packet_info *pinfo _U_, 
409                                    int offset, proto_tree *tree)
410 {
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);
416     return offset+6;
417 }
418
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)
422 {
423     /* <Address List> ::= <List Size (guint8)> <Address>* */
424     return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Address", dissect_edonkey_address);
425 }
426
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)
430 {
431     /* <Address List> ::= <List Size (guint16)> <Address>* */
432     return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Address", dissect_edonkey_address);
433 }
434
435 /* Dissects the eDonkey hash */
436 static int dissect_edonkey_hash(tvbuff_t *tvb, packet_info *pinfo _U_, 
437                                        int offset, proto_tree *tree)
438 {
439     /* <hash> ::= HASH (16 word MD4 digest) */
440     proto_tree_add_item(tree, hf_edonkey_hash, tvb, offset, 16, FALSE);
441     return offset+16;
442 }
443
444
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)
448 {
449     /* <Hash List> ::= <List Size (guint16)> <Hash>* */
450     return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Hash", dissect_edonkey_hash);
451 }
452
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)
456 {
457     /* <Meta Tag List> ::= <List Size (guint32)> <Meta tag>* */
458     return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Meta Tag", dissect_edonkey_metatag);
459 }
460
461 /* Dissects the eDonkey String */
462 static int dissect_edonkey_string(tvbuff_t *tvb, packet_info *pinfo _U_, 
463                                   int offset, proto_tree *tree)
464 {
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;
470 }
471
472 /* Dissects the eDonkey Directory */
473 static int dissect_edonkey_directory(tvbuff_t *tvb, packet_info *pinfo _U_, 
474                                      int offset, proto_tree *tree)
475 {
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;
481 }
482
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)
486 {
487     /* <Filename> ::= <String> */
488     return dissect_edonkey_string(tvb, pinfo, offset, tree);
489 }
490
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)
494 {
495     /* <Directory List> ::= <List Size (guint32)> <Directory>* */
496     return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Directory", dissect_edonkey_directory);
497 }
498
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)
502 {
503     /* <File hash> ::= HASH (16 word MD4 digest) */
504     proto_tree_add_item(tree, hf_edonkey_file_hash, tvb, offset, 16, FALSE);
505     return offset+16;
506 }
507
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)
511 {
512     /* <Server hash> ::= HASH (16 word MD4 digest) */
513     proto_tree_add_item(tree, hf_edonkey_server_hash, tvb, offset, 16, FALSE);
514     return offset+16;
515 }
516
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)
520 {
521     /* <Client hash> ::= HASH (16 word MD4 digest) */
522     proto_tree_add_item(tree, hf_edonkey_client_hash, tvb, offset, 16, FALSE);
523     return offset+16;
524 }
525
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)
529 {
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);
534     return offset+4;
535 }
536
537 /* Dissects the eDonkey port */
538 static int dissect_edonkey_port(tvbuff_t *tvb, packet_info *pinfo _U_, 
539                                 int offset, proto_tree *tree)
540 {
541     /* <Port> ::= guint16 */
542     proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
543     return offset+2;
544 }
545
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)
549 {
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);
553     return offset+4;
554 }
555
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)
559 {
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);
563     return offset+4;
564 }
565
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)
569 {
570     /* <Client info> ::= <Client hash> <Client ID> <Port> <Meta tag list> */
571     proto_item *ti;
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); 
580     return offset;
581 }
582
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)
586 {
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);
589 }
590
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)
594 {
595     /* <Server info> ::= <Server hash> <Server Address> <Meta tag list> */
596     proto_item *ti;
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); 
604     return offset;
605 }
606
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)
610 {
611     /* <File info> ::= <File hash> <Client ID> <Port> <Meta tag list> */
612     proto_item *ti;
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); 
621     return offset;
622 }
623
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)
627 {
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);
630 }
631
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)
635 {
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);
639     return offset+1;
640 }
641
642 /* Dissects the Overnet peer */
643 static int dissect_overnet_peer(tvbuff_t *tvb, packet_info *pinfo _U_, 
644                                 int offset, proto_tree *tree)
645 {
646     /* <Peer> ::= <Hash> <Address> <Peer type> */
647     proto_item *ti;
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);        
654     return offset;
655 }
656
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)
660 {
661     /* <Search Query> ::= <Search Type> <Search> */
662     proto_item *ti;
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;
668
669     search_type = tvb_get_guint8(tvb, offset);
670     search_length = 1;
671
672     switch (search_type)
673     {        
674         case EDONKEY_SEARCH_BOOL: 
675             /* <Search> ::=  <Operator> <Search Query> <Search Query> */
676             search_length += 1;
677             operator = tvb_get_guint8(tvb, offset+1);
678             
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);
682
683             /* Add query info */
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);
686
687             offset+=2;
688             offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
689             offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
690             break;
691
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;
697
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);
701
702             /* Add query info */
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;
707             break;
708
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;
714
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;
719
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);
723
724             /* Add query info */
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;
731             break;
732
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);
738
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;
743
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);
747
748             /* Add query info */
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;
754             break;
755
756         default:
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; 
762             break;
763     }
764
765     return offset;    
766 }
767
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) 
771 {   
772     int msg_start, msg_end, bytes_remaining;
773     guint8  hello, more;
774     guint32 nusers, nfiles;
775
776     if (tree == NULL) return;
777     
778     bytes_remaining = tvb_reported_length_remaining(tvb, offset);
779     if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
780     if (length <= 0) return;
781
782     msg_start = offset;
783     msg_end = offset + length;
784
785     switch (msg_type) {
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 */
791                 offset += 1;
792             offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree);
793             break;
794
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);
798             break;
799
800         case EDONKEY_MSG_SERVER_CB_REQ: /* Server Callback Request: <Client address> */
801             offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
802             break;
803
804         case EDONKEY_MSG_SERVER_INFO_DATA: /* Server Info Data: <Server Info> */
805             offset = dissect_edonkey_server_info(tvb, pinfo, offset, tree);
806             break;
807
808         case EDONKEY_MSG_SERVER_LIST: /* Server List: <Address List> */
809             offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
810             break;
811
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);
815             break;
816
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);
820             if (more)
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);            
823             break;
824
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);
828             break;
829        
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);
838             break;
839
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);
843             break;
844
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);
849             break;
850
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);
854             break;
855
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);
859             break;
860
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);
866             break;
867
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);
871             break;
872
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);
881             break;
882
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);
890             }
891             break;
892
893
894         case EDONKEY_MSG_SEARCH_USER_RESULTS: /* Search User Results: <Client info list> */                 
895             offset = dissect_edonkey_client_info_list(tvb, pinfo, offset, tree);
896             break;
897
898         case EDONKEY_MSG_GET_SHARED_FILES:    /* Get Shared Files: <Directory> */
899             offset = dissect_edonkey_directory(tvb, pinfo, offset, tree);
900             break;
901
902         case EDONKEY_MSG_SHARED_DIRS: /* Shared Dirs: <Directory List> */
903             offset = dissect_edonkey_directory_list(tvb, pinfo, offset, tree);
904             break;
905
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);
909             break;
910
911         case EDONKEY_MSG_HASHSET_ANSWER:      /* Hashset Answer: <Hash List>  */
912             offset = dissect_edonkey_hash_list(tvb, pinfo, offset, tree);
913             break;
914
915         default:
916             proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
917             break;
918     }
919         return;
920 }
921
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) 
925 {   
926     int msg_start, msg_end, bytes_remaining;
927     guint32 packed_length;
928     guint16 version, rank;
929
930     if (tree == NULL) return;
931
932     bytes_remaining = tvb_reported_length_remaining(tvb, offset);
933     if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
934     if (length <= 0) return;
935
936     msg_start = offset;
937     msg_end = offset + length;
938
939     switch (msg_type) {
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);
945             break;
946
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);
950             break;
951
952         case EMULE_MSG_SOURCES_REQUEST: /* Sources Request: <File Hash> */
953             offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
954             break;
955
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);
959             break;
960
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);
966             offset += 4;
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);
971             }
972             break;
973
974         default:
975             dissect_edonkey_tcp_message(msg_type, tvb, pinfo, offset, length, tree);
976             break;
977     }
978         return;
979 }
980
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) 
984 {   
985     int msg_start, msg_end, bytes_remaining;
986     guint8 type;
987     guint16 min, max;
988     guint32 nusers, nfiles;
989
990     if (tree == NULL) return;
991
992     bytes_remaining = tvb_reported_length_remaining(tvb, offset);
993     if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
994     if (length <= 0) return;
995
996     msg_start = offset;
997     msg_end = offset + length;
998
999     switch (msg_type) {
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);
1004             break;
1005
1006         case EDONKEY_MSG_UDP_CALLBACK_FAIL: /* Callback Fail: <Client ID> */
1007             offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
1008             break;
1009
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);
1013             break;
1014
1015         case EDONKEY_MSG_UDP_SERVER_LIST: /* Server List: <Address List> */
1016             offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
1017             break;
1018
1019         case EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS: /* Search File Result: <File Info> */
1020             offset = dissect_edonkey_file_info(tvb, pinfo, offset, tree);
1021             break;
1022
1023         case EDONKEY_MSG_UDP_SEARCH_FILE: /* Search File: <Search query> */
1024             offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree);
1025             break;
1026        
1027         case EDONKEY_MSG_UDP_GET_SOURCES:     /* Get Sources: <File Hash> */
1028             offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1029             break;
1030
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);
1034             break;
1035
1036         case EDONKEY_MSG_UDP_SERVER_STATUS:  /* Server Status: <guint32> <Nusers> <Nfiles> <Nusersmax> */
1037             offset += 4;
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);
1042             offset += 8;
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);
1046                 offset += 4;
1047             }
1048             break;
1049
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);
1054             break;
1055
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);
1058             break;
1059
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);
1064             break;
1065
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);
1074             break;
1075
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);
1079             break;
1080
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); 
1086             break;
1087
1088         case OVERNET_MSG_UDP_SEARCH_END:  /* Search End: <Hash> */
1089             offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
1090             break;
1091
1092         case OVERNET_MSG_UDP_PUBLISH_ACK:  /* Publish ACK: <File Hash> */
1093             offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1094             break;
1095
1096         case OVERNET_MSG_UDP_IP_QUERY:  /* IP Query: <TCP Port> */
1097             proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
1098             break;
1099
1100         case OVERNET_MSG_UDP_IP_QUERY_ANSWER:  /* IP Query Answer: <IP> */
1101             offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
1102             break;
1103
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);
1108             break;
1109
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);
1112             break;
1113
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);
1117             break;
1118
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);
1122             break;
1123
1124         default:
1125             proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
1126             break;
1127     }
1128         return;
1129 }
1130
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) 
1134 {   
1135     int msg_start, msg_end, bytes_remaining;
1136     guint16 rank;
1137
1138     bytes_remaining = tvb_reported_length_remaining(tvb, offset);
1139     if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
1140     if (length <= 0) return;
1141
1142     msg_start = offset;
1143     msg_end = offset + length;
1144
1145     switch (msg_type) {
1146         case EMULE_MSG_UDP_REASKFILEPING:     /* Reask File Ping: <File Hash> */
1147             offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
1148             break;
1149
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);
1153             break;
1154
1155         default:
1156             dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree);
1157             break;
1158     }
1159         return;
1160 }
1161
1162 static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
1163 {
1164         proto_item *ti;
1165         proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
1166         int offset, bytes, messages;
1167         guint8 protocol, msg_type;
1168     guint32 msg_len;
1169     gchar *protocol_name, *message_name;
1170     void  (*dissector)(guint8, tvbuff_t*, packet_info*, int, int, proto_tree*);
1171
1172         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1173                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
1174
1175         if (check_col(pinfo->cinfo, COL_INFO))
1176                 col_clear(pinfo->cinfo, COL_INFO);
1177
1178         if (tree) {
1179         ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
1180         edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
1181     }
1182
1183     offset = 0;
1184     messages = 0;
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);
1188         
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");
1194             if (edonkey_tree) {
1195                 bytes = tvb_length_remaining(tvb, offset);
1196                 proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes);
1197             }
1198             return;
1199         }
1200
1201         /* Add edonkey message tree */
1202         if (edonkey_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);
1206             
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);
1210         }
1211
1212
1213         /* Skip past the EDONKEY Header */
1214         offset += EDONKEY_TCP_HEADER_LENGTH;
1215         
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)) {
1219                 if (messages == 0)
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);
1222             }
1223             return;
1224         } 
1225
1226         if (check_col(pinfo->cinfo, COL_INFO)) {
1227             if (messages == 0)
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);
1230         }
1231
1232         msg_type = tvb_get_guint8(tvb, offset);
1233         switch (protocol) {
1234             case EDONKEY_PROTO_EDONKEY:
1235                 message_name =  val_to_str(msg_type, edonkey_tcp_msgs, "Unknown");
1236                 dissector = dissect_edonkey_tcp_message;
1237                 break;
1238             
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;
1243                 break;
1244
1245             default:
1246                 message_name = "Unknown";
1247                 dissector = NULL;
1248                 break;
1249         }
1250
1251         if (check_col(pinfo->cinfo, COL_INFO)) {
1252             col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name);
1253         }
1254
1255
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);
1261         }
1262
1263         offset += msg_len;
1264         messages++;
1265         }
1266 }
1267
1268 static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
1269 {
1270         proto_item *ti;
1271         proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
1272         int offset;
1273         guint8 protocol, msg_type;
1274     gchar *protocol_name, *message_name;
1275
1276         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1277                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
1278
1279         if (check_col(pinfo->cinfo, COL_INFO))
1280                 col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message");
1281
1282         if (tree) {
1283         ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
1284         edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
1285     }
1286
1287     offset = 0;
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");
1294
1295         if (check_col(pinfo->cinfo, COL_INFO)) {
1296             col_add_fstr(pinfo->cinfo, COL_INFO, "%s UDP: %s", protocol_name, message_name);
1297         }
1298
1299         if (edonkey_tree) {
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);
1302             
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);
1307             
1308             offset += EDONKEY_UDP_HEADER_LENGTH;
1309
1310             switch (protocol) {
1311                 case EDONKEY_PROTO_EDONKEY:
1312                     dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree);
1313                     break;
1314                             
1315                 case EDONKEY_PROTO_EMULE_EXT:
1316                     dissect_emule_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree); 
1317                     break;
1318
1319                 default:
1320                     break;
1321             }
1322         }
1323         }
1324 }
1325
1326 void proto_register_edonkey(void) {
1327
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 } },
1353         { &hf_edonkey_ip,
1354           { "IP", "edonkey.ip",
1355             FT_IPv4, BASE_DEC, NULL, 0, "eDonkey IP", HFILL } },
1356         { &hf_edonkey_port,
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 } },
1377         { &hf_edonkey_hash,
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 } },
1398                 { &hf_overnet_peer,  
1399           { "Overnet Peer", "overnet.peer",
1400             FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } },
1401         };
1402
1403         static gint *ett[] = {
1404                 &ett_edonkey,
1405         &ett_edonkey_message,
1406         &ett_edonkey_metatag,
1407         &ett_edonkey_search,
1408         &ett_edonkey_fileinfo,
1409         &ett_edonkey_serverinfo,
1410         &ett_edonkey_clientinfo,
1411         &ett_overnet_peer
1412         };
1413
1414         proto_edonkey = proto_register_protocol("eDonkey Protocol", "EDONKEY", "edonkey");
1415
1416         proto_register_field_array(proto_edonkey, hf, array_length(hf));
1417
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);
1421 }
1422
1423 void proto_reg_handoff_edonkey(void) {
1424         dissector_handle_t edonkey_tcp_handle;
1425         dissector_handle_t edonkey_udp_handle;
1426
1427         edonkey_tcp_handle = find_dissector("edonkey.tcp");
1428         edonkey_udp_handle = find_dissector("edonkey.udp");
1429
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);
1435 }