Fix the bitcoin dissector to be able to dissect recent version of the protocol. Bug 8844 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8844)

Changes:
  - All messages now have a checksum (and not only version and verack).
  - In the version message: user agent added as a string preceded by a varint length.
  - Port in an address is in little endian and not big endian.
  - In the version message the receiving and emitting address where inverted.

From Eric Masson

svn path=/trunk/; revision=52609
This commit is contained in:
Michael Mann 2013-10-15 00:05:45 +00:00
parent 21e17b82d2
commit 856668d739
1 changed files with 68 additions and 30 deletions

View File

@ -55,8 +55,9 @@ static const value_string inv_types[] =
* - Magic - 4 bytes
* - Command - 12 bytes
* - Payload length - 4 bytes
* - Checksum - 4 bytes
*/
#define BITCOIN_HEADER_LENGTH 4+12+4
#define BITCOIN_HEADER_LENGTH 4+12+4+4
void proto_register_bitcoin(void);
void proto_reg_handoff_bitcoin(void);
@ -96,13 +97,13 @@ static header_field_info hfi_msg_version_addr_me BITCOIN_HFI_INIT =
{ "Address of emmitting node", "bitcoin.version.addr_me", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_msg_version_addr_you BITCOIN_HFI_INIT =
{ "Address as seen by the emitting node", "bitcoin.version.addr_you", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
{ "Address as receiving node", "bitcoin.version.addr_you", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_msg_version_nonce BITCOIN_HFI_INIT =
{ "Random nonce", "bitcoin.version.nonce", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_msg_version_subver BITCOIN_HFI_INIT =
{ "Sub-version string", "bitcoin.version.subver", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_msg_version_user_agent BITCOIN_HFI_INIT =
{ "User agent", "bitcoin.version.user_agent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_msg_version_start_height BITCOIN_HFI_INIT =
{ "Block start height", "bitcoin.version.start_height", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL };
@ -350,10 +351,28 @@ static header_field_info hfi_address_address BITCOIN_HFI_INIT =
static header_field_info hfi_address_port BITCOIN_HFI_INIT =
{ "Node port", "bitcoin.address.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL };
/* variable string */
static header_field_info hfi_string_value BITCOIN_HFI_INIT =
{ "String value", "bitcoin.string.value", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_string_varint_count8 BITCOIN_HFI_INIT =
{ "Count", "bitcoin.string.count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_string_varint_count16 BITCOIN_HFI_INIT =
{ "Count", "bitcoin.string.count", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_string_varint_count32 BITCOIN_HFI_INIT =
{ "Count", "bitcoin.string.count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL };
static header_field_info hfi_string_varint_count64 BITCOIN_HFI_INIT =
{ "Count", "bitcoin.string.count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL };
static gint ett_bitcoin = -1;
static gint ett_bitcoin_msg = -1;
static gint ett_services = -1;
static gint ett_address = -1;
static gint ett_string = -1;
static gint ett_addr_list = -1;
static gint ett_inv_list = -1;
static gint ett_getdata_list = -1;
@ -374,13 +393,6 @@ get_bitcoin_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
guint32 length;
length = BITCOIN_HEADER_LENGTH;
if (tvb_memeql(tvb, offset+4, "version", 7) != 0 &&
tvb_memeql(tvb, offset+4, "verack", 6) != 0)
{
/* add checksum field */
length += 4;
}
/* add payload length */
length += tvb_get_letohl(tvb, offset+16);
@ -434,7 +446,7 @@ create_address_tree(tvbuff_t *tvb, proto_item *ti, guint32 offset)
offset += 16;
/* port */
proto_tree_add_item(tree, &hfi_address_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, &hfi_address_port, tvb, offset, 2, ENC_BIG_ENDIAN);
return tree;
}
@ -497,6 +509,36 @@ static void add_varint_item(proto_tree *tree, tvbuff_t *tvb, const gint offset,
}
}
static proto_tree *
create_string_tree(proto_tree *tree, header_field_info* hfi, tvbuff_t *tvb, guint32* offset)
{
proto_tree *subtree;
proto_item *ti;
gint varint_length;
guint64 varint;
gint string_length;
/* First is the length of the following string as a varint */
get_varint(tvb, *offset, &varint_length, &varint);
string_length = (gint) varint;
ti = proto_tree_add_item(tree, hfi, tvb, *offset, varint_length + string_length, ENC_NA);
subtree = proto_item_add_subtree(ti, ett_string);
/* length */
add_varint_item(subtree, tvb, *offset, varint_length, &hfi_string_varint_count8,
&hfi_string_varint_count16, &hfi_string_varint_count32,
&hfi_string_varint_count64);
*offset += varint_length;
/* string */
proto_tree_add_item(subtree, &hfi_string_value, tvb, *offset, string_length,
ENC_ASCII|ENC_NA);
*offset += string_length;
return subtree;
}
/* Note: A number of the following message handlers include code of the form:
* ...
* guint64 count;
@ -529,7 +571,6 @@ static void
dissect_bitcoin_msg_version(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
{
proto_item *ti;
gint subver_length;
guint32 version;
guint32 offset = 0;
@ -551,23 +592,20 @@ dissect_bitcoin_msg_version(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
proto_tree_add_item(tree, &hfi_msg_version_timestamp, tvb, offset, 8, ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN);
offset += 8;
ti = proto_tree_add_item(tree, &hfi_msg_version_addr_me, tvb, offset, 26, ENC_NA);
ti = proto_tree_add_item(tree, &hfi_msg_version_addr_you, tvb, offset, 26, ENC_NA);
create_address_tree(tvb, ti, offset);
offset += 26;
if (version >= 106)
{
ti = proto_tree_add_item(tree, &hfi_msg_version_addr_you, tvb, offset, 26, ENC_NA);
ti = proto_tree_add_item(tree, &hfi_msg_version_addr_me, tvb, offset, 26, ENC_NA);
create_address_tree(tvb, ti, offset);
offset += 26;
proto_tree_add_item(tree, &hfi_msg_version_nonce, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset += 8;
/* find null terminated subver */
subver_length = tvb_strsize(tvb, offset);
proto_tree_add_item(tree, &hfi_msg_version_subver, tvb, offset, subver_length, ENC_ASCII|ENC_NA);
offset += subver_length;
create_string_tree(tree, &hfi_msg_version_user_agent, tvb, &offset);
if (version >= 209)
{
@ -1020,17 +1058,9 @@ static void dissect_bitcoin_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tre
proto_tree_add_item(tree, &hfi_bitcoin_magic, tvb, 0, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, &hfi_bitcoin_command, tvb, 4, 12, ENC_ASCII|ENC_NA);
proto_tree_add_item(tree, &hfi_bitcoin_length, tvb, 16, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, &hfi_bitcoin_checksum, tvb, 20, 4, ENC_BIG_ENDIAN);
offset = 20;
if (tvb_memeql(tvb, 4, "version", 7) != 0 &&
tvb_memeql(tvb, 4, "verack", 6) != 0)
{
proto_tree_add_item(tree, &hfi_bitcoin_checksum, tvb, 20, 4, ENC_BIG_ENDIAN);
offset += 4;
/* TODO: verify checksum? */
}
offset = 24;
/* handle command specific message part */
for (i = 0; i < array_length(msg_dissectors); i++)
@ -1104,7 +1134,7 @@ proto_register_bitcoin(void)
&hfi_msg_version_addr_you,
&hfi_msg_version_timestamp,
&hfi_msg_version_nonce,
&hfi_msg_version_subver,
&hfi_msg_version_user_agent,
&hfi_msg_version_start_height,
/* addr message */
@ -1210,6 +1240,13 @@ proto_register_bitcoin(void)
&hfi_address_services,
&hfi_address_address,
&hfi_address_port,
/* variable string */
&hfi_string_value,
&hfi_string_varint_count8,
&hfi_string_varint_count16,
&hfi_string_varint_count32,
&hfi_string_varint_count64,
};
static gint *ett[] = {
@ -1217,6 +1254,7 @@ proto_register_bitcoin(void)
&ett_bitcoin_msg,
&ett_services,
&ett_address,
&ett_string,
&ett_addr_list,
&ett_inv_list,
&ett_getdata_list,