diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-mojito.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-mojito.c')
-rw-r--r-- | epan/dissectors/packet-mojito.c | 1034 |
1 files changed, 1034 insertions, 0 deletions
diff --git a/epan/dissectors/packet-mojito.c b/epan/dissectors/packet-mojito.c new file mode 100644 index 00000000..26a07cf3 --- /dev/null +++ b/epan/dissectors/packet-mojito.c @@ -0,0 +1,1034 @@ +/* packet-mojito.c + * Routines for Dissecting the Gnutella Mojito DHT Protocol + * http://limewire.negatis.com/index.php?title=Mojito_Message_Format + * + * Copyright (c) 2008 by Travis Dawson <travis.dawson@sprint.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/expert.h> + +void proto_register_mojito(void); +void proto_reg_handoff_mojito(void); + +static dissector_handle_t mojito_handle; + +#define MOJITO_HEADER_LENGTH 38 + +/* All the Defines for OpCodes */ +#define MOJITO_PING_REQUEST 1 +#define MOJITO_PING_RESPONSE 2 +#define MOJITO_STORE_REQUEST 3 +#define MOJITO_STORE_RESPONSE 4 +#define MOJITO_FIND_NODE_REQUEST 5 +#define MOJITO_FIND_NODE_RESPONSE 6 +#define MOJITO_FIND_VALUE_REQUEST 7 +#define MOJITO_FIND_VALUE_RESPONSE 8 +#define MOJITO_STATS_REQUEST_DEPRECATED 9 +#define MOJITO_STATS_RESPONSE_DEPRECATED 10 + +/* Initialize the protocol and registered fields */ +static int proto_mojito = -1; + +/* Start of fields */ +static int hf_mojito_messageid = -1; +static int hf_mojito_fdhtmessage = -1; +static int hf_mojito_mjrversion = -1; +static int hf_mojito_mnrversion = -1; +static int hf_mojito_length = -1; +static int hf_mojito_opcode = -1; +static int hf_mojito_vendor = -1; +static int hf_mojito_origmjrversion = -1; +static int hf_mojito_origmnrversion = -1; +static int hf_mojito_kuid = -1; +static int hf_mojito_socketaddress_version = -1; +static int hf_mojito_socketaddress_ipv4 = -1; +static int hf_mojito_socketaddress_ipv6 = -1; +static int hf_mojito_socketaddress_port = -1; +static int hf_mojito_instanceid = -1; +static int hf_mojito_flags = -1; +static int hf_mojito_flags_shutdown = -1; +static int hf_mojito_flags_firewalled = -1; +static int hf_mojito_extendedlength = -1; +static int hf_mojito_kuidcount = -1; +static int hf_mojito_bigintegerlen = -1; +static int hf_mojito_bigintegerval = -1; +static int hf_mojito_dhtvaluetype = -1; +static int hf_mojito_sectokenlen = -1; +static int hf_mojito_sectoken = -1; +static int hf_mojito_contactcount = -1; +static int hf_mojito_contactvendor = -1; +static int hf_mojito_contactversion = -1; +static int hf_mojito_contactkuid = -1; +static int hf_mojito_dhtvaluecount = -1; +static int hf_mojito_dhtvalue_kuid = -1; +static int hf_mojito_target_kuid = -1; +static int hf_mojito_dhtvalue_valuetype = -1; +static int hf_mojito_dhtvalue_version = -1; +static int hf_mojito_dhtvalue_length = -1; +static int hf_mojito_dhtvalue_value = -1; +static int hf_mojito_bigint_value_one = -1; +static int hf_mojito_bigint_value_two = -1; +static int hf_mojito_bigint_value_three = -1; +static int hf_mojito_bigint_value_four = -1; +static int hf_mojito_storestatuscode_count = -1; +static int hf_mojito_storestatuscode_code = -1; +static int hf_mojito_storestatuscode_kuid = -1; +static int hf_mojito_storestatuscode_secondary_kuid = -1; +static int hf_mojito_requestload = -1; +#if 0 +static int hf_mojito_startflag = -1; +static int hf_mojito_endflag = -1; +static int hf_mojito_priorityflag = -1; +#endif +static int hf_mojito_opcode_data = -1; + +/* Initialize the subtree pointers */ +static gint ett_mojito = -1; +static gint ett_mojito_header = -1; +static gint ett_mojito_header_version = -1; +static gint ett_mojito_contact = -1; +static gint ett_mojito_contact_version = -1; +static gint ett_mojito_socket_address = -1; +static gint ett_mojito_flags = -1; +static gint ett_mojito_bigint = -1; +static gint ett_mojito_opcode = -1; +static gint ett_mojito_dht_version = -1; +static gint ett_mojito_dht = -1; +static gint ett_mojito_status_code = -1; +static gint ett_mojito_kuids = -1; + +static expert_field ei_mojito_socketaddress_unknown = EI_INIT; +static expert_field ei_mojito_bigint_unsupported = EI_INIT; + +typedef struct mojito_header_data { + guint8 opcode; + guint32 payloadlength; +} mojito_header_data_t; + +/* Values for OPCode Flags */ +static const value_string opcodeflags[] = { + { MOJITO_PING_REQUEST, "PING REQUEST" }, + { MOJITO_PING_RESPONSE, "PING RESPONSE" }, + { MOJITO_STORE_REQUEST, "STORE REQUEST" }, + { MOJITO_STORE_RESPONSE, "STORE RESPONSE" }, + { MOJITO_FIND_NODE_REQUEST, "FIND NODE REQUEST" }, + { MOJITO_FIND_NODE_RESPONSE, "FIND NODE RESPONSE" }, + { MOJITO_FIND_VALUE_REQUEST, "FIND VALUE REQUEST" }, + { MOJITO_FIND_VALUE_RESPONSE, "FIND VALUE RESPONSE" }, + { MOJITO_STATS_REQUEST_DEPRECATED, "STATS REQUEST (DEPRECATED)" }, + { MOJITO_STATS_RESPONSE_DEPRECATED, "STATS RESPONSE (DEPRECATED)" }, + { 0, NULL } +}; + +static const value_string statuscodeflags[] = { + { 1, "OK" }, + { 2, "Error" }, + { 0, NULL } +}; + +#if 0 +static const value_string vendorcodeflags[] = { + { 0, "MESSAGES_SUPPORTED" }, + { 4, "HOPS_FLOW" }, + { 5, "CRAWLER_PING" }, + { 6, "CRAWLER_PONG" }, + { 7, "UDP_CONNECT_BACK" }, + { 8, "UDP_CONNECT_BACK_REDIR" }, + { 9, "NGTH_MINUS_PAYLOAD" }, + { 10, "CAPABILITIES" }, + { 11, "LIME_ACK" }, + { 12, "REPLY_NUMBER" }, + { 13, "OOB_PROXYING_CONTROL" }, + { 14, "GIVE_STATS" }, + { 15, "STATISTICS" }, + { 16, "SIMPP_REQ" }, + { 17, "SIMPP" }, + { 21, "PUSH_PROXY_REQ" }, + { 22, "PUSH_PROXY_ACK" }, + { 23, "UDP_HEAD_PING" }, + { 24, "UDP_HEAD_PONG" }, + { 25, "HEADER_UPDATE" }, + { 26, "UPDATE_REQ" }, + { 27, "UPDATE_RESP" }, + { 28, "CONTENT_REQ" }, + { 29, "CONTENT_RESP" }, + { 30, "INSPECTION_REQ" }, + { 31, "INSPECTION_RESP" }, + { 32, "ADVANCED_TOGGLE" }, + { 33, "DHT_CONTACTS" }, + + { 0, NULL } +}; +#endif + +static int +dissect_mojito_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + int offset, const char *title) +{ + int offset_start; + guint8 socket_address_version; + proto_tree *socket_tree; + proto_item *socket_item; + + offset_start = offset; + + /* new subtree for socket address*/ + socket_address_version = tvb_get_guint8(tvb, offset); + socket_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_mojito_socket_address, &socket_item, title); + + proto_tree_add_item(socket_tree, hf_mojito_socketaddress_version, tvb, offset, 1, ENC_NA); + offset += 1; + + switch (socket_address_version) + { + case FT_IPv4_LEN: /* IPv4 */ + + proto_tree_add_item(socket_tree, hf_mojito_socketaddress_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + break; + + case FT_IPv6_LEN: /* IPv6 */ + + proto_tree_add_item(socket_tree, hf_mojito_socketaddress_ipv6, tvb, offset, 16, ENC_NA); + offset += 16; + break; + + default: /* ABORT */ + expert_add_info(pinfo, socket_item, &ei_mojito_socketaddress_unknown); + return 0; + } + + proto_tree_add_item(socket_tree, hf_mojito_socketaddress_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_item_set_len(socket_item, offset - offset_start); + + return offset; +} + +static int +dissect_mojito_contact(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int contact_id) +{ + int offset_start; + proto_tree *contact_tree, *version_tree; + proto_item *contact_item, *version_item; + + offset_start = offset; + + if (contact_id > 0) + { + contact_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_mojito_contact, &contact_item, "Contact #%d", contact_id); + } + else + { + contact_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_mojito_contact, &contact_item, "Contact"); + } + + proto_tree_add_item(contact_tree, hf_mojito_contactvendor, tvb, offset, 4, ENC_ASCII); + offset += 4; + + version_item = proto_tree_add_item(contact_tree, hf_mojito_contactversion, tvb, offset, 2, ENC_BIG_ENDIAN); + version_tree = proto_item_add_subtree(version_item, ett_mojito_contact_version); + proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(contact_tree, hf_mojito_contactkuid, tvb, offset, 20, ENC_NA); + offset += 20; + + offset = dissect_mojito_address(tvb, pinfo, contact_tree, offset, "Socket Address"); + + if (offset == 0) + { + return 0; + } + + proto_item_set_len(contact_item, offset - offset_start); + + return offset - offset_start; +} + +static int +dissect_mojito_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + int offset, mojito_header_data_t* header_data) +{ + proto_tree *header_tree, *version_tree, *contact_tree, *flag_tree; + proto_item *header_item, *contact_item, *flag_item; + int start_offset = offset; + int contact_start_offset; + + header_tree = proto_tree_add_subtree(tree, tvb, offset, 61, ett_mojito_header, &header_item, "Gnutella Header"); + + proto_tree_add_item(header_tree, hf_mojito_messageid, tvb, offset, 16, ENC_NA); + offset += 16; + + proto_tree_add_item(header_tree, hf_mojito_fdhtmessage, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + version_tree = proto_tree_add_subtree(header_tree, tvb, offset, 2, ett_mojito_header_version, NULL, "Version"); + + proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* Payload Length : in Little Endian */ + header_data->payloadlength = tvb_get_letohl(tvb, offset); + proto_tree_add_item(header_tree, hf_mojito_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + header_data->opcode = tvb_get_guint8(tvb, offset); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const(header_data->opcode, opcodeflags, "Unknown")); + proto_tree_add_item(header_tree, hf_mojito_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + contact_start_offset = offset; + contact_tree = proto_tree_add_subtree(header_tree, tvb, offset, 35, ett_mojito_contact, &contact_item, "Originating Contact"); + + proto_tree_add_item(contact_tree, hf_mojito_vendor, tvb, offset, 4, ENC_ASCII); + offset += 4; + + version_tree = proto_tree_add_subtree(contact_tree, tvb, offset, 2, ett_mojito_contact_version, NULL, "Contact Version"); + + proto_tree_add_item(version_tree, hf_mojito_origmjrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(version_tree, hf_mojito_origmnrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(contact_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + + offset = dissect_mojito_address(tvb, pinfo, contact_tree, offset, "Socket Address"); + + if (offset == 0) + { + return 0; + } + + proto_item_set_len(contact_item, offset - contact_start_offset); + + proto_tree_add_item(header_tree, hf_mojito_instanceid, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /*Flags*/ + flag_item = proto_tree_add_item(header_tree, hf_mojito_flags, tvb, offset, 1, ENC_BIG_ENDIAN); + flag_tree = proto_item_add_subtree(flag_item, ett_mojito_flags); + proto_tree_add_item(flag_tree, hf_mojito_flags_shutdown, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(flag_tree, hf_mojito_flags_firewalled, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(header_tree, hf_mojito_extendedlength, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_item_set_len(header_item, offset-start_offset); + return offset; +} + +static void +dissect_mojito_ping_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + guint8 bigintlen; + proto_tree *bigint_tree; + proto_item *bigint_item; + + offset = dissect_mojito_address(tvb, pinfo, tree, + offset, "Requester's External Socket Address"); + + if (offset == 0) + { + return; + } + + /* BigInt subtree */ + bigintlen = tvb_get_guint8(tvb, offset); + bigint_tree = proto_tree_add_subtree(tree, tvb, offset, bigintlen + 1, ett_mojito_bigint, &bigint_item, "Estimated DHT size"); + + proto_tree_add_item(bigint_tree, hf_mojito_bigintegerlen, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + switch (bigintlen) + { + case 1: /* 1 byte */ + proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_one, tvb, offset, bigintlen, ENC_BIG_ENDIAN); + break; + + case 2: /* 2 byte */ + proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_two, tvb, offset, bigintlen, ENC_BIG_ENDIAN); + break; + + case 3: /* 3 byte */ + proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_three, tvb, offset, bigintlen, ENC_BIG_ENDIAN); + break; + + case 4: /* 4 byte */ + proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_four, tvb, offset, bigintlen, ENC_BIG_ENDIAN); + break; + default: /* ABORT */ + expert_add_info(pinfo, bigint_item, &ei_mojito_bigint_unsupported); + return; + } + + /* BigInt Value */ + proto_tree_add_item(bigint_tree, hf_mojito_bigintegerval, tvb, offset, bigintlen, ENC_NA); +} + +static void +dissect_mojito_store_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + proto_tree *dht_tree, *version_tree; + proto_item *dht_item, *version_item; + guint8 ii, contactcount; + guint8 sectokenlen = tvb_get_guint8(tvb, offset); + guint16 dhtvaluelength; + int contact_offset, start_offset; + + proto_tree_add_item(tree, hf_mojito_sectokenlen, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_mojito_sectoken, tvb, offset, sectokenlen, ENC_NA); + offset += sectokenlen; + + /* Contact count */ + proto_tree_add_item(tree, hf_mojito_dhtvaluecount, tvb, offset, 1, ENC_BIG_ENDIAN); + contactcount = tvb_get_guint8(tvb, offset); + offset += 1; + + /* For each Contact, display the info */ + for (ii = 0; ii < contactcount; ii++) + { + dht_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_mojito_dht, &dht_item, "DHTValue #%d", ii+1); + start_offset = offset; + contact_offset = dissect_mojito_contact(tvb, pinfo, dht_tree, offset, -1); + if (contact_offset == 0) + return; + offset += contact_offset; + + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_valuetype, tvb, offset, 4, ENC_ASCII); + offset += 4; + + /* Version */ + version_item = proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_version, tvb, offset, 2, ENC_BIG_ENDIAN); + version_tree = proto_item_add_subtree(version_item, ett_mojito_dht_version); + + proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + dhtvaluelength = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII); + offset += dhtvaluelength; + + proto_item_set_len(dht_item, offset-start_offset); + } +} + +static void +dissect_mojito_store_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset) +{ + proto_tree *sc_tree; + proto_item *sc_item; + guint8 ii, contactcount = tvb_get_guint8(tvb, offset); + guint16 dhtvaluelength; + int start_offset; + + proto_tree_add_item(tree, hf_mojito_storestatuscode_count, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* For each Contact, display the info */ + for (ii = 0; ii < contactcount; ii++) + { + sc_tree = proto_tree_add_subtree_format(tree, tvb, offset, 23, ett_mojito_status_code, &sc_item, "Status Code %d", ii+1); + + start_offset = offset; + + /*Primary KUID */ + proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + + if (tvb_reported_length_remaining(tvb, offset+3) > 0) + { + /* Must be a secondard KUID */ + proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_secondary_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + } + + proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_code, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + dhtvaluelength = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(sc_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(sc_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII); + offset += dhtvaluelength; + + proto_item_set_len(sc_item, offset-start_offset); + } +} + +static void +dissect_mojito_find_node_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + guint8 ii, contactcount; + guint8 sectokenlen = tvb_get_guint8(tvb, offset); + int contact_offset; + + proto_tree_add_item(tree, hf_mojito_sectokenlen, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_mojito_sectoken, tvb, offset, sectokenlen, ENC_NA); + offset += sectokenlen; + + contactcount = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_mojito_contactcount, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* For each Contact, display the info */ + for (ii = 0; ii < contactcount; ii++) + { + contact_offset = dissect_mojito_contact(tvb, pinfo, tree, offset, ii+1); + if (contact_offset == 0) + return; + offset += contact_offset; + } +} + +static void +dissect_mojito_find_value_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset) +{ + proto_tree *kuid_tree; + guint8 i, kuidcount; + + if (!tree) + return; + + proto_tree_add_item(tree, hf_mojito_target_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + + kuidcount = tvb_get_guint8(tvb, offset); + + kuid_tree = proto_tree_add_subtree(tree, tvb, offset, (20 * kuidcount) + 1, ett_mojito_kuids, NULL, "Secondary KUID\'s"); + + proto_tree_add_item(kuid_tree, hf_mojito_kuidcount, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* All the Secondary KUID's */ + for (i = 0; i < kuidcount; i++) + { + proto_tree_add_item(kuid_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + } + + proto_tree_add_item(tree, hf_mojito_dhtvaluetype, tvb, offset, 4, ENC_ASCII); + /*offset += 4;*/ +} + +static void +dissect_mojito_find_value_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + proto_tree *dht_tree, *version_tree, *kuid_tree; + proto_item *dht_item, *version_item; + guint16 dhtvaluelength; + int contact_offset, start_offset; + guint8 ii, dhtvaluescount, kuidcount; + + proto_tree_add_item(tree, hf_mojito_requestload, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + dhtvaluescount = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_mojito_dhtvaluecount, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* For each Contact, display the info */ + for (ii = 0; ii < dhtvaluescount; ii++) + { + dht_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_mojito_dht, &dht_item, "DHTValue #%d", ii+1); + start_offset = offset; + contact_offset = dissect_mojito_contact(tvb, pinfo, dht_tree, offset, -1); + if (contact_offset == 0) + return; + + offset += contact_offset; + + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_valuetype, tvb, offset, 4, ENC_ASCII); + offset += 4; + + /* Version */ + version_item = proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_version, tvb, offset, 2, ENC_BIG_ENDIAN); + version_tree = proto_item_add_subtree(version_item, ett_mojito_dht_version); + + proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* Length */ + dhtvaluelength = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* Value */ + proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII); + offset += dhtvaluelength; + + proto_item_set_len(dht_item, offset-start_offset); + } + + /*KUID Count */ + kuidcount = tvb_get_guint8(tvb, offset); + kuid_tree = proto_tree_add_subtree(tree, tvb, offset, (20 * kuidcount) + 1, ett_mojito_kuids, NULL, "Secondary KUID\'s"); + proto_tree_add_item(kuid_tree, hf_mojito_kuidcount, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* All the Secondary KUID's */ + for (ii = 0; ii < kuidcount; ii++) + { + proto_tree_add_item(kuid_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA); + offset += 20; + } +} + +static int +dissect_mojito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + proto_tree *mojito_tree, *opcode_tree; + proto_item *ti; + mojito_header_data_t header_data; + gint offset = 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Mojito"); + col_clear(pinfo->cinfo, COL_INFO); + + /* Add a new item to the tree */ + ti = proto_tree_add_item(tree, proto_mojito, tvb, 0, -1, ENC_NA); + mojito_tree = proto_item_add_subtree(ti, ett_mojito); + + offset = dissect_mojito_header(tvb, pinfo, mojito_tree, offset, &header_data); + if (offset == 0) /* Some error occurred */ + return 0; + + opcode_tree = proto_tree_add_subtree_format(mojito_tree, tvb, + offset, header_data.payloadlength - MOJITO_HEADER_LENGTH, + ett_mojito_opcode, NULL, "Opcode specific data (%s)", + val_to_str_const(header_data.opcode, opcodeflags, "Unknown")); + + /* Now use the opcode to figure out what to do next */ + switch (header_data.opcode) + { + case MOJITO_PING_RESPONSE: /* PING RESPONSE */ + dissect_mojito_ping_response(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_STORE_REQUEST: /* STORE REQUEST */ + dissect_mojito_store_request(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_STORE_RESPONSE: /* STORE RESPONSE */ + dissect_mojito_store_response(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_FIND_NODE_REQUEST: /* FIND NODE REQUEST */ + proto_tree_add_item(opcode_tree, hf_mojito_target_kuid, tvb, offset, 20, ENC_NA); + break; + + case MOJITO_FIND_NODE_RESPONSE: /* FIND NODE RESPONSE */ + dissect_mojito_find_node_response(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_FIND_VALUE_REQUEST: /* FIND VALUE REQUEST */ + dissect_mojito_find_value_request(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_FIND_VALUE_RESPONSE: /* FIND VALUE RESPONSE */ + dissect_mojito_find_value_response(tvb, pinfo, opcode_tree, offset); + break; + + case MOJITO_PING_REQUEST: /* PING REQUEST */ + case MOJITO_STATS_REQUEST_DEPRECATED: /* STATS REQUEST (DEPRECATED) */ + case MOJITO_STATS_RESPONSE_DEPRECATED: /* STATS RESPONSE (DEPRECATED) */ + default: + if (header_data.payloadlength - MOJITO_HEADER_LENGTH > 0) + proto_tree_add_item(opcode_tree, hf_mojito_opcode_data, tvb, + offset, header_data.payloadlength - MOJITO_HEADER_LENGTH, ENC_NA); + break; + } + + return tvb_captured_length(tvb); +} + +static gboolean dissect_mojito_heuristic (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + /* + Test the overall length to make sure it's at least 61 bytes (the header) + Test to make sure that it's of type 44 (mojito) + Test to make sure that the length field is there and correct + (tvb_get_letohl(tvb, 20) + 23) == tvb_length(tvb) + */ + if ((tvb_captured_length(tvb) >= 60) && + (tvb_get_guint8(tvb, 16) == 68) && + ((tvb_get_letohl(tvb, 19) + 23) == tvb_reported_length(tvb))) + { + dissect_mojito(tvb, pinfo, tree, NULL); + return TRUE; + } + + return FALSE; +} + +/* Register the mojito dissector */ +void +proto_register_mojito(void) +{ + expert_module_t* expert_mojito; + + static hf_register_info hf[] = { + { &hf_mojito_dhtvaluecount, + { "DHTValue Count", "mojito.dhtvaluecount", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_messageid, + { "Message ID", "mojito.messageid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_requestload, + { "Request Load", "mojito.requestload", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_fdhtmessage, + { "FDHTMessage", "mojito.fdhtmessage", + FT_UINT8, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_mjrversion, + { "Major Version", "mojito.majorversion", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_mnrversion, + { "Minor Version", "mojito.minorversion", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_length, + { "Payload Length", "mojito.payloadlength", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_opcode, + { "OPCode", "mojito.opcode", + FT_UINT8, BASE_DEC, + VALS(opcodeflags), 0x0, + NULL, HFILL } + }, + { &hf_mojito_vendor, + { "Vendor", "mojito.vendor", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_origmjrversion, + { "Major Version", "mojito.majorversion", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_origmnrversion, + { "Minor Version", "mojito.minorversion", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_kuid, + { "Kademlia Unique ID (KUID)", "mojito.kuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_socketaddress_version, + { "IP Version", "mojito.socketaddressversion", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_socketaddress_ipv4, + { "IP Address", "mojito.socketaddressipv4", + FT_IPv4, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_socketaddress_ipv6, + { "IP Address", "mojito.socketaddressipv6", + FT_IPv6, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_socketaddress_port, + { "IP Port", "mojito.socketaddressport", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_instanceid, + { "Instance ID", "mojito.instanceid", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_flags, + { "Flags", "mojito.flags", + FT_UINT8, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_flags_shutdown, + { "SHUTDOWN", "mojito.shutdownflag", + FT_BOOLEAN, 8, + NULL, 2, + NULL, HFILL } + }, + { &hf_mojito_flags_firewalled, + { "Firewalled", "mojito.firewalledflag", + FT_BOOLEAN, 8, + NULL, 1, + NULL, HFILL } + }, + { &hf_mojito_extendedlength, + { "Extended Length", "mojito.extlength", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_kuidcount, + { "Secondary KUID Count", "mojito.kuidcount", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvaluetype, + { "DHT Value Type", "mojito.dhtvaluetype", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigintegerlen, + { "Big Integer Length", "mojito.bigintegerlen", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigintegerval, + { "Big Integer HEX Value", "mojito.bigintegerhexval", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_sectokenlen, + { "Security Token Length", "mojito.sectokenlen", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_sectoken, + { "Security Token", "mojito.sectoken", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_contactcount, + { "Contact Count", "mojito.contactcount", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_contactvendor, + { "Vendor", "mojito.contactvendor", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_contactversion, + { "Contact Version", "mojito.contactversion", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_contactkuid, + { "KUID of the Contact", "mojito.contactkuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvalue_valuetype, + { "DHTValue ValueType", "mojito.dhtvaluevaluetype", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvalue_version, + { "DHTValue Version", "mojito.dhtvalueversion", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvalue_length, + { "DHTValue Length", "mojito.dhtvaluelength", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvalue_value, + { "DHTValue", "mojito.dhtvaluehexvalue", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigint_value_one, + { "Big Integer DEC Value", "mojito.bigintegerval", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigint_value_two, + { "Big Integer DEC Value", "mojito.bigintegerval", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigint_value_three, + { "Big Integer DEC Value", "mojito.bigintegerval", + FT_UINT24, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_bigint_value_four, + { "Big Integer DEC Value", "mojito.bigintegerval", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_dhtvalue_kuid, + { "Kademlia Unique ID (KUID)", "mojito.kuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_target_kuid, + { "Target Kademlia Unique ID (KUID)", "mojito.kuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_storestatuscode_count, + { "Status Code Count", "mojito.statuscodecount", + FT_UINT8, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_storestatuscode_code, + { "StatusCode", "mojito.statuscodecode", + FT_UINT16, BASE_DEC, + VALS(statuscodeflags), 0x0, + NULL, HFILL } + }, + { &hf_mojito_storestatuscode_kuid, + { "Primary KUID of the Status Code", "mojito.statuscodekuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_storestatuscode_secondary_kuid, + { "Secondary KUID of the Status Code", "mojito.statuscodesecondarykuid", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_mojito_opcode_data, + { "Data", "mojito.opcode.data", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_mojito, + &ett_mojito_header, + &ett_mojito_header_version, + &ett_mojito_contact, + &ett_mojito_contact_version, + &ett_mojito_socket_address, + &ett_mojito_flags, + &ett_mojito_bigint, + &ett_mojito_opcode, + &ett_mojito_dht_version, + &ett_mojito_dht, + &ett_mojito_status_code, + &ett_mojito_kuids + }; + + static ei_register_info ei[] = { + { &ei_mojito_socketaddress_unknown, { "mojito.socketaddress.unknown", PI_PROTOCOL, PI_ERROR, "Unsupported Socket Address Type", EXPFILL }}, + { &ei_mojito_bigint_unsupported, { "mojito.bigint.unsupported", PI_PROTOCOL, PI_ERROR, "Unsupported BigInt length", EXPFILL }}, + }; + + proto_mojito = proto_register_protocol("Mojito DHT", "Mojito", "mojito"); + + proto_register_field_array(proto_mojito, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_mojito = expert_register_protocol(proto_mojito); + expert_register_field_array(expert_mojito, ei, array_length(ei)); + + mojito_handle = register_dissector("mojito", dissect_mojito, proto_mojito); +} + +/* Control the handoff */ +void +proto_reg_handoff_mojito(void) +{ + heur_dissector_add("udp", dissect_mojito_heuristic, "Mojito over UDP", "mojito_udp", proto_mojito, HEURISTIC_ENABLE); + dissector_add_for_decode_as_with_preference("udp.port", mojito_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + * + * vi: set shiftwidth=8 tabstop=8 noexpandtab: + * :indentSize=8:tabSize=8:noTabs=false: + */ |