Redo dissction of blocks in a bluecom packet.

It *looks* as if a bluecom packet has a count of blocks, and a sequence
of that number of blocks, with each one containing a block header and a
block data.

Dissect the packet in that fashion.  If we get an exception (other than
"we hit the snaplen") while dissecting a block, record it and step on to
the next block.

Don't try to avoid hitting the snaplen - we *want* that to be reported,
so the user knows that the capture only includes the first part of the
packet.

Change-Id: I1b668ffea9b67d3a6ff06100b868f7d941c1f509
Reviewed-on: https://code.wireshark.org/review/27106
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2018-04-23 13:45:15 -07:00
parent 40de0010bb
commit 352b7a9fd5
1 changed files with 177 additions and 259 deletions

View File

@ -20,6 +20,8 @@
#include <epan/packet.h>
#include <epan/etypes.h>
#include <epan/to_str.h>
#include <epan/exceptions.h>
#include <epan/show_exception.h>
/* bluecom protocol defines */
@ -153,268 +155,254 @@ static const value_string bcp_cmds[] = {
/*
* dissector function of connect data (request and response)
*
* input: tree, buffer (data), offset (data pointer), length of data, flags (req or rsp)
* output: offset
* input: tree, buffer (block data), flags (req or rsp)
* return: nothing
*/
static void
dissect_bcp_connect_data(proto_tree *bcp_tree, tvbuff_t *tvb,
guint *offset, guint len, gint flags)
dissect_bcp_connect_data(proto_tree *bcp_tree, tvbuff_t *tvb, gint flags)
{
proto_tree *bcp_subtree = NULL;
guint offset_base = *offset;
guint offset = 0;
guint offset_base = offset;
guint len = tvb_reported_length(tvb);
if (flags & BCP_PROT_FLG_REQ)
{
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Connect Request: Name=%s IpAddr=%s",
tvb_get_string_enc(wmem_packet_scope(), tvb, *offset + 16, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, *offset + 12));
tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 16, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, offset + 12));
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenin, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenout, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_cycletime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_offlinefactor, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ipaddr, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_name, tvb, *offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
*offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
if((len-(*offset-offset_base)))
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_cycletime, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_offlinefactor, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
if((len-(offset-offset_base)))
{
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr2, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
}
}
if (flags & BCP_PROT_FLG_RSP)
{
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Connect Response: Error=%d",
tvb_get_ntohl(tvb, *offset));
tvb_get_ntohl(tvb, offset));
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_error, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenin, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenout, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_error, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
*offset = offset_base + len;
}
/*
* dissector function of search data (request and response)
*
* input: tree, buffer (data), offset (data pointer), length of data, flags (req or rsp)
* output: offset
* input: tree, buffer (block data) flags (req or rsp)
* return: nothing
*/
static void
dissect_bcp_search_data(proto_tree *bcp_tree, tvbuff_t *tvb,
guint *offset, guint len, gint flags)
dissect_bcp_search_data(proto_tree *bcp_tree, tvbuff_t *tvb, gint flags)
{
proto_tree *bcp_subtree = NULL;
guint type = 0;
guint offset_base = *offset;
guint offset = 0;
guint offset_base = offset;
guint len = tvb_reported_length(tvb);
if (flags & BCP_PROT_FLG_REQ)
{
type = tvb_get_ntohl(tvb, *offset);
type = tvb_get_ntohl(tvb, offset);
switch (type)
{
case BCP_SEARCH_IPADDR:
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Search Request: IpAddrFirst=%s, IpAddrLast=%s",
tvb_ip_to_str(tvb, *offset + 8),
tvb_ip_to_str(tvb, *offset + 12)
tvb_ip_to_str(tvb, offset + 8),
tvb_ip_to_str(tvb, offset + 12)
);
break;
case BCP_SEARCH_NAME:
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Search Request: Name=%s",
tvb_get_string_enc(wmem_packet_scope(), tvb, *offset + 8, BCP_NAME_LEN, ENC_ASCII)
tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 8, BCP_NAME_LEN, ENC_ASCII)
);
break;
default:
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Search Request: Unknown AddrType");
break;
}
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_addrtype, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_reserved, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_addrtype, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
switch (type)
{
case BCP_SEARCH_IPADDR:
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrfirst, tvb, *offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrlast, tvb, *offset + 4, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrfirst, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrlast, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
break;
case BCP_SEARCH_NAME:
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_name, tvb, *offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
break;
default:
proto_tree_add_bytes_format(bcp_subtree, hf_bcp_searchreq_addrdata, tvb, *offset, BCP_NAME_LEN,
proto_tree_add_bytes_format(bcp_subtree, hf_bcp_searchreq_addrdata, tvb, offset, BCP_NAME_LEN,
NULL, "Unknown Address Data (%u bytes)", BCP_NAME_LEN);
break;
}
*offset += BCP_NAME_LEN;
offset += BCP_NAME_LEN;
}
if (flags & BCP_PROT_FLG_RSP)
{
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Search Response: Name=%s, IpAddr=%s Error=%d",
tvb_get_string_enc(wmem_packet_scope(), tvb, *offset + 16, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, *offset + 12),
tvb_get_letohl(tvb, *offset)
tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 16, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, offset + 12),
tvb_get_letohl(tvb, offset)
);
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_error, tvb, *offset, 4, ENC_NA);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_starttime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenin, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenout, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ipaddr, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_name, tvb, *offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
*offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
if((len-(*offset-offset_base)))
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_error, tvb, offset, 4, ENC_NA);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
if((len-(offset-offset_base)))
{
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr2, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
}
}
*offset = offset_base + len;
}
/*
* dissector function of identify data (request)
*
* input: tree, buffer (data), offset (data pointer), length of data, flags (req or rsp)
* output: offset
* input: tree, buffer (block data), flags (req or rsp)
* return: nothing
*/
static void
dissect_bcp_identify_data(proto_tree *bcp_tree, tvbuff_t *tvb,
guint *offset, guint len)
dissect_bcp_identify_data(proto_tree *bcp_tree, tvbuff_t *tvb)
{
proto_tree *bcp_subtree = NULL;
guint offset_base = *offset;
guint offset = 0;
guint offset_base = offset;
guint len = tvb_reported_length(tvb);
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Identify Request: Name=%s, IpAddr=%s",
tvb_get_string_enc(wmem_packet_scope(), tvb, *offset + 12, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, *offset + 8)
tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 12, BCP_NAME_LEN, ENC_ASCII),
tvb_ip_to_str(tvb, offset + 8)
);
proto_tree_add_item(bcp_subtree, hf_bcp_identify_error, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_starttime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ipaddr, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_name, tvb, *offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
*offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
if((len-(*offset-offset_base)))
proto_tree_add_item(bcp_subtree, hf_bcp_identify_error, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
offset += BCP_NAME_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
if((len-(offset-offset_base)))
{
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr2, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
}
*offset = offset_base + len;
}
/*
* dissector function of sync data
*
* input: tree, buffer (data), offset (data pointer), length of data
* output: offset
* input: tree, buffer (block data)
* return: nothing
*/
static void
dissect_bcp_sync_data(proto_tree *bcp_tree, tvbuff_t *tvb,
guint *offset, guint len)
dissect_bcp_sync_data(proto_tree *bcp_tree, tvbuff_t *tvb)
{
proto_tree *bcp_subtree = NULL;
guint offset_base = *offset;
guint offset = 0;
guint offset_base = offset;
guint len = tvb_reported_length(tvb);
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, len, ett_bcp_data, NULL,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
"BCP Sync Data: Identify=%s",
BOOLSTR(tvb_get_guint8(tvb, *offset + 9)));
proto_tree_add_item(bcp_subtree, hf_bcp_sync_starttime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_cycletime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_dataratio, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_identify, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_vlantag, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
BOOLSTR(tvb_get_guint8(tvb, offset + 9)));
proto_tree_add_item(bcp_subtree, hf_bcp_sync_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_cycletime, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_dataratio, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_identify, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_vlantag, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* protocol expansion*/
if((len-(*offset-offset_base)))
if((len-(offset-offset_base)))
{
proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr2, tvb, *offset, BCP_ETHADDR_LEN, ENC_NA);
*offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
offset += BCP_ETHADDR_LEN;
}
*offset = offset_base + len;
}
/*
* dissector function of data command
*
* input: tree, buffer (data), offset (data pointer), length of data
* output: offset
* input: tree, buffer (block data)
* return: nothing
*/
static void
dissect_bcp_data(proto_tree *bcp_tree, packet_info *pinfo, tvbuff_t *tvb,
guint *offset, guint len, gint segcode)
guint segcode)
{
dissector_handle_t handle;
tvbuff_t *next_tvb;
/* Probably a sub-dissector exists for this type/version combination. */
handle = dissector_get_uint_handle(bcp_subdissector_table, segcode);
if (handle)
{
/* Generate a new tvb for the rest. */
next_tvb = tvb_new_subset_length_caplen(tvb, *offset, len, len);
/* Call the sub-dissector. */
call_dissector(handle, next_tvb, pinfo, bcp_tree);
*offset += len;
call_dissector(handle, tvb, pinfo, bcp_tree);
}
else
{
proto_tree_add_item(bcp_tree, hf_bcp_userdata, tvb, *offset, len, ENC_NA);
*offset += len;
proto_tree_add_item(bcp_tree, hf_bcp_userdata, tvb, 0, -1, ENC_NA);
}
}
@ -428,7 +416,7 @@ dissect_bcp_data(proto_tree *bcp_tree, packet_info *pinfo, tvbuff_t *tvb,
*/
static void
dissect_bcp_block_header(proto_tree *bcp_tree, tvbuff_t *tvb, guint *offset,
gint blocknb, gint *cmd, guint *len)
guint blocknb, guint *cmd, guint *len)
{
proto_tree *bcp_subtree = NULL;
@ -436,7 +424,7 @@ dissect_bcp_block_header(proto_tree *bcp_tree, tvbuff_t *tvb, guint *offset,
*len = tvb_get_ntohs(tvb, *offset + 12);
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, *offset, BCP_BLOCK_HDR_LEN, ett_bcp_blockheader, NULL,
"BCP Block Header (%d): Cmd=%s (%d), Len=%d",
"BCP Block Header (%u): Cmd=%s (%u), Len=%u",
blocknb,
val_to_str(*cmd, bcp_cmds, "UNKNOWN"), *cmd,
*len
@ -471,7 +459,8 @@ dissect_bcp_block_header(proto_tree *bcp_tree, tvbuff_t *tvb, guint *offset,
*/
static void
dissect_bcp_protocol_header(proto_tree *bcp_tree, tvbuff_t *tvb,
guint *offset, gint *flags, gint *blocknb, gint *segcode)
guint *offset, gint *flags, guint *blocknb,
guint *segcode)
{
proto_tree *bcp_subtree = NULL;
@ -481,8 +470,8 @@ dissect_bcp_protocol_header(proto_tree *bcp_tree, tvbuff_t *tvb,
bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, 0, BCP_PROTOCOL_HDR_LEN, ett_bcp_header, NULL,
"BCP Protocol Header: BlockNb=%d, SegCode=%d",
tvb_get_guint8(tvb, *offset + 3),
tvb_get_ntohs(tvb, *offset + 4));
*blocknb,
*segcode);
proto_tree_add_item(bcp_subtree, hf_bcp_hdr_version, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
@ -504,12 +493,12 @@ dissect_bcp_protocol_header(proto_tree *bcp_tree, tvbuff_t *tvb,
*/
static int dissect_bluecom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
gint cmd, flags, blocknb, segcode=0;
gint data_cnt = 0;
guint len, rlen;
guint cmd, flags, blocknb, segcode=0, block;
guint len;
guint offset = 0;
proto_tree *bcp_tree = NULL;
proto_item *bcp_item_base = NULL;
tvbuff_t *block_tvb;
/* set protocol name column */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "bluecom");
@ -523,128 +512,57 @@ static int dissect_bluecom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* BCP header */
dissect_bcp_protocol_header(bcp_tree, tvb, &offset, &flags, &blocknb, &segcode);
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, data_cnt, &cmd, &len);
/* set info column */
col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d) segcode=%d blocks=%d",
val_to_str(cmd, bcp_cmds, "UNKNOWN"), cmd, segcode, blocknb);
col_append_fstr(pinfo->cinfo, COL_INFO, "segcode=%u blocks=%u",
segcode, blocknb);
/* append text to BCP base */
proto_item_append_text(bcp_item_base, ", %s (%d) len=%d",
val_to_str(cmd, bcp_cmds, "UNKNOWN"), cmd, tvb_reported_length(tvb));
/* Iterate over blocks */
for (block = 0; block < blocknb; block++)
{
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, block, &cmd, &len);
switch (cmd) {
case BCP_BLK_CMD_SYNC:
dissect_bcp_sync_data(bcp_tree, tvb, &offset, len);
break;
/* append text to BCP base */
proto_item_append_text(bcp_item_base, ", %s (%u) len=%u",
val_to_str(cmd, bcp_cmds, "UNKNOWN"), cmd, len);
case BCP_BLK_CMD_IDENTIFY:
dissect_bcp_identify_data(bcp_tree, tvb, &offset, len);
rlen = tvb_captured_length_remaining(tvb, offset);
/* ignore additional bytes if < block header. Could be padding or cut of recording */
while (rlen >= BCP_BLOCK_HDR_LEN)
block_tvb = tvb_new_subset_length(tvb, offset, len);
TRY {
switch (cmd)
{
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, ++data_cnt, &cmd, &len);
rlen = tvb_captured_length_remaining(tvb, offset);
/* calculate remaining data length */
if (len > rlen)
{
len = rlen;
col_append_fstr(pinfo->cinfo, COL_INFO, " [data len of block %d limited to %d]",
data_cnt, len);
break;
}
dissect_bcp_identify_data(bcp_tree, tvb, &offset, len);
rlen = tvb_captured_length_remaining(tvb, offset);
case BCP_BLK_CMD_SYNC:
dissect_bcp_sync_data(bcp_tree, block_tvb);
break;
case BCP_BLK_CMD_IDENTIFY:
dissect_bcp_identify_data(bcp_tree, block_tvb);
break;
case BCP_BLK_CMD_SEARCH:
col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
dissect_bcp_search_data(bcp_tree, block_tvb, flags);
break;
case BCP_BLK_CMD_CONNECT:
col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
dissect_bcp_connect_data(bcp_tree, block_tvb, flags);
break;
case BCP_BLK_CMD_DATA:
default:
dissect_bcp_data(bcp_tree, pinfo, block_tvb, segcode);
break;
}
offset += rlen;
break;
case BCP_BLK_CMD_SEARCH:
col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
dissect_bcp_search_data(bcp_tree, tvb, &offset, len, flags);
rlen = tvb_captured_length_remaining(tvb, offset);
/* ignore additional bytes if < block header. Could be padding or cut of recording */
while (rlen >= BCP_BLOCK_HDR_LEN)
{
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, ++data_cnt, &cmd, &len);
rlen = tvb_captured_length_remaining(tvb, offset);
/* calculate remaining data length */
if (len > rlen)
{
len = rlen;
col_append_fstr(pinfo->cinfo, COL_INFO, " [data len of block %d limited to %d]",
data_cnt, len);
break;
}
dissect_bcp_search_data(bcp_tree, tvb, &offset, len, flags);
rlen = tvb_captured_length_remaining(tvb, offset);
}
offset += rlen;
break;
case BCP_BLK_CMD_CONNECT:
col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
dissect_bcp_connect_data(bcp_tree, tvb, &offset, len, flags);
rlen = tvb_captured_length_remaining(tvb, offset);
/* ignore additional bytes if < block header. Could be padding or cut of recording */
while (rlen >= BCP_BLOCK_HDR_LEN)
{
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, ++data_cnt, &cmd, &len);
rlen = tvb_captured_length_remaining(tvb, offset);
/* calculate remaining data length */
if (len > rlen)
{
len = rlen;
col_append_fstr(pinfo->cinfo, COL_INFO, " [data len of block %d limited to %d]",
data_cnt, len);
break;
}
dissect_bcp_connect_data(bcp_tree, tvb, &offset, len, flags);
rlen = tvb_captured_length_remaining(tvb, offset);
}
offset += rlen;
break;
case BCP_BLK_CMD_DATA:
default:
/* check if data packet was limited */
rlen = tvb_captured_length_remaining(tvb, offset);
if (len > rlen)
{
len = rlen;
col_append_fstr(pinfo->cinfo, COL_INFO, " [data len of block %d limited to %d]",
data_cnt, len);
}
dissect_bcp_data(bcp_tree, pinfo, tvb, &offset, len, segcode);
rlen = tvb_captured_length_remaining(tvb, offset);
/* ignore additional bytes if < block header. Could be padding or cut of recording */
while (rlen >= BCP_BLOCK_HDR_LEN)
{
/* BCP block header*/
dissect_bcp_block_header(bcp_tree, tvb, &offset, ++data_cnt, &cmd, &len);
rlen = tvb_captured_length_remaining(tvb, offset);
/* calculate remaining data length */
if (len > rlen)
{
len = rlen;
col_append_fstr(pinfo->cinfo, COL_INFO, " [data len of block %d limited to %d]",
data_cnt, len);
break;
}
dissect_bcp_data(bcp_tree, pinfo, tvb, &offset, len, segcode);
rlen = tvb_captured_length_remaining(tvb, offset);
}
offset += rlen;
break;
} CATCH_NONFATAL_ERRORS {
/*
* Somebody threw an exception that means that there was
* a problem dissecting the block. Just show the exception
* and then continue to dissect blocks.
*/
show_exception(block_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
} ENDTRY;
offset += len;
}
return offset;