Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-vuze-dht.c
1 /* packet-vuze-dht.c
2  * Routines for Vuze-DHT dissection
3  * Copyright 2011, Xiao Xiangquan <xiaoxiangquan@gmail.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1999 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31
32 #define DEFAULT_UDP_PORT 11273
33
34 /* --- protocol specification:
35  * http://wiki.vuze.com/w/Distributed_hash_table
36  */
37
38 /* protocol versions */
39 enum {
40   PV_DIV_AND_CONT           =  6,
41   PV_ANTI_SPOOF             =  7,
42   PV_ANTI_SPOOF2            =  8,
43   PV_FIX_ORIGINATOR         =  9,
44   PV_NETWORKS               =  9,
45   PV_VIVALDI                = 10,
46   PV_REMOVE_DIST_ADD_VER    = 11,
47   PV_XFER_STATUS            = 12,
48   PV_SIZE_ESTIMATE          = 13,
49   PV_VENDOR_ID              = 14,
50   PV_BLOCK_KEYS             = 14,
51   PV_GENERIC_NETPOS         = 15,
52   PV_VIVALDI_FINDVALUE      = 16,
53   PV_ANON_VALUES            = 17,
54   PV_CVS_FIX_OVERLOAD_V1    = 18,
55   PV_CVS_FIX_OVERLOAD_V2    = 19,
56   PV_MORE_STATS             = 20,
57   PV_CVS_FIX_OVERLOAD_V3    = 21,
58   PV_MORE_NODE_STATUS       = 22,
59   PV_LONGER_LIFE            = 23,
60   PV_REPLICATION_CONTROL    = 24,
61   PV_RESTRICT_ID_PORTS      = 32,
62   PV_RESTRICT_ID_PORTS2     = 33,
63   PV_RESTRICT_ID_PORTS2X    = 34,
64   PV_RESTRICT_ID_PORTS2Y    = 35,
65   PV_RESTRICT_ID_PORTS2Z    = 36,
66   PV_RESTRICT_ID3           = 50
67 };
68
69 /* Type Length */
70 enum {
71   TL_BYTE  =  1,
72   TL_BOOL  =  1,
73   TL_SHORT =  2,
74   TL_INT   =  4,
75   TL_IPv4  =  4,
76   TL_LONG  =  8,
77   TL_IPv6  = 16
78 };
79
80 /* Bool type */
81 enum {
82   BT_FALSE = 0x0,
83   BT_TRUE = 0x1
84 };
85 static const value_string vuze_dht_bool_type_vals[] = {
86   { BT_FALSE, "False" },
87   { BT_TRUE, "True" },
88   { 0, NULL }
89 };
90
91 /* action type */
92 enum {
93   AT_PING_REQUEST       = 1024,
94   AT_PING_REPLY         = 1025,
95   AT_STORE_REQUEST      = 1026,
96   AT_STORE_REPLY        = 1027,
97   AT_FIND_NODE_REQUEST  = 1028,
98   AT_FIND_NODE_REPLY    = 1029,
99   AT_FIND_VALUE_REQUEST = 1030,
100   AT_FIND_VALUE_REPLY   = 1031,
101   AT_ERROR_REPLY        = 1032,
102   AT_KEY_BLOCK_REQUEST  = 1036,
103   AT_KEY_BLOCK_REPLY    = 1037
104 };
105 static const value_string vuze_dht_action_type_vals[] = {
106   { AT_PING_REQUEST,        "PING request" },
107   { AT_PING_REPLY,          "PING reply" },
108   { AT_STORE_REQUEST,       "STORE request" },
109   { AT_STORE_REPLY,         "STORE reply" },
110   { AT_FIND_NODE_REQUEST,   "FIND_NODE request" },
111   { AT_FIND_NODE_REPLY,     "FIND_NODE reply" },
112   { AT_FIND_VALUE_REQUEST,  "FIND_VALUE request" },
113   { AT_FIND_VALUE_REPLY,    "FIND_VALUE reply" },
114   { AT_ERROR_REPLY,         "ERROR reply" },
115   { AT_KEY_BLOCK_REQUEST,   "kEY_BLOCK request" },
116   { AT_KEY_BLOCK_REPLY,     "KEY_BLOCK reply" },
117   { 0, NULL }
118 };
119
120 /* Contact type, must be 1(UDP) */
121 enum {
122   CONTACT_UDP = 1
123 };
124 static const value_string vuze_dht_contact_type_vals[] = {
125   { CONTACT_UDP, "UDP" },
126   { 0, NULL }
127 };
128
129 /* Node type */
130 enum {
131   NT_BOOTSTRAP_NODE = 0x0,
132   NT_ORDINARY_NODE  = 0x1,
133   NT_UNKNOWN_NODE   = 0xffffffff
134 };
135 static const value_string vuze_dht_node_type_vals[] = {
136   { NT_BOOTSTRAP_NODE, "Bootstrap node" },
137   { NT_ORDINARY_NODE,  "Ordinary node" },
138   { NT_UNKNOWN_NODE,   "Unknown node" },
139   { 0, NULL }
140 };
141
142 /* flag type */
143 enum {
144     FT_SINGLE_VALUE = 0x00,
145     FT_DOWNLOADING  = 0x01,
146     FT_SEEDING      = 0x02,
147     FT_MULTI_VALUE  = 0x04,
148     FT_STATS        = 0x08
149 };
150 static const value_string vuze_dht_flag_type_vals[] = {
151   { FT_SINGLE_VALUE, "Single value" },
152   { FT_DOWNLOADING,  "Downloading" },
153   { FT_SEEDING,      "Seeding" },
154   { FT_MULTI_VALUE,  "Multi value" },
155   { FT_STATS,        "Stats" },
156   { 0, NULL }
157 };
158
159 /* error type */
160 enum {
161   ET_WRONG_ADDRESS  = 1,
162   ET_KEY_BLOCKED    = 2
163 };
164 static const value_string vuze_dht_error_type_vals[] = {
165   { ET_WRONG_ADDRESS, "Originator's address stored in the request is incorrect" },
166   { ET_KEY_BLOCKED,   "The requested key has been blocked" },
167   { 0, NULL }
168 };
169
170 static int proto_vuze_dht = -1;
171
172 /* --- fields ---*/
173
174 /* address appears in contacts, request header, reply error */
175 static int hf_vuze_dht_address = -1;
176 static int hf_vuze_dht_address_len = -1;
177 static int hf_vuze_dht_address_v4 = -1;
178 static int hf_vuze_dht_address_v6 = -1;
179 static int hf_vuze_dht_address_port = -1;
180
181 /* contact appears in values, reply find_node, reply find_value */
182 static int hf_vuze_dht_contact = -1;
183 static int hf_vuze_dht_contact_type = -1;
184 static int hf_vuze_dht_proto_ver = -1;
185
186 /* value appears in reply find_value */
187 static int hf_vuze_dht_value = -1;
188 static int hf_vuze_dht_value_ver = -1;
189 static int hf_vuze_dht_value_created = -1;
190 static int hf_vuze_dht_value_bytes_count = -1;
191 static int hf_vuze_dht_value_bytes = -1;
192 static int hf_vuze_dht_value_flags = -1;
193 static int hf_vuze_dht_value_life_hours = -1;
194 static int hf_vuze_dht_value_replication_factor = -1;
195
196 /* firstly appear in request header */
197 static int hf_vuze_dht_connection_id = -1;
198 static int hf_vuze_dht_action = -1;
199 static int hf_vuze_dht_transaction_id = -1;
200 static int hf_vuze_dht_vendor_id = -1;
201 static int hf_vuze_dht_network_id = -1;
202 static int hf_vuze_dht_local_proto_ver = -1;
203 static int hf_vuze_dht_instance_id = -1;
204 static int hf_vuze_dht_time = -1;
205
206 /* firstly appear in reply ping */
207 static int hf_vuze_dht_network_coordinates_count = -1;
208 static int hf_vuze_dht_network_coordinates = -1;
209 static int hf_vuze_dht_network_coordinate = -1;
210 static int hf_vuze_dht_network_coordinate_type = -1;
211 static int hf_vuze_dht_network_coordinate_size = -1;
212 static int hf_vuze_dht_network_coordinate_data = -1;
213
214 /* firstly appear in request store */
215 static int hf_vuze_dht_spoof_id = -1;
216 static int hf_vuze_dht_keys_count = -1;
217 static int hf_vuze_dht_keys = -1;
218 static int hf_vuze_dht_key = -1;
219 static int hf_vuze_dht_key_len = -1;
220 static int hf_vuze_dht_key_data = -1;
221 static int hf_vuze_dht_value_group = -1;
222 static int hf_vuze_dht_value_groups = -1;
223 static int hf_vuze_dht_value_groups_count = -1;
224 static int hf_vuze_dht_values_count = -1;
225
226 /* firstly appear in reply store */
227 static int hf_vuze_dht_diversifications_len = -1;
228 static int hf_vuze_dht_diversifications = -1;
229
230 /* firstly appear in request find_node */
231 static int hf_vuze_dht_id_len = -1;
232 static int hf_vuze_dht_id = -1;
233 static int hf_vuze_dht_node_status = -1;
234 static int hf_vuze_dht_size = -1;
235
236 /* firstly appear in reply find_node */
237 static int hf_vuze_dht_node_type = -1;
238 static int hf_vuze_dht_contacts_count = -1;
239 static int hf_vuze_dht_contacts = -1;
240
241 /* firstly appear in request find_value */
242 static int hf_vuze_dht_flags = -1;
243 static int hf_vuze_dht_values_num = -1;
244 static int hf_vuze_dht_values_total = -1;
245 static int hf_vuze_dht_reads_per_min = -1;
246 static int hf_vuze_dht_diversification_type = -1;
247 static int hf_vuze_dht_max_values = -1;
248
249 /* firstly appear in reply find_value */
250 static int hf_vuze_dht_has_continuation = -1;
251 static int hf_vuze_dht_has_values = -1;
252
253 /* firstly appear in reply error */
254 static int hf_vuze_dht_error_type = -1;
255 static int hf_vuze_dht_key_block_request_len = -1;
256 static int hf_vuze_dht_key_block_request = -1;
257 static int hf_vuze_dht_signature_len = -1;
258 static int hf_vuze_dht_signature = -1;
259
260 /* trees */
261 static gint ett_vuze_dht = -1;
262 static gint ett_vuze_dht_address = -1;
263 static gint ett_vuze_dht_contacts = -1;
264 static gint ett_vuze_dht_contact = -1;
265 static gint ett_vuze_dht_keys = -1;
266 static gint ett_vuze_dht_key = -1;
267 static gint ett_vuze_dht_value_groups = -1;
268 static gint ett_vuze_dht_value_group = -1;
269 static gint ett_vuze_dht_value = -1;
270 static gint ett_vuze_dht_network_coordinates = -1;
271 static gint ett_vuze_dht_network_coordinate = -1;
272
273 /* port use */
274 static guint global_vuze_dht_udp_port = DEFAULT_UDP_PORT;
275
276 void proto_reg_handoff_vuze_dht(void);
277
278 /* --- Address format --------------
279
280 byte:          indicates length of the IP address (4 for IPv4, 16 for IPv6)
281 4 or 16 bytes: the address in network byte order
282 short:         port number
283
284 */
285 static int
286 dissect_vuze_dht_address(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, const char* addr_name)
287 {
288   guint8 ip_length;
289   proto_tree *sub_tree;
290   proto_item *ti;
291   address addr;
292
293   ip_length = tvb_get_guint8(tvb,offset);
294   /* the decoded length is ip length+3, see the format above */
295   ti = proto_tree_add_none_format(tree, hf_vuze_dht_address, tvb, offset, ip_length+3, "%s: ", addr_name );
296   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_address);
297
298   proto_tree_add_item(sub_tree, hf_vuze_dht_address_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
299   offset += TL_BYTE;
300
301   switch(ip_length)
302   {
303   case TL_IPv4:
304     proto_tree_add_item(sub_tree, hf_vuze_dht_address_v4, tvb, offset, ip_length, ENC_BIG_ENDIAN);
305     SET_ADDRESS( &addr, AT_IPv4, ip_length, tvb_get_ptr( tvb, offset, ip_length) );
306     break;
307   case TL_IPv6:
308     proto_tree_add_item(sub_tree, hf_vuze_dht_address_v6, tvb, offset, ip_length, ENC_NA);
309     SET_ADDRESS( &addr, AT_IPv6, ip_length, tvb_get_ptr( tvb, offset, ip_length) );
310     break;
311   default:
312     addr.type = AT_NONE;
313     break;
314   }
315   offset += ip_length;
316
317   proto_tree_add_item(sub_tree, hf_vuze_dht_address_port, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
318   proto_item_append_text( ti, "%s:%d", ep_address_to_str( &addr ), tvb_get_ntohs(tvb,offset) );
319   offset += TL_SHORT;
320
321   return offset;
322 }
323
324 /* --- Contact format --------------
325
326 byte:        indicates contact type, which must be UDP(1)
327 byte:        the contact's protocol version
328 7 or 19 bytes: Address
329
330 */
331 static int
332 dissect_vuze_dht_contact(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
333 {
334   proto_item *ti;
335   proto_tree *sub_tree;
336
337   /* the decoded length is ip length+5, see the format above */
338   ti = proto_tree_add_none_format( tree, hf_vuze_dht_contact, tvb, offset, tvb_get_guint8(tvb,offset+2)+5,
339       "%s contact, version %d",
340       val_to_str( tvb_get_guint8(tvb, offset), vuze_dht_contact_type_vals, "Unknown"),
341       tvb_get_guint8(tvb, offset+1) );
342   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_contact);
343
344   proto_tree_add_item(sub_tree, hf_vuze_dht_contact_type, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
345   offset += TL_BYTE;
346   proto_tree_add_item(sub_tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
347   offset += TL_BYTE;
348   offset = dissect_vuze_dht_address( tvb, pinfo, sub_tree, offset, "Contact Address" );
349
350   return offset;
351 }
352
353 /* --- Contact List --- */
354 static int
355 dissect_vuze_dht_contacts(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int contacts_count)
356 {
357   proto_item *ti;
358   proto_tree *sub_tree;
359   int i;
360
361   ti = proto_tree_add_none_format( tree, hf_vuze_dht_contacts, tvb, offset, 0, "%d contacts", contacts_count );
362   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_contacts);
363   for( i=1; i<=contacts_count; i++ )
364     offset = dissect_vuze_dht_contact( tvb, pinfo, sub_tree, offset );
365
366   return offset;
367 }
368
369 /* --- Key format
370  Name               | Type
371  LENGTH               byte
372  KEY                  byte[LENGTH]
373  --- */
374 static int
375 dissect_vuze_dht_key(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset)
376 {
377   proto_item *ti;
378   proto_tree *sub_tree;
379   guint key_len;
380
381   key_len = tvb_get_guint8( tvb, offset );
382   ti = proto_tree_add_item( tree, hf_vuze_dht_key, tvb, offset, key_len+1, ENC_NA );
383   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_key);
384
385   proto_tree_add_item( sub_tree, hf_vuze_dht_key_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN );
386   offset += TL_BYTE;
387
388   proto_tree_add_item( sub_tree, hf_vuze_dht_key_data, tvb, offset, key_len, ENC_NA );
389   proto_item_append_text( ti, ": %d bytes ( %s )", key_len, tvb_bytes_to_str(tvb, offset, key_len ) );
390   offset += key_len;
391
392   return offset;
393 }
394
395 /* --- Keys List --- */
396 static int
397 dissect_vuze_dht_keys(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int keys_count)
398 {
399   proto_item *ti;
400   proto_tree *sub_tree;
401   int i;
402
403   ti = proto_tree_add_none_format( tree, hf_vuze_dht_keys, tvb, offset, 0, "%d keys", keys_count );
404   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_keys);
405   for( i=1; i<=keys_count; i++ )
406     offset = dissect_vuze_dht_key( tvb, pinfo, sub_tree, offset );
407
408   return offset;
409 }
410
411 /* --- Value format --------------
412
413 Name             | Type  | Protocol version    | Note
414 VERSION            byte    >=REMOVE_DIST_ADD_VER  Version of the value. (details later)
415 CREATED            long    always                Creation time. Units unknown; probably milliseconds since the epoch.
416 VALUE_BYTES_COUNT  short   always                Number of bytes in the value.
417 VALUE_BYTES        bytes   always                The bytes of the value.
418 ORIGINATOR         contact always                presumably the node that created the value.
419 FLAGS              byte    always
420 LIFE_HOURS         byte    >=LONGER_LIFE          Hours for the value to live. (Details of how it's handled)
421 REPLICATION_FACTOR byte    >=REPLICATION_CONTROL  Per-value # of replicas to maintain.
422
423 If STATS are used in request, then some stats for the value are returned instead of value itself.
424 They are serialised as follows:
425   0 (byte) - version,
426   number of stored values for the key (int),
427   total size of stored values (int),
428   reads per minute (int),
429   diversification type (byte).
430 */
431 static int
432 dissect_vuze_dht_value(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
433 {
434   proto_item *ti;
435   proto_tree *sub_tree;
436   int value_ver = -1;
437
438   ti = proto_tree_add_item( tree, hf_vuze_dht_value, tvb, offset, 0, ENC_NA );
439   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value);
440   if( ver >= PV_REMOVE_DIST_ADD_VER )
441   {
442     proto_tree_add_item(sub_tree, hf_vuze_dht_value_ver, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
443     value_ver = tvb_get_ntohl( tvb, offset );
444     offset += TL_INT;
445   }
446   /* It's a return for STATS */
447   if( value_ver==0 )
448   {
449     proto_item_append_text( ti,
450                             " (reply to STATS): %d values for the key, out of %d in total...",
451                             tvb_get_ntohl(tvb, offset), tvb_get_ntohl(tvb, offset+TL_INT) );
452
453     proto_tree_add_item(tree, hf_vuze_dht_values_num, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
454     offset += TL_INT;
455     proto_tree_add_item(tree, hf_vuze_dht_values_total, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
456     offset += TL_INT;
457     proto_tree_add_item(tree, hf_vuze_dht_reads_per_min, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
458     offset += TL_INT;
459     proto_tree_add_item(tree, hf_vuze_dht_diversification_type, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
460     offset += TL_BYTE;
461   }
462   /* regular value */
463   else
464   {
465     int value_bytes_count;
466
467     proto_tree_add_item(sub_tree, hf_vuze_dht_value_created, tvb, offset, TL_LONG, ENC_BIG_ENDIAN);
468     offset += TL_LONG;
469
470     proto_tree_add_item(sub_tree, hf_vuze_dht_value_bytes_count, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
471     value_bytes_count = tvb_get_ntohs(tvb, offset);
472     offset += TL_SHORT;
473
474     proto_tree_add_item(sub_tree, hf_vuze_dht_value_bytes, tvb, offset, value_bytes_count, ENC_NA);
475     proto_item_append_text( ti, ": %d bytes ( %s )", value_bytes_count, tvb_bytes_to_str(tvb, offset, value_bytes_count ) );
476     offset += value_bytes_count;
477
478     offset = dissect_vuze_dht_contact( tvb, pinfo, sub_tree, offset );
479
480     proto_tree_add_item(sub_tree, hf_vuze_dht_value_flags, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
481     offset += TL_BYTE;
482     proto_tree_add_item(sub_tree, hf_vuze_dht_value_life_hours, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
483     offset += TL_BYTE;
484     proto_tree_add_item(sub_tree, hf_vuze_dht_value_replication_factor, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
485     offset += TL_BYTE;
486   }
487
488   return offset;
489 }
490
491 /* --- Values format
492 values_count        short
493 values              value[values_count]
494  --- */
495 static int
496 dissect_vuze_dht_value_group(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver)
497 {
498   proto_item *ti;
499   proto_tree *sub_tree;
500   int values_count;
501   int i;
502
503   values_count = tvb_get_ntohs( tvb, offset );
504
505   ti = proto_tree_add_none_format( tree, hf_vuze_dht_value_group, tvb, offset, 0, "%d values", values_count );
506   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value_group);
507
508   proto_tree_add_item( sub_tree, hf_vuze_dht_values_count, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN );
509   offset += TL_SHORT;
510
511   for( i=1; i<=values_count; i++ )
512     offset = dissect_vuze_dht_value( tvb, pinfo, sub_tree, offset, ver );
513
514   return offset;
515 }
516
517 /* --- Values Groups format
518 value_group[value_groups_count]
519  --- */
520 static int
521 dissect_vuze_dht_value_groups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int value_groups_count, int ver)
522 {
523   proto_item *ti;
524   proto_tree *sub_tree;
525   int i;
526
527   ti = proto_tree_add_none_format( tree, hf_vuze_dht_value_groups, tvb, offset, 0, "%d value groups", value_groups_count );
528   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value_groups);
529   for( i=1; i<=value_groups_count; i++ )
530     offset = dissect_vuze_dht_value_group( tvb, pinfo, sub_tree, offset, ver );
531
532   return offset;
533 }
534
535 /* --- Network Coordinates format ------
536 Name               | Type
537 TYPE                 byte
538 SIZE                 byte
539 Network Coordinates  byte[SIZE]
540  */
541 static int
542 dissect_vuze_dht_network_coordinate(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset)
543 {
544   proto_item *ti;
545   proto_tree *sub_tree;
546   guint coordinate_size;
547
548   coordinate_size = tvb_get_guint8( tvb, offset+1 );
549
550   ti = proto_tree_add_item( tree, hf_vuze_dht_network_coordinate, tvb, offset, coordinate_size+2, ENC_NA );
551   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_network_coordinate);
552
553   proto_item_append_text( ti, ": type %d, length %d ( %s )",
554     tvb_get_guint8(tvb,offset), tvb_get_guint8(tvb,offset+TL_BYTE), tvb_bytes_to_str(tvb, offset+TL_BYTE+TL_BYTE, coordinate_size ) );
555
556   proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_type, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN );
557   offset += TL_BYTE;
558   proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_size, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN );
559   offset += TL_BYTE;
560   proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_data, tvb, offset, coordinate_size, ENC_NA );
561   offset += coordinate_size;
562
563   return offset;
564 }
565
566 /* --- Network Coordinates List ---
567 Name                     | Type              | Protocol version
568 Network Coordinates Count  byte                >=PV_GENERIC_NETPOS
569 Network Coordinates        Network Coordinate  >=PV_GENERIC_NETPOS
570  */
571 static int
572 dissect_vuze_dht_network_coordinates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver)
573 {
574   proto_item *ti;
575   proto_tree *sub_tree;
576   guint i;
577   guint network_coordinates_count;
578
579   if( ver >= PV_GENERIC_NETPOS )
580   {
581     proto_tree_add_item(tree, hf_vuze_dht_network_coordinates_count, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
582     network_coordinates_count = tvb_get_guint8( tvb, offset );
583     offset += TL_BYTE;
584
585     ti = proto_tree_add_none_format( tree, hf_vuze_dht_network_coordinates, tvb, offset, 0, "%d network coordinates", network_coordinates_count );
586     sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_network_coordinates);
587     for( i=1; i<=network_coordinates_count; i++ )
588       offset = dissect_vuze_dht_network_coordinate( tvb, pinfo, sub_tree, offset );
589   }
590   return offset;
591 }
592
593 /* ---  Request Header format --------------
594
595 Name                  | Type  | Protocol version | Note
596 CONNECTION_ID           long    always             random number with most significant bit set to 1
597 ACTION                  int     always             type of the packet
598 TRANSACTION_ID          int     always             unique number used through the communication; it is randomly generated
599                                                    at the start of the application and increased by 1 with each sent packet
600 PROTOCOL_VERSION        byte    always             version of protocol used in this packet
601 VENDOR_ID               byte    >=VENDOR_ID         ID of the DHT implementator; 0 = Azureus, 1 = ShareNet, 255 = unknown
602 NETWORK_ID              int     >=NETWORKS          ID of the network; 0 = stable version; 1 = CVS version
603 LOCAL_PROTOCOL_VERSION  byte    >=FIX_ORIGINATOR    maximum protocol version this node supports; if this packet's protocol
604                                                    version is <FIX_ORIGINATOR then the value is stored at the end of the packet
605 NODE_ADDRESS            address always             address of the local node
606 INSTANCE_ID             int     always             application's helper number; randomly generated at the start
607 TIME                    long    always             time of the local node; stored as number of milliseconds since Epoch
608
609 */
610 static int
611 dissect_vuze_dht_request_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int *action, int *ver )
612 {
613   proto_tree_add_item(tree, hf_vuze_dht_connection_id, tvb, offset, TL_LONG, ENC_BIG_ENDIAN);
614   offset += TL_LONG;
615
616   proto_tree_add_item(tree, hf_vuze_dht_action, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
617   *action = tvb_get_ntohl(tvb, offset);
618   col_append_fstr(pinfo->cinfo, COL_INFO, " Action: %s", val_to_str( *action, vuze_dht_action_type_vals, "Unknown") );
619   offset += TL_INT;
620
621   proto_tree_add_item(tree, hf_vuze_dht_transaction_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
622   offset += TL_INT;
623
624   proto_tree_add_item(tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
625   *ver = tvb_get_guint8( tvb, offset );
626   offset += TL_BYTE;
627
628   if( *ver >= PV_VENDOR_ID )
629   {
630     proto_tree_add_item(tree, hf_vuze_dht_vendor_id, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
631     offset += TL_BYTE;
632   }
633
634   if( *ver > PV_NETWORKS )
635   {
636     proto_tree_add_item(tree, hf_vuze_dht_network_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
637     offset += TL_INT;
638   }
639   if( *ver > PV_FIX_ORIGINATOR )
640   {
641     proto_tree_add_item(tree, hf_vuze_dht_local_proto_ver, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
642     offset += TL_BYTE;
643   }
644
645   offset = dissect_vuze_dht_address(tvb, pinfo, tree, offset, "Local Address");
646   proto_tree_add_item(tree, hf_vuze_dht_instance_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
647   offset += TL_INT;
648   proto_tree_add_item(tree, hf_vuze_dht_time, tvb, offset, TL_LONG, ENC_BIG_ENDIAN);
649   offset += TL_LONG;
650
651   return offset;
652 }
653
654 /* ---  Reply Header format --------------
655
656 Name           | Type | Protocol version | Note
657 ACTION           int    always             type of the packet
658 TRANSACTION_ID   int    always             must be equal to TRANSACTION_ID from the request
659 CONNECTION_ID    long   always             must be equal to CONNECTION_ID from the request
660 PROTOCOL_VERSION byte   always             version of protocol used in this packet
661 VENDOR_ID        byte   >=VENDOR_ID         same meaning as in the request
662 NETWORK_ID       int    >=NETWORKS          same meaning as in the request
663 INSTANCE_ID      int    always             instance id of the node that replies to the request
664
665 */
666 static int
667 dissect_vuze_dht_reply_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int *action, int *ver )
668 {
669   proto_tree_add_item(tree, hf_vuze_dht_action, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
670   *action = tvb_get_ntohl(tvb, offset);
671   col_append_fstr(pinfo->cinfo, COL_INFO, " Action: %s", val_to_str( *action, vuze_dht_action_type_vals, "Unknown") );
672   offset += TL_INT;
673
674   proto_tree_add_item(tree, hf_vuze_dht_transaction_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
675   offset += TL_INT;
676
677   proto_tree_add_item(tree, hf_vuze_dht_connection_id, tvb, offset, TL_LONG, ENC_BIG_ENDIAN);
678   offset += TL_LONG;
679
680   proto_tree_add_item(tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
681   *ver = tvb_get_guint8( tvb, offset );
682   offset += TL_BYTE;
683
684   if( *ver >= PV_VENDOR_ID )
685   {
686     proto_tree_add_item(tree, hf_vuze_dht_vendor_id, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
687     offset += TL_BYTE;
688   }
689
690   if( *ver > PV_NETWORKS )
691   {
692     proto_tree_add_item(tree, hf_vuze_dht_network_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
693     offset += TL_INT;
694   }
695
696   proto_tree_add_item(tree, hf_vuze_dht_instance_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
697   offset += TL_INT;
698
699   return offset;
700 }
701
702 /* --- Reply Ping -----------------
703
704 ACTION equal to 1025
705 If protocol version is >=VIVALDI then packet's body carries network coordinates.
706
707 */
708 static int
709 dissect_vuze_dht_reply_ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
710 {
711   if( ver >= PV_VIVALDI )
712   {
713     offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
714   }
715   return offset;
716 }
717
718 /* --- Request Store -----------------
719
720 Name             | Type       | Protocol version | Note
721 SPOOF_ID           int          >=ANTI_SPOOF        Spoof ID of the target node; it must be the same number as previously retrived through FIND_NODE reply.
722 KEYS_COUNT         byte         always             Number of keys that follow.
723 KEYS               keys         always             Keys that the target node should store.
724 VALUE_GROUPS_COUNT byte         always             Number of groups of values this packet contains.
725 VALUES             value groups always             Groups of values, one for each key; values are stored in the same order as keys.
726
727 */
728 static int
729 dissect_vuze_dht_request_store(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
730 {
731   guint8 keys_count, value_groups_count;
732   if( ver >= PV_ANTI_SPOOF )
733   {
734     proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
735     offset += TL_INT;
736   }
737   proto_tree_add_item(tree, hf_vuze_dht_keys_count, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
738   keys_count = tvb_get_guint8( tvb, offset );
739   offset += TL_BYTE;
740
741   offset = dissect_vuze_dht_keys( tvb, pinfo, tree, offset, keys_count );
742
743   proto_tree_add_item(tree, hf_vuze_dht_value_groups_count, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
744   value_groups_count = tvb_get_guint8( tvb, offset );
745   offset += TL_BYTE;
746
747   offset = dissect_vuze_dht_value_groups( tvb, pinfo, tree, offset, value_groups_count, ver );
748
749   return offset;
750 }
751
752 /* --- Reply Store -----------------
753
754 Name                  | Type | Protocol version | Note
755 DIVERSIFICATIONS_LENGTH byte   >=DIV_AND_CONT      Number of diversifications this packet contains.
756 DIVERSIFICATIONS        byte[] >=DIV_AND_CONT      Array with diversifications;
757                                                   they are stored in the same order as keys and values from the request.
758 */
759 static int
760 dissect_vuze_dht_reply_store(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
761 {
762   if( ver >= PV_DIV_AND_CONT )
763   {
764     guint diversifications_len;
765     proto_tree_add_item(tree, hf_vuze_dht_diversifications_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
766     diversifications_len = tvb_get_guint8( tvb, offset );
767     offset += TL_BYTE;
768
769     proto_tree_add_item(tree, hf_vuze_dht_diversifications, tvb, offset, diversifications_len, ENC_NA);
770     offset += diversifications_len;
771   }
772
773   return offset;
774 }
775
776 /* --- Request Find node -----------------
777
778 Name      | Type | Protocol version | Note
779 ID_LENGTH   byte   always             Length of the following ID.
780 ID          byte[] always             ID to search
781 NODE_STATUS int    >=MORE_NODE_STATUS  Node status
782 DHT_SIZE    int    >=MORE_NODE_STATUS  Estimated size of the DHT; Unknown value can be indicated as zero.
783
784 */
785 static int
786 dissect_vuze_dht_request_find_node(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
787 {
788   guint id_len;
789
790   proto_tree_add_item(tree, hf_vuze_dht_id_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
791   id_len = tvb_get_guint8( tvb, offset );
792   offset += TL_BYTE;
793
794   proto_tree_add_item(tree, hf_vuze_dht_id, tvb, offset, id_len, ENC_NA);
795   offset += id_len;
796
797   if( ver >= PV_MORE_NODE_STATUS )
798   {
799     proto_tree_add_item(tree, hf_vuze_dht_node_status, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
800     offset += TL_INT;
801     proto_tree_add_item(tree, hf_vuze_dht_size, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
802     offset += TL_INT;
803   }
804
805   return offset;
806 }
807
808 /* --- Reply Find node -----------------
809
810 Name              | Type              | Protocol version | Note
811 SPOOF_ID            int                 >=ANTI_SPOOF        Spoof ID of the requesting node;
812                                                            it should be constructed from information known about
813                                                            requesting contact and not easily guessed by others.
814 NODE_TYPE           int                 >=XFER_STATUS       Type of the replying node;
815                                                            Possible values are 0 for bootstrap node,
816                                                            1 for ordinary node and ffffffffh for unknown type.
817 DHT_SIZE            int                 >=SIZE_ESTIMATE     Estimated size of the DHT; Unknown value can be indicated as zero.
818 NETWORK_COORDINATES network coordinates >=VIVALDI           Network coordinates of replying node.
819 CONTACTS_COUNT      short               always             Number of carried contacts.
820 CONTACTS            contacts            always             List with contacts.
821
822 */
823 static int
824 dissect_vuze_dht_reply_find_node(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
825 {
826   guint contacts_count;
827
828   if( ver >= PV_ANTI_SPOOF )
829   {
830     proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
831     offset += TL_INT;
832   }
833   if( ver >= PV_XFER_STATUS )
834   {
835     proto_tree_add_item(tree, hf_vuze_dht_node_type, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
836     offset += TL_INT;
837   }
838   if( ver >= PV_SIZE_ESTIMATE )
839   {
840     proto_tree_add_item(tree, hf_vuze_dht_size, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
841     offset += TL_INT;
842   }
843   if( ver >= PV_VIVALDI )
844   {
845     offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
846   }
847
848   proto_tree_add_item(tree, hf_vuze_dht_contacts_count, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
849   contacts_count = tvb_get_ntohs( tvb, offset );
850   offset += TL_SHORT;
851
852   offset = dissect_vuze_dht_contacts( tvb, pinfo, tree, offset, contacts_count );
853
854   return offset;
855 }
856
857 /* --- Request Find value -----------------
858
859 Name     | Type | Note
860 KEY        key    Key for which the values are requested.
861 FLAGS      byte   Flags for the operation, possible values are:
862                       SINGLE_VALUE = 00h
863                       DOWNLOADING = 01h
864                       SEEDING = 02h
865                       MULTI_VALUE = 04h
866                       STATS = 08h
867 MAX_VALUES byte   Maximum number of returned values.
868 */
869 static int
870 dissect_vuze_dht_request_find_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver _U_ )
871 {
872   offset = dissect_vuze_dht_key( tvb, pinfo, tree, offset );
873   proto_tree_add_item(tree, hf_vuze_dht_flags, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
874   offset += TL_BYTE;
875   proto_tree_add_item(tree, hf_vuze_dht_max_values, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
876   offset += TL_BYTE;
877
878   return offset;
879 }
880
881 /* --- Reply Find value -----------------
882
883 Name               | Type              | Condition                     | Note
884 HAS_CONTINUATION     boolean             protocol version >=DIV_AND_CONT  Indicates whether there is at least one other packet with values.
885 HAS_VALUES           boolean             always                          Indicates whether this packet carries values or contacts.
886 CONTACTS_COUNT       short               HAS_VALUES == false             Number of stored contacts.
887 CONTACTS             contacts            HAS_VALUES == false             Stored contacts that are close to the searched key.
888 NETWORK_COORDINATES  network coordinates HAS_VALUES == false             Network coordinates of the replying node.
889                                          && protocol version >=VIVALDI_FINDVALUE
890 DIVERSIFICATION_TYPE byte                HAS_VALUES == true              Type of key's diversification.
891                                          && protocol version >=DIV_AND_CONT
892 VALUES               value group         HAS_VALUES == true              Values that match searched key.
893
894 */
895 static int
896 dissect_vuze_dht_reply_find_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
897 {
898   guint8 has_values;
899   guint contacts_count;
900   if( ver >= PV_DIV_AND_CONT )
901   {
902     proto_tree_add_item(tree, hf_vuze_dht_has_continuation, tvb, offset, TL_BOOL, ENC_BIG_ENDIAN);
903     offset += TL_BOOL;
904   }
905   proto_tree_add_item(tree, hf_vuze_dht_has_values, tvb, offset, TL_BOOL, ENC_BIG_ENDIAN);
906   has_values = tvb_get_guint8( tvb, offset );
907   offset += TL_BOOL;
908
909   if( has_values )
910   {
911     proto_tree_add_item(tree, hf_vuze_dht_contacts_count, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
912     contacts_count = tvb_get_ntohs( tvb, offset );
913     offset += TL_SHORT;
914     offset = dissect_vuze_dht_contacts( tvb, pinfo, tree, offset, contacts_count  );
915
916     if( ver >= PV_VIVALDI_FINDVALUE )
917     {
918       offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
919     }
920     if( ver >= PV_DIV_AND_CONT )
921     {
922       proto_tree_add_item(tree, hf_vuze_dht_diversification_type, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
923       offset += TL_BYTE;
924     }
925     offset = dissect_vuze_dht_value_group( tvb, pinfo, tree, offset, ver );
926   }
927
928   return offset;
929 }
930
931 /* --- Reply Error -----------------
932
933 Name                   | Type   | Condition                 | Note
934 ERROR_TYPE               int      always                      Type of the error. Possible values are:
935                                                                 WRONG_ADDRESS = 1 - originator's address stored in the request is incorrect
936                                                                 KEY_BLOCKED = 2 - the requested key has been blocked
937 SENDER_ADDRESS           address  ERROR_TYPE == WRONG_ADDRESS Real originator's address.
938 KEY_BLOCK_REQUEST_LENGTH byte     ERROR_TYPE == KEY_BLOCKED   Length of the following request.
939 KEY_BLOCK_REQUEST        byte[]   ERROR_TYPE == KEY_BLOCKED   Request that blocks/unlocks the key.
940 SIGNATURE_LENGTH         short    ERROR_TYPE == KEY_BLOCKED   Length of the following signature.
941 SIGNATURE                byte[]   ERROR_TYPE == KEY_BLOCKED   Signature of the request.
942
943 */
944 static int
945 dissect_vuze_dht_reply_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver _U_ )
946 {
947   guint error_type;
948   guint8 key_block_request_len;
949   guint signature_len;
950
951   proto_tree_add_item(tree, hf_vuze_dht_error_type, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
952   error_type = tvb_get_ntohl( tvb, offset );
953   col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", val_to_str( error_type, vuze_dht_error_type_vals, "Unknown") );
954   offset += TL_INT;
955
956   switch(error_type)
957   {
958   case ET_WRONG_ADDRESS:
959     offset = dissect_vuze_dht_address( tvb, pinfo, tree, offset, "Sender Address" );
960     break;
961   case ET_KEY_BLOCKED:
962     proto_tree_add_item(tree, hf_vuze_dht_key_block_request_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
963     key_block_request_len = tvb_get_guint8( tvb, offset );
964     offset += TL_BYTE;
965
966     proto_tree_add_item(tree, hf_vuze_dht_key_block_request, tvb, offset, key_block_request_len, ENC_NA);
967     offset += key_block_request_len;
968
969     proto_tree_add_item(tree, hf_vuze_dht_signature_len, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
970     signature_len = tvb_get_ntohs( tvb, offset );
971     offset += TL_SHORT;
972
973     proto_tree_add_item(tree, hf_vuze_dht_signature, tvb, offset, signature_len, ENC_NA);
974     offset += signature_len;
975     break;
976   default:
977     break;
978   }
979
980   return offset;
981 }
982
983 /* --- Request Key block -----------------
984
985 Name                    | Type  | Note
986 SPOOF_ID                  int     Spoof ID obtained through FIND_NODE request.
987 KEY_BLOCK_REQUEST_LENGTH  byte    Length of the following request.
988 KEY_BLOCK_REQUEST         byte[]  Request that blocks/unlocks the key.
989 SIGNATURE_LENGTH          short   Length of the following signature.
990 SIGNATURE                 byte[]  Signature of the request.
991
992 */
993 static int
994 dissect_vuze_dht_request_key_block(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver _U_ )
995 {
996   guint8 key_block_request_len;
997   guint signature_len;
998
999   proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, ENC_BIG_ENDIAN);
1000   offset += TL_INT;
1001
1002   proto_tree_add_item(tree, hf_vuze_dht_key_block_request_len, tvb, offset, TL_BYTE, ENC_BIG_ENDIAN);
1003   key_block_request_len = tvb_get_guint8( tvb, offset );
1004   offset += TL_BYTE;
1005
1006   proto_tree_add_item(tree, hf_vuze_dht_key_block_request, tvb, offset, key_block_request_len, ENC_NA);
1007   offset += key_block_request_len;
1008
1009   proto_tree_add_item(tree, hf_vuze_dht_signature_len, tvb, offset, TL_SHORT, ENC_BIG_ENDIAN);
1010   signature_len = tvb_get_ntohs( tvb, offset );
1011   offset += TL_SHORT;
1012
1013   proto_tree_add_item(tree, hf_vuze_dht_signature, tvb, offset, signature_len, ENC_NA);
1014   offset += signature_len;
1015
1016   return offset;
1017 }
1018
1019 static int
1020 dissect_vuze_dht(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1021 {
1022   proto_item *ti;
1023   proto_tree *sub_tree;
1024   int action, proto_ver;
1025   int decoded_length = 0;
1026
1027   /* set the protocol column */
1028   col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vuze-DHT");
1029   /* clear the info column */
1030   col_clear( pinfo->cinfo, COL_INFO);
1031
1032   ti = proto_tree_add_item(tree, proto_vuze_dht, tvb, 0, -1, ENC_NA);
1033   sub_tree = proto_item_add_subtree(ti, ett_vuze_dht);
1034
1035   /*
1036     Requests always start with Connection IDs, which guaranteed to have their MSB set to 1
1037     Replies always start with the action, which always has the MSB clear
1038     Therefore, the MSB of an incoming packet should be used to distinguish requests from replies.
1039   */
1040   if( tvb_get_guint8(tvb,0) & 0x80 )
1041   {
1042     decoded_length = dissect_vuze_dht_request_header(tvb, pinfo, sub_tree, decoded_length, &action, &proto_ver );
1043   }
1044   else
1045   {
1046     decoded_length = dissect_vuze_dht_reply_header(tvb, pinfo, sub_tree, decoded_length, &action, &proto_ver );
1047   }
1048
1049   switch( action )
1050   {
1051   case AT_PING_REQUEST:
1052     break;
1053   case AT_PING_REPLY:
1054     decoded_length = dissect_vuze_dht_reply_ping(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1055     break;
1056   case AT_STORE_REQUEST:
1057     decoded_length = dissect_vuze_dht_request_store(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1058     break;
1059   case AT_STORE_REPLY:
1060     decoded_length = dissect_vuze_dht_reply_store(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1061     break;
1062   case AT_FIND_NODE_REQUEST:
1063     decoded_length = dissect_vuze_dht_request_find_node(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1064     break;
1065   case AT_FIND_NODE_REPLY:
1066     decoded_length = dissect_vuze_dht_reply_find_node(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1067     break;
1068   case AT_FIND_VALUE_REQUEST:
1069     decoded_length = dissect_vuze_dht_request_find_value(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1070     break;
1071   case AT_FIND_VALUE_REPLY:
1072     decoded_length = dissect_vuze_dht_reply_find_value(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1073     break;
1074   case AT_ERROR_REPLY:
1075     decoded_length = dissect_vuze_dht_reply_error(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1076     break;
1077   case AT_KEY_BLOCK_REQUEST:
1078     decoded_length = dissect_vuze_dht_request_key_block(tvb, pinfo, sub_tree, decoded_length, proto_ver );
1079     break;
1080   default:
1081     break;
1082   }
1083
1084   return decoded_length;
1085 }
1086
1087 void
1088 proto_register_vuze_dht(void)
1089 {
1090   static hf_register_info hf[] = {
1091     { &hf_vuze_dht_address,
1092       { "Address", "vuze-dht.address",
1093       FT_NONE, BASE_NONE, NULL, 0x0,
1094       NULL, HFILL }
1095     },
1096     { &hf_vuze_dht_address_len,
1097       { "Address Length", "vuze-dht.address.length",
1098       FT_UINT8, BASE_DEC, NULL, 0x0,
1099       NULL, HFILL }
1100     },
1101     { &hf_vuze_dht_address_v4,
1102       { "IPv4 Address", "vuze-dht.address.ipv4",
1103       FT_IPv4, BASE_NONE, NULL, 0x0,
1104       NULL, HFILL }
1105     },
1106     { &hf_vuze_dht_address_v6,
1107       { "IPv6 Address", "vuze-dht.address.ipv6",
1108       FT_IPv6, BASE_NONE, NULL, 0x0,
1109       NULL, HFILL }
1110     },
1111     { &hf_vuze_dht_address_port,
1112       { "Port", "vuze-dht.address.port",
1113       FT_UINT16, BASE_DEC, NULL, 0x0,
1114       NULL, HFILL }
1115     },
1116     { &hf_vuze_dht_contact,
1117       { "Contact", "vuze-dht.contact",
1118       FT_NONE, BASE_NONE,  NULL, 0x0,
1119       NULL, HFILL }
1120     },
1121     { &hf_vuze_dht_contact_type,
1122       { "Contact Type", "vuze-dht.contact.type",
1123       FT_UINT8, BASE_DEC,  VALS(vuze_dht_contact_type_vals), 0x0,
1124       NULL, HFILL }
1125     },
1126     { &hf_vuze_dht_proto_ver,
1127       { "Protocol Version", "vuze-dht.proto_ver",
1128       FT_UINT8, BASE_DEC,  NULL, 0x0,
1129       NULL, HFILL }
1130     },
1131     { &hf_vuze_dht_value,
1132       { "Value", "vuze-dht.value",
1133       FT_NONE, BASE_NONE,  NULL, 0x0,
1134       NULL, HFILL }
1135     },
1136     { &hf_vuze_dht_value_ver,
1137       { "Value Version", "vuze-dht.value.ver",
1138       FT_UINT32, BASE_DEC,  NULL, 0x0,
1139       NULL, HFILL }
1140     },
1141     { &hf_vuze_dht_value_created,
1142       { "Value Creation Time", "vuze-dht.value.creation_time",
1143       FT_UINT64, BASE_DEC,  NULL, 0x0,
1144       NULL, HFILL }
1145     },
1146     { &hf_vuze_dht_value_bytes_count,
1147       { "Value Bytes Count", "vuze-dht.value.bytes_count",
1148       FT_UINT16, BASE_DEC,  NULL, 0x0,
1149       NULL, HFILL }
1150     },
1151     { &hf_vuze_dht_value_bytes,
1152       { "Value Bytes", "vuze-dht.value.bytes",
1153       FT_BYTES, BASE_NONE,  NULL, 0x0,
1154       NULL, HFILL }
1155     },
1156     { &hf_vuze_dht_value_flags,
1157       { "Value Flags", "vuze-dht.value.flags",
1158       FT_UINT8, BASE_DEC,  NULL, 0x0,
1159       NULL, HFILL }
1160     },
1161     { &hf_vuze_dht_value_life_hours,
1162       { "Value Life Hours", "vuze-dht.value.life_hours",
1163       FT_UINT8, BASE_DEC,  NULL, 0x0,
1164       NULL, HFILL }
1165     },
1166     { &hf_vuze_dht_value_replication_factor,
1167       { "Value Replication Factor", "vuze-dht.value.replication_factor",
1168       FT_UINT8, BASE_DEC,  NULL, 0x0,
1169       NULL, HFILL }
1170     },
1171     { &hf_vuze_dht_connection_id,
1172       { "Connection ID", "vuze-dht.connection_id",
1173       FT_UINT64, BASE_DEC,  NULL, 0x0,
1174       NULL, HFILL }
1175     },
1176     { &hf_vuze_dht_action,
1177       { "Action", "vuze-dht.action",
1178       FT_UINT32, BASE_DEC,  VALS(vuze_dht_action_type_vals), 0x0,
1179       NULL, HFILL }
1180     },
1181     { &hf_vuze_dht_transaction_id,
1182       { "Transaction ID", "vuze-dht.transaction_id",
1183       FT_UINT32, BASE_DEC,  NULL, 0x0,
1184       NULL, HFILL }
1185     },
1186     { &hf_vuze_dht_vendor_id,
1187       { "Vendor ID", "vuze-dht.vendor_id",
1188       FT_UINT8, BASE_DEC,  NULL, 0x0,
1189       NULL, HFILL }
1190     },
1191     { &hf_vuze_dht_network_id,
1192       { "Network ID", "vuze-dht.network_id",
1193       FT_UINT32, BASE_DEC,  NULL, 0x0,
1194       NULL, HFILL }
1195     },
1196     { &hf_vuze_dht_local_proto_ver,
1197       { "Local Protocol Version", "vuze-dht.local_proto_ver",
1198       FT_UINT8, BASE_DEC,  NULL, 0x0,
1199       NULL, HFILL }
1200     },
1201     { &hf_vuze_dht_instance_id,
1202       { "Instance ID", "vuze-dht.instance_id",
1203       FT_UINT32, BASE_DEC,  NULL, 0x0,
1204       NULL, HFILL }
1205     },
1206     { &hf_vuze_dht_time,
1207       { "Time", "vuze-dht.time",
1208       FT_UINT64, BASE_DEC,  NULL, 0x0,
1209       NULL, HFILL }
1210     },
1211     { &hf_vuze_dht_network_coordinates_count,
1212       { "Network Coordinates Count", "vuze-dht.network_coordinates_count",
1213       FT_UINT8, BASE_DEC,  NULL, 0x0,
1214       NULL, HFILL }
1215     },
1216     { &hf_vuze_dht_network_coordinates,
1217       { "Network Coordinates", "vuze-dht.network_coordinates",
1218       FT_NONE, BASE_NONE,  NULL, 0x0,
1219       NULL, HFILL }
1220     },
1221     { &hf_vuze_dht_network_coordinate,
1222       { "Network Coordinate", "vuze-dht.network_coordinate",
1223       FT_NONE, BASE_NONE,  NULL, 0x0,
1224       NULL, HFILL }
1225     },
1226     { &hf_vuze_dht_network_coordinate_type,
1227       { "Network Coordinate Type", "vuze-dht.network_coordinate.type",
1228       FT_UINT8, BASE_DEC,  NULL, 0x0,
1229       NULL, HFILL }
1230     },
1231     { &hf_vuze_dht_network_coordinate_size,
1232       { "Network Coordinate Size", "vuze-dht.network_coordinate.size",
1233       FT_UINT8, BASE_DEC,  NULL, 0x0,
1234       NULL, HFILL }
1235     },
1236     { &hf_vuze_dht_network_coordinate_data,
1237       { "Network Coordinate Data", "vuze-dht.network_coordinate.data",
1238       FT_BYTES, BASE_NONE,  NULL, 0x0,
1239       NULL, HFILL }
1240     },
1241     { &hf_vuze_dht_spoof_id,
1242       { "Spoof ID", "vuze-dht.spoof_id",
1243       FT_UINT32, BASE_DEC,  NULL, 0x0,
1244       NULL, HFILL }
1245     },
1246     { &hf_vuze_dht_keys_count,
1247       { "Keys Count", "vuze-dht.keys_count",
1248       FT_UINT8, BASE_DEC,  NULL, 0x0,
1249       NULL, HFILL }
1250     },
1251     { &hf_vuze_dht_keys,
1252       { "Keys", "vuze-dht.keys",
1253       FT_NONE, BASE_NONE,  NULL, 0x0,
1254       NULL, HFILL }
1255     },
1256     { &hf_vuze_dht_key,
1257       { "Key", "vuze-dht.key",
1258       FT_NONE, BASE_NONE,  NULL, 0x0,
1259       NULL, HFILL }
1260     },
1261     { &hf_vuze_dht_key_len,
1262       { "Key Length", "vuze-dht.key.len",
1263       FT_UINT8, BASE_DEC,  NULL, 0x0,
1264       NULL, HFILL }
1265     },
1266     { &hf_vuze_dht_key_data,
1267       { "Key Data", "vuze-dht.key.data",
1268       FT_BYTES, BASE_NONE,  NULL, 0x0,
1269       NULL, HFILL }
1270     },
1271     { &hf_vuze_dht_values_count,
1272       { "Values Count", "vuze-dht.values_count",
1273       FT_UINT16, BASE_DEC,  NULL, 0x0,
1274       NULL, HFILL }
1275     },
1276     { &hf_vuze_dht_value_groups_count,
1277       { "Value Groups Count", "vuze-dht.value_groups_count",
1278       FT_UINT8, BASE_DEC,  NULL, 0x0,
1279       NULL, HFILL }
1280     },
1281     { &hf_vuze_dht_value_group,
1282       { "Values", "vuze-dht.values",
1283       FT_NONE, BASE_NONE,  NULL, 0x0,
1284       NULL, HFILL }
1285     },
1286     { &hf_vuze_dht_value_groups,
1287       { "Value Groups", "vuze-dht.value_groups",
1288       FT_NONE, BASE_NONE,  NULL, 0x0,
1289       NULL, HFILL }
1290     },
1291     { &hf_vuze_dht_diversifications_len,
1292       { "Diversifications Length", "vuze-dht.diversifications_len",
1293       FT_UINT8, BASE_DEC,  NULL, 0x0,
1294       NULL, HFILL }
1295     },
1296     { &hf_vuze_dht_diversifications,
1297       { "Diversifications", "vuze-dht.diversifications",
1298       FT_BYTES, BASE_NONE,  NULL, 0x0,
1299       NULL, HFILL }
1300     },
1301     { &hf_vuze_dht_id_len,
1302       { "ID Length", "vuze-dht.id_len",
1303       FT_UINT8, BASE_DEC,  NULL, 0x0,
1304       NULL, HFILL }
1305     },
1306     { &hf_vuze_dht_id,
1307       { "ID", "vuze-dht.id",
1308       FT_BYTES, BASE_NONE,  NULL, 0x0,
1309       NULL, HFILL }
1310     },
1311     { &hf_vuze_dht_node_status,
1312       { "Node Status", "vuze-dht.node_status",
1313       FT_UINT32, BASE_HEX,  NULL, 0x0,
1314       NULL, HFILL }
1315     },
1316     { &hf_vuze_dht_size,
1317       { "DHT Size", "vuze-dht.dht_size",
1318       FT_UINT32, BASE_DEC,  NULL, 0x0,
1319       NULL, HFILL }
1320     },
1321     { &hf_vuze_dht_node_type,
1322       { "Node Type", "vuze-dht.node_type",
1323       FT_UINT32, BASE_DEC,  VALS(vuze_dht_node_type_vals), 0x0,
1324       NULL, HFILL }
1325     },
1326     { &hf_vuze_dht_contacts_count,
1327       { "Contacts Count", "vuze-dht.contacts_count",
1328       FT_UINT16, BASE_DEC,  NULL, 0x0,
1329       NULL, HFILL }
1330     },
1331     { &hf_vuze_dht_contacts,
1332       { "Contacts", "vuze-dht.contacts",
1333       FT_NONE, BASE_NONE,  NULL, 0x0,
1334       NULL, HFILL }
1335     },
1336     { &hf_vuze_dht_flags,
1337       { "Flags", "vuze-dht.flags",
1338       FT_UINT8, BASE_DEC,  VALS(vuze_dht_flag_type_vals), 0x0,
1339       NULL, HFILL }
1340     },
1341     { &hf_vuze_dht_values_num,
1342       { "Values Num", "vuze-dht.stats.values_num",
1343       FT_UINT32, BASE_DEC,  NULL, 0x0,
1344       NULL, HFILL }
1345     },
1346     { &hf_vuze_dht_values_total,
1347       { "Values Total", "vuze-dht.stats.values_total",
1348       FT_UINT32, BASE_DEC,  NULL, 0x0,
1349       NULL, HFILL }
1350     },
1351     { &hf_vuze_dht_reads_per_min,
1352       { "Reads Per Minute", "vuze-dht.stats.reads_per_min",
1353       FT_UINT32, BASE_DEC,  NULL, 0x0,
1354       NULL, HFILL }
1355     },
1356     { &hf_vuze_dht_diversification_type,
1357       { "Diversification Type", "vuze-dht.stats.diversification_type",
1358       FT_UINT8, BASE_DEC,  NULL, 0x0,
1359       NULL, HFILL }
1360     },
1361     { &hf_vuze_dht_max_values,
1362       { "Max values", "vuze-dht.max_values",
1363       FT_UINT8, BASE_DEC,  NULL, 0x0,
1364       NULL, HFILL }
1365     },
1366     { &hf_vuze_dht_has_continuation,
1367       { "Has Continuation", "vuze-dht.has_continuation",
1368       FT_UINT8, BASE_DEC,  VALS(vuze_dht_bool_type_vals), 0x0,
1369       NULL, HFILL }
1370     },
1371     { &hf_vuze_dht_has_values,
1372       { "Has Values", "vuze-dht.has_values",
1373       FT_UINT8, BASE_DEC,  VALS(vuze_dht_bool_type_vals), 0x0,
1374       NULL, HFILL }
1375     },
1376     { &hf_vuze_dht_error_type,
1377       { "Error Type", "vuze-dht.error_type",
1378       FT_UINT32, BASE_DEC,  VALS(vuze_dht_error_type_vals), 0x0,
1379       NULL, HFILL }
1380     },
1381     { &hf_vuze_dht_key_block_request_len,
1382       { "Key Block Request Length", "vuze-dht.key_block_request_len",
1383       FT_UINT8, BASE_DEC,  NULL, 0x0,
1384       NULL, HFILL }
1385     },
1386     { &hf_vuze_dht_key_block_request,
1387       { "Key Block Request", "vuze-dht.key_block_request",
1388       FT_BYTES, BASE_NONE,  NULL, 0x0,
1389       NULL, HFILL }
1390     },
1391     { &hf_vuze_dht_signature_len,
1392       { "Signature Length", "vuze-dht.signature_len",
1393       FT_UINT16, BASE_DEC,  NULL, 0x0,
1394       NULL, HFILL }
1395     },
1396     { &hf_vuze_dht_signature,
1397       { "Signature", "vuze-dht.signature",
1398       FT_BYTES, BASE_NONE,  NULL, 0x0,
1399       NULL, HFILL }
1400     }
1401   };
1402
1403   /* Setup protocol subtree array */
1404   static gint *ett[] = {
1405       &ett_vuze_dht,
1406       &ett_vuze_dht_address,
1407       &ett_vuze_dht_contacts,
1408       &ett_vuze_dht_contact,
1409       &ett_vuze_dht_keys,
1410       &ett_vuze_dht_key,
1411       &ett_vuze_dht_value_groups,
1412       &ett_vuze_dht_value_group,
1413       &ett_vuze_dht_value,
1414       &ett_vuze_dht_network_coordinates,
1415       &ett_vuze_dht_network_coordinate
1416   };
1417
1418   module_t *vuze_dht_module;
1419
1420   /* Register protocol */
1421   proto_vuze_dht = proto_register_protocol (
1422                         "Vuze DHT Protocol",  /* name */
1423                         "Vuze-DHT",               /* short name */
1424                         "vuze-dht"                /* abbrev */
1425                         );
1426
1427   proto_register_field_array(proto_vuze_dht, hf, array_length(hf));
1428   proto_register_subtree_array(ett, array_length(ett));
1429   new_register_dissector("vuze-dht", dissect_vuze_dht, proto_vuze_dht);
1430
1431   /* Register our configuration options */
1432   vuze_dht_module = prefs_register_protocol(proto_vuze_dht, proto_reg_handoff_vuze_dht);
1433
1434   prefs_register_uint_preference(vuze_dht_module, "udp_port",
1435                                            "Vuze DHT Protocol UDP port",
1436                                            "Set the UDP port for Vuze DHT Protocol.",
1437                                            10, &global_vuze_dht_udp_port);
1438 }
1439
1440 void
1441 proto_reg_handoff_vuze_dht(void)
1442 {
1443   static gboolean vuze_dht_prefs_initialized = FALSE;
1444   static dissector_handle_t vuze_dht_handle;
1445   static guint vuze_dht_udp_port;
1446
1447   if (!vuze_dht_prefs_initialized)
1448   {
1449     vuze_dht_handle = new_create_dissector_handle(dissect_vuze_dht, proto_vuze_dht);
1450     vuze_dht_prefs_initialized = TRUE;
1451   }
1452   else
1453   {
1454     dissector_delete_uint("udp.port", vuze_dht_udp_port, vuze_dht_handle);
1455   }
1456
1457   /* Set our port number for future use */
1458   vuze_dht_udp_port = global_vuze_dht_udp_port;
1459   dissector_add_uint("udp.port", global_vuze_dht_udp_port, vuze_dht_handle);
1460 }
1461 /*
1462  * Editor modelines
1463  *
1464  * Local Variables:
1465  * c-basic-offset: 2
1466  * tab-width: 8
1467  * indent-tabs-mode: nil
1468  * End:
1469  *
1470  * ex: set shiftwidth=2 tabstop=8 expandtab:
1471  * :indentSize=2:tabSize=8:noTabs=true:
1472  */
1473