From f11f450bf0dd462810cfc9842150f88f4352cb55 Mon Sep 17 00:00:00 2001 From: Bill Meier Date: Wed, 22 Jun 2011 19:52:13 +0000 Subject: 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 --- epan/dissectors/packet-vuze-dht.c | 1473 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1473 insertions(+) create mode 100644 epan/dissectors/packet-vuze-dht.c (limited to 'epan/dissectors/packet-vuze-dht.c') 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 + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 +#include + +#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 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: + */ + -- cgit v1.2.3