/* store a guid to name mapping */ void guids_add_guid(const e_guid_t *guid, const gchar *name) { wmem_tree_key_t guidkey[2]; guint32 g[4]; g[0]=guid->data1; g[1]=guid->data2; g[1]<<=16; g[1]|=guid->data3; g[2]=guid->data4[0]; g[2]<<=8; g[2]|=guid->data4[1]; g[2]<<=8; g[2]|=guid->data4[2]; g[2]<<=8; g[2]|=guid->data4[3]; g[3]=guid->data4[4]; g[3]<<=8; g[3]|=guid->data4[5]; g[3]<<=8; g[3]|=guid->data4[6]; g[3]<<=8; g[3]|=guid->data4[7]; guidkey[0].key=g; guidkey[0].length=4; guidkey[1].length=0; wmem_tree_insert32_array(guid_to_name_tree, &guidkey[0], (gchar *) name); }
void nvme_add_cmd_cqe_to_done_list(struct nvme_q_ctx *q_ctx, struct nvme_cmd_ctx *cmd_ctx, guint16 cmd_id) { wmem_tree_key_t cmd_key[3]; guint32 key = cmd_id; guint32 frame_num; nvme_build_done_cmd_key(cmd_key, &key, &frame_num); /* found matchng entry. Add entries to the matched table for both cmd and cqe. */ frame_num = cmd_ctx->cqe_pkt_num; wmem_tree_insert32_array(q_ctx->done_cmds, cmd_key, (void*)cmd_ctx); frame_num = cmd_ctx->cmd_pkt_num; wmem_tree_insert32_array(q_ctx->done_cmds, cmd_key, (void*)cmd_ctx); }
void nvme_add_data_response(struct nvme_q_ctx *q_ctx, struct nvme_cmd_ctx *cmd_ctx, guint32 rkey) { wmem_tree_key_t cmd_key[3]; guint32 key = rkey; guint32 frame_num; nvme_build_done_cmd_key(cmd_key, &key, &frame_num); /* Found matching data response packet. Add entries to the matched table * for cmd and response packets */ frame_num = cmd_ctx->data_req_pkt_num; wmem_tree_insert32_array(q_ctx->data_responses, cmd_key, (void*)cmd_ctx); frame_num = cmd_ctx->data_resp_pkt_num; wmem_tree_insert32_array(q_ctx->data_responses, cmd_key, (void*)cmd_ctx); }
void nvme_add_data_request(packet_info *pinfo, struct nvme_q_ctx *q_ctx, struct nvme_cmd_ctx *cmd_ctx, void *ctx) { wmem_tree_key_t cmd_key[3]; guint32 key = cmd_ctx->remote_key; cmd_ctx->data_req_pkt_num = pinfo->num; cmd_ctx->data_resp_pkt_num = 0; nvme_build_pending_cmd_key(cmd_key, &key); wmem_tree_insert32_array(q_ctx->data_requests, cmd_key, (void *)ctx); }
void nvme_add_cmd_to_pending_list(packet_info *pinfo, struct nvme_q_ctx *q_ctx, struct nvme_cmd_ctx *cmd_ctx, void *ctx, guint16 cmd_id) { wmem_tree_key_t cmd_key[3]; guint32 key = cmd_id; cmd_ctx->cmd_pkt_num = pinfo->num; cmd_ctx->cqe_pkt_num = 0; cmd_ctx->cmd_start_time = pinfo->abs_ts; nstime_set_zero(&cmd_ctx->cmd_end_time); cmd_ctx->remote_key = 0; /* this is a new cmd, create a new command context and map it to the unmatched table */ nvme_build_pending_cmd_key(cmd_key, &key); wmem_tree_insert32_array(q_ctx->pending_cmds, cmd_key, (void *)ctx); }
static gint dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_tree *hci_mon_item; proto_item *hci_mon_tree; proto_item *sub_item; gint offset = 0; guint16 opcode; guint16 adapter_id; bluetooth_data_t *bluetooth_data; tvbuff_t *next_tvb; guint32 *adapter_disconnect_in_frame; wmem_tree_t *subtree; wmem_tree_key_t key[4]; guint32 k_interface_id; guint32 k_adapter_id; guint32 k_frame_number; bluetooth_data = (bluetooth_data_t *) data; DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_BTMON); adapter_id = bluetooth_data->previous_protocol_data.btmon->adapter_id; opcode = bluetooth_data->previous_protocol_data.btmon->opcode; if (opcode == 0x00 || opcode == 0x01) pinfo->p2p_dir = P2P_DIR_RECV; else if (opcode % 2) pinfo->p2p_dir = P2P_DIR_RECV; else pinfo->p2p_dir = P2P_DIR_SENT; hci_mon_item = proto_tree_add_item(tree, proto_hci_mon, tvb, offset, tvb_captured_length(tvb), ENC_NA); hci_mon_tree = proto_item_add_subtree(hci_mon_item, ett_hci_mon); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_MON"); if (opcode == 0x00 || opcode == 0x01) col_set_str(pinfo->cinfo, COL_INFO, "Info "); else switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection "); break; } sub_item = proto_tree_add_uint(hci_mon_tree, hf_adapter_id, tvb, offset, 0, adapter_id); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(hci_mon_tree, hf_opcode, tvb, offset, 0, opcode); PROTO_ITEM_SET_GENERATED(sub_item); col_append_fstr(pinfo->cinfo, COL_INFO, "Adapter Id: %u, Opcode: %s", adapter_id, val_to_str_ext_const(opcode, &hci_mon_opcode_vals_ext, "Unknown")); bluetooth_data->adapter_id = adapter_id; k_interface_id = bluetooth_data->interface_id; k_adapter_id = adapter_id; k_frame_number = pinfo->num; key[0].length = 1; key[0].key = &k_interface_id; key[1].length = 1; key[1].key = &k_adapter_id; if (!pinfo->fd->flags.visited && opcode == 0x01) { /* Delete Index */ guint32 *disconnect_in_frame; key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; disconnect_in_frame = wmem_new(wmem_file_scope(), guint32); if (disconnect_in_frame) { *disconnect_in_frame = pinfo->num; wmem_tree_insert32_array(adapter_to_disconnect_in_frame, key, disconnect_in_frame); } } key[2].length = 0; key[2].key = NULL; subtree = (wmem_tree_t *) wmem_tree_lookup32_array(adapter_to_disconnect_in_frame, key); adapter_disconnect_in_frame = (subtree) ? (guint32 *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL; if (adapter_disconnect_in_frame) { bluetooth_data->adapter_disconnect_in_frame = adapter_disconnect_in_frame; } else { bluetooth_data->adapter_disconnect_in_frame = &max_disconnect_in_frame; } pinfo->ptype = PT_BLUETOOTH; next_tvb = tvb_new_subset_remaining(tvb, offset); switch(opcode) { case 0x00: /* New Index */ proto_tree_add_item(hci_mon_tree, hf_bus, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(hci_mon_tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; offset = dissect_bd_addr(hf_bd_addr, pinfo, hci_mon_tree, tvb, offset, TRUE, bluetooth_data->interface_id, bluetooth_data->adapter_id, NULL); proto_tree_add_item(hci_mon_tree, hf_name, tvb, offset, 8, ENC_NA | ENC_ASCII); offset += 8; break; case 0x01: /* Delete Index */ /* No parameters */ break; case 0x02: /* HCI Command Packet */ call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data); offset = tvb_reported_length(tvb); break; case 0x03: /* HCI Event Packet */ call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data); offset = tvb_reported_length(tvb); break; case 0x04: /* ACL Tx Packet */ case 0x05: /* ACL Rx Packet */ call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data); offset = tvb_reported_length(tvb); break; case 0x06: /* SCO Tx Packet */ case 0x07: /* SCO Rx Packet */ call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data); offset = tvb_reported_length(tvb); break; } if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(hci_mon_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset)); offset = tvb_reported_length(tvb); } /* NOTE: Oops... HCI_MON have special packet with length 0, but there is a pseudo-header with certain infos, mark it as dissected */ if (opcode == 0x01) return 1; return offset; }
static void save_command(guint32 cmd, guint32 arg0, guint32 arg1, guint32 data_length, guint32 crc32, service_data_t *service_data, gint proto, void *data, packet_info *pinfo, service_data_t **returned_service_data, command_data_t **returned_command_data) { wmem_tree_key_t key[6]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; command_data_t *command_data; wmem_tree_t *wmem_tree; gint direction = P2P_DIR_UNKNOWN; usb_conv_info_t *usb_conv_info = (usb_conv_info_t *) data; frame_number = pinfo->fd->num; if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 1; key[3].key = &side_id; key[4].length = 1; key[4].key = &frame_number; key[5].length = 0; key[5].key = NULL; } else { /* tcp */ if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 1; key[3].key = &side_id; key[4].length = 1; key[4].key = &frame_number; key[5].length = 0; key[5].key = NULL; } if (direction == P2P_DIR_SENT) if (cmd == A_CLSE) side_id = arg1; /* OUT: local id */ else side_id = arg0; /* OUT: local id */ else side_id = arg1; /* IN: remote id */ if (cmd == A_OPEN) { service_data = wmem_new(wmem_file_scope(), service_data_t); service_data->start_in_frame = pinfo->fd->num; service_data->close_local_in_frame = max_in_frame; service_data->close_remote_in_frame = max_in_frame; service_data->local_id = arg0; service_data->remote_id = arg1; service_data->service = "unknown"; wmem_tree_insert32_array(service_info, key, service_data); } command_data = wmem_new(wmem_file_scope(), command_data_t); command_data->command = cmd; command_data->arg0 = arg0; command_data->arg1 = arg1; command_data->command_in_frame = pinfo->fd->num; command_data->response_in_frame = max_in_frame; command_data->crc32 = crc32; command_data->data_length = data_length; if (data_length == 0) command_data->completed_in_frame = pinfo->fd->num; else command_data->completed_in_frame = max_in_frame; command_data->reassemble_data_length = 0; command_data->reassemble_data = (guint8 *) wmem_alloc(wmem_file_scope(), command_data->data_length); key[3].length = 1; key[3].key = &frame_number; key[4].length = 0; key[4].key = NULL; wmem_tree_insert32_array(command_info, key, command_data); if (direction == P2P_DIR_SENT) if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ else side_id = command_data->arg1; /* IN: remote id */ key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); } if (cmd == A_OKAY) { if (!service_data) { if (direction == P2P_DIR_SENT) side_id = command_data->arg0; /* OUT: local id */ else side_id = command_data->arg1; /* IN: remote id */ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); } } if (service_data && service_data->remote_id == 0 && direction == P2P_DIR_RECV) { if (direction == P2P_DIR_SENT) { service_data->remote_id = arg1; } else { service_data->remote_id = arg0; } side_id = service_data->remote_id; key[4].length = 1; key[4].key = &frame_number; key[5].length = 0; key[5].key = NULL; wmem_tree_insert32_array(service_info, key, service_data); } } else if (cmd == A_CLSE) { if (service_data) { if (direction == P2P_DIR_RECV && service_data->local_id == arg1) service_data->close_local_in_frame = pinfo->fd->num; else if (direction == P2P_DIR_SENT && service_data->remote_id == arg1) service_data->close_remote_in_frame = pinfo->fd->num; } } DISSECTOR_ASSERT(returned_service_data && returned_command_data); *returned_service_data = service_data; *returned_command_data = command_data; }
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) { gcp_msg_t* m; guint32 framenum = (guint32)pinfo->fd->num; guint32 offset = (guint32)o; address* src = &(pinfo->src); address* dst = &(pinfo->dst); address* lo_addr; address* hi_addr; if (keep_persistent_data) { wmem_tree_key_t key[3]; key[0].length = 1; key[0].key = &(framenum); key[1].length = 1; key[1].key = &offset; key[2].length = 0; key[2].key =NULL; if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(msgs,key) )) { m->committed = TRUE; return m; } else { m = wmem_new(wmem_file_scope(), gcp_msg_t); m->framenum = framenum; m->time = pinfo->fd->abs_ts; m->trxs = NULL; m->committed = FALSE; wmem_tree_insert32_array(msgs,key,m); } } else { m = wmem_new0(wmem_packet_scope(), gcp_msg_t); m->framenum = framenum; m->trxs = NULL; m->committed = FALSE; } if (CMP_ADDRESS(src, dst) < 0) { lo_addr = src; hi_addr = dst; } else { lo_addr = dst; hi_addr = src; } switch(lo_addr->type) { case AT_NONE: m->lo_addr = 0; m->hi_addr = 0; break; case AT_IPv4: memcpy((guint8*)&(m->hi_addr),hi_addr->data,4); memcpy((guint8*)&(m->lo_addr),lo_addr->data,4); break; case AT_SS7PC: m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data); m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data); break; default: /* XXX: heuristic and error prone */ m->hi_addr = g_str_hash(ep_address_to_str(hi_addr)); m->lo_addr = g_str_hash(ep_address_to_str(lo_addr)); break; } return m; }
static void wmem_test_tree(void) { wmem_allocator_t *allocator, *extra_allocator; wmem_tree_t *tree; guint32 i; int seen_values = 0; int j; gchar *str_key; #define WMEM_TREE_MAX_KEY_COUNT 8 #define WMEM_TREE_MAX_KEY_LEN 4 int key_count; wmem_tree_key_t keys[WMEM_TREE_MAX_KEY_COUNT]; allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); extra_allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); tree = wmem_tree_new(allocator); g_assert(tree); g_assert(wmem_tree_is_empty(tree)); /* test basic 32-bit key operations */ for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); if (i > 0) { g_assert(wmem_tree_lookup32_le(tree, i) == GINT_TO_POINTER(i-1)); } wmem_tree_insert32(tree, i, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, i) == GINT_TO_POINTER(i)); g_assert(!wmem_tree_is_empty(tree)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { guint32 rand_int = g_test_rand_int(); wmem_tree_insert32(tree, rand_int, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, rand_int) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); /* test auto-reset functionality */ tree = wmem_tree_new_autoreset(allocator, extra_allocator); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); wmem_tree_insert32(tree, i, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, i) == GINT_TO_POINTER(i)); } wmem_free_all(extra_allocator); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); g_assert(wmem_tree_lookup32_le(tree, i) == NULL); } wmem_free_all(allocator); /* test array key functionality */ tree = wmem_tree_new(allocator); key_count = g_random_int_range(1, WMEM_TREE_MAX_KEY_COUNT); for (j=0; j<key_count; j++) { keys[j].length = g_random_int_range(1, WMEM_TREE_MAX_KEY_LEN); } keys[key_count].length = 0; for (i=0; i<CONTAINER_ITERS; i++) { for (j=0; j<key_count; j++) { keys[j].key = (guint32*)wmem_test_rand_string(allocator, (keys[j].length*4), (keys[j].length*4)+1); } wmem_tree_insert32_array(tree, keys, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32_array(tree, keys) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); keys[0].length = 1; keys[0].key = wmem_new(allocator, guint32); *(keys[0].key) = 0; keys[1].length = 0; for (i=0; i<CONTAINER_ITERS; i++) { wmem_tree_insert32_array(tree, keys, GINT_TO_POINTER(i)); *(keys[0].key) += 4; } *(keys[0].key) = 0; for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32_array(tree, keys) == GINT_TO_POINTER(i)); for (j=0; j<3; j++) { (*(keys[0].key)) += 1; g_assert(wmem_tree_lookup32_array_le(tree, keys) == GINT_TO_POINTER(i)); } *(keys[0].key) += 1; } wmem_free_all(allocator); /* test string key functionality */ tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { str_key = wmem_test_rand_string(allocator, 1, 64); wmem_tree_insert_string(tree, str_key, GINT_TO_POINTER(i), 0); g_assert(wmem_tree_lookup_string(tree, str_key, 0) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { str_key = wmem_test_rand_string(allocator, 1, 64); wmem_tree_insert_string(tree, str_key, GINT_TO_POINTER(i), WMEM_TREE_STRING_NOCASE); g_assert(wmem_tree_lookup_string(tree, str_key, WMEM_TREE_STRING_NOCASE) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); /* test for-each functionality */ tree = wmem_tree_new(allocator); expected_user_data = GINT_TO_POINTER(g_test_rand_int()); for (i=0; i<CONTAINER_ITERS; i++) { gint tmp; do { tmp = g_test_rand_int(); } while (wmem_tree_lookup32(tree, tmp)); value_seen[i] = FALSE; wmem_tree_insert32(tree, tmp, GINT_TO_POINTER(i)); } cb_called_count = 0; cb_continue_count = CONTAINER_ITERS; wmem_tree_foreach(tree, wmem_test_foreach_cb, expected_user_data); g_assert(cb_called_count == CONTAINER_ITERS); g_assert(cb_continue_count == 0); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(value_seen[i]); value_seen[i] = FALSE; } cb_called_count = 0; cb_continue_count = 10; wmem_tree_foreach(tree, wmem_test_foreach_cb, expected_user_data); g_assert(cb_called_count == 10); g_assert(cb_continue_count == 0); for (i=0; i<CONTAINER_ITERS; i++) { if (value_seen[i]) { seen_values++; } } g_assert(seen_values == 10); wmem_destroy_allocator(extra_allocator); wmem_destroy_allocator(allocator); }
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) { gcp_ctx_t* context = NULL; gcp_ctx_t** context_p = NULL; if ( !m || !t ) return NULL; if (persistent) { wmem_tree_key_t ctx_key[4]; wmem_tree_key_t trx_key[4]; ctx_key[0].length = 1; ctx_key[0].key = &(m->hi_addr); ctx_key[1].length = 1; ctx_key[1].key = &(m->lo_addr); ctx_key[2].length = 1; ctx_key[2].key = &(c_id); ctx_key[3].length = 0; ctx_key[3].key = NULL; trx_key[0].length = 1; trx_key[0].key = &(m->hi_addr); trx_key[1].length = 1; trx_key[1].key = &(m->lo_addr); trx_key[2].length = 1; trx_key[2].key = &(t->id); trx_key[3].length = 0; trx_key[3].key = NULL; if (m->committed) { if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) { return context; } if ((context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key))) { context = *context_p; do { if (context->initial->framenum <= m->framenum) { return context; } } while(( context = context->prev )); DISSECTOR_ASSERT(! "a context should exist"); } } else { if (c_id == CHOOSE_CONTEXT) { if (! ( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key))) { context = wmem_new(wmem_file_scope(), gcp_ctx_t); context->initial = m; context->cmds = NULL; context->id = c_id; context->terms.last = &(context->terms); context->terms.next = NULL; context->terms.term = NULL; wmem_tree_insert32_array(ctxs_by_trx,trx_key,context); } } else { if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) { if (( context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key) )) { if (context != *context_p) { if(context->id != CHOOSE_CONTEXT) { context = wmem_new(wmem_file_scope(), gcp_ctx_t); } context->initial = m; context->id = c_id; context->cmds = NULL; context->terms.last = &(context->terms); context->terms.next = NULL; context->terms.term = NULL; context->prev = *context_p; *context_p = context; } } else { context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*); *context_p = context; context->initial = m; context->id = c_id; wmem_tree_insert32_array(ctxs,ctx_key,context_p); } } else if (! ( context_p = (gcp_ctx_t**)wmem_tree_lookup32_array(ctxs,ctx_key) )) { context = wmem_new(wmem_file_scope(), gcp_ctx_t); context->initial = m; context->id = c_id; context->cmds = NULL; context->terms.last = &(context->terms); context->terms.next = NULL; context->terms.term = NULL; context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*); *context_p = context; wmem_tree_insert32_array(ctxs,ctx_key,context_p); } else { context = *context_p; } }
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) { gcp_trx_t* t = NULL; gcp_trx_msg_t* trxmsg; if ( !m ) return NULL; if (keep_persistent_data) { if (m->committed) { for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) { if (trxmsg->trx && trxmsg->trx->id == t_id) { return trxmsg->trx; } } DISSECTOR_ASSERT_NOT_REACHED(); } else { wmem_tree_key_t key[4]; key[0].length = 1; key[0].key = &(m->hi_addr); key[1].length = 1; key[1].key = &(m->lo_addr); key[2].length = 1; key[2].key = &(t_id); key[3].length = 0; key[3].key = NULL; trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t); t = (gcp_trx_t *)wmem_tree_lookup32_array(trxs,key); if (!t) { t = wmem_new(wmem_file_scope(), gcp_trx_t); t->initial = m; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; wmem_tree_insert32_array(trxs,key,t); } /* XXX: request, reply and ack + point to frames where they are */ switch ( type ) { case GCP_TRX_PENDING: t->pendings++; break; default: break; } } } else { t = wmem_new(wmem_packet_scope(), gcp_trx_t); trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t); t->initial = NULL; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; } DISSECTOR_ASSERT(trxmsg); trxmsg->trx = t; trxmsg->next = NULL; trxmsg->last = trxmsg; if (m->trxs) { m->trxs->last = m->trxs->last->next = trxmsg; } else { m->trxs = trxmsg; } return t; }
static gint dissect_acr122(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *p1_item; proto_tree *p1_tree; proto_item *p2_item; proto_tree *p2_tree; proto_item *sub_item; proto_item *sub_tree; proto_item *sw2_item; proto_item *sw2_tree; gint offset = 0; guint32 value; tvbuff_t *next_tvb; guint8 acr_class; guint8 ins; guint8 p1; guint8 p2; guint8 length; guint8 command = CMD_UNKNOWN; command_data_t *command_data; usb_conv_info_t *usb_conv_info; wmem_tree_key_t key[5]; guint32 bus_id; guint32 device_address; guint32 endpoint; guint32 k_bus_id; guint32 k_device_address; guint32 k_endpoint; guint32 k_frame_number; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACR 122"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_acr122, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_acr122); if (!data) return offset; usb_conv_info = (usb_conv_info_t *) data; bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; endpoint = usb_conv_info->endpoint; k_bus_id = bus_id; k_device_address = device_address; k_endpoint = endpoint; k_frame_number = pinfo->fd->num; key[0].length = 1; key[0].key = &k_bus_id; key[1].length = 1; key[1].key = &k_device_address; key[2].length = 1; key[2].key = &k_endpoint; key[3].length = 1; key[3].key = &k_frame_number; key[4].length = 0; key[4].key = NULL; if (pinfo->p2p_dir == P2P_DIR_SENT) { /* Request */ acr_class = tvb_get_guint8(tvb, offset); ins = tvb_get_guint8(tvb, offset + 1); p1 = tvb_get_guint8(tvb, offset + 2); p2 = tvb_get_guint8(tvb, offset + 3); length = tvb_get_guint8(tvb, offset + 4); /* Recognize command by simple heuristic */ if (acr_class == 0xFF) { if (ins == 0xCA && p1 == 0x00 && p2 == 0x00 && length == 0) command = CMD_GET_DATA_UID; if (ins == 0xCA && p1 == 0x01 && p2 == 0x00 && length == 0) command = CMD_GET_DATA_ATS; else if (ins == 0x82 && length == 6) command = CMD_LOAD_AUTHENTICATION_KEYS; else if (ins == 0x88 && p1 == 0x00) command = CMD_AUTHENTICATION_OBSOLETE; else if (ins == 0x86 && p1 == 0x00 && p2 == 0x00 && length == 5) command = CMD_AUTHENTICATION; else if (ins == 0xB0 && p1 == 0x00) command = CMD_READ_BINARY_BLOCKS; else if (ins == 0xD6 && p1 == 0x00) command = CMD_UPDATE_BINARY_BLOCKS; else if (ins == 0xD7 && p1 == 0x00 && length == 5) command = CMD_VALUE_BLOCK_OPERATION; else if (ins == 0xB1 && p1 == 0x00 && length == 4) command = CMD_READ_VALUE_BLOCK; else if (ins == 0xD7 && p1 == 0x00 && length == 2) command = CMD_RESTORE_VALUE_BLOCK; else if (ins == 0x00 && p1 == 0x00 && p2 == 0x00) command = CMD_DIRECT_TRANSMIT; else if (ins == 0x00 && p1 == 0x40 && length == 4) command = CMD_BI_COLOR_AND_BUZZER_LED_CONTROL; else if (ins == 0x00 && p1 == 0x48 && p2 == 0x00) command = CMD_GET_FIRMWARE_VERSION; else if (ins == 0x00 && p1 == 0x50 && p2 == 0x00) command = CMD_GET_PICC_OPERATING_PARAMETER; else if (ins == 0x00 && p1 == 0x51 && length == 0) command = CMD_SET_PICC_OPERATING_PARAMETER; else if (ins == 0x00 && p1 == 0x41 && length == 0) command = CMD_SET_TIMEOUT_PARAMETER; else if (ins == 0x00 && p1 == 0x52 && length == 0) command = CMD_SET_BUZZER_OUTPUT_FOR_CARD_DETECTION; } sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 4 + length, command); PROTO_ITEM_SET_GENERATED(sub_item); if (command == CMD_UNKNOWN) proto_tree_add_expert(sub_item, pinfo, &ei_unknown_command_or_invalid_parameters, tvb, offset, 4 + length); col_add_fstr(pinfo->cinfo, COL_INFO, "Command: %s", val_to_str_const(command, command_vals, "Unknown")); proto_tree_add_item(main_tree, hf_class, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_ins, tvb, offset, 1, ENC_NA); offset += 1; p1_item = proto_tree_add_item(main_tree, hf_p1, tvb, offset, 1, ENC_NA); offset += 1; p2_item = proto_tree_add_item(main_tree, hf_p2, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_length, tvb, offset, 1, ENC_NA); offset += 1; switch (command) { case CMD_DIRECT_TRANSMIT: if (length > 0) { next_tvb = tvb_new_subset(tvb, offset, length, length); call_dissector_with_data(pn532_handle, next_tvb, pinfo, tree, usb_conv_info); offset += length; } break; case CMD_BI_COLOR_AND_BUZZER_LED_CONTROL: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_led_green_blinking_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_red_blinking_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_green_mask, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_red_mask, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_initial_green_blinking_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_initial_red_blinking_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_final_green_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_led_final_red_state, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_led_t1_duration, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_led_t2_duration, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_led_number_of_repetition, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_led_link_to_buzzer, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case CMD_GET_DATA_UID: case CMD_GET_DATA_ATS: /* Nothing to decode */ break; case CMD_LOAD_AUTHENTICATION_KEYS: p1_tree = proto_item_add_subtree(p1_item, ett_p1_item); proto_tree_add_item(p1_tree, hf_key_structure, tvb, offset - 3, 1, ENC_BIG_ENDIAN); p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_key_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_key, tvb, offset, 6, ENC_NA); offset += 6; break; case CMD_AUTHENTICATION_OBSOLETE: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_key_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_key_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case CMD_AUTHENTICATION: proto_tree_add_item(main_tree, hf_version, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(main_tree, hf_block_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_key_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_key_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case CMD_READ_BINARY_BLOCKS: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); break; case CMD_UPDATE_BINARY_BLOCKS: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_data, tvb, offset, length, ENC_NA); offset += length; break; case CMD_VALUE_BLOCK_OPERATION: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_vb_op, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_value, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case CMD_READ_VALUE_BLOCK: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); break; case CMD_RESTORE_VALUE_BLOCK: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_source_block_number, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(main_tree, hf_static_byte, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(main_tree, hf_target_block_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case CMD_SET_PICC_OPERATING_PARAMETER: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_picc_operating_auto_picc_polling, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_auto_ats_generation, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_polling_interval, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_felica_424k, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_felica_212k, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_topaz, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_iso_14443_type_b, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p2_tree, hf_picc_operating_iso_14443_type_a, tvb, offset - 2, 1, ENC_BIG_ENDIAN); break; case CMD_SET_TIMEOUT_PARAMETER: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_timeout, tvb, offset - 2, 1, ENC_BIG_ENDIAN); break; case CMD_SET_BUZZER_OUTPUT_FOR_CARD_DETECTION: p2_tree = proto_item_add_subtree(p2_item, ett_p2_item); proto_tree_add_item(p2_tree, hf_poll_buzzer_status, tvb, offset - 2, 1, ENC_BIG_ENDIAN); break; case CMD_GET_PICC_OPERATING_PARAMETER: /* No parameters */ break; } if (!pinfo->fd->flags.visited) { command_data = wmem_new(wmem_file_scope(), command_data_t); command_data->bus_id = bus_id; command_data->device_address = device_address; command_data->endpoint = endpoint; command_data->command = command; command_data->command_frame_number = pinfo->fd->num; command_data->response_frame_number = 0; wmem_tree_insert32_array(command_info, key, command_data); } } else { /* Response */ guint32 command_frame_number = 0; gboolean use_status_word = FALSE; wmem_tree_t *wmem_tree; key[3].length = 0; key[3].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->fd->num); if (command_data && (command_data->response_frame_number == 0 || command_data->response_frame_number == pinfo->fd->num)) { command = command_data->command; command_frame_number = command_data->command_frame_number; if (!pinfo->fd->flags.visited && command_data->response_frame_number == 0) { command_data->response_frame_number = pinfo->fd->num; } } } sub_item = proto_tree_add_uint(main_tree, hf_response, tvb, offset, tvb_length_remaining(tvb, offset), command); PROTO_ITEM_SET_GENERATED(sub_item); col_add_fstr(pinfo->cinfo, COL_INFO, "Response: %s", val_to_str_const(command, command_vals, "Unknown")); if (command != CMD_UNKNOWN) { sub_item = proto_tree_add_uint(main_tree, hf_response_for, tvb, offset, tvb_length_remaining(tvb, offset), command_frame_number); PROTO_ITEM_SET_GENERATED(sub_item); } switch (command) { case CMD_GET_FIRMWARE_VERSION: proto_tree_add_item(main_tree, hf_firmware_version, tvb, offset, -1, ENC_NA | ENC_ASCII); offset += tvb_length_remaining(tvb, offset); break; case CMD_DIRECT_TRANSMIT: use_status_word = TRUE; if (tvb_length_remaining(tvb, offset) > 2) { next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset) - 2, tvb_length_remaining(tvb, offset) - 2); call_dissector_with_data(pn532_handle, next_tvb, pinfo, tree, usb_conv_info); offset += tvb_length_remaining(tvb, offset) - 2; } break; case CMD_READ_BINARY_BLOCKS: use_status_word = TRUE; proto_tree_add_item(main_tree, hf_data, tvb, offset, tvb_length_remaining(tvb, offset) - 2, ENC_NA); offset += tvb_length_remaining(tvb, offset) - 2; break; case CMD_READ_VALUE_BLOCK: use_status_word = TRUE; proto_tree_add_item(main_tree, hf_value, tvb, offset, 4, ENC_BIG_ENDIAN); break; case CMD_GET_DATA_UID: use_status_word = TRUE; proto_tree_add_item(main_tree, hf_uid, tvb, offset, tvb_length_remaining(tvb, offset) - 2, ENC_NA); offset += tvb_length_remaining(tvb, offset) - 2; break; case CMD_GET_DATA_ATS: use_status_word = TRUE; proto_tree_add_item(main_tree, hf_ats, tvb, offset, tvb_length_remaining(tvb, offset) - 2, ENC_NA); offset += tvb_length_remaining(tvb, offset) - 2; break; case CMD_BI_COLOR_AND_BUZZER_LED_CONTROL: case CMD_LOAD_AUTHENTICATION_KEYS: case CMD_AUTHENTICATION: case CMD_AUTHENTICATION_OBSOLETE: case CMD_UPDATE_BINARY_BLOCKS: case CMD_VALUE_BLOCK_OPERATION: case CMD_RESTORE_VALUE_BLOCK: case CMD_SET_TIMEOUT_PARAMETER: case CMD_SET_BUZZER_OUTPUT_FOR_CARD_DETECTION: case CMD_SET_PICC_OPERATING_PARAMETER: case CMD_GET_PICC_OPERATING_PARAMETER: default: use_status_word = TRUE; break; } if (use_status_word) { value = tvb_get_ntohs(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, " - %s%s", (((value & 0xFF00) != 0x9000) && (value & 0xFF00) != 0x6100) ? "Error: " : "", rval_to_str(value, status_word_rvals, "Unknown error")); if ((value & 0xFF00) == 0x6100) col_append_fstr(pinfo->cinfo, COL_INFO, " - Length %u", value & 0x00FF); sub_item = proto_tree_add_item(main_tree, hf_status_word, tvb, offset, 2, ENC_BIG_ENDIAN); sub_tree = proto_item_add_subtree(sub_item, ett_status_word); proto_tree_add_item(sub_tree, hf_status_word_sw1, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; sw2_item = proto_tree_add_item(sub_tree, hf_status_word_sw2, tvb, offset, 1, ENC_BIG_ENDIAN); if (command == CMD_BI_COLOR_AND_BUZZER_LED_CONTROL) { sw2_tree = proto_item_add_subtree(sw2_item, ett_status_word_sw2); col_append_fstr(pinfo->cinfo, COL_INFO, " - Red LED: %s, Green LED: %s", (value & 0x02) ? "On" : "Off", (value & 0x01) ? "On" : "Off"); proto_tree_add_item(sw2_tree, hf_status_word_led_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_status_word_led_green, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_status_word_led_red, tvb, offset, 1, ENC_BIG_ENDIAN); } else if (command == CMD_SET_PICC_OPERATING_PARAMETER || command == CMD_GET_PICC_OPERATING_PARAMETER) { sw2_tree = proto_item_add_subtree(sw2_item, ett_status_word_sw2); proto_tree_add_item(sw2_tree, hf_picc_operating_auto_picc_polling, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_auto_ats_generation, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_polling_interval, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_felica_424k, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_felica_212k, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_topaz, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_iso_14443_type_b, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sw2_tree, hf_picc_operating_iso_14443_type_a, tvb, offset - 2, 1, ENC_BIG_ENDIAN); } offset += 1; } } return offset; }
static gint dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *sub_item; proto_tree *sub_tree; gint offset = 0; adb_service_data_t *adb_service_data = (adb_service_data_t *) data; const guint8 *service; wmem_tree_key_t key[5]; wmem_tree_t *subtree; guint32 i_key; main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb_service); DISSECTOR_ASSERT(adb_service_data); service = adb_service_data->service; sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service); PROTO_ITEM_SET_GENERATED(sub_item); if (g_strcmp0(service, "host:version") == 0) { guint32 version; guint32 data_length; continuation_data_t *continuation_data; DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small"); for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { key[i_key].length = 1; key[i_key].key = &adb_service_data->session_key[i_key]; } key[i_key].length = 0; key[i_key].key = NULL; subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key); continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL; if (continuation_data && continuation_data->completed_in_frame < pinfo->num) continuation_data = NULL; if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->num)) offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); if (!pinfo->fd->flags.visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) { key[i_key].length = 1; key[i_key++].key = &pinfo->num; key[i_key].length = 0; key[i_key].key = NULL; continuation_data = wmem_new(wmem_file_scope(), continuation_data_t); continuation_data->length_in_frame = pinfo->num; continuation_data->completed_in_frame = G_MAXUINT32; continuation_data->length = data_length; wmem_tree_insert32_array(continuation_infos, key, continuation_data); continuation_data = NULL; } if (tvb_reported_length_remaining(tvb, offset) >= 4 || (continuation_data && continuation_data->completed_in_frame == pinfo->num)) { if (!pinfo->fd->flags.visited && continuation_data) { continuation_data->completed_in_frame = pinfo->num; } offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version); col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version); } } else if (g_strcmp0(service, "host:devices") == 0 || g_strcmp0(service, "host:devices-l") == 0 || g_strcmp0(service, "host:track-devices") == 0) { guint32 data_length; offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII); if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) { expert_add_info(pinfo, sub_item, &ei_incomplete_message); } } else if (g_strcmp0(service, "host:get-state") == 0 || g_strcmp0(service, "host:get-serialno") == 0 || g_strcmp0(service, "host:get-devpath") == 0 || g_str_has_prefix(service, "connect:") || g_str_has_prefix(service, "disconnect:")) { guint32 data_length; offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII); if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) { expert_add_info(pinfo, sub_item, &ei_incomplete_message); } } else if (g_str_has_prefix(service, "framebuffer:")) { framebuffer_data_t *framebuffer_data = NULL; DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small"); for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { key[i_key].length = 1; key[i_key].key = &adb_service_data->session_key[i_key]; } key[i_key].length = 0; key[i_key].key = NULL; subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key); framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL; if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->num) framebuffer_data = NULL; if (!pinfo->fd->flags.visited && !framebuffer_data) { key[i_key].length = 1; key[i_key++].key = &pinfo->num; key[i_key].length = 0; key[i_key].key = NULL; framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t); framebuffer_data->data_in = pinfo->num; framebuffer_data->current_size = 0; framebuffer_data->completed_in_frame = G_MAXUINT32; framebuffer_data->size = tvb_get_letohl(tvb, offset + 4 * 2); framebuffer_data->red_offset = tvb_get_letohl(tvb, offset + 4 * 5); framebuffer_data->red_length = tvb_get_letohl(tvb, offset + 4 * 6); framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7); framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8); framebuffer_data->blue_offset = tvb_get_letohl(tvb, offset + 4 * 9); framebuffer_data->blue_length = tvb_get_letohl(tvb, offset + 4 * 10); framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11); framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12); wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data); } if (framebuffer_data && framebuffer_data->data_in == pinfo->num) { proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; } if (tvb_reported_length_remaining(tvb, offset) > 0) { sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_data); if (!pinfo->fd->flags.visited && framebuffer_data) { framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset); if (framebuffer_data->current_size >= framebuffer_data->size) framebuffer_data->completed_in_frame = pinfo->num; } if (pref_dissect_more_detail_framebuffer) { proto_item *pixel_item; proto_tree *pixel_tree; if (framebuffer_data && framebuffer_data->red_length == 5 && framebuffer_data->green_length == 6 && framebuffer_data->blue_length == 5 && framebuffer_data->red_offset == 11 && framebuffer_data->green_offset == 5 && framebuffer_data->blue_offset == 0) { while (tvb_reported_length_remaining(tvb, offset) > 0) { if (tvb_reported_length_remaining(tvb, offset) < 2) { proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA); offset += 1; } pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA); pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel); proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } } else if (framebuffer_data && framebuffer_data->red_length == 8 && framebuffer_data->green_length == 8 && framebuffer_data->blue_length == 8 && (framebuffer_data->alpha_length == 0 || framebuffer_data->alpha_length == 8)) { while (tvb_reported_length_remaining(tvb, offset) > 0) { if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) { proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA); offset = tvb_captured_length(tvb); break; } pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA); pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel); proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_LITTLE_ENDIAN); if (framebuffer_data->alpha_offset > 0) { if (framebuffer_data->alpha_length == 0) proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN); else proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_item_set_len(pixel_item, 4); } offset += 3; } } else { offset = tvb_captured_length(tvb); } } else { offset = tvb_captured_length(tvb); } } } else if (g_strcmp0(service, "track-jdwp") == 0) { guint32 data_length; offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); if (tvb_reported_length_remaining(tvb, offset) > 0) { sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII); if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) { expert_add_info(pinfo, sub_item, &ei_incomplete_message); } } offset = tvb_captured_length(tvb); } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) || (g_strcmp0(service, "shell:logcat -B") == 0)) { tvbuff_t *next_tvb; tvbuff_t *new_tvb; guint8 *buffer = NULL; gint size = 0; gint i_offset = offset; gint old_offset; gint i_char = 0; guint8 c1; guint8 c2 = '\0'; guint16 payload_length; guint16 try_header_size; gint logcat_length = 0; fragment_t *fragment; DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small"); for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { key[i_key].length = 1; key[i_key].key = &adb_service_data->session_key[i_key]; } key[i_key].length = 0; key[i_key].key = NULL; subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key); fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->num - 1) : NULL; if (fragment) { if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1) fragment->reassembled_in_frame = pinfo->num; if (fragment->reassembled_in_frame == pinfo->num) { size += fragment->length; i_char += fragment->length; } } size += tvb_reported_length_remaining(tvb, i_offset); if (size > 0) { buffer = (guint8 *) wmem_alloc(pinfo->pool, size); if (fragment && i_char > 0) memcpy(buffer, fragment->data, i_char); if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') { buffer[i_char - 1] = '\n'; i_offset += 1; } c1 = tvb_get_guint8(tvb, i_offset); i_offset += 1; old_offset = i_offset; while (tvb_reported_length_remaining(tvb, i_offset) > 0) { c2 = tvb_get_guint8(tvb, i_offset); if (c1 == '\r' && c2 == '\n') { buffer[i_char] = c2; if (tvb_reported_length_remaining(tvb, i_offset) > 1) { c1 = tvb_get_guint8(tvb, i_offset + 1); i_offset += 2; i_char += 1; } else { i_offset += 1; } continue; } buffer[i_char] = c1; c1 = c2; i_char += 1; i_offset += 1; } if (tvb_reported_length_remaining(tvb, old_offset) == 0) { buffer[i_char] = c1; i_char += 1; } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) { buffer[i_char] = c2; i_char += 1; } next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char); add_new_data_source(pinfo, next_tvb, "Logcat"); i_offset = 0; while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) { if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) { payload_length = tvb_get_letohs(next_tvb, i_offset); try_header_size = tvb_get_letohs(next_tvb, i_offset + 2); if (try_header_size != 24) logcat_length = payload_length + 20; else logcat_length = payload_length + 24; } if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) { new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length); call_dissector(logcat_handle, new_tvb, pinfo, main_tree); i_offset += logcat_length; } else { if (!pinfo->fd->flags.visited) { DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small"); for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { key[i_key].length = 1; key[i_key].key = &adb_service_data->session_key[i_key]; } key[i_key].length = 1; key[i_key++].key = &pinfo->num; key[i_key].length = 0; key[i_key].key = NULL; fragment = wmem_new(wmem_file_scope(), fragment_t); fragment->length = tvb_captured_length_remaining(next_tvb, i_offset); fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length); tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length); fragment->reassembled_in_frame = -1; wmem_tree_insert32_array(fragments, key, fragment); } proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA); i_offset = tvb_captured_length(next_tvb); } } } offset = tvb_captured_length(tvb); } else if (g_str_has_prefix(service, "shell:")) { if (adb_service_data->direction == P2P_DIR_SENT) { proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset))); } else { proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset))); } offset = tvb_captured_length(tvb); } else if (g_str_has_prefix(service, "jdwp:")) { /* TODO */ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_captured_length(tvb); } else if (g_str_has_prefix(service, "sync:")) { /* TODO */ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_captured_length(tvb); } else if (g_strcmp0(service, "host:list-forward") == 0 || g_str_has_prefix(service, "root:") || g_str_has_prefix(service, "remount:") || g_str_has_prefix(service, "tcpip:") || g_str_has_prefix(service, "usb:")) { if (tvb_reported_length_remaining(tvb, offset)) { proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset))); offset = tvb_captured_length(tvb); } } else { proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_captured_length(tvb); } return offset; }
static gint dissect_usb_dfu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *command_item; proto_item *sub_item; proto_tree *command_tree; gint offset = 0; gint p2p_dir_save; guint8 command; gint16 command_response = -1; command_data_t *command_data = NULL; wmem_tree_t *wmem_tree; wmem_tree_key_t key[5]; guint32 bus_id; guint32 device_address; guint32 k_bus_id; guint32 k_device_address; guint32 k_frame_number; gint32 block_number = -1; usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data; if (!usb_conv_info) return offset; bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; k_bus_id = bus_id; k_device_address = device_address; k_frame_number = pinfo->fd->num; key[0].length = 1; key[0].key = &k_bus_id; key[1].length = 1; key[1].key = &k_device_address; main_item = proto_tree_add_item(tree, proto_usb_dfu, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_usb_dfu); col_set_str(pinfo->cinfo, COL_PROTOCOL, "USB DFU"); p2p_dir_save = pinfo->p2p_dir; pinfo->p2p_dir = (usb_conv_info->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV; switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction "); break; } if (usb_conv_info->is_setup) { guint16 interface; command_item = proto_tree_add_item(main_tree, hf_setup_command, tvb, offset, 1, ENC_NA); command = tvb_get_guint8(tvb, offset); if (!((usb_conv_info->setup_requesttype == 0x21 && (command == 0x00 || command == 0x01 || command == 0x04 || command == 0x06)) || (usb_conv_info->setup_requesttype == 0xa1 && (command == 0x02 || command == 0x03 || command == 0x05)))) expert_add_info(pinfo, command_item, &ei_invalid_command_for_request_type); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, "Command: %s", val_to_str_ext_const(command, &command_vals_ext, "Unknown")); if (command == 0x00) { /* Detach */ proto_tree_add_item(main_tree, hf_setup_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " Timeout=%u", tvb_get_letohs(tvb, offset)); } else if (command == 0x01 || command == 0x02) { /* Download || Upload */ proto_tree_add_item(main_tree, hf_setup_block_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " Block Number=%u", tvb_get_letohs(tvb, offset)); block_number = tvb_get_letohs(tvb, offset); } else { proto_tree_add_item(main_tree, hf_setup_unused, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; proto_tree_add_item(main_tree, hf_setup_interface, tvb, offset, 2, ENC_LITTLE_ENDIAN); interface = tvb_get_letohs(tvb, offset); offset += 2; proto_tree_add_item(main_tree, hf_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (command == 0x01) { /* Download */ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_length(tvb); } if (tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(main_tree, pinfo, &ei_unexpected_data, tvb, offset, tvb_length_remaining(tvb, offset)); offset = tvb_length(tvb); } /* Save request info (command_data) */ if (!pinfo->fd->flags.visited && command != 21) { key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; command_data = wmem_new(wmem_file_scope(), command_data_t); command_data->bus_id = bus_id; command_data->device_address = device_address; command_data->command = command; command_data->interface = interface; command_data->command_frame_number = pinfo->fd->num; command_data->block_number = block_number; wmem_tree_insert32_array(command_info, key, command_data); } pinfo->p2p_dir = p2p_dir_save; return offset; } /* Get request info (command_data) */ key[2].length = 0; key[2].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->fd->num); if (command_data) { command_response = command_data->command; block_number = command_data->block_number; } } if (!command_data) { col_append_str(pinfo->cinfo, COL_INFO, "Response: Unknown"); proto_tree_add_expert(main_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_length_remaining(tvb, offset)); pinfo->p2p_dir = p2p_dir_save; return tvb_length(tvb); } col_append_fstr(pinfo->cinfo, COL_INFO, "Response: %s", val_to_str_ext_const(command_response, &command_vals_ext, "Unknown")); command_item = proto_tree_add_uint(main_tree, hf_response, tvb, offset, 0, command_response); command_tree = proto_item_add_subtree(command_item, ett_command); PROTO_ITEM_SET_GENERATED(command_item); if (command_data) { command_item = proto_tree_add_uint(main_tree, hf_setup_interface, tvb, offset, 0, command_data->interface); PROTO_ITEM_SET_GENERATED(command_item); command_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_frame_number); PROTO_ITEM_SET_GENERATED(command_item); } switch (command_response) { case 0x02: /* Upload */ if (block_number != -1) { sub_item = proto_tree_add_uint(main_tree, hf_setup_block_number, tvb, offset, 0, block_number); PROTO_ITEM_SET_GENERATED(sub_item); col_append_fstr(pinfo->cinfo, COL_INFO, " Block Number=%u", block_number); } proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_length(tvb); break; case 0x03: /* Get Status */ col_append_fstr(pinfo->cinfo, COL_INFO, " = Status: %s, PollTimeout: %u ms, State: %s", val_to_str_ext_const(tvb_get_guint8(tvb, offset), &status_vals_ext, "Unknown"), tvb_get_letoh24(tvb, offset + 1), val_to_str_ext_const(tvb_get_guint8(tvb, offset + 4), &state_vals_ext, "Unknown")); proto_tree_add_item(main_tree, hf_status, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_poll_timeout, tvb, offset, 3, ENC_LITTLE_ENDIAN); offset += 3; proto_tree_add_item(main_tree, hf_state, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_iString, tvb, offset, 1, ENC_NA); offset += 1; break; case 0x05: /* Get State */ proto_tree_add_item(main_tree, hf_state, tvb, offset, 1, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, " = %s", val_to_str_ext_const(tvb_get_guint8(tvb, offset), &state_vals_ext, "Unknown")); offset += 1; break; case 0x00: /* Detach */ case 0x01: /* Download */ case 0x04: /* Clear Status */ case 0x06: /* Abort */ default: proto_tree_add_expert(command_tree, pinfo, &ei_unexpected_response, tvb, offset, 0); if (tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(main_tree, pinfo, &ei_unknown_data, tvb, offset, -1); offset = tvb_length(tvb); } } pinfo->p2p_dir = p2p_dir_save; return offset; }