diff options
author | Guy Harris <guy@alum.mit.edu> | 2004-11-03 19:12:49 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2004-11-03 19:12:49 +0000 |
commit | 3d37d77f53c6f75a5ba2af8661cbf685b1b7af79 (patch) | |
tree | 5e3d8739de323f47996616574bebaf6126a2851b /epan/dissectors/packet-edonkey.c | |
parent | fdb482446437d139e02960960f1574e71b94101a (diff) |
Add support for desegmentation of eDonkey-over-TCP.
Clean up indentation.
Give edonkey.protocol a value_string table.
svn path=/trunk/; revision=12476
Diffstat (limited to 'epan/dissectors/packet-edonkey.c')
-rw-r--r-- | epan/dissectors/packet-edonkey.c | 237 |
1 files changed, 132 insertions, 105 deletions
diff --git a/epan/dissectors/packet-edonkey.c b/epan/dissectors/packet-edonkey.c index 038c224162..cfbadc6445 100644 --- a/epan/dissectors/packet-edonkey.c +++ b/epan/dissectors/packet-edonkey.c @@ -37,7 +37,9 @@ #include <glib.h> #include <epan/packet.h> +#include <epan/prefs.h> #include "packet-edonkey.h" +#include "packet-tcp.h" static int proto_edonkey = -1; @@ -75,6 +77,9 @@ static gint ett_edonkey_serverinfo = -1; static gint ett_edonkey_clientinfo = -1; static gint ett_overnet_peer = -1; +/* desegmentation of eDonkey over TCP */ +static gboolean edonkey_desegment = TRUE; + static const value_string edonkey_protocols[] = { { EDONKEY_PROTO_EDONKEY, "eDonkey" }, { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" }, @@ -1159,127 +1164,141 @@ static void dissect_emule_udp_message(guint8 msg_type, return; } -static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) + +static guint get_edonkey_tcp_pdu_len(tvbuff_t *tvb, int offset) { - proto_item *ti; - proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; - int offset, bytes, messages; - guint8 protocol, msg_type; + guint32 msg_len; + + /* + * Get the length of the eDonkey packet. + */ + msg_len = tvb_get_letohl(tvb, offset+1); + + /* + * That length doesn't include the header; add that in. + * XXX - what if it overflows? + */ + return msg_len + EDONKEY_TCP_HEADER_LENGTH; +} + +static void dissect_edonkey_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; + int offset, bytes, messages; + guint8 protocol, msg_type; guint32 msg_len; gchar *protocol_name, *message_name; void (*dissector)(guint8, tvbuff_t*, packet_info*, int, int, proto_tree*); - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); - if (check_col(pinfo->cinfo, COL_INFO)) - col_clear(pinfo->cinfo, COL_INFO); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); - if (tree) { + if (tree) { ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE); edonkey_tree = proto_item_add_subtree(ti, ett_edonkey); } offset = 0; messages = 0; - while (tvb_length_remaining(tvb, offset) >= EDONKEY_TCP_HEADER_LENGTH) { - protocol = tvb_get_guint8(tvb, offset); - msg_len = tvb_get_letohl(tvb, offset+1); + protocol = tvb_get_guint8(tvb, offset); + msg_len = tvb_get_letohl(tvb, offset+1); - protocol_name = match_strval(protocol, edonkey_protocols); - if (protocol_name == NULL) { - /* Not a recognized eDonkey protocol - probably a continuation */ - if (check_col(pinfo->cinfo, COL_INFO)) - col_add_str(pinfo->cinfo, COL_INFO, "eDonkey Continuation"); - if (edonkey_tree) { - bytes = tvb_length_remaining(tvb, offset); - proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes); - } - return; + protocol_name = match_strval(protocol, edonkey_protocols); + if (protocol_name == NULL) { + /* Not a recognized eDonkey protocol - probably a continuation */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_str(pinfo->cinfo, COL_INFO, "eDonkey Continuation"); + if (edonkey_tree) { + bytes = tvb_length_remaining(tvb, offset); + proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes); } + return; + } - /* Add edonkey message tree */ - if (edonkey_tree) { - ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, - offset, EDONKEY_TCP_HEADER_LENGTH + msg_len, FALSE); - edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message); + /* Add edonkey message tree */ + if (edonkey_tree) { + ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, + offset, EDONKEY_TCP_HEADER_LENGTH + msg_len, FALSE); + edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message); - proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol, - "Protocol: %s (0x%02x)", protocol_name, protocol); - proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len); - } + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol, + "Protocol: %s (0x%02x)", protocol_name, protocol); + proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len); + } - /* Skip past the EDONKEY Header */ - offset += EDONKEY_TCP_HEADER_LENGTH; + /* Skip past the EDONKEY Header */ + offset += EDONKEY_TCP_HEADER_LENGTH; - if(tvb_reported_length_remaining(tvb, offset) <= 0) { - /* There is not enough space for the msg_type - mark as fragment */ - if (check_col(pinfo->cinfo, COL_INFO)) { - if (messages == 0) - col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP Message Fragment", protocol_name); - else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP Message Fragment", protocol_name); - } - return; - } - + if(tvb_reported_length_remaining(tvb, offset) <= 0) { + /* There is not enough space for the msg_type - mark as fragment */ if (check_col(pinfo->cinfo, COL_INFO)) { - if (messages == 0) - col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP", protocol_name); - else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP", protocol_name); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP Message Fragment", protocol_name); } + return; + } - msg_type = tvb_get_guint8(tvb, offset); - switch (protocol) { - case EDONKEY_PROTO_EDONKEY: - message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"); - dissector = dissect_edonkey_tcp_message; - break; + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP", protocol_name); + } + + msg_type = tvb_get_guint8(tvb, offset); + switch (protocol) { + case EDONKEY_PROTO_EDONKEY: + message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"); + dissector = dissect_edonkey_tcp_message; + break; - case EDONKEY_PROTO_EMULE_EXT: - message_name = val_to_str(msg_type, emule_tcp_msgs, - val_to_str(msg_type, edonkey_tcp_msgs, "Unknown")); - dissector = dissect_emule_tcp_message; - break; - - default: - message_name = "Unknown"; - dissector = NULL; - break; - } + case EDONKEY_PROTO_EMULE_EXT: + message_name = val_to_str(msg_type, emule_tcp_msgs, + val_to_str(msg_type, edonkey_tcp_msgs, "Unknown")); + dissector = dissect_emule_tcp_message; + break; - if (check_col(pinfo->cinfo, COL_INFO)) { - col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name); - } + default: + message_name = "Unknown"; + dissector = NULL; + break; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name); + } - if (edonkey_msg_tree) { - proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset, 1, msg_type, - "Message Type: %s (0x%02x)", message_name, msg_type); - if (dissector && (msg_len > 1)) - (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree); - } + if (edonkey_msg_tree) { + proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset, 1, msg_type, + "Message Type: %s (0x%02x)", message_name, msg_type); + if (dissector && (msg_len > 1)) + (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree); + } +} - offset += msg_len; - messages++; - } +static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + tcp_dissect_pdus(tvb, pinfo, tree, edonkey_desegment, 5, + get_edonkey_tcp_pdu_len, dissect_edonkey_tcp_pdu); } static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_item *ti; - proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; - int offset; - guint8 protocol, msg_type; + proto_item *ti; + proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL; + int offset; + guint8 protocol, msg_type; gchar *protocol_name, *message_name; - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey"); - if (check_col(pinfo->cinfo, COL_INFO)) - col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message"); - if (tree) { + if (tree) { ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE); edonkey_tree = proto_item_add_subtree(ti, ett_edonkey); } @@ -1320,22 +1339,22 @@ static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t break; } } - } + } } void proto_register_edonkey(void) { static hf_register_info hf[] = { - { &hf_edonkey_message, + { &hf_edonkey_message, { "eDonkey Message", "edonkey.message", FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } }, - { &hf_edonkey_protocol, + { &hf_edonkey_protocol, { "Protocol", "edonkey.protocol", - FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Protocol", HFILL } }, - { &hf_edonkey_message_length, + FT_UINT8, BASE_HEX, VALS(edonkey_protocols), 0, "eDonkey Protocol", HFILL } }, + { &hf_edonkey_message_length, { "Message Length", "edonkey.message.length", FT_UINT32, BASE_DEC, NULL, 0, "eDonkey Message Length", HFILL } }, - { &hf_edonkey_message_type, + { &hf_edonkey_message_type, { "Message Type", "edonkey.message.type", FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Message Type", HFILL } }, { &hf_edonkey_client_hash, @@ -1356,7 +1375,7 @@ void proto_register_edonkey(void) { { &hf_edonkey_port, { "Port", "edonkey.port", FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Port", HFILL } }, - { &hf_edonkey_metatag, + { &hf_edonkey_metatag, { "eDonkey Meta Tag", "edonkey.metatag", FT_NONE, BASE_NONE, NULL, 0, "eDonkey Meta Tag", HFILL } }, { &hf_edonkey_metatag_type, @@ -1371,7 +1390,7 @@ void proto_register_edonkey(void) { { &hf_edonkey_metatag_namesize, { "Meta Tag Name Size", "edonkey.metatag.namesize", FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Meta Tag Name Size", HFILL } }, - { &hf_edonkey_search, + { &hf_edonkey_search, { "eDonkey Search", "edonkey.search", FT_NONE, BASE_NONE, NULL, 0, "eDonkey Search", HFILL } }, { &hf_edonkey_hash, @@ -1386,30 +1405,31 @@ void proto_register_edonkey(void) { { &hf_edonkey_directory, { "Directory", "edonkey.directory", FT_STRING, BASE_NONE, NULL, 0, "eDonkey Directory", HFILL } }, - { &hf_edonkey_fileinfo, + { &hf_edonkey_fileinfo, { "eDonkey File Info", "edonkey.fileinfo", FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Info", HFILL } }, - { &hf_edonkey_serverinfo, + { &hf_edonkey_serverinfo, { "eDonkey Server Info", "edonkey.serverinfo", FT_NONE, BASE_NONE, NULL, 0, "eDonkey Server Info", HFILL } }, - { &hf_edonkey_clientinfo, + { &hf_edonkey_clientinfo, { "eDonkey Client Info", "edonkey.clientinfo", FT_NONE, BASE_NONE, NULL, 0, "eDonkey Client Info", HFILL } }, - { &hf_overnet_peer, + { &hf_overnet_peer, { "Overnet Peer", "overnet.peer", FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } }, - }; + }; static gint *ett[] = { &ett_edonkey, - &ett_edonkey_message, - &ett_edonkey_metatag, - &ett_edonkey_search, - &ett_edonkey_fileinfo, - &ett_edonkey_serverinfo, - &ett_edonkey_clientinfo, - &ett_overnet_peer + &ett_edonkey_message, + &ett_edonkey_metatag, + &ett_edonkey_search, + &ett_edonkey_fileinfo, + &ett_edonkey_serverinfo, + &ett_edonkey_clientinfo, + &ett_overnet_peer }; + module_t *edonkey_module; proto_edonkey = proto_register_protocol("eDonkey Protocol", "EDONKEY", "edonkey"); @@ -1418,6 +1438,13 @@ void proto_register_edonkey(void) { proto_register_subtree_array(ett, array_length(ett)); register_dissector("edonkey.tcp", dissect_edonkey_tcp, proto_edonkey); register_dissector("edonkey.udp", dissect_edonkey_udp, proto_edonkey); + + edonkey_module = prefs_register_protocol(proto_edonkey, NULL); + prefs_register_bool_preference(edonkey_module, "desegment", + "Reassemble eDonkey messages spanning multiple TCP segments", + "Whether the eDonkey dissector should reassemble messages spanning multiple TCP segments." + " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", + &edonkey_desegment); } void proto_reg_handoff_edonkey(void) { |