From e64c877ca63534274ad955d08e217481227d1523 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 15 Aug 2014 12:39:57 +0300 Subject: [PATCH] monitor: Fix L2CAP fragment tracking for duplex data streams The fragmentation state is independent in each direction of the data flow. We should therefore track outgoing and incoming fragmentation state separately. This patch extends the state tracking table with a second column to fix this. --- monitor/l2cap.c | 56 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/monitor/l2cap.c b/monitor/l2cap.c index 7e23469a5..c004d6bcd 100644 --- a/monitor/l2cap.c +++ b/monitor/l2cap.c @@ -263,14 +263,14 @@ struct index_data { uint16_t frag_cid; }; -static struct index_data index_list[MAX_INDEX]; +static struct index_data index_list[MAX_INDEX][2]; -static void clear_fragment_buffer(uint16_t index) +static void clear_fragment_buffer(uint16_t index, bool in) { - free(index_list[index].frag_buf); - index_list[index].frag_buf = NULL; - index_list[index].frag_pos = 0; - index_list[index].frag_len = 0; + free(index_list[index][in].frag_buf); + index_list[index][in].frag_buf = NULL; + index_list[index][in].frag_pos = 0; + index_list[index][in].frag_len = 0; } static void print_psm(uint16_t psm) @@ -2673,10 +2673,10 @@ void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags, switch (flags) { case 0x00: /* start of a non-automatically-flushable PDU */ case 0x02: /* start of an automatically-flushable PDU */ - if (index_list[index].frag_len) { + if (index_list[index][in].frag_len) { print_text(COLOR_ERROR, "unexpected start frame"); packet_hexdump(data, size); - clear_fragment_buffer(index); + clear_fragment_buffer(index, in); return; } @@ -2704,54 +2704,54 @@ void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags, return; } - index_list[index].frag_buf = malloc(len); - if (!index_list[index].frag_buf) { + index_list[index][in].frag_buf = malloc(len); + if (!index_list[index][in].frag_buf) { print_text(COLOR_ERROR, "failed buffer allocation"); packet_hexdump(data, size); return; } - memcpy(index_list[index].frag_buf, data, size); - index_list[index].frag_pos = size; - index_list[index].frag_len = len - size; - index_list[index].frag_cid = cid; + memcpy(index_list[index][in].frag_buf, data, size); + index_list[index][in].frag_pos = size; + index_list[index][in].frag_len = len - size; + index_list[index][in].frag_cid = cid; break; case 0x01: /* continuing fragment */ - if (!index_list[index].frag_len) { + if (!index_list[index][in].frag_len) { print_text(COLOR_ERROR, "unexpected continuation"); packet_hexdump(data, size); return; } - if (size > index_list[index].frag_len) { + if (size > index_list[index][in].frag_len) { print_text(COLOR_ERROR, "fragment too long"); packet_hexdump(data, size); - clear_fragment_buffer(index); + clear_fragment_buffer(index, in); return; } - memcpy(index_list[index].frag_buf + - index_list[index].frag_pos, data, size); - index_list[index].frag_pos += size; - index_list[index].frag_len -= size; + memcpy(index_list[index][in].frag_buf + + index_list[index][in].frag_pos, data, size); + index_list[index][in].frag_pos += size; + index_list[index][in].frag_len -= size; - if (!index_list[index].frag_len) { + if (!index_list[index][in].frag_len) { /* complete frame */ l2cap_frame(index, in, handle, - index_list[index].frag_cid, - index_list[index].frag_buf, - index_list[index].frag_pos); - clear_fragment_buffer(index); + index_list[index][in].frag_cid, + index_list[index][in].frag_buf, + index_list[index][in].frag_pos); + clear_fragment_buffer(index, in); return; } break; case 0x03: /* complete automatically-flushable PDU */ - if (index_list[index].frag_len) { + if (index_list[index][in].frag_len) { print_text(COLOR_ERROR, "unexpected complete frame"); packet_hexdump(data, size); - clear_fragment_buffer(index); + clear_fragment_buffer(index, in); return; } -- 2.47.3