aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-vuze-dht.c
diff options
context:
space:
mode:
authorBill Meier <wmeier@newsguy.com>2011-06-22 19:52:13 +0000
committerBill Meier <wmeier@newsguy.com>2011-06-22 19:52:13 +0000
commitf11f450bf0dd462810cfc9842150f88f4352cb55 (patch)
tree4ded4528cec42e1c3cc25779a2a68458c6411c80 /epan/dissectors/packet-vuze-dht.c
parent05d9997311b579ebfb4267f78d1dc5218fc00179 (diff)
From Xiao Xiangquan: A new dissector for Vuze DHT;
Vuze, called Azureus before, is a great BT client and has a lot of users, while its DHT implementation is different from the official one. From me: New-style dissectors are supposed to to always return "bytes dissected" (not just when tree != NULL); svn path=/trunk/; revision=37755
Diffstat (limited to 'epan/dissectors/packet-vuze-dht.c')
-rw-r--r--epan/dissectors/packet-vuze-dht.c1473
1 files changed, 1473 insertions, 0 deletions
diff --git a/epan/dissectors/packet-vuze-dht.c b/epan/dissectors/packet-vuze-dht.c
new file mode 100644
index 0000000000..15ddc7c50b
--- /dev/null
+++ b/epan/dissectors/packet-vuze-dht.c
@@ -0,0 +1,1473 @@
+/* packet-vuze-dht.c
+ * Routines for Vuze-DHT dissection
+ * Copyright 2011, Xiao Xiangquan <xiaoxiangquan@gmail.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1999 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+#define DEFAULT_UDP_PORT 11273
+
+/* --- protocol specification:
+ * http://wiki.vuze.com/w/Distributed_hash_table
+ */
+
+/* protocol versions */
+enum {
+ PV_DIV_AND_CONT = 6,
+ PV_ANTI_SPOOF = 7,
+ PV_ANTI_SPOOF2 = 8,
+ PV_FIX_ORIGINATOR = 9,
+ PV_NETWORKS = 9,
+ PV_VIVALDI = 10,
+ PV_REMOVE_DIST_ADD_VER = 11,
+ PV_XFER_STATUS = 12,
+ PV_SIZE_ESTIMATE = 13,
+ PV_VENDOR_ID = 14,
+ PV_BLOCK_KEYS = 14,
+ PV_GENERIC_NETPOS = 15,
+ PV_VIVALDI_FINDVALUE = 16,
+ PV_ANON_VALUES = 17,
+ PV_CVS_FIX_OVERLOAD_V1 = 18,
+ PV_CVS_FIX_OVERLOAD_V2 = 19,
+ PV_MORE_STATS = 20,
+ PV_CVS_FIX_OVERLOAD_V3 = 21,
+ PV_MORE_NODE_STATUS = 22,
+ PV_LONGER_LIFE = 23,
+ PV_REPLICATION_CONTROL = 24,
+ PV_RESTRICT_ID_PORTS = 32,
+ PV_RESTRICT_ID_PORTS2 = 33,
+ PV_RESTRICT_ID_PORTS2X = 34,
+ PV_RESTRICT_ID_PORTS2Y = 35,
+ PV_RESTRICT_ID_PORTS2Z = 36,
+ PV_RESTRICT_ID3 = 50
+};
+
+/* Type Length */
+enum {
+ TL_BYTE = 1,
+ TL_BOOL = 1,
+ TL_SHORT = 2,
+ TL_INT = 4,
+ TL_IPv4 = 4,
+ TL_LONG = 8,
+ TL_IPv6 = 16
+};
+
+/* Bool type */
+enum {
+ BT_FALSE = 0x0,
+ BT_TRUE = 0x1
+};
+static const value_string vuze_dht_bool_type_vals[] = {
+ { BT_FALSE, "False" },
+ { BT_TRUE, "True" },
+ { 0, NULL }
+};
+
+/* action type */
+enum {
+ AT_PING_REQUEST = 1024,
+ AT_PING_REPLY = 1025,
+ AT_STORE_REQUEST = 1026,
+ AT_STORE_REPLY = 1027,
+ AT_FIND_NODE_REQUEST = 1028,
+ AT_FIND_NODE_REPLY = 1029,
+ AT_FIND_VALUE_REQUEST = 1030,
+ AT_FIND_VALUE_REPLY = 1031,
+ AT_ERROR_REPLY = 1032,
+ AT_KEY_BLOCK_REQUEST = 1036,
+ AT_KEY_BLOCK_REPLY = 1037
+};
+static const value_string vuze_dht_action_type_vals[] = {
+ { AT_PING_REQUEST, "PING request" },
+ { AT_PING_REPLY, "PING reply" },
+ { AT_STORE_REQUEST, "STORE request" },
+ { AT_STORE_REPLY, "STORE reply" },
+ { AT_FIND_NODE_REQUEST, "FIND_NODE request" },
+ { AT_FIND_NODE_REPLY, "FIND_NODE reply" },
+ { AT_FIND_VALUE_REQUEST, "FIND_VALUE request" },
+ { AT_FIND_VALUE_REPLY, "FIND_VALUE reply" },
+ { AT_ERROR_REPLY, "ERROR reply" },
+ { AT_KEY_BLOCK_REQUEST, "kEY_BLOCK request" },
+ { AT_KEY_BLOCK_REPLY, "KEY_BLOCK reply" },
+ { 0, NULL }
+};
+
+/* Contact type, must be 1(UDP) */
+enum {
+ CONTACT_UDP = 1
+};
+static const value_string vuze_dht_contact_type_vals[] = {
+ { CONTACT_UDP, "UDP" },
+ { 0, NULL }
+};
+
+/* Node type */
+enum {
+ NT_BOOTSTRAP_NODE = 0x0,
+ NT_ORDINARY_NODE = 0x1,
+ NT_UNKNOWN_NODE = 0xffffffff
+};
+static const value_string vuze_dht_node_type_vals[] = {
+ { NT_BOOTSTRAP_NODE, "Bootstrap node" },
+ { NT_ORDINARY_NODE, "Ordinary node" },
+ { NT_UNKNOWN_NODE, "Unknown node" },
+ { 0, NULL }
+};
+
+/* flag type */
+enum {
+ FT_SINGLE_VALUE = 0x00,
+ FT_DOWNLOADING = 0x01,
+ FT_SEEDING = 0x02,
+ FT_MULTI_VALUE = 0x04,
+ FT_STATS = 0x08
+};
+static const value_string vuze_dht_flag_type_vals[] = {
+ { FT_SINGLE_VALUE, "Single value" },
+ { FT_DOWNLOADING, "Downloading" },
+ { FT_SEEDING, "Seeding" },
+ { FT_MULTI_VALUE, "Multi value" },
+ { FT_STATS, "Stats" },
+ { 0, NULL }
+};
+
+/* error type */
+enum {
+ ET_WRONG_ADDRESS = 1,
+ ET_KEY_BLOCKED = 2
+};
+static const value_string vuze_dht_error_type_vals[] = {
+ { ET_WRONG_ADDRESS, "Originator's address stored in the request is incorrect" },
+ { ET_KEY_BLOCKED, "The requested key has been blocked" },
+ { 0, NULL }
+};
+
+static int proto_vuze_dht = -1;
+
+/* --- fields ---*/
+
+/* address appears in contacts, request header, reply error */
+static int hf_vuze_dht_address = -1;
+static int hf_vuze_dht_address_len = -1;
+static int hf_vuze_dht_address_v4 = -1;
+static int hf_vuze_dht_address_v6 = -1;
+static int hf_vuze_dht_address_port = -1;
+
+/* contact appears in values, reply find_node, reply find_value */
+static int hf_vuze_dht_contact = -1;
+static int hf_vuze_dht_contact_type = -1;
+static int hf_vuze_dht_proto_ver = -1;
+
+/* value appears in reply find_value */
+static int hf_vuze_dht_value = -1;
+static int hf_vuze_dht_value_ver = -1;
+static int hf_vuze_dht_value_created = -1;
+static int hf_vuze_dht_value_bytes_count = -1;
+static int hf_vuze_dht_value_bytes = -1;
+static int hf_vuze_dht_value_flags = -1;
+static int hf_vuze_dht_value_life_hours = -1;
+static int hf_vuze_dht_value_replication_factor = -1;
+
+/* firstly appear in request header */
+static int hf_vuze_dht_connection_id = -1;
+static int hf_vuze_dht_action = -1;
+static int hf_vuze_dht_transaction_id = -1;
+static int hf_vuze_dht_vendor_id = -1;
+static int hf_vuze_dht_network_id = -1;
+static int hf_vuze_dht_local_proto_ver = -1;
+static int hf_vuze_dht_instance_id = -1;
+static int hf_vuze_dht_time = -1;
+
+/* firstly appear in reply ping */
+static int hf_vuze_dht_network_coordinates_count = -1;
+static int hf_vuze_dht_network_coordinates = -1;
+static int hf_vuze_dht_network_coordinate = -1;
+static int hf_vuze_dht_network_coordinate_type = -1;
+static int hf_vuze_dht_network_coordinate_size = -1;
+static int hf_vuze_dht_network_coordinate_data = -1;
+
+/* firstly appear in request store */
+static int hf_vuze_dht_spoof_id = -1;
+static int hf_vuze_dht_keys_count = -1;
+static int hf_vuze_dht_keys = -1;
+static int hf_vuze_dht_key = -1;
+static int hf_vuze_dht_key_len = -1;
+static int hf_vuze_dht_key_data = -1;
+static int hf_vuze_dht_value_group = -1;
+static int hf_vuze_dht_value_groups = -1;
+static int hf_vuze_dht_value_groups_count = -1;
+static int hf_vuze_dht_values_count = -1;
+
+/* firstly appear in reply store */
+static int hf_vuze_dht_diversifications_len = -1;
+static int hf_vuze_dht_diversifications = -1;
+
+/* firstly appear in request find_node */
+static int hf_vuze_dht_id_len = -1;
+static int hf_vuze_dht_id = -1;
+static int hf_vuze_dht_node_status = -1;
+static int hf_vuze_dht_size = -1;
+
+/* firstly appear in reply find_node */
+static int hf_vuze_dht_node_type = -1;
+static int hf_vuze_dht_contacts_count = -1;
+static int hf_vuze_dht_contacts = -1;
+
+/* firstly appear in request find_value */
+static int hf_vuze_dht_flags = -1;
+static int hf_vuze_dht_values_num = -1;
+static int hf_vuze_dht_values_total = -1;
+static int hf_vuze_dht_reads_per_min = -1;
+static int hf_vuze_dht_diversification_type = -1;
+static int hf_vuze_dht_max_values = -1;
+
+/* firstly appear in reply find_value */
+static int hf_vuze_dht_has_continuation = -1;
+static int hf_vuze_dht_has_values = -1;
+
+/* firstly appear in reply error */
+static int hf_vuze_dht_error_type = -1;
+static int hf_vuze_dht_key_block_request_len = -1;
+static int hf_vuze_dht_key_block_request = -1;
+static int hf_vuze_dht_signature_len = -1;
+static int hf_vuze_dht_signature = -1;
+
+/* trees */
+static gint ett_vuze_dht = -1;
+static gint ett_vuze_dht_address = -1;
+static gint ett_vuze_dht_contacts = -1;
+static gint ett_vuze_dht_contact = -1;
+static gint ett_vuze_dht_keys = -1;
+static gint ett_vuze_dht_key = -1;
+static gint ett_vuze_dht_value_groups = -1;
+static gint ett_vuze_dht_value_group = -1;
+static gint ett_vuze_dht_value = -1;
+static gint ett_vuze_dht_network_coordinates = -1;
+static gint ett_vuze_dht_network_coordinate = -1;
+
+/* port use */
+static guint global_vuze_dht_udp_port = DEFAULT_UDP_PORT;
+
+void proto_reg_handoff_vuze_dht(void);
+
+/* --- Address format --------------
+
+byte: indicates length of the IP address (4 for IPv4, 16 for IPv6)
+4 or 16 bytes: the address in network byte order
+short: port number
+
+*/
+static int
+dissect_vuze_dht_address(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, const char* addr_name)
+{
+ guint8 ip_length;
+ proto_tree *sub_tree;
+ proto_item *ti;
+ address addr;
+
+ ip_length = tvb_get_guint8(tvb,offset);
+ /* the decoded length is ip length+3, see the format above */
+ ti = proto_tree_add_none_format(tree, hf_vuze_dht_address, tvb, offset, ip_length+3, "%s: ", addr_name );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_address);
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_address_len, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+
+ switch(ip_length)
+ {
+ case TL_IPv4:
+ proto_tree_add_item(sub_tree, hf_vuze_dht_address_v4, tvb, offset, ip_length, FALSE);
+ SET_ADDRESS( &addr, AT_IPv4, ip_length, tvb_get_ptr( tvb, offset, ip_length) );
+ break;
+ case TL_IPv6:
+ proto_tree_add_item(sub_tree, hf_vuze_dht_address_v6, tvb, offset, ip_length, FALSE);
+ SET_ADDRESS( &addr, AT_IPv6, ip_length, tvb_get_ptr( tvb, offset, ip_length) );
+ break;
+ default:
+ addr.type = AT_NONE;
+ break;
+ }
+ offset += ip_length;
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_address_port, tvb, offset, TL_SHORT, FALSE);
+ proto_item_append_text( ti, "%s:%d", ep_address_to_str( &addr ), tvb_get_ntohs(tvb,offset) );
+ offset += TL_SHORT;
+
+ return offset;
+}
+
+/* --- Contact format --------------
+
+byte: indicates contact type, which must be UDP(1)
+byte: the contact's protocol version
+7 or 19 bytes: Address
+
+*/
+static int
+dissect_vuze_dht_contact(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+
+ /* the decoded length is ip length+5, see the format above */
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_contact, tvb, offset, tvb_get_guint8(tvb,offset+2)+5,
+ "%s contact, version %d",
+ val_to_str( tvb_get_guint8(tvb, offset), vuze_dht_contact_type_vals, "Unknown"),
+ tvb_get_guint8(tvb, offset+1) );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_contact);
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_contact_type, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ proto_tree_add_item(sub_tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ offset = dissect_vuze_dht_address( tvb, pinfo, sub_tree, offset, "Contact Address" );
+
+ return offset;
+}
+
+/* --- Contact List --- */
+static int
+dissect_vuze_dht_contacts(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int contacts_count)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int i;
+
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_contacts, tvb, offset, 0, "%d contacts", contacts_count );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_contacts);
+ for( i=1; i<=contacts_count; i++ )
+ offset = dissect_vuze_dht_contact( tvb, pinfo, sub_tree, offset );
+
+ return offset;
+}
+
+/* --- Key format
+ Name | Type
+ LENGTH byte
+ KEY byte[LENGTH]
+ --- */
+static int
+dissect_vuze_dht_key(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ guint key_len;
+
+ key_len = tvb_get_guint8( tvb, offset );
+ ti = proto_tree_add_item( tree, hf_vuze_dht_key, tvb, offset, key_len+1, FALSE );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_key);
+
+ proto_tree_add_item( sub_tree, hf_vuze_dht_key_len, tvb, offset, TL_BYTE, FALSE );
+ offset += TL_BYTE;
+
+ proto_tree_add_item( sub_tree, hf_vuze_dht_key_data, tvb, offset, key_len, FALSE );
+ proto_item_append_text( ti, ": %d bytes ( %s )", key_len, tvb_bytes_to_str(tvb, offset, key_len ) );
+ offset += key_len;
+
+ return offset;
+}
+
+/* --- Keys List --- */
+static int
+dissect_vuze_dht_keys(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int keys_count)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int i;
+
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_keys, tvb, offset, 0, "%d keys", keys_count );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_keys);
+ for( i=1; i<=keys_count; i++ )
+ offset = dissect_vuze_dht_key( tvb, pinfo, sub_tree, offset );
+
+ return offset;
+}
+
+/* --- Value format --------------
+
+Name | Type | Protocol version | Note
+VERSION byte >=REMOVE_DIST_ADD_VER Version of the value. (details later)
+CREATED long always Creation time. Units unknown; probably milliseconds since the epoch.
+VALUE_BYTES_COUNT short always Number of bytes in the value.
+VALUE_BYTES bytes always The bytes of the value.
+ORIGINATOR contact always presumably the node that created the value.
+FLAGS byte always
+LIFE_HOURS byte >=LONGER_LIFE Hours for the value to live. (Details of how it's handled)
+REPLICATION_FACTOR byte >=REPLICATION_CONTROL Per-value # of replicas to maintain.
+
+If STATS are used in request, then some stats for the value are returned instead of value itself.
+They are serialised as follows:
+ 0 (byte) - version,
+ number of stored values for the key (int),
+ total size of stored values (int),
+ reads per minute (int),
+ diversification type (byte).
+*/
+static int
+dissect_vuze_dht_value(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int value_ver = -1;
+
+ ti = proto_tree_add_item( tree, hf_vuze_dht_value, tvb, offset, 0, FALSE );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value);
+ if( ver >= PV_REMOVE_DIST_ADD_VER )
+ {
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_ver, tvb, offset, TL_INT, FALSE);
+ value_ver = tvb_get_ntohl( tvb, offset );
+ offset += TL_INT;
+ }
+ /* It's a return for STATS */
+ if( value_ver==0 )
+ {
+ proto_item_append_text( ti,
+ " (reply to STATS): %d values for the key, out of %d in total...",
+ tvb_get_ntohl(tvb, offset), tvb_get_ntohl(tvb, offset+TL_INT) );
+
+ proto_tree_add_item(tree, hf_vuze_dht_values_num, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ proto_tree_add_item(tree, hf_vuze_dht_values_total, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ proto_tree_add_item(tree, hf_vuze_dht_reads_per_min, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ proto_tree_add_item(tree, hf_vuze_dht_diversification_type, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+ /* regular value */
+ else
+ {
+ int value_bytes_count;
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_created, tvb, offset, TL_LONG, FALSE);
+ offset += TL_LONG;
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_bytes_count, tvb, offset, TL_SHORT, FALSE);
+ value_bytes_count = tvb_get_ntohs(tvb, offset);
+ offset += TL_SHORT;
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_bytes, tvb, offset, value_bytes_count, FALSE);
+ proto_item_append_text( ti, ": %d bytes ( %s )", value_bytes_count, tvb_bytes_to_str(tvb, offset, value_bytes_count ) );
+ offset += value_bytes_count;
+
+ offset = dissect_vuze_dht_contact( tvb, pinfo, sub_tree, offset );
+
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_flags, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_life_hours, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ proto_tree_add_item(sub_tree, hf_vuze_dht_value_replication_factor, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+
+ return offset;
+}
+
+/* --- Values format
+values_count short
+values value[values_count]
+ --- */
+static int
+dissect_vuze_dht_value_group(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int values_count;
+ int i;
+
+ values_count = tvb_get_ntohs( tvb, offset );
+
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_value_group, tvb, offset, 0, "%d values", values_count );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value_group);
+
+ proto_tree_add_item( sub_tree, hf_vuze_dht_values_count, tvb, offset, TL_SHORT, FALSE );
+ offset += TL_SHORT;
+
+ for( i=1; i<=values_count; i++ )
+ offset = dissect_vuze_dht_value( tvb, pinfo, sub_tree, offset, ver );
+
+ return offset;
+}
+
+/* --- Values Groups format
+value_group[value_groups_count]
+ --- */
+static int
+dissect_vuze_dht_value_groups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int value_groups_count, int ver)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int i;
+
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_value_groups, tvb, offset, 0, "%d value groups", value_groups_count );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_value_groups);
+ for( i=1; i<=value_groups_count; i++ )
+ offset = dissect_vuze_dht_value_group( tvb, pinfo, sub_tree, offset, ver );
+
+ return offset;
+}
+
+/* --- Network Coordinates format ------
+Name | Type
+TYPE byte
+SIZE byte
+Network Coordinates byte[SIZE]
+ */
+static int
+dissect_vuze_dht_network_coordinate(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ guint coordinate_size;
+
+ coordinate_size = tvb_get_guint8( tvb, offset+1 );
+
+ ti = proto_tree_add_item( tree, hf_vuze_dht_network_coordinate, tvb, offset, coordinate_size+2, FALSE );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_network_coordinate);
+
+ proto_item_append_text( ti, ": type %d, length %d ( %s )",
+ tvb_get_guint8(tvb,offset), tvb_get_guint8(tvb,offset+TL_BYTE), tvb_bytes_to_str(tvb, offset+TL_BYTE+TL_BYTE, coordinate_size ) );
+
+ proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_type, tvb, offset, TL_BYTE, FALSE );
+ offset += TL_BYTE;
+ proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_size, tvb, offset, TL_BYTE, FALSE );
+ offset += TL_BYTE;
+ proto_tree_add_item( sub_tree, hf_vuze_dht_network_coordinate_data, tvb, offset, coordinate_size, FALSE );
+ offset += coordinate_size;
+
+ return offset;
+}
+
+/* --- Network Coordinates List ---
+Name | Type | Protocol version
+Network Coordinates Count byte >=PV_GENERIC_NETPOS
+Network Coordinates Network Coordinate >=PV_GENERIC_NETPOS
+ */
+static int
+dissect_vuze_dht_network_coordinates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ guint i;
+ guint network_coordinates_count;
+
+ if( ver >= PV_GENERIC_NETPOS )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_network_coordinates_count, tvb, offset, TL_BYTE, FALSE);
+ network_coordinates_count = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ ti = proto_tree_add_none_format( tree, hf_vuze_dht_network_coordinates, tvb, offset, 0, "%d network coordinates", network_coordinates_count );
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht_network_coordinates);
+ for( i=1; i<=network_coordinates_count; i++ )
+ offset = dissect_vuze_dht_network_coordinate( tvb, pinfo, sub_tree, offset );
+ }
+ return offset;
+}
+
+/* --- Request Header format --------------
+
+Name | Type | Protocol version | Note
+CONNECTION_ID long always random number with most significant bit set to 1
+ACTION int always type of the packet
+TRANSACTION_ID int always unique number used through the communication; it is randomly generated
+ at the start of the application and increased by 1 with each sent packet
+PROTOCOL_VERSION byte always version of protocol used in this packet
+VENDOR_ID byte >=VENDOR_ID ID of the DHT implementator; 0 = Azureus, 1 = ShareNet, 255 = unknown
+NETWORK_ID int >=NETWORKS ID of the network; 0 = stable version; 1 = CVS version
+LOCAL_PROTOCOL_VERSION byte >=FIX_ORIGINATOR maximum protocol version this node supports; if this packet's protocol
+ version is <FIX_ORIGINATOR then the value is stored at the end of the packet
+NODE_ADDRESS address always address of the local node
+INSTANCE_ID int always application's helper number; randomly generated at the start
+TIME long always time of the local node; stored as number of milliseconds since Epoch
+
+*/
+static int
+dissect_vuze_dht_request_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int *action, int *ver )
+{
+ proto_tree_add_item(tree, hf_vuze_dht_connection_id, tvb, offset, TL_LONG, FALSE);
+ offset += TL_LONG;
+
+ proto_tree_add_item(tree, hf_vuze_dht_action, tvb, offset, TL_INT, FALSE);
+ *action = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Action: %s", val_to_str( *action, vuze_dht_action_type_vals, "Unknown") );
+ offset += TL_INT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_transaction_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, FALSE);
+ *ver = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ if( *ver >= PV_VENDOR_ID )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_vendor_id, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+
+ if( *ver > PV_NETWORKS )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_network_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+ if( *ver > PV_FIX_ORIGINATOR )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_local_proto_ver, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+
+ offset = dissect_vuze_dht_address(tvb, pinfo, tree, offset, "Local Address");
+ proto_tree_add_item(tree, hf_vuze_dht_instance_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ proto_tree_add_item(tree, hf_vuze_dht_time, tvb, offset, TL_LONG, FALSE);
+ offset += TL_LONG;
+
+ return offset;
+}
+
+/* --- Reply Header format --------------
+
+Name | Type | Protocol version | Note
+ACTION int always type of the packet
+TRANSACTION_ID int always must be equal to TRANSACTION_ID from the request
+CONNECTION_ID long always must be equal to CONNECTION_ID from the request
+PROTOCOL_VERSION byte always version of protocol used in this packet
+VENDOR_ID byte >=VENDOR_ID same meaning as in the request
+NETWORK_ID int >=NETWORKS same meaning as in the request
+INSTANCE_ID int always instance id of the node that replies to the request
+
+*/
+static int
+dissect_vuze_dht_reply_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int *action, int *ver )
+{
+ proto_tree_add_item(tree, hf_vuze_dht_action, tvb, offset, TL_INT, FALSE);
+ *action = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Action: %s", val_to_str( *action, vuze_dht_action_type_vals, "Unknown") );
+ offset += TL_INT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_transaction_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_connection_id, tvb, offset, TL_LONG, FALSE);
+ offset += TL_LONG;
+
+ proto_tree_add_item(tree, hf_vuze_dht_proto_ver, tvb, offset, TL_BYTE, FALSE);
+ *ver = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ if( *ver >= PV_VENDOR_ID )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_vendor_id, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+
+ if( *ver > PV_NETWORKS )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_network_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+
+ proto_tree_add_item(tree, hf_vuze_dht_instance_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+
+ return offset;
+}
+
+/* --- Reply Ping -----------------
+
+ACTION equal to 1025
+If protocol version is >=VIVALDI then packet's body carries network coordinates.
+
+*/
+static int
+dissect_vuze_dht_reply_ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
+{
+ if( ver >= PV_VIVALDI )
+ {
+ offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
+ }
+ return offset;
+}
+
+/* --- Request Store -----------------
+
+Name | Type | Protocol version | Note
+SPOOF_ID int >=ANTI_SPOOF Spoof ID of the target node; it must be the same number as previously retrived through FIND_NODE reply.
+KEYS_COUNT byte always Number of keys that follow.
+KEYS keys always Keys that the target node should store.
+VALUE_GROUPS_COUNT byte always Number of groups of values this packet contains.
+VALUES value groups always Groups of values, one for each key; values are stored in the same order as keys.
+
+*/
+static int
+dissect_vuze_dht_request_store(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
+{
+ guint8 keys_count, value_groups_count;
+ if( ver >= PV_ANTI_SPOOF )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+ proto_tree_add_item(tree, hf_vuze_dht_keys_count, tvb, offset, TL_BYTE, FALSE);
+ keys_count = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ offset = dissect_vuze_dht_keys( tvb, pinfo, tree, offset, keys_count );
+
+ proto_tree_add_item(tree, hf_vuze_dht_value_groups_count, tvb, offset, TL_BYTE, FALSE);
+ value_groups_count = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ offset = dissect_vuze_dht_value_groups( tvb, pinfo, tree, offset, value_groups_count, ver );
+
+ return offset;
+}
+
+/* --- Reply Store -----------------
+
+Name | Type | Protocol version | Note
+DIVERSIFICATIONS_LENGTH byte >=DIV_AND_CONT Number of diversifications this packet contains.
+DIVERSIFICATIONS byte[] >=DIV_AND_CONT Array with diversifications;
+ they are stored in the same order as keys and values from the request.
+*/
+static int
+dissect_vuze_dht_reply_store(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
+{
+ if( ver >= PV_DIV_AND_CONT )
+ {
+ guint diversifications_len;
+ proto_tree_add_item(tree, hf_vuze_dht_diversifications_len, tvb, offset, TL_BYTE, FALSE);
+ diversifications_len = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ proto_tree_add_item(tree, hf_vuze_dht_diversifications, tvb, offset, diversifications_len, FALSE);
+ offset += diversifications_len;
+ }
+
+ return offset;
+}
+
+/* --- Request Find node -----------------
+
+Name | Type | Protocol version | Note
+ID_LENGTH byte always Length of the following ID.
+ID byte[] always ID to search
+NODE_STATUS int >=MORE_NODE_STATUS Node status
+DHT_SIZE int >=MORE_NODE_STATUS Estimated size of the DHT; Unknown value can be indicated as zero.
+
+*/
+static int
+dissect_vuze_dht_request_find_node(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver )
+{
+ guint id_len;
+
+ proto_tree_add_item(tree, hf_vuze_dht_id_len, tvb, offset, TL_BYTE, FALSE);
+ id_len = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ proto_tree_add_item(tree, hf_vuze_dht_id, tvb, offset, id_len, FALSE);
+ offset += id_len;
+
+ if( ver >= PV_MORE_NODE_STATUS )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_node_status, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ proto_tree_add_item(tree, hf_vuze_dht_size, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+
+ return offset;
+}
+
+/* --- Reply Find node -----------------
+
+Name | Type | Protocol version | Note
+SPOOF_ID int >=ANTI_SPOOF Spoof ID of the requesting node;
+ it should be constructed from information known about
+ requesting contact and not easily guessed by others.
+NODE_TYPE int >=XFER_STATUS Type of the replying node;
+ Possible values are 0 for bootstrap node,
+ 1 for ordinary node and ffffffffh for unknown type.
+DHT_SIZE int >=SIZE_ESTIMATE Estimated size of the DHT; Unknown value can be indicated as zero.
+NETWORK_COORDINATES network coordinates >=VIVALDI Network coordinates of replying node.
+CONTACTS_COUNT short always Number of carried contacts.
+CONTACTS contacts always List with contacts.
+
+*/
+static int
+dissect_vuze_dht_reply_find_node(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
+{
+ guint contacts_count;
+
+ if( ver >= PV_ANTI_SPOOF )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+ if( ver >= PV_XFER_STATUS )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_node_type, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+ if( ver >= PV_SIZE_ESTIMATE )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_size, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+ }
+ if( ver >= PV_VIVALDI )
+ {
+ offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
+ }
+
+ proto_tree_add_item(tree, hf_vuze_dht_contacts_count, tvb, offset, TL_SHORT, FALSE);
+ contacts_count = tvb_get_ntohs( tvb, offset );
+ offset += TL_SHORT;
+
+ offset = dissect_vuze_dht_contacts( tvb, pinfo, tree, offset, contacts_count );
+
+ return offset;
+}
+
+/* --- Request Find value -----------------
+
+Name | Type | Note
+KEY key Key for which the values are requested.
+FLAGS byte Flags for the operation, possible values are:
+ SINGLE_VALUE = 00h
+ DOWNLOADING = 01h
+ SEEDING = 02h
+ MULTI_VALUE = 04h
+ STATS = 08h
+MAX_VALUES byte Maximum number of returned values.
+*/
+static int
+dissect_vuze_dht_request_find_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver _U_ )
+{
+ offset = dissect_vuze_dht_key( tvb, pinfo, tree, offset );
+ proto_tree_add_item(tree, hf_vuze_dht_flags, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ proto_tree_add_item(tree, hf_vuze_dht_max_values, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+
+ return offset;
+}
+
+/* --- Reply Find value -----------------
+
+Name | Type | Condition | Note
+HAS_CONTINUATION boolean protocol version >=DIV_AND_CONT Indicates whether there is at least one other packet with values.
+HAS_VALUES boolean always Indicates whether this packet carries values or contacts.
+CONTACTS_COUNT short HAS_VALUES == false Number of stored contacts.
+CONTACTS contacts HAS_VALUES == false Stored contacts that are close to the searched key.
+NETWORK_COORDINATES network coordinates HAS_VALUES == false Network coordinates of the replying node.
+ && protocol version >=VIVALDI_FINDVALUE
+DIVERSIFICATION_TYPE byte HAS_VALUES == true Type of key's diversification.
+ && protocol version >=DIV_AND_CONT
+VALUES value group HAS_VALUES == true Values that match searched key.
+
+*/
+static int
+dissect_vuze_dht_reply_find_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver )
+{
+ guint8 has_values;
+ guint contacts_count;
+ if( ver >= PV_DIV_AND_CONT )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_has_continuation, tvb, offset, TL_BOOL, FALSE);
+ offset += TL_BOOL;
+ }
+ proto_tree_add_item(tree, hf_vuze_dht_has_values, tvb, offset, TL_BOOL, FALSE);
+ has_values = tvb_get_guint8( tvb, offset );
+ offset += TL_BOOL;
+
+ if( has_values )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_contacts_count, tvb, offset, TL_SHORT, FALSE);
+ contacts_count = tvb_get_ntohs( tvb, offset );
+ offset += TL_SHORT;
+ offset = dissect_vuze_dht_contacts( tvb, pinfo, tree, offset, contacts_count );
+
+ if( ver >= PV_VIVALDI_FINDVALUE )
+ {
+ offset = dissect_vuze_dht_network_coordinates( tvb, pinfo, tree, offset, ver );
+ }
+ if( ver >= PV_DIV_AND_CONT )
+ {
+ proto_tree_add_item(tree, hf_vuze_dht_diversification_type, tvb, offset, TL_BYTE, FALSE);
+ offset += TL_BYTE;
+ }
+ offset = dissect_vuze_dht_value_group( tvb, pinfo, tree, offset, ver );
+ }
+
+ return offset;
+}
+
+/* --- Reply Error -----------------
+
+Name | Type | Condition | Note
+ERROR_TYPE int always Type of the error. Possible values are:
+ WRONG_ADDRESS = 1 - originator's address stored in the request is incorrect
+ KEY_BLOCKED = 2 - the requested key has been blocked
+SENDER_ADDRESS address ERROR_TYPE == WRONG_ADDRESS Real originator's address.
+KEY_BLOCK_REQUEST_LENGTH byte ERROR_TYPE == KEY_BLOCKED Length of the following request.
+KEY_BLOCK_REQUEST byte[] ERROR_TYPE == KEY_BLOCKED Request that blocks/unlocks the key.
+SIGNATURE_LENGTH short ERROR_TYPE == KEY_BLOCKED Length of the following signature.
+SIGNATURE byte[] ERROR_TYPE == KEY_BLOCKED Signature of the request.
+
+*/
+static int
+dissect_vuze_dht_reply_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int ver _U_ )
+{
+ guint error_type;
+ guint8 key_block_request_len;
+ guint signature_len;
+
+ proto_tree_add_item(tree, hf_vuze_dht_error_type, tvb, offset, TL_INT, FALSE);
+ error_type = tvb_get_ntohl( tvb, offset );
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", val_to_str( error_type, vuze_dht_error_type_vals, "Unknown") );
+ offset += TL_INT;
+
+ switch(error_type)
+ {
+ case ET_WRONG_ADDRESS:
+ offset = dissect_vuze_dht_address( tvb, pinfo, tree, offset, "Sender Address" );
+ break;
+ case ET_KEY_BLOCKED:
+ proto_tree_add_item(tree, hf_vuze_dht_key_block_request_len, tvb, offset, TL_BYTE, FALSE);
+ key_block_request_len = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ proto_tree_add_item(tree, hf_vuze_dht_key_block_request, tvb, offset, key_block_request_len, FALSE);
+ offset += key_block_request_len;
+
+ proto_tree_add_item(tree, hf_vuze_dht_signature_len, tvb, offset, TL_SHORT, FALSE);
+ signature_len = tvb_get_ntohs( tvb, offset );
+ offset += TL_SHORT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_signature, tvb, offset, signature_len, FALSE);
+ offset += signature_len;
+ break;
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+/* --- Request Key block -----------------
+
+Name | Type | Note
+SPOOF_ID int Spoof ID obtained through FIND_NODE request.
+KEY_BLOCK_REQUEST_LENGTH byte Length of the following request.
+KEY_BLOCK_REQUEST byte[] Request that blocks/unlocks the key.
+SIGNATURE_LENGTH short Length of the following signature.
+SIGNATURE byte[] Signature of the request.
+
+*/
+static int
+dissect_vuze_dht_request_key_block(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset, int ver _U_ )
+{
+ guint8 key_block_request_len;
+ guint signature_len;
+
+ proto_tree_add_item(tree, hf_vuze_dht_spoof_id, tvb, offset, TL_INT, FALSE);
+ offset += TL_INT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_key_block_request_len, tvb, offset, TL_BYTE, FALSE);
+ key_block_request_len = tvb_get_guint8( tvb, offset );
+ offset += TL_BYTE;
+
+ proto_tree_add_item(tree, hf_vuze_dht_key_block_request, tvb, offset, key_block_request_len, FALSE);
+ offset += key_block_request_len;
+
+ proto_tree_add_item(tree, hf_vuze_dht_signature_len, tvb, offset, TL_SHORT, FALSE);
+ signature_len = tvb_get_ntohs( tvb, offset );
+ offset += TL_SHORT;
+
+ proto_tree_add_item(tree, hf_vuze_dht_signature, tvb, offset, signature_len, FALSE);
+ offset += signature_len;
+
+ return offset;
+}
+
+static int
+dissect_vuze_dht(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *sub_tree;
+ int action, proto_ver;
+ int decoded_length = 0;
+
+ /* set the protocol column */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vuze-DHT");
+ /* clear the info column */
+ col_clear( pinfo->cinfo, COL_INFO);
+
+ ti = proto_tree_add_item(tree, proto_vuze_dht, tvb, 0, -1, FALSE);
+ sub_tree = proto_item_add_subtree(ti, ett_vuze_dht);
+
+ /*
+ Requests always start with Connection IDs, which guaranteed to have their MSB set to 1
+ Replies always start with the action, which always has the MSB clear
+ Therefore, the MSB of an incoming packet should be used to distinguish requests from replies.
+ */
+ if( tvb_get_guint8(tvb,0) & 0x80 )
+ {
+ decoded_length = dissect_vuze_dht_request_header(tvb, pinfo, sub_tree, decoded_length, &action, &proto_ver );
+ }
+ else
+ {
+ decoded_length = dissect_vuze_dht_reply_header(tvb, pinfo, sub_tree, decoded_length, &action, &proto_ver );
+ }
+
+ switch( action )
+ {
+ case AT_PING_REQUEST:
+ break;
+ case AT_PING_REPLY:
+ decoded_length = dissect_vuze_dht_reply_ping(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_STORE_REQUEST:
+ decoded_length = dissect_vuze_dht_request_store(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_STORE_REPLY:
+ decoded_length = dissect_vuze_dht_reply_store(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_FIND_NODE_REQUEST:
+ decoded_length = dissect_vuze_dht_request_find_node(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_FIND_NODE_REPLY:
+ decoded_length = dissect_vuze_dht_reply_find_node(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_FIND_VALUE_REQUEST:
+ decoded_length = dissect_vuze_dht_request_find_value(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_FIND_VALUE_REPLY:
+ decoded_length = dissect_vuze_dht_reply_find_value(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_ERROR_REPLY:
+ decoded_length = dissect_vuze_dht_reply_error(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ case AT_KEY_BLOCK_REQUEST:
+ decoded_length = dissect_vuze_dht_request_key_block(tvb, pinfo, sub_tree, decoded_length, proto_ver );
+ break;
+ default:
+ break;
+ }
+
+ return decoded_length;
+}
+
+void
+proto_register_vuze_dht(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vuze_dht_address,
+ { "Address", "vuze-dht.address",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_address_len,
+ { "Address Length", "vuze-dht.address.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_address_v4,
+ { "IPv4 Address", "vuze-dht.address.ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_address_v6,
+ { "IPv6 Address", "vuze-dht.address.ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_address_port,
+ { "Port", "vuze-dht.address.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_contact,
+ { "Contact", "vuze-dht.contact",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_contact_type,
+ { "Contact Type", "vuze-dht.contact.type",
+ FT_UINT8, BASE_DEC, VALS(vuze_dht_contact_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_proto_ver,
+ { "Protocol Version", "vuze-dht.proto_ver",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value,
+ { "Value", "vuze-dht.value",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_ver,
+ { "Value Version", "vuze-dht.value.ver",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_created,
+ { "Value Creation Time", "vuze-dht.value.creation_time",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_bytes_count,
+ { "Value Bytes Count", "vuze-dht.value.bytes_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_bytes,
+ { "Value Bytes", "vuze-dht.value.bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_flags,
+ { "Value Flags", "vuze-dht.value.flags",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_life_hours,
+ { "Value Life Hours", "vuze-dht.value.life_hours",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_replication_factor,
+ { "Value Replication Factor", "vuze-dht.value.replication_factor",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_connection_id,
+ { "Connection ID", "vuze-dht.connection_id",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_action,
+ { "Action", "vuze-dht.action",
+ FT_UINT32, BASE_DEC, VALS(vuze_dht_action_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_transaction_id,
+ { "Transaction ID", "vuze-dht.transaction_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_vendor_id,
+ { "Vendor ID", "vuze-dht.vendor_id",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_id,
+ { "Network ID", "vuze-dht.network_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_local_proto_ver,
+ { "Local Protocol Version", "vuze-dht.local_proto_ver",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_instance_id,
+ { "Instance ID", "vuze-dht.instance_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_time,
+ { "Time", "vuze-dht.time",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinates_count,
+ { "Network Coordinates Count", "vuze-dht.network_coordinates_count",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinates,
+ { "Network Coordinates", "vuze-dht.network_coordinates",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinate,
+ { "Network Coordinate", "vuze-dht.network_coordinate",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinate_type,
+ { "Network Coordinate Type", "vuze-dht.network_coordinate.type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinate_size,
+ { "Network Coordinate Size", "vuze-dht.network_coordinate.size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_network_coordinate_data,
+ { "Network Coordinate Data", "vuze-dht.network_coordinate.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_spoof_id,
+ { "Spoof ID", "vuze-dht.spoof_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_keys_count,
+ { "Keys Count", "vuze-dht.keys_count",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_keys,
+ { "Keys", "vuze-dht.keys",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_key,
+ { "Key", "vuze-dht.key",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_key_len,
+ { "Key Length", "vuze-dht.key.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_key_data,
+ { "Key Data", "vuze-dht.key.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_values_count,
+ { "Values Count", "vuze-dht.values_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_groups_count,
+ { "Value Groups Count", "vuze-dht.value_groups_count",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_group,
+ { "Values", "vuze-dht.values",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_value_groups,
+ { "Value Groups", "vuze-dht.value_groups",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_diversifications_len,
+ { "Diversifications Length", "vuze-dht.diversifications_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_diversifications,
+ { "Diversifications", "vuze-dht.diversifications",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_id_len,
+ { "ID Length", "vuze-dht.id_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_id,
+ { "ID", "vuze-dht.id",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_node_status,
+ { "Node Status", "vuze-dht.node_status",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_size,
+ { "DHT Size", "vuze-dht.dht_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_node_type,
+ { "Node Type", "vuze-dht.node_type",
+ FT_UINT32, BASE_DEC, VALS(vuze_dht_node_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_contacts_count,
+ { "Contacts Count", "vuze-dht.contacts_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_contacts,
+ { "Contacts", "vuze-dht.contacts",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_flags,
+ { "Flags", "vuze-dht.flags",
+ FT_UINT8, BASE_DEC, VALS(vuze_dht_flag_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_values_num,
+ { "Values Num", "vuze-dht.stats.values_num",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_values_total,
+ { "Values Total", "vuze-dht.stats.values_total",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_reads_per_min,
+ { "Reads Per Minute", "vuze-dht.stats.reads_per_min",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_diversification_type,
+ { "Diversification Type", "vuze-dht.stats.diversification_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_max_values,
+ { "Max values", "vuze-dht.max_values",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_has_continuation,
+ { "Has Continuation", "vuze-dht.has_continuation",
+ FT_UINT8, BASE_DEC, VALS(vuze_dht_bool_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_has_values,
+ { "Has Values", "vuze-dht.has_values",
+ FT_UINT8, BASE_DEC, VALS(vuze_dht_bool_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_error_type,
+ { "Error Type", "vuze-dht.error_type",
+ FT_UINT32, BASE_DEC, VALS(vuze_dht_error_type_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_key_block_request_len,
+ { "Key Block Request Length", "vuze-dht.key_block_request_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_key_block_request,
+ { "Key Block Request", "vuze-dht.key_block_request",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_signature_len,
+ { "Signature Length", "vuze-dht.signature_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_vuze_dht_signature,
+ { "Signature", "vuze-dht.signature",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_vuze_dht,
+ &ett_vuze_dht_address,
+ &ett_vuze_dht_contacts,
+ &ett_vuze_dht_contact,
+ &ett_vuze_dht_keys,
+ &ett_vuze_dht_key,
+ &ett_vuze_dht_value_groups,
+ &ett_vuze_dht_value_group,
+ &ett_vuze_dht_value,
+ &ett_vuze_dht_network_coordinates,
+ &ett_vuze_dht_network_coordinate
+ };
+
+ module_t *vuze_dht_module;
+
+ /* Register protocol */
+ proto_vuze_dht = proto_register_protocol (
+ "Vuze DHT Protocol", /* name */
+ "Vuze-DHT", /* short name */
+ "vuze-dht" /* abbrev */
+ );
+
+ proto_register_field_array(proto_vuze_dht, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ new_register_dissector("vuze-dht", dissect_vuze_dht, proto_vuze_dht);
+
+ /* Register our configuration options */
+ vuze_dht_module = prefs_register_protocol(proto_vuze_dht, proto_reg_handoff_vuze_dht);
+
+ prefs_register_uint_preference(vuze_dht_module, "udp_port",
+ "Vuze DHT Protocol UDP port",
+ "Set the UDP port for Vuze DHT Protocol.",
+ 10, &global_vuze_dht_udp_port);
+}
+
+void
+proto_reg_handoff_vuze_dht(void)
+{
+ static gboolean vuze_dht_prefs_initialized = FALSE;
+ static dissector_handle_t vuze_dht_handle;
+ static guint vuze_dht_udp_port;
+
+ if (!vuze_dht_prefs_initialized)
+ {
+ vuze_dht_handle = new_create_dissector_handle(dissect_vuze_dht, proto_vuze_dht);
+ vuze_dht_prefs_initialized = TRUE;
+ }
+ else
+ {
+ dissector_delete_uint("udp.port", vuze_dht_udp_port, vuze_dht_handle);
+ }
+
+ /* Set our port number for future use */
+ vuze_dht_udp_port = global_vuze_dht_udp_port;
+ dissector_add_uint("udp.port", global_vuze_dht_udp_port, vuze_dht_handle);
+}
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */
+