Beispiel #1
0
static void
dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
			   proto_tree *tree, guint32 remaining_length)
{
	gboolean save_fragmented = pinfo->fragmented;
	int save_visited = pinfo->fd->flags.visited;
	conversation_t *conversation = NULL;
	fragment_head *fd_head = NULL;
	tvbuff_t *payload_tvb = NULL;
	gboolean more_frags = FALSE;
	gboolean fd_head_not_cached = FALSE;
	heur_dtbl_entry_t *hdtbl_entry;

	if (!smb_direct_reassemble) {
		payload_tvb = tvb;
		goto dissect_payload;
	}

	conversation = find_or_create_conversation(pinfo);

	if (remaining_length > 0) {
		more_frags = TRUE;
	}

	fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0);
	if (fd_head == NULL) {
		fd_head_not_cached = TRUE;

		pinfo->fd->flags.visited = 0;
		fd_head = fragment_add_seq_next(&smb_direct_reassembly_table,
						tvb, 0, pinfo,
						conversation->index,
						NULL, tvb_captured_length(tvb),
						more_frags);
	}

	if (fd_head == NULL) {
		/*
		 * We really want the fd_head and pass it to
		 * process_reassembled_data()
		 *
		 * So that individual fragments gets the
		 * reassembled in field.
		 */
		fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table,
						      pinfo,
						      conversation->index);
	}

	if (fd_head == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

	if (fd_head_not_cached) {
		p_add_proto_data(wmem_file_scope(), pinfo,
				 proto_smb_direct, 0, fd_head);
	}

	payload_tvb = process_reassembled_data(tvb, 0, pinfo,
					       "Reassembled SMB Direct",
					       fd_head,
					       &smb_direct_frag_items,
					       NULL, /* update_col_info*/
					       tree);
	if (payload_tvb == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

dissect_payload:
	pinfo->fragmented = FALSE;
	if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
				     payload_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
		call_dissector(data_handle, payload_tvb, pinfo, tree);
	}
done:
	pinfo->fragmented = save_fragmented;
	pinfo->fd->flags.visited = save_visited;
	return;
}
static gint
dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item     *ttree = NULL;
    proto_tree     *titem = NULL;
    proto_item     *pitem = NULL;
    gint            offset = 0;
    usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data;
    tvbuff_t       *next_tvb = NULL;
    hci_data_t     *hci_data;
    gint            p2p_dir_save;
    guint32         session_id;
    fragment_head  *reassembled;

    if (tvb_length_remaining(tvb, offset) <= 0)
        return 0;

    titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA);
    ttree = proto_item_add_subtree(titem, ett_hci_usb);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB");

    DISSECTOR_ASSERT(usb_conv_info);

    p2p_dir_save = pinfo->p2p_dir;
    pinfo->p2p_dir = usb_conv_info->direction;

    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;
    }

    session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint;

    hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t);
    hci_data->interface_id = HCI_INTERFACE_USB;
    hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address;
    hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table;
    hci_data->bdaddr_to_name_table = bdaddr_to_name_table;
    hci_data->localhost_bdaddr = localhost_bdaddr;
    hci_data->localhost_name = localhost_name;

    pinfo->ptype = PT_BLUETOOTH;

    next_tvb = tvb_new_subset_remaining(tvb, offset);
    if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02) {
        fragment_info_t  *fragment_info;

        fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id);
        if (fragment_info == NULL) {
            fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t);
            fragment_info->fragment_id = 0;
            fragment_info->remaining_length = 0;

            wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
        }

        if (fragment_info->fragment_id == 0) {
            switch(usb_conv_info->endpoint)
            {
            case 0:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3;
                break;
            case 1:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2;
                break;
            case 2:
                fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4;
                break;
            }
        }

        fragment_info->remaining_length -= tvb_ensure_length_remaining(tvb, offset);

        fragment_add_seq_check(&hci_usb_reassembly_table,
                               tvb, offset, pinfo, session_id, NULL,
                               fragment_info->fragment_id, tvb_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE);
        if (fragment_info->remaining_length > 0)
            fragment_info->fragment_id += 1;
        else
            fragment_info->fragment_id = 0;
    }

    reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id);
    if (reassembled && pinfo->fd->num < reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        col_append_str(pinfo->cinfo, COL_INFO, " Fragment");
    } else if (reassembled && pinfo->fd->num == reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        if (reassembled->len > tvb_ensure_length_remaining(tvb, offset)) {
            next_tvb = process_reassembled_data(tvb, 0, pinfo,
                    "Reassembled HCI_USB",
                    reassembled, &hci_usb_msg_frag_items,
                    NULL, ttree);
        }

        switch(usb_conv_info->endpoint)
        {
        case 0:
            call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data);
            break;
        case 1:
            call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data);
            break;
        case 2:
            call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data);
            break;
        }
    } else {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);
    }

    if (usb_conv_info->endpoint == 0x03) {
        call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data);
    } else if (usb_conv_info->endpoint > 0x03) {
        proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA);
    }

    offset += tvb_length_remaining(tvb, offset);

    pinfo->p2p_dir = p2p_dir_save;

    return offset;
}
Beispiel #3
0
static gint
dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item        *ttree = NULL;
    proto_tree        *titem = NULL;
    proto_item        *pitem = NULL;
    gint               offset = 0;
    usb_conv_info_t   *usb_conv_info;
    tvbuff_t          *next_tvb = NULL;
    bluetooth_data_t  *bluetooth_data;
    gint               p2p_dir_save;
    guint32            session_id;
    fragment_head     *reassembled;

    bluetooth_data = (bluetooth_data_t *) data;

    /* Reject the packet if data is NULL */
    if (data == NULL)
        return 0;

    DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_USB_CONV_INFO);
    usb_conv_info = bluetooth_data->previous_protocol_data.usb_conv_info;

    titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA);
    ttree = proto_item_add_subtree(titem, ett_hci_usb);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB");

    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_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection");
        break;
    }

    if (usb_conv_info->is_setup) {
        proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset += 1;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;
    }

    session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint;

    bluetooth_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address;
