/* * Given two address/port pairs for a packet, search for a matching * conversation and, if found and it has a conversation dissector, * call that dissector and return TRUE, otherwise return FALSE. * * This helper uses call_dissector_only which will NOT call the default * "data" dissector if the packet was rejected. * Our caller is responsible to call the data dissector explicitly in case * this function returns FALSE. */ gboolean try_conversation_dissector(const address *addr_a, const address *addr_b, const port_type ptype, const guint32 port_a, const guint32 port_b, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { conversation_t *conversation; conversation = find_conversation(pinfo->fd->num, addr_a, addr_b, ptype, port_a, port_b, 0); if (conversation != NULL) { int ret; dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->fd->num); if (handle == NULL) return FALSE; ret=call_dissector_only(handle, tvb, pinfo, tree, data); if(!ret) { /* this packet was rejected by the dissector * so return FALSE in case our caller wants * to do some cleaning up. */ return FALSE; } return TRUE; } return FALSE; }
void lbttcp_transport_sid_add(const address * source_address, guint16 source_port, guint32 frame, guint32 session_id) { conversation_t * conv = NULL; lbttcp_transport_conv_data_t * conv_data = NULL; lbttcp_transport_t * transport = NULL; conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); if (conv == NULL) { conv = conversation_new(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); } conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp); if (conv_data == NULL) { conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t); conv_data->frame_tree = wmem_tree_new(wmem_file_scope()); conv_data->session_tree = wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data); } /* Lookup by frame */ transport = (lbttcp_transport_t *) wmem_tree_lookup32_le(conv_data->frame_tree, frame); if (transport != NULL) { if (transport->session_id != session_id) { transport = NULL; } } if (transport == NULL) { transport = lbttcp_transport_create(source_address, source_port, session_id); wmem_tree_insert32(conv_data->session_tree, session_id, (void *) transport); wmem_tree_insert32(conv_data->frame_tree, frame, (void *) transport); } }
gboolean lbttcp_transport_sid_find(const address * source_address, guint16 source_port, guint32 frame, guint32 * session_id) { conversation_t * conv = NULL; lbttcp_transport_conv_data_t * conv_data = NULL; lbttcp_transport_t * transport = NULL; conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); if (conv == NULL) { return (FALSE); } conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp); if (conv_data == NULL) { return (FALSE); } if (conv_data->frame_tree == NULL) { return (FALSE); } transport = (lbttcp_transport_t *)wmem_tree_lookup32_le(conv_data->frame_tree, frame); if (transport == NULL) { return (FALSE); } *session_id = transport->session_id; return (TRUE); }
static itl_nexus_t * get_itl_nexus(packet_info *pinfo) { itl_nexus_t *itl = NULL; if (!(itl = (itl_nexus_t *)wmem_tree_lookup32_le(rsvd_conv_data->itl, pinfo->num))) { itl = wmem_new(wmem_file_scope(), itl_nexus_t); itl->cmdset = 0xff; itl->conversation = rsvd_conv_data->conversation; wmem_tree_insert32(rsvd_conv_data->itl, pinfo->num, itl); } return itl; }
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 gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->fd->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { 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 = 0; key[3].key = NULL; } else { /* tcp */ 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 = 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, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; 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 if (command_data->command == A_OKAY) { side_id = command_data->arg1; /* IN: remote 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 (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } 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; }
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); }
dissector_handle_t conversation_get_dissector(conversation_t *conversation, const guint32 frame_num) { return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num); }
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; }