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