/* TODO: adapter disconnect on some USB action, for now do not support adapter disconnection */
    bluetooth_data->adapter_disconnect_in_frame = &max_disconnect_in_frame;

    next_tvb = tvb_new_subset_remaining(tvb, offset);
    if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02 &&
            tvb_captured_length(tvb) == tvb_reported_length(tvb)) {
        fragment_info_t  *fragment_info;

        fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id);
        if (fragment_info == NULL) {
            fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t);
            fragment_info->fragment_id = 0;
            fragment_info->remaining_length = 0;

            wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
        }

        if (fragment_info->fragment_id == 0) {
            switch(usb_conv_info->endpoint)
            {
            case 0:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3;
                break;
            case 1:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2;
                break;
            case 2:
                fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4;
                break;
            }
        }

        fragment_info->remaining_length -= tvb_reported_length_remaining(tvb, offset);

        fragment_add_seq_check(&hci_usb_reassembly_table,
                               tvb, offset, pinfo, session_id, NULL,
                               fragment_info->fragment_id, tvb_reported_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE);
        if (fragment_info->remaining_length > 0)
            fragment_info->fragment_id += 1;
        else
            fragment_info->fragment_id = 0;
    }

    reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id);
    if (reassembled && pinfo->num < reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        col_append_str(pinfo->cinfo, COL_INFO, " Fragment");
    } else if (reassembled && pinfo->num == reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        if (reassembled->len > (guint) tvb_reported_length_remaining(tvb, offset)) {
            next_tvb = process_reassembled_data(tvb, 0, pinfo,
                    "Reassembled HCI_USB",
                    reassembled, &hci_usb_msg_frag_items,
                    NULL, ttree);
        }

        switch(usb_conv_info->endpoint)
        {
        case 0:
            call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data);
            break;
        case 1:
            call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data);
            break;
        case 2:
            call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data);
            break;
        }
    } else {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);
    }

    if (usb_conv_info->endpoint == 0x03) {
        call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data);
    } else if (usb_conv_info->endpoint > 0x03) {
        proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA);
    }

    offset += tvb_reported_length_remaining(tvb, offset);

    pinfo->p2p_dir = p2p_dir_save;

    return offset;
}