diff options
author | Martin Haaß <vvvrrooomm@gmail.com> | 2021-02-09 05:01:18 +0000 |
---|---|---|
committer | AndersBroman <a.broman58@gmail.com> | 2021-02-09 05:01:18 +0000 |
commit | 40e59344442dbc1dda303978a87af21920493107 (patch) | |
tree | 2f283aeed249fae7ef627273517ea001bc1537fc | |
parent | 9b771d2c14845bdcb7306ebb1a96cc68e5a3b9c0 (diff) |
first version of reassembly btatt
does trigger reassembly but never accumulates data
-rw-r--r-- | epan/dissectors/packet-btatt.c | 232 | ||||
-rw-r--r-- | epan/reassemble.c | 3 | ||||
-rw-r--r-- | epan/show_exception.c | 4 |
3 files changed, 218 insertions, 21 deletions
diff --git a/epan/dissectors/packet-btatt.c b/epan/dissectors/packet-btatt.c index c20f761daf..4625603b26 100644 --- a/epan/dissectors/packet-btatt.c +++ b/epan/dissectors/packet-btatt.c @@ -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[] = { diff --git a/epan/reassemble.c b/epan/reassemble.c index b291b47dcc..09d37c4aba 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -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 */ diff --git a/epan/show_exception.c b/epan/show_exception.c index 930b592a84..c052362c22 100644 --- a/epan/show_exception.c +++ b/epan/show_exception.c @@ -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 |