forked from osmocom/wireshark
first version of reassembly btatt
does trigger reassembly but never accumulates data
This commit is contained in:
parent
9b771d2c14
commit
40e5934444
|
@ -16,12 +16,14 @@
|
|||
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include <epan/frame_data.h>
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/decode_as.h>
|
||||
#include <epan/tap.h>
|
||||
#include <epan/proto_data.h>
|
||||
#include <epan/unit_strings.h>
|
||||
#include <epan/reassemble.h>
|
||||
|
||||
#include "packet-bluetooth.h"
|
||||
#include "packet-btatt.h"
|
||||
|
@ -33,6 +35,10 @@
|
|||
|
||||
#define HANDLE_TVB -1
|
||||
|
||||
/* packet reassembly */
|
||||
static reassembly_table msg_reassembly_table;
|
||||
/* end packet reassebly */
|
||||
|
||||
/* Initialize the protocol and registered fields */
|
||||
static int proto_btatt = -1;
|
||||
static int proto_btgatt = -1;
|
||||
|
@ -2107,6 +2113,8 @@ static gint ett_btgatt_microbit_magnetometer = -1;
|
|||
static gint ett_btgatt_microbit_pin_data = -1;
|
||||
static gint ett_btgatt_microbit_pin_ad_config = -1;
|
||||
static gint ett_btgatt_microbit_pin_io_config = -1;
|
||||
static gint ett_btatt_fragment = -1;
|
||||
static gint ett_btatt_fragments = -1;
|
||||
|
||||
static expert_field ei_btatt_uuid_format_unknown = EI_INIT;
|
||||
static expert_field ei_btatt_handle_too_few = EI_INIT;
|
||||
|
@ -2137,6 +2145,39 @@ static dissector_handle_t btmesh_proxy_handle;
|
|||
|
||||
static dissector_table_t att_handle_dissector_table;
|
||||
|
||||
static gint hf_btatt_fragments = -1;
|
||||
static gint hf_btatt_fragment = -1;
|
||||
static gint hf_btatt_fragment_overlap = -1;
|
||||
static gint hf_btatt_fragment_overlap_conflicts = -1;
|
||||
static gint hf_btatt_fragment_multiple_tails = -1;
|
||||
static gint hf_btatt_fragment_too_long_fragment = -1;
|
||||
static gint hf_btatt_fragment_error = -1;
|
||||
static gint hf_btatt_fragment_count = -1;
|
||||
static gint hf_btatt_reassembled_in = -1;
|
||||
static gint hf_btatt_reassembled_length = -1;
|
||||
static gint hf_btatt_reassembled_data = -1;
|
||||
|
||||
static const fragment_items msg_frag_items = {
|
||||
/* Fragment subtrees */
|
||||
&ett_btatt_fragment,
|
||||
&ett_btatt_fragments,
|
||||
/* Fragment fields */
|
||||
&hf_btatt_fragments, /* FT_NONE */
|
||||
&hf_btatt_fragment, /* FT_FRAMENUM */
|
||||
&hf_btatt_fragment_overlap, /* FT_BOOLEAN */
|
||||
&hf_btatt_fragment_overlap_conflicts, /* FT_BOOLEAN */
|
||||
&hf_btatt_fragment_multiple_tails, /* FT_BOOLEAN */
|
||||
&hf_btatt_fragment_too_long_fragment, /* FT_BOOLEAN */
|
||||
&hf_btatt_fragment_error,
|
||||
&hf_btatt_fragment_count,
|
||||
/* Reassembled in field */
|
||||
&hf_btatt_reassembled_in,
|
||||
/* Reassembled length field */
|
||||
&hf_btatt_reassembled_length,
|
||||
&hf_btatt_reassembled_data,
|
||||
/* Tag */
|
||||
"Message fragments"};
|
||||
|
||||
extern value_string_ext ext_usb_vendors_vals;
|
||||
|
||||
/* Opcodes */
|
||||
|
@ -4612,6 +4653,113 @@ btatt_call_dissector_by_dissector_name_with_data(const char *dissector_name,
|
|||
REPORT_DISSECTOR_BUG("Dissector %s not registered", dissector_name);
|
||||
}
|
||||
|
||||
/*
|
||||
dissects attribute handle and takes care of reassemly:
|
||||
If sub-dissector sets pinfo->deseg_offset >0 && < pktlen the leftover bytes are stored and front-attached to the next packet
|
||||
returns 0 if paket was not handled
|
||||
returns #bytes consumed
|
||||
*/
|
||||
static gint
|
||||
btatt_dissect_with_reassmbly(guint16 handle, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, btatt_data_t *att_data){
|
||||
/*
|
||||
* Cases
|
||||
* 1) single paket: deseg_len=0 deseg_offset=pktlen oder 0??
|
||||
* 2) start stream: deseg_len=MORE_BYTE deseg_offset>-1<pktlen -> partially consumed, store fragment, finish
|
||||
* 3) cont stream: deseg_len=MORE_BYTE deseg_offset=-1 (due to header mismatch) -> not consumed, add previous fragment, run again
|
||||
* 4) end stream: deseg_len=0 deseg_offset=pktlen -> completely consumed, return pktlen
|
||||
*
|
||||
* case 3 can lead to case 2 -> stop fragment stream, create new fragment stream
|
||||
* */
|
||||
guint consumed;
|
||||
gboolean save_fragmented;
|
||||
gboolean more_fragments = FALSE;
|
||||
gint offset = 0;
|
||||
// do not test for (PINFO_FD_VISITED(pinfo)) otherwise the lua dissector is not added
|
||||
|
||||
again:
|
||||
pinfo->desegment_offset = -1;
|
||||
pinfo->desegment_len = 0;
|
||||
consumed = btatt_dissect_attribute_handle(handle, tvb, pinfo, tree, att_data);
|
||||
|
||||
//consumed == 0: paket was rejected by subdissector, do not test for fragmentation
|
||||
if (!(consumed == 0 && pinfo->desegment_len == 0))
|
||||
{
|
||||
guint32 msg_seqid = handle << 16 | ( att_data->opcode & 0xffff);
|
||||
pinfo->srcport = handle;
|
||||
pinfo->destport = att_data->opcode;
|
||||
if ((guint)pinfo->desegment_offset == tvb_captured_length(tvb))
|
||||
{
|
||||
// case 1
|
||||
more_fragments = FALSE;
|
||||
}
|
||||
if (pinfo->desegment_offset > -1 && (guint)pinfo->desegment_offset < tvb_captured_length(tvb))
|
||||
{
|
||||
// case 2
|
||||
//drop leftovers before a fresh fragment ist started
|
||||
tvbuff_t *old_tvb_data = fragment_delete(&msg_reassembly_table, pinfo, msg_seqid, NULL);
|
||||
if (old_tvb_data)
|
||||
tvb_free(old_tvb_data);
|
||||
more_fragments = TRUE;
|
||||
}
|
||||
if (pinfo->desegment_offset == -1)
|
||||
{
|
||||
// case 3
|
||||
more_fragments = FALSE;
|
||||
}
|
||||
if (pinfo->desegment_offset == -1 && consumed == tvb_captured_length(tvb))
|
||||
{
|
||||
// case 4
|
||||
more_fragments = FALSE;
|
||||
}
|
||||
|
||||
save_fragmented = pinfo->fragmented;
|
||||
if (consumed < tvb_captured_length(tvb))
|
||||
{
|
||||
offset = (pinfo->desegment_offset==-1?0:pinfo->desegment_offset);
|
||||
tvbuff_t *new_tvb = NULL;
|
||||
fragment_item *frag_msg = NULL;
|
||||
pinfo->fragmented = TRUE;
|
||||
frag_msg = fragment_add_seq_next(&msg_reassembly_table,
|
||||
tvb, offset, pinfo,
|
||||
msg_seqid, NULL, /* ID for fragments belonging together */
|
||||
tvb_captured_length_remaining(tvb, offset),
|
||||
more_fragments); /* More fragments? */
|
||||
|
||||
new_tvb = process_reassembled_data(tvb, offset, pinfo,
|
||||
"Reassembled Message", frag_msg, &msg_frag_items,
|
||||
NULL, tree);
|
||||
|
||||
if (frag_msg)
|
||||
{ /* Reassembled */
|
||||
col_append_str(pinfo->cinfo, COL_INFO,
|
||||
"Last Pckt (Message Reassembled)");
|
||||
}
|
||||
else
|
||||
{ /* Not last packet of reassembled Short Message */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO,
|
||||
"(Message fragment %u)", pinfo->num);
|
||||
}
|
||||
|
||||
pinfo->fragmented = save_fragmented;
|
||||
//Reassembly buffer is empty but reassembly requested. break the loop
|
||||
if (new_tvb && (tvb_captured_length(tvb) == tvb_captured_length(new_tvb)))
|
||||
return 0;
|
||||
if (new_tvb)
|
||||
{ /* take it all */
|
||||
tvb = new_tvb;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{ /* make a new subset */
|
||||
tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *pinfo, tvbuff_t *old_tvb,
|
||||
gint old_offset, gint length, guint16 handle, bluetooth_uuid_t uuid, btatt_data_t *att_data)
|
||||
|
@ -4619,7 +4767,7 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
proto_item *sub_item;
|
||||
proto_tree *sub_tree = NULL;
|
||||
tvbuff_t *tvb;
|
||||
gint offset = 0;
|
||||
guint offset = 0;
|
||||
bluetooth_uuid_t sub_uuid;
|
||||
bluetooth_uuid_t service_uuid;
|
||||
guint16 sub_handle;
|
||||
|
@ -4648,8 +4796,9 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
p_add_proto_data(pinfo->pool, pinfo, proto_btatt, PROTO_DATA_BTATT_HANDLE, value_data);
|
||||
}
|
||||
|
||||
if (btatt_dissect_attribute_handle(handle, tvb, pinfo, tree, att_data))
|
||||
return old_offset + length;
|
||||
offset = btatt_dissect_with_reassmbly(handle,tvb,pinfo,tree,att_data);
|
||||
if (offset == tvb_captured_length(tvb))
|
||||
return old_offset + offset;
|
||||
|
||||
if (p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
|
||||
guint8 *value_data;
|
||||
|
@ -4658,7 +4807,8 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
|
||||
p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
|
||||
}
|
||||
|
||||
/* hier wird subddisector aufgerufen */
|
||||
/* dort wird auch von einem neuen PAket ausgegangen, was es natürlich nicht ist, darum fehelern und kein subddisector aufgerufen*/
|
||||
if (dissector_try_string(bluetooth_uuid_table, print_numeric_uuid(&uuid), tvb, pinfo, tree, att_data))
|
||||
return old_offset + length;
|
||||
else if (!uuid.bt_uuid) {
|
||||
|
@ -4693,7 +4843,9 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", print_uuid(&sub_uuid));
|
||||
|
||||
save_handle(pinfo, sub_uuid, handle, ATTRIBUTE_TYPE_SERVICE, bluetooth_data);
|
||||
} else if (tvb_reported_length_remaining(tvb, offset) == 16) {
|
||||
}
|
||||
else if (tvb_reported_length_remaining(tvb, offset) == 16)
|
||||
{
|
||||
proto_tree_add_item(tree, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
|
||||
sub_uuid = get_uuid(tvb, offset, 16);
|
||||
proto_item_append_text(patron_item, ", UUID128: %s", print_uuid(&sub_uuid));
|
||||
|
@ -4702,7 +4854,9 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", print_uuid(&sub_uuid));
|
||||
|
||||
save_handle(pinfo, sub_uuid, handle, ATTRIBUTE_TYPE_SERVICE, bluetooth_data);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_item = proto_tree_add_item(tree, hf_btatt_value, tvb, offset, -1, ENC_NA);
|
||||
expert_add_info(pinfo, sub_item, &ei_btatt_bad_data);
|
||||
offset = tvb_captured_length(tvb);
|
||||
|
@ -4760,7 +4914,9 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", print_uuid(&sub_uuid));
|
||||
|
||||
save_handle(pinfo, sub_uuid, sub_handle, ATTRIBUTE_TYPE_CHARACTERISTIC, bluetooth_data);
|
||||
} else if (tvb_reported_length_remaining(tvb, offset) == 2) {
|
||||
}
|
||||
else if (tvb_reported_length_remaining(tvb, offset) == 2)
|
||||
{
|
||||
proto_tree_add_item(tree, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
sub_uuid = get_uuid(tvb, offset, 2);
|
||||
proto_item_append_text(patron_item, ", Characteristic Handle: 0x%04x, UUID: %s", sub_handle, print_uuid(&sub_uuid));
|
||||
|
@ -10522,6 +10678,7 @@ btatt_dissect_attribute_handle(guint16 handle, tvbuff_t *tvb, packet_info *pinfo
|
|||
* It will implicitly call dissect_btgatt() which retrieves the BT UUID
|
||||
* from its protocol name and then calls dissect_attribute_value().
|
||||
*/
|
||||
|
||||
return dissector_try_uint_new(att_handle_dissector_table, handle, tvb, pinfo, tree, TRUE, att_data);
|
||||
}
|
||||
|
||||
|
@ -10735,7 +10892,9 @@ dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|||
guint16 handle;
|
||||
bluetooth_uuid_t uuid;
|
||||
guint mtu;
|
||||
|
||||
/* desegmentation stuff */
|
||||
// int deseg_offset = 0;
|
||||
/*end desgementation stuff */
|
||||
memset(&uuid, 0, sizeof uuid);
|
||||
|
||||
bluetooth_data = (bluetooth_data_t *) data;
|
||||
|
@ -10770,11 +10929,8 @@ dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|||
opcode = tvb_get_guint8(tvb, 0);
|
||||
att_data.opcode = opcode;
|
||||
offset++;
|
||||
|
||||
request_data = get_request(tvb, offset, pinfo, opcode, bluetooth_data);
|
||||
|
||||
col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>"));
|
||||
|
||||
switch (opcode) {
|
||||
case 0x01: /* Error Response */
|
||||
{
|
||||
|
@ -11333,11 +11489,8 @@ dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|||
case 0x1b: /* Handle Value Notification */
|
||||
offset = dissect_handle(main_tree, pinfo, hf_btatt_handle, tvb, offset, bluetooth_data, &uuid, HANDLE_TVB);
|
||||
handle = tvb_get_letohs(tvb, offset - 2);
|
||||
|
||||
col_append_info_by_handle(pinfo, handle, bluetooth_data);
|
||||
|
||||
offset = dissect_attribute_value(main_tree, NULL, pinfo, tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_get_guint16(tvb, offset - 2, ENC_LITTLE_ENDIAN), uuid, &att_data);
|
||||
|
||||
if (!pinfo->fd->visited && bluetooth_data && (opcode == 0x12 || opcode == 0x1d)) {
|
||||
union request_parameters_union request_parameters;
|
||||
|
||||
|
@ -11469,11 +11622,9 @@ dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|||
sub_item = proto_tree_add_uint(main_tree, hf_request_in_frame, tvb, 0, 0, request_data->request_in_frame);
|
||||
proto_item_set_generated(sub_item);
|
||||
}
|
||||
|
||||
if (!pinfo->fd->visited && request_data->response_in_frame == 0 &&
|
||||
pinfo->num > request_data->request_in_frame)
|
||||
request_data->response_in_frame = pinfo->num;
|
||||
|
||||
if (request_data->response_in_frame > 0 && request_data->response_in_frame != pinfo->num) {
|
||||
sub_item = proto_tree_add_uint(main_tree, hf_response_in_frame, tvb, 0, 0, request_data->response_in_frame);
|
||||
proto_item_set_generated(sub_item);
|
||||
|
@ -11945,13 +12096,21 @@ dissect_btgatt_microbit_temperature_period(tvbuff_t *tvb, packet_info *pinfo _U_
|
|||
return offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
proto_register_btatt(void)
|
||||
{
|
||||
module_t *module;
|
||||
expert_module_t *expert_btatt;
|
||||
|
||||
|
||||
//src_port will be filled wiht handle
|
||||
//dst_port will be filled with opcode
|
||||
reassembly_table_register(&msg_reassembly_table,
|
||||
&addresses_ports_reassembly_table_functions);
|
||||
reassembly_table_init(&msg_reassembly_table,
|
||||
&addresses_ports_reassembly_table_functions);
|
||||
static hf_register_info hf[] = {
|
||||
{&hf_btatt_opcode,
|
||||
{"Opcode", "btatt.opcode",
|
||||
|
@ -17286,6 +17445,40 @@ proto_register_btatt(void)
|
|||
FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
/* Reassembly fields. */
|
||||
{ &hf_btatt_fragments,
|
||||
{ "Message fragments", "btatt.fragments",
|
||||
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment,
|
||||
{ "Message fragment", "btatt.fragment",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_overlap,
|
||||
{ "Message fragment overlap", "btatt.fragmet.overlap",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_overlap_conflicts,
|
||||
{ "Message fragment overlapping with conflicting data", "btatt.fragmet.overlap.conflicts",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_multiple_tails,
|
||||
{ "Message has multiple tail fragments", "btatt.fragmet.multiple_tails",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_too_long_fragment,
|
||||
{ "Message fragment too long", "btatt.fragmet.too_long_fragment",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_error,
|
||||
{ "Message defragmentation error", "btatt.fragmet.error",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_fragment_count,
|
||||
{ "Message fragment count", "btatt.fragmet.count",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_reassembled_in,
|
||||
{ "Reassembled in", "btatt.reassembled.in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_reassembled_length,
|
||||
{ "Reassembled msg length", "btatt.reassembled.length",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_btatt_reassembled_data,
|
||||
{ "Reassembled msg ata", "btatt.reassembled.data",
|
||||
FT_BYTES, SEP_SPACE, NULL, 0x00, NULL, HFILL }},
|
||||
};
|
||||
|
||||
/* Setup protocol subtree array */
|
||||
|
@ -17295,7 +17488,10 @@ proto_register_btatt(void)
|
|||
&ett_btatt_value,
|
||||
&ett_btatt_opcode,
|
||||
&ett_btatt_handle,
|
||||
&ett_btatt_characteristic_properties
|
||||
&ett_btatt_characteristic_properties,
|
||||
/* reassembly subtree */
|
||||
&ett_btatt_fragment,
|
||||
&ett_btatt_fragments,
|
||||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
|
|
|
@ -2572,6 +2572,7 @@ fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo,
|
|||
* was reassembled, put the fragment information into the protocol
|
||||
* tree, and construct a tvbuff with the reassembled data, otherwise
|
||||
* just put a "reassembled in" item into the protocol tree.
|
||||
* offset from start of tvb, result up to end of tvb
|
||||
*/
|
||||
tvbuff_t *
|
||||
process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo,
|
||||
|
@ -2613,7 +2614,7 @@ process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo,
|
|||
} else {
|
||||
/*
|
||||
* No.
|
||||
* Return a tvbuff with the payload.
|
||||
* Return a tvbuff with the payload. next_tvb ist from offset until end
|
||||
*/
|
||||
next_tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
pinfo->fragmented = FALSE; /* one-fragment packet */
|
||||
|
|
|
@ -104,9 +104,9 @@ show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
break;
|
||||
|
||||
case FragmentBoundsError:
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "[Unreassembled Packet%s]", pinfo->noreassembly_reason);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "[BoundErrorUnreassembled Packet%s]", pinfo->noreassembly_reason);
|
||||
proto_tree_add_protocol_format(tree, proto_unreassembled,
|
||||
tvb, 0, 0, "[Unreassembled Packet%s: %s]",
|
||||
tvb, 0, 0, "[BoundError Unreassembled Packet%s: %s]",
|
||||
pinfo->noreassembly_reason, pinfo->current_proto);
|
||||
/* Don't record FragmentBoundsError exceptions as expert events - they merely
|
||||
* reflect dissection done with reassembly turned off
|
||||
|
|
Loading…
Reference in New Issue